- Compiler: PP → Lexer → Parser → Analyzer → Gengo pipeline - Parser: 232/236 (98%) Harbour compatibility, registry-based dispatch - RTL: 351 Harbour-compatible functions - RDD: DBF/NTX/CDX engines with Rushmore bitmap optimization - Go Interop: IMPORT + pkg.Func() + obj:Method() with FastPath (15M calls/sec) - HB_FUNC API: Full Harbour C API compatible Go bridge - Concurrency: SPAWN/LAUNCH/GOROUTINE, <-, WATCH, PARALLEL FOR, ASYNC/AWAIT - Extensions: Multi-return, DEFER, Slice, f-string, Nil-safe ?:, CONST - Macro Compiler: Runtime AST parsing and evaluation - Debugger: TUI debugger with source display, breakpoints, stepping - FRB: Native + Pcode dual mode runtime binary - Tests: 13 packages ALL PASS Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
173 lines
3.7 KiB
Plaintext
173 lines
3.7 KiB
Plaintext
// Five MENU TO — simplified port of Harbour menuto.prg
|
|
// Compiles via gengo to native binary
|
|
|
|
STATIC aPrompts := {}
|
|
|
|
// @row, col PROMPT text → collects menu items
|
|
FUNCTION __AtPrompt(nRow, nCol, cPrompt, cMsg)
|
|
AAdd(aPrompts, {nRow, nCol, cPrompt, cMsg})
|
|
SetPos(nRow, nCol)
|
|
DevOut(cPrompt)
|
|
RETURN .F.
|
|
|
|
// MENU TO nChoice → displays menu, returns selection
|
|
FUNCTION __MenuTo(nStart)
|
|
LOCAL n, nKey, nLen, q, lExit
|
|
|
|
nLen := Len(aPrompts)
|
|
IF nLen = 0
|
|
RETURN 0
|
|
ENDIF
|
|
|
|
n := nStart
|
|
IF n < 1
|
|
n := 1
|
|
ENDIF
|
|
IF n > nLen
|
|
n := nLen
|
|
ENDIF
|
|
|
|
SetCursor(0)
|
|
lExit := .F.
|
|
|
|
DO WHILE !lExit
|
|
|
|
// Highlight current item (reverse video)
|
|
SetPos(aPrompts[n][1], aPrompts[n][2])
|
|
DevOut(Chr(27) + "[7m" + aPrompts[n][3] + Chr(27) + "[0m")
|
|
|
|
// Show message if any
|
|
IF aPrompts[n][4] != NIL .AND. Len(aPrompts[n][4]) > 0
|
|
SetPos(MaxRow(), 0)
|
|
DevOut(PadR(aPrompts[n][4], MaxCol() + 1))
|
|
ENDIF
|
|
|
|
// Wait for key
|
|
nKey := Inkey(0)
|
|
|
|
// Unhighlight current
|
|
q := n
|
|
SetPos(aPrompts[q][1], aPrompts[q][2])
|
|
DevOut(aPrompts[q][3])
|
|
|
|
DO CASE
|
|
CASE nKey = 24 .OR. nKey = 4 // Down or Right
|
|
n++
|
|
IF n > nLen
|
|
n := 1
|
|
ENDIF
|
|
CASE nKey = 5 .OR. nKey = 19 // Up or Left
|
|
n--
|
|
IF n < 1
|
|
n := nLen
|
|
ENDIF
|
|
CASE nKey = 1 // Home
|
|
n := 1
|
|
CASE nKey = 6 // End
|
|
n := nLen
|
|
CASE nKey = 13 .OR. nKey = 10 // Enter (CR or LF)
|
|
lExit := .T.
|
|
CASE nKey = 27 // ESC
|
|
n := 0
|
|
lExit := .T.
|
|
ENDCASE
|
|
ENDDO
|
|
|
|
// Clear message line
|
|
SetPos(MaxRow(), 0)
|
|
DevOut(Space(MaxCol() + 1))
|
|
|
|
SetCursor(1)
|
|
|
|
// Clear prompts for next use
|
|
aPrompts := {}
|
|
|
|
RETURN n
|
|
|
|
// AChoice — array-based menu selection
|
|
FUNCTION AChoice(nTop, nLeft, nBottom, nRight, aItems)
|
|
LOCAL n := 1, nKey, nLen, nVisible, nOffset, r, i, lExit
|
|
|
|
nLen := Len(aItems)
|
|
IF nLen = 0
|
|
RETURN 0
|
|
ENDIF
|
|
|
|
nVisible := nBottom - nTop + 1
|
|
nOffset := 0
|
|
lExit := .F.
|
|
|
|
SetCursor(0)
|
|
|
|
DO WHILE !lExit
|
|
|
|
// Draw visible items
|
|
FOR r := 1 TO nVisible
|
|
i := nOffset + r
|
|
SetPos(nTop + r - 1, nLeft)
|
|
IF i <= nLen
|
|
IF i = n
|
|
DevOut(Chr(27) + "[7m" + PadR(aItems[i], nRight - nLeft + 1) + Chr(27) + "[0m")
|
|
ELSE
|
|
DevOut(PadR(aItems[i], nRight - nLeft + 1))
|
|
ENDIF
|
|
ELSE
|
|
DevOut(Space(nRight - nLeft + 1))
|
|
ENDIF
|
|
NEXT
|
|
|
|
nKey := Inkey(0)
|
|
|
|
DO CASE
|
|
CASE nKey = 24 // Down
|
|
IF n < nLen
|
|
n++
|
|
IF n > nOffset + nVisible
|
|
nOffset++
|
|
ENDIF
|
|
ENDIF
|
|
CASE nKey = 5 // Up
|
|
IF n > 1
|
|
n--
|
|
IF n <= nOffset
|
|
nOffset := n - 1
|
|
ENDIF
|
|
ENDIF
|
|
CASE nKey = 3 // PgDn
|
|
n += nVisible
|
|
IF n > nLen
|
|
n := nLen
|
|
ENDIF
|
|
nOffset := n - nVisible
|
|
IF nOffset < 0
|
|
nOffset := 0
|
|
ENDIF
|
|
CASE nKey = 18 // PgUp
|
|
n -= nVisible
|
|
IF n < 1
|
|
n := 1
|
|
ENDIF
|
|
nOffset := n - 1
|
|
IF nOffset < 0
|
|
nOffset := 0
|
|
ENDIF
|
|
CASE nKey = 1 // Home
|
|
n := 1
|
|
nOffset := 0
|
|
CASE nKey = 6 // End
|
|
n := nLen
|
|
nOffset := nLen - nVisible
|
|
IF nOffset < 0
|
|
nOffset := 0
|
|
ENDIF
|
|
CASE nKey = 13 // Enter
|
|
lExit := .T.
|
|
CASE nKey = 27 // ESC
|
|
n := 0
|
|
lExit := .T.
|
|
ENDCASE
|
|
ENDDO
|
|
|
|
SetCursor(1)
|
|
RETURN n
|