Files
five/hbrtl/tbrowse_rtl.go
Charles KWON OhJun 59568f3301 Five v0.9 — Harbour + Go fusion language
- 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>
2026-03-31 09:41:50 +09:00

163 lines
3.4 KiB
Go

// Copyright (c) 2026 Charles KWON OhJun (charleskwonohjun@gmail.com)
// All rights reserved.
// TBrowse RTL constructor functions.
package hbrtl
import (
"five/hbrt"
"five/hbrdd"
"strings"
)
// TBrowseNew creates a new TBrowse object.
// Harbour: TBrowseNew(nTop, nLeft, nBottom, nRight)
func rtlTBrowseNew(t *hbrt.Thread) {
t.Frame(4, 0)
defer t.EndProc()
obj := hbrt.NewObject(tbrowseClassID)
// Call Init
oldSelf := t.GetSelf()
t.PushValue(obj)
t.PushValue(t.Local(1))
t.PushValue(t.Local(2))
t.PushValue(t.Local(3))
t.PushValue(t.Local(4))
t.Send("INIT", 4)
result := t.Pop2()
_ = oldSelf
t.PushValue(result)
t.RetValue()
}
// TBrowseDB creates a TBrowse pre-configured for database browsing.
// Harbour: TBrowseDB(nTop, nLeft, nBottom, nRight)
func rtlTBrowseDB(t *hbrt.Thread) {
t.Frame(4, 0)
defer t.EndProc()
obj := hbrt.NewObject(tbrowseClassID)
arr := obj.AsArray()
cls := hbrt.GetClass(arr.Class)
// Set coordinates
if idx := cls.FieldIndex("NTOP"); idx >= 0 {
arr.Items[idx] = t.Local(1)
}
if idx := cls.FieldIndex("NLEFT"); idx >= 0 {
arr.Items[idx] = t.Local(2)
}
if idx := cls.FieldIndex("NBOTTOM"); idx >= 0 {
arr.Items[idx] = t.Local(3)
}
if idx := cls.FieldIndex("NRIGHT"); idx >= 0 {
arr.Items[idx] = t.Local(4)
}
nRowCount := int(t.Local(3).AsNumInt()) - int(t.Local(1).AsNumInt()) - 1
if nRowCount < 1 {
nRowCount = 1
}
if idx := cls.FieldIndex("NROWCOUNT"); idx >= 0 {
arr.Items[idx] = hbrt.MakeInt(nRowCount)
}
// Set DB skip/gotop/gobottom blocks
wa := getDbEditWA(t)
if wa != nil {
if idx := cls.FieldIndex("BSKIPBLOCK"); idx >= 0 {
arr.Items[idx] = hbrt.MakeBlock(func(bt *hbrt.Thread) {
bt.Frame(1, 0)
defer bt.EndProc()
nRecs := int(bt.Local(1).AsNumInt())
skipped := dbSkipBlock(wa, nRecs)
bt.RetInt(int64(skipped))
}, 0)
}
if idx := cls.FieldIndex("BGOTOPBLOCK"); idx >= 0 {
arr.Items[idx] = hbrt.MakeBlock(func(bt *hbrt.Thread) {
bt.Frame(0, 0)
defer bt.EndProc()
if area := wa.Current(); area != nil {
area.GoTop()
}
bt.RetNil()
}, 0)
}
if idx := cls.FieldIndex("BGOBOTTOMBLOCK"); idx >= 0 {
arr.Items[idx] = hbrt.MakeBlock(func(bt *hbrt.Thread) {
bt.Frame(0, 0)
defer bt.EndProc()
if area := wa.Current(); area != nil {
area.GoBottom()
}
bt.RetNil()
}, 0)
}
}
t.PushValue(obj)
t.RetValue()
}
// dbSkipBlock — Harbour Skipped() function
func dbSkipBlock(wa *hbrdd.WorkAreaManager, nRecs int) int {
area := wa.Current()
if area == nil {
return 0
}
nSkipped := 0
if nRecs > 0 {
for nSkipped < nRecs {
area.Skip(1)
if area.EOF() {
area.Skip(-1)
break
}
nSkipped++
}
} else if nRecs < 0 {
for nSkipped > nRecs {
area.Skip(-1)
if area.BOF() {
break
}
nSkipped--
}
}
return nSkipped
}
// TBColumnNew creates a new TBColumn.
// Harbour: TBColumnNew(cHeading, bBlock)
func rtlTBColumnNew(t *hbrt.Thread) {
t.Frame(2, 0)
defer t.EndProc()
obj := hbrt.NewObject(tbcolumnClassID)
arr := obj.AsArray()
cls := hbrt.GetClass(arr.Class)
heading := t.Local(1)
block := t.Local(2)
if idx := cls.FieldIndex("CHEADING"); idx >= 0 {
arr.Items[idx] = heading
}
if idx := cls.FieldIndex("BBLOCK"); idx >= 0 {
arr.Items[idx] = block
}
// Auto-detect width from heading
if idx := cls.FieldIndex("NWIDTH"); idx >= 0 {
w := len(strings.TrimSpace(heading.AsString()))
if w < 10 {
w = 10
}
arr.Items[idx] = hbrt.MakeInt(w)
}
t.PushValue(obj)
t.RetValue()
}