FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index WhatsNew / Novedades New FTDN July 2026 (FWH 26.07)
Posts: 44508
Joined: Thu Oct 06, 2005 05:47 PM

New FTDN July 2026 (FWH 26.07)

Posted: Fri Jul 24, 2026 10:40 AM

=========

July 2026

  • Enhancement: Class TWebView2 Method New() accepts a third optional
    parameter cBrowserExecutableFolder (Microsoft's browserExecutableFolder).
    When set, WebView2 loads the Fixed Version / standalone Runtime from that
    folder instead of the Evergreen Runtime installed on the system. Useful on
    older OS (e.g. Windows Server 2012 R2) where current Evergreen builds no
    longer work, or when the Runtime cannot be installed machine-wide.
    Example:
    oWeb := TWebView2():New( oWnd, , "C:\MiPrograma\WebView2Runtime" )
    The path must be the Fixed Version root (folder that contains
    msedgewebview2.exe). Existing code without the parameter is unchanged.
    Also fixed: cUserDataFolder (2nd parameter) was being overwritten with a
    default AppData path; it is now honoured.

  • Fix: MAPISendMail() / DEFINE MAIL ÔÇö when TO is given with a single
    parameter (TO cEmail), only MapiRecipDesc.lpszName was filled and
    lpszAddress stayed empty. Outlook often accepts that; Thunderbird and
    other stricter Simple MAPI clients leave the To: field empty.
    mapi.c now copies the display name into the address when the address
    is empty (same effect as TO cEmail, cEmail). Dual form
    TO cName, cAddress is unchanged. Origin and MAPIAddress() predefined
    recipients use the same fallback.
    https://forums.fivetechsupport.com/ (thanks for the detailed report)

  • Enhancement: window.prg added TSBROWSE to static cBrwClassList.
    https://forums.fivetechsupport.com/viewtopic.php?p=285833#p285833
    Thanks to Adolfo.

  • Fix: TXBrowse: SelectRow() on a browse using SetMultiSelectCol() raised
    a "Zero divisor" error when the browse had no SetSum() / totaled columns.
    Now SelectRow() only saves/recalcs totals when ::aSumCols is not empty,
    ReCalcTotals() returns immediately when there are no totaled columns, and
    TXBrwColumn:footerStr() guards the standard-deviation division (nCount-1
    could be zero with a single counted row). Ctrl+click, Shift+click, double
    click and header select-all/clear work and keep aSelected consistent with
    no changes required in user code.

  • New: Tensor Logic engine ÔÇö Pedro Domingos' "Tensor Logic: The Language of
    AI" (arXiv:2510.12269) implemented in FWH. A program is a set of tensor
    equations; logical rules and Einstein summation are the same operation, so
    one engine runs both neural components and symbolic (Datalog) reasoning:

  • source\function\fwtensor.c: FWT_EinSum( cSpec, t1, ... ) generalized
    Einstein summation over FW_Tensor float32 tensors (join + projection,
    the paper's single construct), new nonlinearities FWT_SoftmaxLast,
    FWT_Sigmoid( t, nTemperature ), FWT_Step, FWT_ReLU, FWT_Tanh,
    FWT_LNormLast, their backward kernels (FWT_ActDeriv,
    FWT_SoftmaxBackwardLast, FWT_LNormBackwardLast), utility ops
    (FWT_Mul, FWT_Sub, FWT_Fill, FWT_Clone, FWT_MaxDiff) and C-speed tensor
    builders replacing per-element PRG loops (FWT_OneHot, FWT_CausalMask,
    FWT_SinPos, FWT_NotEq, FWT_UnitEmb).
  • OpenBLAS acceleration: fwtensor.c loads OpenBLAS DYNAMICALLY at first
    use (libopenblas.dll on PATH / beside the exe, or the FWT_BLAS_DLL env
    var; set it to "off" to force the portable C loops; ILP64 builds such as
    numpy's libscipy_openblas64_ are detected too). Never a hard dependency.
    FWT_MatMul and every 2-operand FWT_EinSum reducible to a (batched) GEMM
    run on cblas_sgemm, using BLAS transposes so the common attention
    patterns need no repacking. FWT_BlasActive() reports the backend.
    Measured on a Xeon W-2140B (8c): 1024x1024x1024 matmul went from
    0.32 GFLOPS (C loops) to 497 GFLOPS ÔÇö above numpy's OpenBLAS (446) and
    within 2x of PyTorch/MKL (982) on the same machine.
  • source\classes\tensorlogic.prg: TTensorLogic ÔÇö tensor logic programs as
    equation strings: oTL:Eq( "Y = step( W[i,j] * X[j] + B )" ).
    Joins, projections, nonlinearities (step, sigmoid, relu, tanh, gelu,
    softmax, lnorm), Run() = forward chaining to fixpoint (recursive Datalog
    rules converge), and automatic differentiation: the gradient of an
    equation is the same einsum with factor and output swapped, so
    Forward() / Seed() / Backward() / Step() train ANY program with no
    hand-written backprop (verified against central finite differences,
    max error 1e-6). Datalog over DBF tables: TTLDomain maps entity names
    to tensor indices, LetDbf() turns records into boolean relation tensors,
    LetSet() unary predicates, Query() decodes result tensors back to tuples
    of names. Helpers TL_TensorND(), TL_NotEq(), TL_UnitEmb().
    Terms with ANY number of factors are evaluated by chaining pairwise
    contractions (only the letters still needed survive each step), so every
    step takes the BLAS GEMM fast path. TTransformerTL (GPT-style
    transformer facade over a tensor logic program: New / ForwardSeq /
    TrainStep / AccumStep / EvalLoss / Generate / LoadFromTransformer) also
    lives in tensorlogic.prg.
    Professional training support: StepAdam() (Adam optimizer, C kernel
    FWT_AdamUpdate with bias correction), ClipGrads() (global L2 gradient
    clipping, C FWT_SumSq/FWT_ScaleInPlace), gradient ACCUMULATION across
    mini-batches (AccumStep + ClearActGrads: parameter grads add up,
    activation grads reset), and checkpointing: SaveParams()/LoadParams()
    persist every Param() tensor as raw float32 (C FWT_GetBytes/FWT_SetBytes)
    plus a user hash (vocabulary, config).
  • Samples (samples\ai): tensorlogic.prg ÔÇö engine test suite (einsum vs
    matmul, attention head as 6 equations, Datalog transitive closure,
    gradient checks, XOR training: 9 PASS). tltransformer.prg ÔÇö a GPT-style
    transformer written as 15 equations per layer (multi-head via a head
    INDEX, no column slicing) with a TTransformerTL facade; with identical
    weights it reproduces the classic Transformer:ForwardSeq() to 1e-8 and
    trains/generates through the generic autodiff (3 PASS).
    tldatalog.prg ÔÇö family DBF -> Father/Grandparent/Sibling/Ancestor rules
  • embedding-space reasoning with temperature (deductive vs analogical,
    6 PASS). tlbench.prg ÔÇö einsum benchmark, BLAS vs C loops.
    tlminillm.prg ÔÇö a DeepSeek / MiMo style mini-LLM written PURELY as
    equations: MLA (multi-head latent attention, the low-rank KV compression
    behind DeepSeek's small KV cache), RoPE (rotary positions as a
    signed-permutation join), MoE (mixture-of-experts FFN with a softmax
    gate) and MTP (multi-token prediction, two heads trained jointly);
    trains, head 2 predicts t+2 at 8/8 positions, generates (3 PASS).
    tlfwcode.prg ÔÇö char-level language model trained on real FWH sources
    (source\classes\*.prg) with a professional loop: Adam + linear warmup +
    cosine decay, mini-batch gradient accumulation, global gradient
    clipping, train/validation split (held-out 10%), best-validation
    checkpointing to tlfwcode.chk (TLFW_RESUME=1 continues a previous run),
    top-k + temperature sampling and tokens/s metrics. Everything
    configurable via TLFW_* environment variables (steps, batch, layers,
    d_model, heads, window, corpus KB, lr).
  • Docs: docs\<lang>\ai\tensorlogic.html (reference) and
    docs\<lang>\ai\tensorlogic-tutorial.html ÔÇö "Tensor Logic: from 0 to 100",
    a 10-lesson tutorial (tensors, einsum, equations, logic rules, recursion,
    Datalog over DBFs, attention, autodiff, Adam training, and the road to
    the transformer/LLM samples) with a runnable companion,
    samples\ai\tltutor.prg, whose tltutor.log matches the text lesson by
    lesson.
  • New: samples\ai\tlc.prg ÔÇö the synthetic-training recipe for code,
    end to end in miniature ("how would a model learn C without a human
    dataset"). A mini-C toy language (2 variables, mod-10 arithmetic, if):
    1) synthetic GENERATOR of valid programs with a built-in exact ORACLE
    (the pair every code-training pipeline needs, at zero labeling cost);
    2) EXECUTION LEARNING: a TL transformer predicts the output of programs
    it has never seen ÔÇö 36-40% exact-digit accuracy vs 10% chance ÔÇö with
    the key finding documented in code: a single answer target per
    sequence learns nothing (chance); dense next-char targets plus the
    answer (multitask) is what makes the task land;
    3) GRAMMAR-CONSTRAINED DECODING: a prefix automaton masks illegal
    characters during sampling ÔÇö an UNTRAINED model emits 25/25 valid
    programs (free sampling: 0/25). Syntax is imposed, never learned.
    Also documents a Harbour numeric gotcha: LCG multipliers like 1103515245
    overflow double precision (n*mult > 253) and the random stream silently
    degenerates ÔÇö use MINSTD (48271) with Int().

  • Fix: samples\ai\transf2.prg did not link (undefined ArgMax(), it was only
    defined in other transformer samples) and samples\ai\transf_subq.prg did
    not link either (its local CrossEntropyLoss() collided with the public one
    in source\classes\transformer.prg): ArgMax() added, CrossEntropyLoss()
    made STATIC. All 11 transformer samples build again; transftest.prg suite
    passes 8/8.

  • Fix: FWMariaConnection bOnLostServer not fired on AUTOMATIC reconnect
    (source\internal\fwmaria.prg):
    The client option MYSQL_OPT_RECONNECT was enabled on connect, so when the
    server dropped the connection (wait_timeout, network oscillation, KILL) the
    MySQL/MariaDB client library silently re-opened the session INSIDE
    mysql_real_query() and retried the statement itself: no error, no callback,
    and all SET SESSION state (time_zone, sql_mode, lc_time_names, ...) silently
    reverted to server defaults, so applications kept writing data with wrong
    session settings. Only the explicit oCn:ReConnect() path fired bOnLostServer.
    Fixed: driver-level auto-reconnect is now DISABLED; a dead session always
    surfaces as an error, and only the controlled helper mysql_ping_reconnect()
    in C may revive it (it detects the reconnect via mysql_thread_id() change and
    flags it to the PRG layer). Execute_Sql()/Check() then fire bOnLostServer,
    re-apply tracked session state (RestoreSessionState()) and retry the failed
    statement, both on the explicit ReConnect() path and on the automatic path
    (plain Execute on a dropped connection). No statement runs any longer on a
    reconnected session before its state is restored.
    Unit test: samples\fwmaria_ut.prg (U_TestAutoReconnect). Sample: fwmatz.prg.

  • Fix: samples\fwmalost.prg could be mistaken for a library error dialog:
    FWSetLanguage( 1 ) selects English, not Portuguese (4 = Portuguese), and the
    demo MARIA_ONCONNECTERROR hook itself showed a MsgStop() built with the same
    FWString() texts the library uses ("Error" title, "Please check your
    connection and try again"), so the sample's own dialog looked like a
    non-suppressible library MessageBox. To be clear: the library shows NO dialog
    on a failed connect while lShowErrors / lShowMessages keep their default .F.
    The sample now selects Portuguese and titles its own dialog
    "APP HOOK: MARIA_ONCONNECTERROR".

  • Enhancement: TX8 class (the TComboMetro drop-down browse) is no longer
    STATIC (source\classes\combom.prg), so applications can subclass it or
    OVERRIDE its methods (drop-down direction, selection colours, etc.) without
    keeping a private copy of combom.prg. No behaviour change.

  • Fix: TWBrowse array-bound error (BASE/1132) on drag-scroll and inertial
    (flick) scroll near the end of the data (source\classes\wbrowse.prg):
    LButtonUp() and MouseMove() advanced ::nAt directly by the visible row count
    ( ::nRowCount() - ::nRowPos ) without the [1, nLen] clamp that ::bSkip
    already enforces. When fewer records remained than visible rows (array
    length not a multiple of the pane height), ::nAt overshot ::nLen and the
    next bLine evaluation indexed past the end of the array. Now the three
    direct ::nAt writes apply the same clamp used in SetArray()'s bSkip:
    ::nAt := Min( Max( ::nAt, 1 ), Eval( ::bLogicLen, Self ) ), which also
    refreshes ::nLen.

  • Fix: FW_SaveImage() silent crash saving alpha bitmaps to JPG/PNG/GIF/TIFF
    (source\winapi\gdipfwh.cpp):
    A March 2025 memory-leak fix in GDIP_SAVEIMAGE() added a second delete of the
    GDI+ bitmap after BitmapFromAlphaBmp(), which already frees the original image
    internally. Saving 32-bit alpha HBITMAPs (e.g. after GdiBmp:Conver24to32Alpha()
    or bmp2alpha()) to non-BMP formats caused a double-free and immediate process exit
    with no Harbour error. Restored the pre-leak-fix assignment pattern:
    pImage = BitmapFromAlphaBmp( pImage ). Affected typical barcode/QR workflows such as
    FW_BarCodeBmp() + bmp2alpha() + FW_SaveImage( hBmp, cFile + '.jpg' ).

  • Fix: MsgYesNoCancel() returned logical instead of Windows button code
    (source\function\msgs.c):
    Since the 2015 Unicode refactor, MSGYESNOCANCEL used hb_retl() on the raw
    MessageBox return code, so every choice (Yes/No/Cancel) evaluated as .T.
    Restored hb_retnl() so the function again returns 6 (Yes), 7 (No), 2 (Cancel).

  • Fix: TGet:KeyDown bKeyDown reads stale bound variable (source\classes\tget.prg):
    On xHarbour, TGet:KeyDown evaluated bKeyDown before syncing the edit buffer to
    the bound variable. bKeyDown callbacks that read the variable (e.g. Enter key
    handlers for product-code lookups) saw a stale/empty value because the buffer
    was never committed. Fixed: sync oGet:buffer from GetWindowText/GetText, then
    VarPut(UnTransform()) / VarPut(GetText()) before Eval(bKeyDown), mirroring what
    lValid/KeyChar already do. VarPut is used instead of full Assign() to avoid
    resetting oGet:Original and oGet:Changed, which would break bChange in KeyChar
    for VK_RETURN/VK_TAB. Sample: samples\getkdwn.prg.

  • Fix: FWMariaConnection hardcoded English error dialog not suppressible
    (source\internal\fwmaria.prg):
    On connection error, ShowError() called Msg_Alert() unconditionally, showing
    a hardcoded English MessageBox even when lShowErrors was .F. or the app wanted
    to localise errors. Fixed: ShowError() now checks lShowErrors .or. lShowMessages
    before calling Msg_Alert(). Apps can suppress all internal error dialogs by
    setting oCn:lShowErrors := .F. Connect-time errors can be localised via the
    optional MARIA_ONCONNECTERROR( nError, cErrMsg, oCn ) hook or :bOnConnectError.
    The "Please check your connection..." suffix is now passed through FWString().
    Sample: samples\fwmalost.prg.

  • Fix: FWMariaConnection silent reconnect gives app no hook (source\internal\fwmaria.prg):
    When the connection dropped, mysql_ping auto-reconnect retried the next
    statement in C with no callback and no re-apply of SET SESSION state
    (time_zone, lc_time_names, etc.). Fixed: C marks reconnect but does not
    retry the failing query; Check()/ReConnect() fire bOnLostServer and
    RestoreSessionState() re-applies tracked session vars before PRG retries.
    Sample: samples\fwmatz.prg.

  • Fix: FWMariaConnection transaction silently split on auto-reconnect
    (source\internal\fwmaria.prg):
    If the socket died with START TRANSACTION open, mysql_ping auto-reconnect
    retried the next statement on a fresh autocommit session with no error.
    Fixed: client-side lInTransaction tracking, HandleLostTxn() blocks ping-retry
    in C and PRG while a transaction is open, fires bOnLostServer, and surfaces
    error 2013 with a localised message. Sample: samples\fwmatx.prg.

  • New: FWMariaConnection schema metadata cache (source\internal\fwmaria.prg):
    Restored hMetaCache for DbExists, TableExists, FKeyColumns and ListViews (public
    methods delegate to *_org implementations). Positive DbExists/TableExists results
    are cached; FKeyColumns and ListViews cache all results. DDL (CREATE/DROP/ALTER/
    RENAME) invalidates the cache; ClearMetaCache() clears it explicitly. CurrentDB()
    short-circuits when ::cDB is already set; SelectDB() forces a re-read. Unit tests:
    samples\fwmaria_ut.prg.

  • Fix: FWMariaConnection xHarbour BASE/1066 on Execute_Sql (source\internal\fwmaria.prg):
    FWMARIA_WAS_RECONNECTED() could return NIL under xHarbour, crashing Execute_Sql at the
    reconnect conditional. Fixed: C returns only hb_retl(); PRG wrapper MariaWasReconnected()
    always yields .T./.F. Multi-result sets from MYSQL_INIT_COMMAND are drained after
    mysql_real_connect and at the end of Execute_Sql (mysql_clear_next_results).

  • Fix: FWMariaConnection Connect hang on SHOW variables (source\internal\fwmaria.prg):
    The bootstrap query SHOW variables like 'version_compile_os' ran reconnect/clear logic
    in Execute_Sql and could hang or crash on the first statement after connect. Fixed:
    lInConnect skips reconnect retry and result draining during Connect bootstrap; Check()
    restores session state after a successful ping when the connection was lost.

  • Fix: fwmaria_ut console harness exit hang (samples\fwmaria_ut.prg):
    QUIT after the test summary left fwmaria_ut.exe running and blocked run_fwmaria_ut.bat.
    Fixed: RETURN nExit from Main(); batch reads fwmaria_ut.log and fwmaria_ut.rc.

  • New: TRibbonBar standard Windows-style accelerators (source\classes\tribbon.prg,
    source\classes\window.prg):
    Ribbon tabs now support standard Alt+letter accelerators using '&' prefixes in
    prompts (e.g. "&Configuraci├│n", "&Ficheros"). When lUseAcc is .F. (the default),
    pressing Alt+key switches to the matching tab ÔÇö no keytip boxes shown.
    Underlined accelerator letters are rendered in tab prompts via DrawTextEx without
    DT_NOPREFIX. Three message paths are handled:

    • SC_KEYMENU in TRibbonBar:SysCommand (ribbon has focus)
    • SC_KEYMENU in TWindow:SysCommand (main window dispatches)
    • WM_MENUCHAR in TWindow:MenuChar (menu already active, subsequent keystrokes)
      SetOption now sets focus back to the main window so the menu bar stays accessible.
  • New: certify tool for signing FWH executables (certify\):
    Generic batch script (certify.bat) to create self-signed certificates and
    sign EXEs built with FiveWin. Uses OpenSSL (C:\OpenSSL-Win32) for certificate
    generation and Windows SDK signtool.exe for code signing. Features:

    • Auto-detects OpenSSL and signtool paths
    • Creates Root CA + server certificate with Code Signing EKU
    • Generates PFX and signs the executable in one step
    • Usage: certify.bat [path\to\executable.exe]
    • Requires: OpenSSL, Windows SDK, run CMD as Administrator
  • Fix: TRibbonBar tab keyboard accelerators with 10+ tabs (source\classes\tribbon.prg):
    With more than 10 tabs, RunAction() only fired accelerators after two keystrokes
    (logic meant for ribbon controls like A0, B1). A single key such as 1 for Tab 1
    was treated as a prefix of 10/11/12 and never executed. Fixed: unified prefix/exact
    matching in RunAction() and zero-padded tab hints (01-09) in PaintAccTabs() when
    there are 10 or more tabs.

  • Fix: PIM sample resources and OpenJSON (samples\misc\pim.prg, pim.rc):
    The PIM sample had no .rc file, so all RESOURCE bitmap references (toolbar
    buttons, menu icons, MDI background) failed with "invalid resource" at
    runtime. Created pim.rc with bitmaps (New, Open, Save, Exit and variants),
    tiled marble background, and app icon. Also completed the OpenJSON() stub
    ÔÇö was empty (return nil), now parses simple JSON files into the TreeView
    using key-value tokenization with brace-depth tracking. Removed dead
    GenDblClickBlock() static function that was never called.

  • Fix: FiveDBU cRDD nil on startup (samples\database\fivedbu.prg):
    Static variable cRDD was declared without initialization (nil). When the
    MRU menu triggered Open() before any file-extension detection, the USE
    command passed nil as the RDD argument, causing DBCMD/1015 "Argument error:
    DBUSEAREA". Fixed: initialize cRDD := "DBFCDX" at declaration.

  • Fix: FiveDBU Preferences RDD not saved (samples\database\fivedbu.prg):
    The OK button in the Preferences dialog called ApplyDarkMode() before
    SavePreferences(). ApplyDarkMode() internally calls SyncToGlobals() which
    overwrites all static globals (including cDefRdd) with the OLD class values,
    so the user's RDD selection was silently reverted before being saved to the
    INI file. Fixed: swap order ÔÇö SavePreferences() first, then ApplyDarkMode().

  • Fix: TreeView SelChanged not firing in Unicode mode (source\classes\window.prg,
    source\ceclasses\window.prg):
    When FW_SetUnicode(.T.) is active, the TreeView control sends TVN_SELCHANGEDW
    (-456) instead of TVN_SELCHANGEDA (-402). The Notify() handler only matched
    the ANSI code, so bChanged callbacks never fired in Unicode mode. Fixed: add
    TVN_SELCHANGEDW to the case condition alongside TVN_SELCHANGEDA.

  • June 2026

    • FWUnit ÔÇö automated regression test suite (samples\test\fwunit\) ÔÇö NEW:
      Mini unit-test framework for FiveWin/Harbour (FwuAssert*, FwuSuite, FwuSummary).
      Output goes to fwunit_results.log via LogFile() only (no console ?).
      FwuAssertEq/FwuAssertNE compare ValType() before == to avoid BASE/1070 errors.

      Test modules (158 assertions, all passing on hm32):
      fwunit.prg ÔÇö framework
      tst_unicode.prg ÔÇö FW_ISUTF8, ANSI vs Unicode mode
      tst_strings.prg ÔÇö fwstring CP1252 (ES/PT/FR/DE/EN)
      tst_utils.prg ÔÇö uValBlank, IfNil, fw_Default
      tst_format.prg ÔÇö FW_TRANSFORM, NumPict, nRGB, FWNumFormat
      tst_cdptran.prg ÔÇö FW_CdpTranslate, FW_StrToUtf8, HBCDP, FW_SetCdp
      tst_sys.prg ÔÇö getsysin, screen metrics, cWinVersion, FW_SetDarkMode
      tst_resources.prg ÔÇö PalBmp register/unregister, CheckRes, FWAddResource
      tst_winapi.prg ÔÇö PostMessageW ring buffer (40├ù UTF-8)
      tst_ui.prg ÔÇö dialog dark CtlColor, ComboBox, bitmap nil guards
      tst_fivedbu.prg ÔÇö FiveDBU_ChrKeep, Soundex, ParseLine, FieldList, IsSelectSql
      run_fwunit.prg ÔÇö runner (#includes all suites, FW_ExitProcess pragma)
      run_all.bat ÔÇö builds fwunit + test_mcp, verifies ALL TESTS PASSED

      Build and run:
      cd samples\test\fwunit
      run_all.bat
      ÔÇö or ÔÇö
      C:\fwteam\samples\build_new.bat run_fwunit hm32
      run_fwunit.exe

      Note: run only one fwunit instance at a time; parallel runs corrupt
      fwunit_results.log and checkres.txt.

    • FiveDBU ÔÇö major upgrade (samples\database\fivedbu.prg) ÔÇö NEW:
      Flagship DBU sample (DBF, ADO, ODBC, MariaDB). Modular layout:

      samples\database\fivedbu\
      fivedbu.ch ÔÇö color constants and macros
      fivedbu_lib.prg ÔÇö pure helpers (unit-testable, no UI)
      tfivedbu.prg ÔÇö TFiveDBU class (preferences in %APPDATA%\fivedbu.ini)
      fivedbu_test.prg ÔÇö automated integration test mode

      Sprint 1 ÔÇö UI and regression tests:

    • fivedbu.exe --test  32 integration tests, log: tests\fivedbu_test.log

    • Dark mode (Preferences + BrwApplyColors on DBF browse)

    • Preferences persist: RDD, shared, language, pijama, DarkMode

      Sprint 2 ÔÇö ADO/MariaDB and DBF relations:

    • RSFreeSql() ÔÇö free-form SQL on ADO/ODBC browses (SELECT opens browse;
      DML shows rows affected)

    • ImpExpImportAdo() ÔÇö CSV/TXT import into ADO/Maria rowsets

    • ImpExpExport() ÔÇö export ADO rowsets to CSV/TXT with header

    • RelEdit() ÔÇö scoped relations (DbInfo DBI_SCOPEDRELATION checkbox)

    • MariaDB MRU (oMruMariaConnections) in Database menu

      Sprint 3 ÔÇö helpers and fwunit:

    • FiveDBU_ChrKeep(), FiveDBU_Soundex(), FiveDBU_ParseLine(),
      FiveDBU_FieldList(), FiveDBU_IsSelectSql()

    • FiveDBU_Soundex() fix for Harbour empty-string comparison

    • Search dialog: optional Soundex lookup via FiveDBU_Soundex()

    • tst_fivedbu.prg in fwunit (15 asserts)

      Build:
      cd samples\database
      C:\fwteam\samples\build_new.bat fivedbu hm32

      Related: fivedburv.prg adds Remote View (browser live control).

  • Fix: FWString() crash on startup (source\function\strings.prg):
    Trailing comma in aStrings table created a NIL row (516th element). FWString
    ("&Window") in TMENU:AddMdi scanned the full array and crashed with BASE/1068.
    Fixed: remove NIL row, CheckArray() on first FWString call, FWStrMatchRow()
    helper with ValType guard. Restored CP1252 encoding (accents in Spanish, etc.).

  • Fix: fwArray pList pointer (source\internal\fwarray.c) ÔÇö critical:
    fwArrayNew() and Size() after GlobalReAlloc now set
    pArray->pList = (BYTE *)pArray + sizeof(FWARRAY).
    Previously pList was left NULL/uninitialized, causing ACCESS_VIOLATION in
    FW_PalBmpRegister and any code using fwArray (PalBmp list, hand lists, etc.).

  • Fix: PalBmp register/unregister restored (source\internal\fwpalctl.c):
    FW_PalBmpRegister / FW_PalBmpUnregister exported again; pBmpScan null guard.
    bitmap.prg PalBmpNew/PalBmpFree now call register/unregister on load/free.

  • Stability and review fixes (sprints 1ÔÇô3):

    • agent.prg: security and agent pipeline hardening
    • combobox.prg, btnbmp.prg, bitmap.prg, control.prg, dialog.prg: nil guards,
      dark-mode CtlColor, ComboBox and bitmap edge cases
    • xbrowse.prg: bar GET button placement, dark mode (see entries below)
    • fwunicode.c: hbcdp_to_wincdp skips OEM codepages when bAnsiOnly (CP_ACP)
    • dlg2chr.c / ctrl2chr.c: CP_ACP for dialog/control template text
    • msgsapi.c, toolbarsw.c, winsock.c, wndproc.c: Unicode and Win32 fixes
    • getsysin.prg: screen/version helpers used by fwunit
  • MCP Server improvements (mcp\mcp_server.prg, mcp\test_mcp.prg):

    • JsonEscape() for safe JSON text fields
    • HWND as decimal string in JSON (64-bit safe); FW_HWNDFROMSTR C helper
    • FWH-only window enumeration (fwEnumProc filters non-FiveWin windows)
    • FW_TypeTextUtf8() types UTF-8 via SendInput instead of keybd_event
    • test_mcp.prg: 55/55 standalone assertions
  • Build: mfwh_new.bat and makes\build_fivehcm.ps1 updated; .gitignore excludes
    mcp/*.exe, comp logs, and local debug scratch files.

  • MCP Server for Computer Use (mcp\mcp_server.prg) ÔÇö NEW:
    Model Context Protocol (MCP) server for desktop automation via stdio.
    Enables AI clients (Claude Code, OpenCode, Cursor) to control the
    Windows desktop through screenshots and UI actions.

    Architecture:
    Client MCP (brain) ? mcp_server.exe (muscles) ? Windows Desktop
    The client analyzes screenshots and decides what actions to execute.
    The server captures screens and executes UI actions via Win32 API.

    MCP Protocol:

    • JSON-RPC 2.0 over stdio (newline-delimited)

    • Protocol version: 2024-11-05

    • Handshake: initialize  notifications/initialized  tools/list

    • Tool execution: tools/call with tool name and arguments

      Tools exposed (6):

    • capture_screen ÔÇö Captures full screen screenshot
      Arguments: format ("base64"|"file"), path (optional)
      Returns: base64 image data or file path

    • execute_action ÔÇö Executes UI action on desktop
      Arguments: action, x, y, text, key, direction, durationMs
      Actions: click, right_click, double_click, type, scroll,
      key, hover, navigate, wait
      Coordinates: normalized 0-1000 relative to screen size

    • get_screen_size ÔÇö Returns screen dimensions in pixels
      Arguments: none
      Returns: {width, height}

    • get_action_history ÔÇö Returns history of executed actions
      Arguments: last_n (optional, default 10)
      Returns: {history: [...], total: N}

    • reset_agent ÔÇö Resets agent state and clears history
      Arguments: none
      Returns: {success, message}

    • save_screenshot ÔÇö Captures and saves screenshot to file
      Arguments: path (file path)
      Returns: {success, path}

      Key combinations supported:
      Modifiers: ctrl, alt, shift
      Navigation: home, end, pageup, pagedown, left, right, up, down
      Function: f1-f12
      Edit: enter, tab, escape, backspace, delete
      Letters: a-z, Numbers: 0-9, Other: space
      Combine with +: ctrl+c, alt+tab, ctrl+shift+s

      Coordinate system:
      All coordinates normalized to 0-1000 (Gemini-compatible).
      Conversion: pixel = normalized * screenSize / 1000

      Files:
      mcp\mcp_server.prg ÔÇö Source code (single file, 1000 lines)
      mcp\mcp_server.exe ÔÇö Compiled executable (5.6 MB)
      mcp\build.bat ÔÇö Build script (Harbour + MSVC 64)
      mcp\demo\demo_mcp.prg ÔÇö Automated demo
      mcp\demo\demo_mcp.exe ÔÇö Demo executable
      mcp\demo\README.md ÔÇö Demo instructions

      Build:
      cd mcp
      build.bat

      Configuration for Claude Code:
      Create .mcp.json in project root:
      {
      "mcpServers": {
      "computer-use": {
      "command": "C:\\FWH\\mcp\\mcp_server.exe"
      }
      }
      }

      Demo (mcp\demo):
      Automated demo that showcases all MCP tools:

    • MCP handshake (initialize)

    • Tool discovery (tools/list)

    • Screen capture (capture_screen)

    • UI actions (hover, click, type, key)

    • Action history (get_action_history)

    • Agent reset (reset_agent)

      Technical details:

    • Pure Harbour/FWH + Win32 API (no external dependencies)

    • Win32 APIs: GetDC, BitBlt, CreateCompatibleBitmap,
      mouse_event, keybd_event, SetCursorPos

    • Console subsystem application (/subsystem:console)

    • Custom DLL functions with FW_ prefix (no FWH conflicts)

    • Screenshots saved as 24-bit BMP files

      Example usage with Claude Code:

    • Configure .mcp.json (see above)

    • Ask Claude: "Open Notepad and type Hello World"

    • Claude will:

    • Call capture_screen to see the desktop
    • Call execute_action to open Notepad
    • Call execute_action to type text
    • Call capture_screen to verify result
  • XBrowse bar GET action buttons (source\classes\xbrowse.prg) ÔÇö fixed:

    • The action button shown on header-bar GETs (oBrw:lGetBar with :cBarGetBmp +
      :bBarGetAction) appeared tiny at the GET's top-left instead of square, full
      GET height and flush on the right side.
    • Cause: TBtnBmp:Display() calls CalcSize() on every paint, which restored the
      button to its bitmap-derived design size (10x10, top-left), silently
      undoing any prior placement. Only a stray late repaint occasionally won.
    • Fix: TXBrwColumn:CreateBarGet() now builds the GET without a button and
      creates the button once afterwards, then clears oBtn:aSizeRect to disable
      the paint-time auto-resize so the assigned geometry sticks. New method
      TXBrwColumn:PlaceBarGetBtn() sizes the button square (nGetBarHeight-4),
      flush right; it is called from CheckBarGet() on every check so it also
      survives scrolling and column-width changes.
    • Note: :cBarGetBmp must reference a bitmap that actually loads (a real linked
      resource name or a .bmp file path). If it fails to load FiveWin falls back
      to the native TButtonBmp, which does not render reliably. The xbgetbtn
      sample now points at ..\..\..\bitmaps\16back.bmp.
  • TXBrowse dark mode (source\classes\xbrowse.prg) ÔÇö new feature:

    • WS_BORDER removed when FW_SetDarkMode() is true (cleaner look).
    • Gradient header/footer: dark brown {58,54,53}{48,46,46} replaces
      classic blue/yellow gradients in dark mode.
    • Header separator pens: hWhitePen and hBtnShadowPen use dark colors
      (64,64,68) and (45,45,48) in dark mode.
    • nRecSelColor conditioned on !FW_SetDarkMode() ÔÇö dark bg in dark mode.
    • SetDarkMode() rewritten: nClrText defaults to CLR_WHITE; hBrushRecSel
      recreated with dark bg; nRecSelColor set to dark bg (not white); each
      column's bClrStd, bClrHeader, bClrFooter updated individually.
    • New method DrawRecSelArrow(): draws white right-pointing triangle via
      GDI PolyPolygon for record selector in dark mode.
    • Paint code conditionally calls DrawRecSelArrow() or PalBmpDraw().
    • Sample xbrkdmod (samples\xbrowses\xbrkdmod.prg): demonstrates dark mode
      TXBrowse with toggle button, per-column color restore in DarkOff().
  • TSmartButton (source\classes\smartbtn.prg) by Silvio Falconi ÔÇö fixes:

    • Fixed: enabled buttons did not fire their ACTION. LButtonDown/LButtonUp/
      KeyChar had an inverted disabled guard (IF ! ::lDisabled RETURN 0), so the
      click/capture path was skipped on active buttons. Corrected to IF ::lDisabled.
    • Fixed: disabled buttons still executed their ACTION. New() defaulted
      bWhen := {||.t.}; with a non-nil bWhen the owner's AEvalWhen() re-enabled the
      control on every event (calling ::Enable(), which clears ::lDisabled). Removed
      the bWhen default so disabled state set via :lDisabled / :Disable() persists.
    • Removed a leftover debug MsgInfo() popup from METHOD SetImage().
    • Sample samples\ui\testsmart.prg demonstrates the 4 shapes (rect, round, pill,
      circle) across normal/hover/pressed/disabled states.
  • vitem.prg ÔÇö fixed build break: added missing #define BDR_RAISEDOUTER (0x0001)
    and BDR_SUNKENOUTER (0x0002). The EDGE_BUMP/EDGE_ETCHED/EDGE_RAISED macros
    referenced these undefined symbols, producing W0001 ambiguous-reference warnings
    that, under -es1, aborted the FiveH.lib PRG build.

  • Sample resdlg (samples\dialog\resdlg.prg) ÔÇö proportional zoom dialog:

    • New sample demonstrating resource-based dialogs with proportional zoom.
    • All controls (labels, edits, buttons) resize proportionally when the
      dialog is resized, including positions, widths, heights and font sizes.
    • Uses DPI-aware initial scaling and uniform scale factors (nSX, nSY)
      for zoom behavior. Font is recreated at scaled size via SetFont().
    • Fixed: added missing LOGPIXELSX constant (value 88) for GetDeviceCaps.
    • Fixed: declared cName and cCity as LOCAL variables (were undeclared).
    • RC file (resdlg.rc) includes #define directives for control IDs.
  • VMenu/VItem Integration (source\classes\VMenu.prg, source\classes\vitem.prg):

    • Integrated TVMenu (ExplorerBar panel) and TVItem classes into FWH library.
    • TVMenu: ExplorerBar-style panel control with title, open/close, items, themes.
    • TVItem: Individual menu items with text, images, popups, separators, groups.
    • New include files: vmenudef.ch (selection/fill mode constants), vmenu.ch.
    • New class TC5ImgList (source\classes\tc5imglst.prg): lightweight image list
      for TVMenu bitmap storage (Add, Draw, nWidth, nHeight, GetCount).
    • TVItem:SetImage() now accepts numeric bitmap handles (not just strings/objects).
    • Fixed vitem.prg lVersion70() paint path: replaced DrawMasked with BitBlt for
      color bitmap rendering, uses parent font instead of hardcoded 12px Tahoma.
    • Added #define local constants (SRCCOPY, DEFAULT_GUI_FONT, BDR_RAISEDINNER,
      BF_BOTTOM, BF_RECT, EDGE_BUMP, EDGE_ETCHED, EDGE_RAISED) to suppress W0001
      ambiguous reference warnings.
    • Added TC5ImgList, VMenu.prg, vitem.prg to fwh.hbp build list.
    • Thanks to Carlos Sincuir for the original TVMenu/TVItem ExplorerBar classes.
  • Sample vmenu_test (samples\test\vmenu_test.prg):

    • Test program demonstrating TVMenu + TVItem with programmatic 32x32 icons.
    • Creates 5 icons: Home, Document, Config (gear), Chart (bars), Help (?).
    • Uses Segoe UI 14pt font, 40px item height, centered window.
  • TransformerSubQ ÔÇö Sub-Quadratic Transformer (source\classes\transformer_subq.prg):

    • New class TransformerSubQ implementing sparse top-k attention.
    • Each query attends only to n_topk most relevant keys instead of all (dense).
    • Reduces attention complexity from O(N2) to O(N*k) where k = n_topk.
    • SubQMultiHeadAttention: sparse attention with manual top-k selection per head.
    • C-optimized variant uses hb_ScaledDotAttention with sparse mask (C kernel).
    • C-optimized stores attention probs from C to avoid recomputation in backward.
    • ForwardSeq/BackwardSeq for autoregressive generation with causal mask.
    • Generate() method for text generation with temperature and top-k sampling.
    • Save/Load serialization with n_topk in config.
    • Compatible with existing Optimizer_Adam and CrossEntropyLoss.
  • Sample transf_subq (samples\ai\transf_subq.prg):

    • Benchmark comparing Transformer (dense) vs TransformerSubQ (sparse).
    • Speed test: forward+backward time for seq_len 32/64/128/256.
    • Training convergence: 100 epochs loss comparison (Dense vs SubQ-8).
    • Memory analysis: theoretical N2 vs N*k attention matrix sizes.
    • Sequence generation test: both models generate text from same seed.
    • XBrowse output with Consolas 14pt font.
  • Sample codegen_subq (samples\ai\codegen_subq.prg):

    • FiveWin code generator trained on representative PRG patterns.
    • Character-level tokenizer with frequency-sorted vocabulary.
    • Training data: 12 FiveWin code patterns (dialogs, xbrowse, classes,
      menus, databases, reports, messages, file ops, timers, functions).
    • TransformerSubQ C-optimized model: 2 layers, d_model=32, 4 heads, topk=8.
    • Generates code from seed prompts: #include, FUNCTION Main,
      DEFINE DIALOG, CLASS, @ SAY, etc.
    • XBrowse output showing training progress and generated code.
    • Next-character prediction with temperature sampling (0.8).
  • Sample transf_subq_copt (samples\ai\transf_subq_copt.prg):

    • Benchmark: SubQ Pure PRG vs SubQ C-Optimized implementation.
    • Pure PRG: manual dot-product, softmax, top-k in Harbour loops.
    • C-Optimized: hb_ScaledDotAttention with sparse mask (C kernel).
    • C-Optimized stores attn probs from C, no recomputation in backward.
    • Measures forward and backward separately for detailed comparison.
    • XBrowse output showing speedup factors.
  • Sample xbrwtre (samples\xbrowses\xbrwtre.prg):

    • XBrowse with Tree mode and incremental search.
    • Switches between normal XBrowse and Tree view (grouped by a field).
    • Combo box to select the search/group field (First, Last, Street, City, State).
    • Search works in both normal and tree modes via XbrTreeSeek().
  • Class Agent (source\classes\agent.prg) ÔÇö major improvements:

    • Orchestration overhaul ÔÇö 8 new methods for multi-agent coordination:
    • cRole / cRolePrompt: each Agent now has a role property (planner,
      analyst, developer, tester) with its own system prompt injection.
    • DispatchAgentsPipeline(aTasks): sequential execution where output of
      each agent feeds into the next. For dependent task chains.
    • DispatchAgentsWithRoles(aAgentDefs): fan-out where each agent is
      pre-configured with role, model, steps via a hash definition.
    • AggregateResults(aResults, cMethod): combine results ÔÇö "join"
      (concatenate), "json" (array), "summary" (LLM-powered summary).
    • GetSharedContext(cKey) / SetSharedContext(cKey, xValue): blackboard
      pattern ÔÇö shared hash between agents for inter-agent communication.
    • RetrySubAgent(cTask, cContract, nMaxRetries): retry with configurable
      attempts (default 3).
    • SubAgentRunWithTimeout(cTask, cContract, nTimeout): time limit per
      sub-agent via interrupt mechanism (default 120s).
    • NotifyProgress(cAgentName, cStatus, cMsg): callback for real-time
      progress monitoring. Set via bOnAgentProgress codeblock.
    • Shared context: sub-agents inherit parent's aSharedContext and sync
      changes back. BuildSystemPrompt() injects shared context summary.
    • Hooks system: RegisterHook(), UnregisterHook(), ListHooks(), RunHooks().
      Four event types: pre_tool_use, post_tool_use, on_error, on_complete.
      Pre-hooks can cancel tool execution (return .F.) or modify arguments.
      Post-hooks can modify results. Hooks execute in priority order.
      LLMRegisterHook() provides preset actions for LLM-driven registration:
      log, audit, block_shell, block_delete, block_write.
      Built-in tools: register_hook, unregister_hook, list_hooks.
    • Streaming SSE: Step() now sends "stream": true with stream_options for
      real-time token usage. Response is parsed from SSE chunks via AG_SseParse().
    • Tool_Shell() fully implemented: executes via cmd.exe (Windows) or
      /bin/sh (Unix), captures stdout+stderr, truncates at 30KB, reports
      exit code. Previously was a stub returning "(ejecutado)".
    • Tool_Python() fully implemented: finds python3/python/py interpreter,
      writes temp .py file, executes, captures output. Accepts code + args.
      Previously delegated to the stub Tool_Shell().
    • Tool_WebSearch() implemented: curl to DuckDuckGo HTML, extracts
      result snippets via AG_ExtractDdgResults(). Previously a stub.
    • Tool_WebFetch() implemented: curl to URL, strips HTML tags via
      AG_StripHtml(), truncates at 40KB. Previously a stub.
    • ExecTool() error handling: BEGIN SEQUENCE / RECOVER wraps every
      tool call so a failing tool doesn't crash the agent loop.
    • Run() interrupt/inject: bInterrupt codeblock checked before each
      step and each tool call; bInject codeblock injects user messages
      mid-run. Enables external cancellation and user interjections.
    • BuildToolsArray() now includes description and parameters schema
      for every built-in tool (previously only had name).
    • Checkpoint system ÔÇö save/restore agent state for task resumption:
    • SaveCheckpoint(cLabel): save full agent state (messages, plan,
      shared context, goal, tool history) to .agents/cp_N.json.
    • LoadCheckpoint(nId): restore from checkpoint by ID, or latest if 0.
    • ListCheckpoints() / DeleteCheckpoint(nId): manage checkpoints.
    • AutoCheckpoint(): generated every N messages during Run() (default 3,
      configurable via nCheckpointInterval; 0 disables).
    • LoadCheckpoints(): loads all cp_*.json from .agents/ on startup.
    • LLM tools: save_checkpoint, list_checkpoints, load_checkpoint,
      delete_checkpoint ÔÇö agent can manage its own checkpoints.
    • Edit system ÔÇö granular file editing without full rewrites:
    • Tool_EditFile(cPath, cOldStr, cNewStr): replace exact text in file.
    • Detects multiple matches and asks for more context.
    • LLM tool: edit_file.
    • Search system ÔÇö glob patterns and content search:
    • Tool_Glob(cPattern, cDir): find files matching *.prg, *.c, etc.
    • Tool_Grep(cPattern, cDir): search contents across source files,
      returns file:line:content. Max 50 results.
    • LLM tools: glob, grep.
    • Git integration ÔÇö version control from agent:
    • Tool_GitStatus/Diff/Log/Commit/Push: full git workflow.
    • LLM tools: git_status, git_diff, git_log, git_commit, git_push.
    • Task tracking ÔÇö persistent task management:
    • TaskCreate/TaskList/TaskDone/TaskBlock/TaskStart: lifecycle mgmt.
    • Tasks persist across Run() calls via aTasks array.
    • LLM tools: task_create, task_list, task_done, task_block, task_start.
    • Persistent actors ÔÇö long-lived sub-agents:
    • ActorSpawn(cPrompt): launch background agent with its own Run() loop.
    • ActorWait(nId): block until actor finishes.
    • ActorSend(nId, cMsg): inject message into running actor.
    • ActorList/ActorCancel: manage actors.
    • Actors share aSharedContext with parent.
    • LLM tools: spawn_actor, wait_actor, send_actor, list_actors, cancel_actor.
    • ToggleSkill() bug fixed: ASort filter didn't remove items; now
      uses hb_ADel() with .T. for in-place deletion.
    • ExecUserTool() fixed: sys.argv construction now properly tokenizes
      space-separated args into a Python list instead of raw concatenation.
    • SendToLLM() synchronized with Step(): streaming + SSE parse.
    • New helper functions: AG_SseParse(), AG_UrlEncode(),
      AG_ExtractDdgResults(), AG_StripHtml(), AG_ToolDesc(),
      AG_ToolParams().
    • GeneratePlan() /plan streaming bug fixed: GeneratePlan() made a direct
      non-streaming API call instead of using Step() (which uses SSE streaming).
      AG_SseParse() only retains the last SSE chunk with "choices"; in streaming
      the final chunk has finish_reason:"stop" with empty delta, so Step()
      returned "" and GeneratePlan produced an empty plan.
    • agents.prg /plan card fixed: WCall("card", ...) changed to
      WCall("planCard", ...) so the interactive editable plan card renders.
  • New class: source\classes\agent.prg ÔÇö Agent IA aut├│nomo con herramientas,
    skills y multi-agente. Implementa el mismo motor agentic que Agents Web:

    • Bucle principal Run()/Step(): observar  decidir  actuar, 14 pasos máx.

    • 15 tools built-in: list_files, read_file, write_file, delete_file, shell,
      python, sql, web_search, web_fetch, register_tool, unregister_tool,
      user_tools, create_skill, toggle_skill, classify_disk.

    • Tools dinámicas: el agente puede crear sus propias herramientas con
      register_tool() y eliminarlas con unregister_tool(). Persisten en disco
      (agent_state/user_tools.json).

    • Skills: instrucciones reutilizables que modifican el system prompt.
      create_skill(), toggle_skill(), ActiveSkillsPrompt(). 5 skills built-in
      (reviewer, summarizer, refactor, documenter, tester) + skills de disco.

    • Multi-agente: DispatchAgents() lanza hasta 4 sub-agentes en paralelo
      usando hb_threadStart(). Cada sub-agente tiene su propia instancia,
      sin acceso a dispatch ni ask_user. Contrato t├®cnico compartido para
      consistencia entre agentes.

    • Planificaci├│n: GeneratePlan() + ExecutePlan() generan pasos JSON desde
      el LLM y los ejecutan secuencialmente.

    • DeepSeek V4: Step() envía POST a api.deepseek.com/chat/completions con
      el array de tools completo (built-in + user tools). M├®tricas de tokens.
      Soporte para thinking mode y streaming (pr├│ximamente).

    • Distill: descubre workflows repetidos en el historial de tool calls
      y los empaqueta como skills (.md) o commands (.bat registrados).
      Analiza n-grams (2-5 pasos), punt├║a por frecuencia, longitud y recencia.
      Tool "distill" invocable por el LLM.

    • Dream: consolida memoria del proyecto leyendo archivos .json/.md del
      directorio de memoria, comprime la trayectoria (max 100 entradas),
      extrae rules/decisions/patterns, y guarda digest.json persistente.
      El digest se inyecta automáticamente en el system prompt.
      Tool "dream" invocable por el LLM.

    • Persistencia: SaveState()/LoadState() guardan tools y skills en disco.
      Compatible con el mismo contrato de Agents Web (mismo formato de tools).
      Fuertemente inspirado en la versi├│n web (fivetechsoft.github.io/Agents).

    • GeneratePlan() corregido: ahora usa API directa sin streaming.
      Step() usaba SSE streaming y AG_SseParse() solo retorna el ultimo chunk
      con "choices", que en streaming es el de finish_reason con delta vacio,
      provocando que GeneratePlan devolviera un plan vacio.

    • agents.prg /plan corregido: WCall("card", ...) cambiado a
      WCall("planCard", ...) para renderizar la card interactiva del plan.

  • New sample: samples\githubdb\githubdb.prg ÔÇö githubDB + XBrowse. Browse
    a githubDB fork (SQL+vector database on GitHub Actions) from FiveWin
    using two HTTP paths:

    • Fast read (CDN): fetches data/<db>.json from raw.githubusercontent.com,
      sub-second, no token needed.
    • Action query: sends SQL via repository_dispatch, polls for result,
      10-30 s, needs a GitHub token with Contents R/W.
      HTTP transport via WinHttp COM object (no curl/DLL dependency).
      Built with build_new.bat (all compiler variants). Docs at
      https://fivetechsoft.github.io/githubdb/
  • New sample: samples\ai\transxbrowse.prg ÔÇö Transformer text classifier
    displayed in XBrowse. Trains a Transformer neural network to classify
    Spanish phrases into 6 categories (Saludo, Despedida, Agradecimiento,
    Pregunta, Comando, Respuesta) using a 25-token vocabulary. Shows
    accuracy % in the window title and displays all predictions in a grid
    with confidence and OK/FAIL status.

  • Class Transformer (source\classes\transformer.prg) ÔÇö multi-head attention,
    GELU activation, LR scheduler, and padding support:

    • LRScheduler: new class implementing Transformer paper warmup + inverse
      sqrt decay: lr = d_model-0.5 * min(step-0.5, step*warmup-1.5).
      Methods: New(d_model, warmup_steps, base_lr), GetLR(step), Update(optimizer, step).
    • MultiHeadAttention: validates d_model % n_heads == 0 at construction,
      shows ALERT if not divisible. Uses integer division instead of Int()
      to avoid truncation.
    • FeedForward: GELU activation replaces ReLU (tanh approximation:
      0.5x(1+tanh(ÔêÜ(2/¤Ç)(x+0.044715x┬│)))). GELU derivative uses
      CDF+PDF formula for correct gradient flow. ff_dim now configurable
      (default 4*d_model). Validates d_model > 0 and ff_dim > 0.
    • EmbeddingLookup: index 0 (PAD token) now returns a zero vector instead
      of crashing with "Bound error: array access" on aVocab[0].
    • Backward: skips gradient accumulation for PAD tokens (index 0 in both
      src_indices and pos_indices). Fixes training with variable-length
      sequences padded to max_seq_len.
    • transxbrowse.prg sample now uses nHeads=2 to demonstrate multi-head.
  • New sample: samples\ai\transsave.prg ÔÇö Transformer Save/Load demo.
    Trains a classifier, saves model to disk (hb_Serialize), loads it back,
    and verifies predictions match. Shows full model roundtrip in XBrowse.

  • New sample: samples\ai\transgen.prg ÔÇö Transformer autoregressive text
    generation. Trains on character sequences, generates new text from seeds,
    displays results in XBrowse with confidence scores.

  • Build: cleared every compiler warning emitted by the GCC32, GCC64,
    MSVC32 and MSVC64 library builds (170 sites) while preserving behavior
    on all supported toolchains (BCC32/BCC64/MSVC32/64, GCC32/64, Harbour
    and xHarbour). Covers -Wcast-function-type (GetProcAddress/FARPROC casts
    now use the portable ( void (*)( void ) ) intermediate), -Wdangling-else,
    -Wimplicit-fallthrough, -Wsign-compare, -Wunused-function (32-bit-only
    COM IDataObject vtable callbacks guarded with #ifndef _WIN64),
    -Wold-style-declaration, -Wmisleading-indentation, redefined macros and
    MSVC C4996. Two real bugs fixed along the way: a buffer overflow in
    BlankQuotes() (vstrfun1.prg) when its 2nd argument exceeds 3 chars, and
    a 3-byte over-read of the GIF graphic-control block in fwgif.c. All nine
    library variants now build warning-free.

  • Fix: TFolder crash "No exported method: MOVE" in AdjustRect(). The method
    called oDlg:Move() on elements of ::aDialogs without checking for NIL.
    Added nil guard for ::aDialogs[1] and each oDlg in the AEval callback,
    consistent with the pattern used elsewhere in the same class.

  • Fix: TGet keyboard input of ANSI characters with Unicode codepoint above
    255 (Turkish s-cedilla, g-breve, dotted I; Polish, Czech, Baltic, Cyrillic
    and Greek letters) showed "?" in non-Unicode applications (FW_SetUnicode(.F.))
    using single-byte codepages CP1250-CP1258. Regression introduced when
    is2byteansi() started treating all 2-byte sequences as ANSI pairs on those
    codepages: WideKey2Asc() in tget.prg built genuine UTF-8 from the WM_CHAR
    wide code but fw_Utf8ToStr()'s isutf8() heuristic refused to convert it,
    so the keystroke was rejected. WideKey2Asc() now converts with explicit
    codepages via FW_CdpTranslate( cUtf8, 65001, -1 ), bypassing the heuristic.
    is2byteansi() display behavior is unchanged.
    New samples: samples\test\trwincdp.prg (conversion-chain check) and
    samples\test\trwinget.prg (sends ş ğ İ WM_CHAR codes to a GET and checks
    the buffer receives CP1254 bytes FE F0 DD).

  • TRichEdit5:SetTextColor( nColor ) applies text color to the current
    selection (SCF_WORD | SCF_SELECTION) using only the CFM_COLOR mask,
    preserving all other character formatting (bold, italic, underline,
    font face, size, etc.). If no text is selected, the color is applied
    to the word under the caret.
    New sample: samples\test\testchclr.prg demonstrates selection coloring
    (Blue/Red/Black buttons) plus Bold/Italic toggle with ON RESIZE child
    control layout.

  • TRichEdit (RichEdit 2.0): same SetTextColor() behavior as TRichEdit5 ÔÇö
    selection-only color change via CFM_COLOR mask, preserves all formatting.
    Requires LoadLibrary("riched20.dll") before instantiation.
    New sample: samples\test\testreclr.prg (mirrors testchclr.prg).

  • AgenticAI sample (samples/AgenticAI): ported the features of the web
    version (github.com/FiveTechSoft/Agents) to the desktop FiveWin app:

    • Live reasoning ("thinking mode"): reasoning_delta events stream into a
      purple glass box while the model thinks (e.g. /model deepseek-reasoner).

    • Status chip in the header while the agent works: elapsed time, session
      token flow (up/down) and tok/s, updated 5 times per second.

    • Live markdown: assistant bubbles render markdown WHILE streaming
      (throttled re-parse), not only at turn end.

    • /goal /plan /run: the web version's action-plan system. /plan asks the
      model for 3-6 JSON steps and shows them as an editable "Plan de Accion"
      card (cycle each step's state, edit titles in place, delete/add steps);
      /run executes the plan one step per agent turn, with the goal + full
      plan as context, pausing when a step ends asking the user something.

    • /btw: interject "what are you doing?" while the agent works; delivered
      between agent actions without interrupting the run. Uses the new
      ccharbour CC_AgentRun hOpts["inject"] hook (polled every iteration).

    • /cost: session metrics card with cache-aware DeepSeek pricing
      (prompt_cache_hit_tokens billed at 98% off, like the web version).

    • /compact + context-window monitor: past 85% of the 128k window a
      "Ventana de Contexto Critica" card offers Compress / Clear; /compact
      folds the middle of the history into one summary message (keeping the
      system prompt and the last plain exchange, skipping tool messages so
      the OpenAI protocol stays valid).

    • /init + AGENTS.md: the agent writes the project rules file; AGENTS.md
      (fallback CLAUDE.md) is injected into the system prompt on every turn.

    • New cards: aborted-execution (Stop), step-limit reached with a
      "Continuar" button, /help as a grid of clickable command buttons.

    • UX: Up/Down prompt history, Esc stops, Ctrl+K clears, prompt stays
      enabled while running so /btw can be typed.

  • ccharbour engine: CC_AgentRun accepts an optional hOpts["inject"]
    codeblock, polled at the start of every iteration; when it returns a
    non-empty string it is appended as a user message before the next model
    request (mid-run interjection that does not interrupt the loop).

  • ccharbour console (cc.exe): responses now render as GUI-style "cards" -
    background-tinted rows like the AgenticAI bubbles: replies on slate,
    live reasoning on a purple glass box, errors on dark red, /cost on an
    emerald metrics card with cache-aware DeepSeek pricing (cached input at
    98% off). Plain output is unchanged when color is off.

  • New sample: testrsz.prg - how to resize an XBrowse at runtime without
    flickering. A plain oBrw:nHeight := nNew assignment repaints twice
    (MoveWindow() immediate repaint plus the later Refresh()) and the dialog
    background erase paints over the browse area before the rows are redrawn,
    both visible as flicker. The correct method: add WS_CLIPCHILDREN to the
    dialog style (FiveWin dialogs do not set it by default), freeze the dialog
    with WM_SETREDRAW around the resize, then repaint dialog + browse once
    (TWindow:Refresh() is a plain InvalidateRect() and does not cascade to
    children, so both Refresh() calls are needed). The sample includes "old
    method" buttons side by side for comparison. Also documented in the
    TXBrowse HTML docs (Example 5: Flicker-Free Runtime Resize).

  • New sample: AgenticAI (samples/AgenticAI) - a GUI front-end for the ccharbour
    agentic engine rendered as a modern web chat panel inside an embedded Edge
    WebView2 (TWebView2), instead of a RichEdit dialog.

    The same streaming chat + tool-calling loop that powers the console cc.exe
    (CC_Client / CC_AgentRun) drives an HTML chat UI (Tailwind dark theme):

    • Live streaming of the assistant answer into chat bubbles; on turn end the
      raw markdown is re-rendered (tables, code blocks, lists) via marked.js.

    • A collapsible "N actions" panel with per-tool icons (file / terminal /
      search / globe / memory), a pending spinner that turns into a green check
      (or red X on error).

    • Per-action permit/reject card for mutating tools (shell / write / edit)
      when "Auto-approve" is off; the agent turn blocks until you decide.

    • ask_user multiple-choice card wired to the webview (replaces ccharbour's
      console selector, unusable without a console).

    • "Code generated" bar with a "View Changes (Diff)" toggle that shows the
      ccharbour diff with red/green lines.

    • In-app /key <api-key> command to set the LLM key at runtime; /tools, /clear,
      /help.

      Transport is in-process libcurl (hbcurl), the same path as TOpenAI:SendStream,
      plugged into ccharbour via hOpts["transport"]. The agent runs on the GUI thread;
      a TTimer launches each turn OUTSIDE the SendToFWH (bOnBind) callback, because
      WebView2 does not deliver a second bound-function call while the first is still
      on the stack - otherwise the permit/ask/stop clicks would deadlock mid-turn.

      Two gotchas captured in the sample: (1) WebView2_Eval converts its argument from
      the ANSI codepage, so non-ASCII is passed as a pure-ASCII \uXXXX-escaped JS string
      literal to avoid mojibake; (2) never put a backslash escape (\n, \t) inside a
      Harbour TEXT INTO block - it is C-escape-processed, so JS strings use
      String.fromCharCode(10) and backslash-free regexes.

  • Remote View: browser page title changed from "C3 Remote View" to "FWH Remote View"
    and made parameterisable via the new optional cTitle parameter:

    RemoteViewStart( [hWnd], [nPort], [cTitle] ) -- default "FWH Remote View"

    ServerStart() in server.c now accepts a const char * title argument; the HTML
    client page is built dynamically inserting the title between HTTP headers + body.
    source/internal/remoteview/server.c, server.h, remoteviewfw.c, RemoteView.cpp.

  • Fix: TGraph commands ADD SERIE TO and SET Y LABELS OF now honour the actual
    object variable (include/tgraph.ch).

    Both #xcommand rules expanded to a hard-coded "oGraph:" instead of the
    <oGraph> matchmarker, so "ADD SERIE TO oMyGraph" / "SET Y LABELS OF oMyGraph"
    called a non-existent oGraph variable and failed unless the variable happened
    to be named oGraph. They now expand to <oGraph>:AddSerie() / <oGraph>:SetYVals(),
    matching DEFINE GRAPH.

  • New: Remote View "login before launch" sample (samples/RemoteView/testrvauth.prg).

    Shows how to make a remote user identify before the application is shown. The
    login is a normal FiveWin dialog owned by the served window, so RemoteView
    composites it on top and the remote user fills it in; on valid credentials the
    app UI opens (also owned, so it appears at once), on failure the session closes.

    Includes the key gotcha: do NOT launch modal UI inside ON INIT. The host window
    has not presented its first frame yet, so PrintWindow (the capture path) blits it
    black before and during login. The sample defers the login with a one-shot
    TTimer, so the window paints first and nothing shows black. Documented in the
    Remote View page (EN/ES/PT). For real use, authenticate over the TLS multi-client
    path (RemoteViewServe + -mt) and store credentials hashed.

  • regards, saludos

    Antonio Linares
    www.fivetechsoft.com

    Continue the discussion