// Copyright (c) 2026 Charles KWON OhJun (charleskwonohjun@gmail.com) // All rights reserved. // Database callable functions: FIELDPUT, ALIAS, DBEVAL, DBUSEAREA, DBCLOSEAREA, // DBGOTO, DBSKIP, DBAPPEND, DBDELETE, DBRECALL, DBCOMMIT, DBSEEK, // DBGOTOP, DBGOBOTTOM, DBRLOCKLIST, DBSETFILTER, DBCLEARFILTER package hbrtl import ( "five/hbrt" "five/hbrdd" ) // FIELDPUT(nField, xValue) → xValue func rtlFieldPut(t *hbrt.Thread) { t.Frame(2, 0) defer t.EndProc() wam := getWA(t) if wam == nil { t.RetNil() return } area := wam.Current() if area == nil { t.RetNil() return } nField := t.Local(1).AsInt() val := t.Local(2) area.PutValue(nField-1, val) // 1-based to 0-based t.RetVal(val) } // ALIAS([nWorkArea]) → cAlias func rtlAlias(t *hbrt.Thread) { nParams := t.ParamCount() t.Frame(nParams, 0) defer t.EndProc() wam := getWA(t) if wam == nil { t.RetString("") return } area := wam.Current() if area != nil { t.RetString(area.Alias()) } else { t.RetString("") } } // DBEVAL(bBlock [, bFor [, bWhile [, nCount [, nRecord [, lRest]]]]]) → NIL func rtlDbEval(t *hbrt.Thread) { nParams := t.ParamCount() t.Frame(nParams, 0) defer t.EndProc() wam := getWA(t) if wam == nil { t.RetNil() return } area := wam.Current() if area == nil { t.RetNil() return } block := t.Local(1) if !block.IsBlock() { t.RetNil() return } var bFor, bWhile hbrt.Value nCount := -1 lRest := false if nParams >= 2 { bFor = t.Local(2) } if nParams >= 3 { bWhile = t.Local(3) } if nParams >= 4 && !t.Local(4).IsNil() { nCount = t.Local(4).AsInt() } if nParams >= 5 && !t.Local(5).IsNil() { nRec := t.Local(5).AsInt() area.GoTo(uint32(nRec)) } if nParams >= 6 && !t.Local(6).IsNil() { lRest = t.Local(6).AsBool() } // If not lRest and no record specified, go top if !lRest && (nParams < 5 || t.Local(5).IsNil()) { area.GoTop() } count := 0 for !area.EOF() { if nCount >= 0 && count >= nCount { break } // While condition if !bWhile.IsNil() && bWhile.IsBlock() { blk := bWhile.AsBlock() t.PendingParams2(0) blk.Fn(t) if !t.GetRetValue().AsBool() { break } } // For condition doBlock := true if !bFor.IsNil() && bFor.IsBlock() { blk := bFor.AsBlock() t.PendingParams2(0) blk.Fn(t) doBlock = t.GetRetValue().AsBool() } if doBlock { blk := block.AsBlock() t.PendingParams2(0) blk.Fn(t) } area.Skip(1) count++ } t.RetNil() } // DBUSEAREA([lNewArea], [cDriver], cName, [cAlias], [lShared], [lReadOnly]) → NIL func rtlDbUseArea(t *hbrt.Thread) { nParams := t.ParamCount() t.Frame(nParams, 0) defer t.EndProc() wam := getWA(t) if wam == nil { t.RetNil() return } cName := "" cAlias := "" cDriver := "DBFNTX" if nParams >= 3 && !t.Local(3).IsNil() { cName = t.Local(3).AsString() } if nParams >= 4 && !t.Local(4).IsNil() { cAlias = t.Local(4).AsString() } if nParams >= 2 && !t.Local(2).IsNil() { cDriver = t.Local(2).AsString() } shared := false readOnly := false if nParams >= 5 && !t.Local(5).IsNil() { shared = t.Local(5).AsBool() } if nParams >= 6 && !t.Local(6).IsNil() { readOnly = t.Local(6).AsBool() } wam.Open(cDriver, cName, cAlias, shared, readOnly) t.RetNil() } // DBCLOSEAREA() → NIL func rtlDbCloseArea(t *hbrt.Thread) { t.Frame(0, 0) defer t.EndProc() wam := getWA(t) if wam != nil { wam.Close() } t.RetNil() } // DBGOTO(nRecNo) → NIL func rtlDbGoTo(t *hbrt.Thread) { t.Frame(1, 0) defer t.EndProc() wam := getWA(t) if wam == nil { t.RetNil() return } area := wam.Current() if area != nil { area.GoTo(uint32(t.Local(1).AsLong())) } t.RetNil() } // DBSKIP([nRecords]) → NIL func rtlDbSkip(t *hbrt.Thread) { nParams := t.ParamCount() t.Frame(nParams, 0) defer t.EndProc() wam := getWA(t) if wam == nil { t.RetNil() return } area := wam.Current() if area == nil { t.RetNil() return } n := int64(1) if nParams >= 1 && !t.Local(1).IsNil() { n = t.Local(1).AsLong() } area.Skip(n) t.RetNil() } // DBGOTOP() → NIL func rtlDbGoTop(t *hbrt.Thread) { t.Frame(0, 0) defer t.EndProc() wam := getWA(t) if wam == nil { t.RetNil() return } area := wam.Current() if area != nil { area.GoTop() } t.RetNil() } // DBGOBOTTOM() → NIL func rtlDbGoBottom(t *hbrt.Thread) { t.Frame(0, 0) defer t.EndProc() wam := getWA(t) if wam == nil { t.RetNil() return } area := wam.Current() if area != nil { area.GoBottom() } t.RetNil() } // DBAPPEND([lUnlock]) → NIL func rtlDbAppend(t *hbrt.Thread) { nParams := t.ParamCount() t.Frame(nParams, 0) defer t.EndProc() wam := getWA(t) if wam == nil { t.RetNil() return } area := wam.Current() if area != nil { area.Append() } t.RetNil() } // DBDELETE() → NIL func rtlDbDelete(t *hbrt.Thread) { t.Frame(0, 0) defer t.EndProc() wam := getWA(t) if wam == nil { t.RetNil() return } area := wam.Current() if area != nil { area.Delete() } t.RetNil() } // DBRECALL() → NIL func rtlDbRecall(t *hbrt.Thread) { t.Frame(0, 0) defer t.EndProc() wam := getWA(t) if wam == nil { t.RetNil() return } area := wam.Current() if area != nil { area.Recall() } t.RetNil() } // DBCOMMIT() → NIL func rtlDbCommit(t *hbrt.Thread) { t.Frame(0, 0) defer t.EndProc() wam := getWA(t) if wam == nil { t.RetNil() return } area := wam.Current() if area != nil { area.Flush() } t.RetNil() } // DBSEEK(xValue [, lSoftSeek [, lLast]]) → lFound func rtlDbSeek(t *hbrt.Thread) { nParams := t.ParamCount() t.Frame(nParams, 0) defer t.EndProc() wam := getWA(t) if wam == nil { t.RetBool(false) return } area := wam.Current() if area == nil { t.RetBool(false) return } val := t.Local(1) softSeek := false findLast := false if nParams >= 2 && !t.Local(2).IsNil() { softSeek = t.Local(2).AsBool() } if nParams >= 3 && !t.Local(3).IsNil() { findLast = t.Local(3).AsBool() } // Check if area implements Indexer if idx, ok := area.(hbrdd.Indexer); ok { found, _ := idx.Seek(val, softSeek, findLast) t.RetBool(found) } else { t.RetBool(false) } } // DBSELECTAREA(nArea | cAlias) → NIL func rtlDbSelectArea(t *hbrt.Thread) { t.Frame(1, 0) defer t.EndProc() wam := getWA(t) if wam == nil { t.RetNil() return } v := t.Local(1) if v.IsString() { wam.Select(v.AsString()) } else { wam.Select(uint16(v.AsInt())) } t.RetNil() } // DBPACK() → NIL func rtlDbPack(t *hbrt.Thread) { t.Frame(0, 0) defer t.EndProc() wam := getWA(t) if wam == nil { t.RetNil() return } area := wam.Current() if area != nil { area.Pack() } t.RetNil() } // DBZAP() → NIL func rtlDbZap(t *hbrt.Thread) { t.Frame(0, 0) defer t.EndProc() wam := getWA(t) if wam == nil { t.RetNil() return } area := wam.Current() if area != nil { area.Zap() } t.RetNil() }