Win 32 API and Clarion versions 10 11 12 and Above

We are starting to replace good old clarion standard procedures with our linux ported binding emulation machine to windows 32.. with the goal of adding the binding machine to clarion template ABC apps with AI generated features…

Heres the call to file dialog as a UBS (universal Binding Machine) macro. Objects can also be bound to call win32 api and CPP bound code. we will demo these as we go and if UBS can live in windows land put it up later next year on GITHUB separate from our linux runtimes… Since this is only old window 32 it will be free.

CPP code updated for Threading.

void scriptFileDialog(ScriptInterface *ifc)
{

 // AI Generated Anthropic add in to UBS win32 version.
// This does not run on the Linux cloud Azure version and is win32 windows only.

void scriptFileDialog(ScriptInterface *ifc)
{
	REFSTART();
	int argc = ifc->getParamCount();
	if (argc < 2)
	{
		ifc->setReturnString("");
		REFEND();
		return;
	}

	string_t title = ifc->getParamAsString(0);
	string_t filter = ifc->getParamAsString(1);

	// Shared result storage
	std::string result;
	bool completed = false;
	std::mutex resultMutex;
	std::condition_variable cv;

	// Launch dialog on separate thread
	std::thread dialogThread([&]() {
		// Convert UBS filter format to Windows format
		char winFilter[1024];
		char *wp = winFilter;
		const char *fp = filter;
		// Convert "Description|*.ext|Description2|*.ext2" to "Description\0*.ext\0Description2\0*.ext2\0\0"
		while (*fp && (wp - winFilter) < 1020)
		{
			if (*fp == '|')
				*wp++ = '\0';
			else
				*wp++ = *fp;
			fp++;
		}
		*wp++ = '\0';
		*wp = '\0';

		char fileName[MAX_PATH] = "";
		OPENFILENAMEA ofn;
		ZeroMemory(&ofn, sizeof(ofn));
		ofn.lStructSize = sizeof(ofn);
		ofn.lpstrFilter = winFilter;
		ofn.lpstrFile = fileName;
		ofn.nMaxFile = MAX_PATH;
		ofn.lpstrTitle = (LPSTR)title;
		ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_NOCHANGEDIR;

		std::lock_guard<std::mutex> lock(resultMutex);
		if (GetOpenFileNameA(&ofn))
		{
			result = fileName;
		}
		else
		{
			result = "No File";
		}
		completed = true;
		cv.notify_one();
	});

	// Wait for completion
	std::unique_lock<std::mutex> lock(resultMutex);
	cv.wait(lock, [&] { return completed; });

	dialogThread.join();
	ifc->setReturnString(result.c_str());
	REFEND();
}

Callable from Clarion..
UBS App Module -

 cexpression = 'filedialog("Select File", "All Files |*.*");' 

UBSAppModule.IFileDialog.FileFolder          Procedure(string Titleselect,string defaultfilter)
Foldercontents     ANY
lcexpression       cstring(555)
    CODE
    Foldercontents = ''  
    if Self.folderdialoghandle  = FALSE    
       lcexpression = 'filedialog("Select File", "All Files|*.*");'    
       if len(Clip(lcexpression)) > FALSE
           ! Call UBS via the local clarion APP Module document interface. 
          Self.folderdialoghandle = self.AppiUBSref.Document(lcexpression)
       END
    END     
    !  message(' after document registered with universal binding service. ')
    if Self.folderdialoghandle> FALSE
       ! Execute scriptbindale handle.  
       Foldercontents = self.AppiUBSref.DocStrId(Self.folderdialoghandle)
     END
     return(Foldercontents)

! WIndow Control styling to come in a few weeks… very busy on linux Azure in the cloud… where the future of computing blues skys calls.

Seems to be working inside the clarion Accept loop as the CPP function uses its own thread… We will try for creating GUI controls in the coming months…

Note: This is ALL AI generated - Anthropic 4.0.

More WIN API Dialogs added for macro script execution from Clarion Windows and non window code . The Threading fences and protects the win API from the Clarion Accept loop. The Support for the WIN32 Dialogs is Anthropic Generated. Can AI take over CPP development of products and should venders consider that they cant keep there products closed off except in the case where IP is involved but with interfaces for allowing access. In the binding machine everything is a bindable and there is no need for a closed off Black BOX accept at the heart of the binding machine… Even what looks like code is nothing but a binding where program statements are nothing but emulation imaged as bindings. As AI says it really shines in the cloud where everything can be bound to everything.. A = B… A binding = B binding..

Where AI can generate software bindings on demand … AI generates and consumes its own creations…

/*
GLOBAL VARIABLES SET BY DIALOGS:

Color Dialog:

  • global.dlgrgbcolors.color (RGB value)
  • global.dlgrgbcolors.red (red component)
  • global.dlgrgbcolors.green (green component)
  • global.dlgrgbcolors.blue (blue component)

Font Dialog:

  • global.fontname (font family name)
  • global.fontsize (font size in points)
  • global.fontweight (font weight)
  • global.fontitalic (italic flag)

Print Dialog:

  • global.printfrom (start page)
  • global.printto (end page)
  • global.printcopies (number of copies)

USAGE EXAMPLES:
result = filedialog(“Open File”, “Text Files|.txt|All Files|.");
result = savefiledialog(“Save As”, "Documents|
.doc|All Files|.”, “doc”);
folder = folderdialog(“Select Directory”);
color = colordialog(“Pick Color”, 16777215); // Sets global.selectedcolor, etc.
font = fontdialog(“Choose Font”); // Sets global.fontname, global.fontsize, etc.
button = messagebox(“Save changes?”, “Confirm”, 4, 32); // MB_YESNO | MB_ICONQUESTION
printer = printdialog(“Print Document”); // Sets global.printfrom, etc.
setup = printsetupdialog();
text = inputdialog(“Enter name:”, “User Input”, “Default”);
*/

// Color Picker Dialog - WITH GLOBAL VARIABLE SETTING
void scriptColorDialog(ScriptInterface *ifc)
{
REFSTART();
int argc = ifc->getParamCount();
string_t title = (argc > 0) ? ifc->getParamAsString(0) : “Choose Color”;
long defaultColor = (argc > 1) ? ifc->getParamAsInteger(1) : RGB(255, 255, 255);

std::string result;
bool completed = false;
bool colorSelected = false;
COLORREF selectedColor = 0;
std::mutex resultMutex;
std::condition_variable cv;

std::thread dialogThread([&]() {
	static COLORREF customColors[16] = { 0 };
	CHOOSECOLORA cc;
	ZeroMemory(&cc, sizeof(cc));
	cc.lStructSize = sizeof(cc);
	cc.rgbResult = defaultColor;
	cc.lpCustColors = customColors;
	cc.Flags = CC_FULLOPEN | CC_RGBINIT;

	std::lock_guard<std::mutex> lock(resultMutex);
	if (ChooseColorA(&cc))
	{
		selectedColor = cc.rgbResult;
		colorSelected = true;
	}
	else
	{
		colorSelected = false;
	}
	completed = true;
	cv.notify_one();
});

std::unique_lock<std::mutex> lock(resultMutex);
cv.wait(lock, [&] { return completed; });
dialogThread.join();

// Set global variables on main thread
if (colorSelected)
{
	result = std::to_string(selectedColor);
	
	Script *scriptCore = (Script *)ifc;
	scriptString_t globalname = scriptStringFromString("global");
	var_t gv = scriptCore->findGlobal(globalname);
	if (gv != NULL)
	{
		BindVar *global = new BindVar(gv);
		
		bindable_t dlgColors = global->selectMember("dlgrgbcolors", 0, 0);
		
		bindable_t colorValue = dlgColors->selectMember("color", 0, 0);
		colorValue->setToInteger(selectedColor);
		colorValue->unShare();
		
		bindable_t redValue = dlgColors->selectMember("red", 0, 0);
		redValue->setToInteger(GetRValue(selectedColor));
		redValue->unShare();
		
		bindable_t greenValue = dlgColors->selectMember("green", 0, 0);
		greenValue->setToInteger(GetGValue(selectedColor));
		greenValue->unShare();
		
		bindable_t blueValue = dlgColors->selectMember("blue", 0, 0);
		blueValue->setToInteger(GetBValue(selectedColor));
		blueValue->unShare();
		
		dlgColors->unShare();
		delete global;
	}
	scriptStringUnShare(globalname);
}
else
{
	result = "No Color";
}

ifc->setReturnString(result.c_str());
REFEND();

}

// Binding everything to everything… AI hello world… is coming..to a cloud near you…

bindNative(“case”, baseOpCase, PRI_CASE, VARATTR_IMMEDIATE | VARATTR_ISOP);
bindNative(“else”, baseOpElse, PRI_ELSEDEFAULT, VARATTR_IMMEDIATE | VARATTR_ISOP);
bindNative(“default”, baseOpElse, PRI_ELSEDEFAULT, VARATTR_IMMEDIATE | VARATTR_ISOP);

bindNative("inherit", baseOpInherit, PRI_VAR, VARATTR_NONE); // operator so no new frame but priority 0 like a function
bindNative("data", baseOpData, PRI_VAR, VARATTR_IMMEDIATE | VARATTR_ISOP);
bindNative("args", baseOpArgs, PRI_VAR, VARATTR_IMMEDIATE);

bindNative("_compound", baseOpCompound, PRI_REPEAT, VARATTR_IMMEDIATE);       // internal !!!
bindNative("_again", baseOpAgain, PRI_REPEAT, VARATTR_IMMEDIATE);       // internal !!!

bindBindable("print", createBindBuiltin(scriptFuncPrint));
bindBindable("source", createBindBuiltin(scriptFuncSource));
bindBindable("assert", createBindBuiltin(scriptAssert));
bindBindable("exists", createBindBuiltin(scriptExists));
bindBindable("remove", createBindBuiltin(scriptRemove));
bindBindable("after", createBindBuiltin(scriptAfter));
bindBindable("addon", createBindBuiltin(scriptAddon));

bindBindable("filedialog", createBindBuiltin(scriptFileDialog));

bindBindable("savefiledialog", createBindBuiltin(scriptSaveFileDialog));

bindBindable(“colordialog”, createBindBuiltin(scriptColorDialog));
bindBindable(“fontdialog”, createBindBuiltin(scriptFontDialog));
bindBindable(“messagebox”, createBindBuiltin(scriptMessageBox));
bindBindable(“printdialog”, createBindBuiltin(scriptPrintDialog));
bindBindable(“printsetupdialog”, createBindBuiltin(scriptPrintSetupDialog));
bindBindable(“inputdialog”, createBindBuiltin(scriptInputDialog));

bindNativeObject("loop", new loopObject(this), PRI_STARTBLOCK, VARATTR_IMMEDIATE | VARATTR_ISOP);

Ai - has recently added over 150 functions to the window version of our linux binding software machine and is proposing the novel creation of a functions based approach to creating win 3 UI controls.

Threading Strategy
UI Thread Management:
Store DispatcherQueue reference in UBS global variable
All builtin functions marshal operations to UI thread using TryEnqueue
Handle cross-thread communication for property access
Example Implementation:
cpp
void scriptWinUISetProp(ScriptInterface ifc) {
// Get parameters from UBS
int controlID = ifc->getParamAsInteger(1);
string propName = ifc->getParamAsString(2);
// Get dispatcher from UBS global
bindable_t global = ifc->findglobalvar(“global”);
bindable_t dispatcherVar = global->selectMember(“winui_dispatcher”, 0, 0);
auto dispatcher = (winrt::DispatcherQueue
)(dispatcherVar->getAsInteger());
// Marshal to UI thread
dispatcher->TryEnqueue([=]{
// Get control from UBS global storage
bindable_t global = ifc->findglobalvar(“global”);
bindable_t controlVar = global->selectMember((“winui_control_” + std::to_string(controlID)).c_str(), 0, 0);
auto control = (winrt::IInspectable)(controlVar->getAsInteger());

// Set property using base class casting
SetControlProperty(control, propName, value);

}

WinUI 3 Integration Proposal for UBS.pdf (229.8 KB)

claude 4.7 review of the windows UBS linux port running in beta in clarion. This post is AI Generated.

UBS VM Taxonomy.

UBS → Windows port , Claude UBS review on the VM taxonomy. This is the structural classification table .

Characteristic JVM / CLR Forth CPython UBS
Stacks 2 2 1 + frames 4 (distinct roles)
Instruction type Numeric opcode Pointer (direct) Numeric opcode Pointer opcode (var_t)
Instruction set Fixed Fixed at build Fixed at build Dynamic — assembled at runtime
Operator precedence Compiled away Postfix — none needed Postfix — none needed Runtime orchestrated
Computation locus VM core VM core VM core Bound C++ objects only
Fetch-execute loop Yes Yes (inner interpreter) Yes Yes (run / getOpVar / execVar)
Scope / frame types Yes Limited Yes Yes — 12 frame types
Cache invalidation No No No Ticket-based per-op re-resolution
Dispatch path Method tables Execution tokens Opcode switch Uniform ScriptBindable interface
Non-local control flow Exceptions Return stack Exceptions VARATTR JUMP short-circuit
Per-instruction copy semantic No No No VAR ATTR COPY ON PARSE

What this means in plain terms

No built-in opcodes. Every operator, every control structure, every service is registered through bindBindable(), bindNative(), or bindNativeObject() at construction time.class, function, loop, data{} , if and while are bindings, registered exactly the same way as an HTTP client or an AI service. The core engine performs zero domain computation.

One dispatch interface. Everything goes through ScriptBindable::selectMember() and invoke(). Arithmetic, string ops, AI calls, COM automation — same path.

Binary Packed Intelligence operation list, dynamically created at runtime and stored for reuse.

Closest prior art.

  • Forth — two stacks, fixed dictionary, postfix. No uniform dispatch interface..
  • Smalltalk / Objective-C — uniform message dispatch, but a conventional bytecode VM underneath with fixed opcodes.
  • Lua — dynamic binding via metatables, but a register-based VM with fixed opcodes and compiled-away precedence.
  • Tcl — extensible command dispatch, but no stack machine; precedence handled by a separate expr parser.
  • COM IDispatch — uniform late-bound dispatch, but not a VM. No stacks, no execution engine.

Classification

UBS is a four-stack, indirect-threaded, infix-dispatching binding execution engine — where the instruction set is dynamically assembled from registered bindings at construction time and every dispatch target is resolved through the uniform ScriptBindable interface.

VM class name: Binding Dispatch Virtual Machine (BDVM).

Micro-kernel footprint: typically below 500 KB, as small as 158 KB in some memory models.

Binding QT to the Cross platform Binding Machine.. A Paper by AI…

https://claude.ai/public/artifacts/30a80937-a5a2-4720-9954-256cc8c572b0

AI implements a cross platform QT binding Class and Proxy framework for QT.. ported from our Linux 64 bit software

To upgrade our old win32 clarion apps we cant run QT 64 bit graphs but we can run old 32 Bit QT DLL’s and AI ported the UBS bindable QT graphic support over and mod’ed it for win32..

Two things were left clarion picture and porting CPP data interfaces bind vars class from linux 64 bit back to window 32..

Once that was done we could look to mix and match old QT win 32 to old clarion win32 and start to upgrade the look and feel of some tired looking apps..

The last piece of the puzzle was clarion pictures and AI has machined the clarion pictures format into a CPP class that imitates clarion pictures as a CPP bindable in the UBS machine… results are well encouraging..

UBS Machine commands to test the win32 QT and Clarion picture support.

qtgui.tablesetitem(‘TBL’,13,0,‘@T3’);
qtgui.tablesetitem(‘TBL’,13,1,‘173000’);
qtgui.tablesetitem(‘TBL’,13,2,picture.formattime(‘@T3’, 173000));
qtgui.tablesetitem(‘TBL’,13,3,‘hh:mmXM 12-hour AM/PM’);
qtgui.tablesetitem(‘TBL’,13,4,“picture.formattime(‘@T3’, 173000)”);

now with the linux binding machine on windows now supporting our old clarion picture formats we wanted some of the ancient code we had in DOS 2.0 to be ported by AI and run inside the binding machine . That ment either getting AI to port the DOS 2 clarion table code to portable MySQL format or creating a look alike clarion DOS Table structure in the windows UBS CPP machine. That is what AI proposed and well we will see if the tests work. The have the Tables display in QT and the old clarion DOS 2 ported memory table code can come back into doing the jobs it once did.. Porting all those modules would have been impossible without AI.

// MemoryTableBindable.h
// (c) Copyright Quantum Dynamics Ltd 2026
// Flat in-memory table ScriptBindable for UBS (Universal Binding Service)
// Win32 32-bit, Visual Studio 2015
//
// ============================================================================
// MODEL - Clarion TB 104 Memory Table semantics, expressed as a UBS bindable
// ============================================================================
//
// The staging buffer is NOT in the entries list. It sits on the table as a
// single, separate working area. Data moves between buffer and entries only
// at ADD / GET / PUT.
//
// MemoryTableBindable
// ±------------------------------------------+
// | std::vector<ScriptVar*> stagingFields | ← ONE staging buffer
// | (the record area - script reads/writes | always on the table
// | land here) |
// ±------------------------------------------+
// | std::vector<MemoryTableEntry*> entries | ← stored rows. Each entry
// | [0] → Entry { rowId, deleted, fields }| carries a stable rowId
// | [1] → Entry { rowId, deleted, fields }| assigned at ADD time.
// | [2] → Entry { rowId, deleted, fields }| Deleted entries are
// | … | flagged in place; the
// | | vector does not shift.
// ±------------------------------------------+
// | unordered_map<uint64_t,intptr_t> | ← rowId → storage position
// | rowIdToPos | Only active rowIds.
// ±------------------------------------------+
// | intptr_t currentPointer | ← 1-based storage index of
// | | current row (entries[
// | | currentPointer-1]). The
// | | script-visible position
// | | is computed by counting
// | | active entries before it.
// ±------------------------------------------+
// | std::vector<MemoryTableKey*> keys | ← maintained sort orders.
// | each key->sortedIndex holds rowIds. | rowIds are stable, so
// | | reordering or flagging
// | | entries never invalidates
// | | sortedIndex contents.
// ±------------------------------------------+
//
// Data flow:
//
// script writes script reads
// | ^
// v |
// ±------------------+
// | stagingFields | <— the record area
// ±------------------+
// | ^ ^ |
// | | | |
// ADD| |GET |PUT|DELETE (no buffer touch)
// v | | v
// ±------------------+
// | entries list |
// ±------------------+
//
// ADD: copy stagingFields → new entry, assign rowId, append,
// update rowIdToPos, insert rowId into every key.
// GET hit: copy entries[storage]->fields → stagingFields.
// PUT: re-place rowId in every key (key values may have changed),
// then copy stagingFields → entries[storage]->fields.
// DELETE: set entries[storage]->deleted = 1, remove rowId from
// rowIdToPos. Entries vector is NOT shifted. Maintained keys
// are NOT touched - searches skip deleted entries.
// FREE: clear entries, rowIdToPos, every key’s sortedIndex.
// stagingFields and key declarations preserved.
// SORT: std::stable_sort entries by ad-hoc keyspec. rowIds stable,
// so maintained keys’ sortedIndex remains valid. Rewrite
// rowIdToPos for new storage positions.
// REBUILDKEYS: compact entries (drop deleted), rewrite rowIdToPos, rebuild
// every maintained key’s sortedIndex from scratch. The script
// calls this after bulk delete cycles to reclaim memory and
// restore O(log N) key search performance.
//
// The entries themselves never share storage with the buffer. Each
// ADD / GET / PUT is a copy across the boundary.
//
// ============================================================================
// UBS SCRIPT USAGE
// ============================================================================
//
// Registration in Script::Script():
// bindBindable(“newmemorytable”, createBindBuiltin(scriptNewMemoryTable));
//
// Construct:
// t = newmemorytable();
//
// Field access (any name that is not a reserved verb/property is a field name):
// t.nmbr = “010” // write into staging buffer
// t.name = “Acme”
// x = t.nmbr // read from staging buffer
//
// Declare maintained keys (“+” ascending default, “-” descending,
// comma-separated for composite):
// t.addkey(“nmbr”)
// t.addkey(“region,-amount”)
// t.removekey(“region,-amount”)
//
// ADD - new entry from staging buffer:
// t.nmbr = “010”
// t.name = “Acme”
// t.add()
//
// GET by position (1-based, counts active entries only):
// t.get(3)
// print(t.name)
//
// GET by key, search values pulled from staging buffer for the named fields:
// t.nmbr = “010”
// t.get(“nmbr”)
//
// GET by key with explicit search values:
// t.get(“region,-amount”, “North”, 500)
//
// PUT - commit staging buffer back to the current entry:
// t.get(3)
// t.name = “Updated”
// t.put()
//
// DELETE - mark current entry deleted; staging buffer is preserved:
// t.get(3)
// t.delete()
//
// REBUILDKEYS - compact deleted entries, rebuild every maintained key:
// t.rebuildkeys()
//
// FREE - clear all entries; staging buffer preserved; key declarations kept:
// t.free()
//
// SORT the whole table by an ad-hoc key spec:
// t.sort(“region,-amount”)
//
// Multi-pass sort (least significant key first, std::stable_sort preserves ties):
// t.sort(“amount”)
// t.sort(“region”)
//
// SORT by a script comparator bindable (deferred - placeholder in current build):
// t.sortbyfunc(mycomparator)
//
// Properties (read-only):
// n = t.records // active row count (excludes deleted)
// pos = t.pointer // current 1-based visible position (alias: t.position)
// ch = t.changes // change counter
// err = t.error // 0 = none, 31 = entry not found,
// // 32 = no prior op, 75 = invalid field/key
// d = t.deleted // count of marked-deleted entries pending rebuild
//
// Error codes match TB 104:
// MT_ERR_NONE 0
// MT_ERR_ENTRY_NOT_FOUND 31 GET miss
// MT_ERR_ENTRY_NOT_AVAILABLE 32 PUT/DELETE with no prior valid op
// MT_ERR_INVALID_FIELD 75 key spec references undeclared field
// or addkey/removekey/sort missing spec

what does our old clarion semantic add get put into a TABLE look like now and how has the UBS Binding machine rendered our clarion dos style table in windows.. complete with faked clarion picture support machined by AI.

This is an AI claude code rendered UBS script.

global.stocks.set()
r = global.stocks.records;

loop(r)
{

global.stocks.next()
row = i - 1;

sparkid = "SPK_" .. global.stocks.symbol;

qtgui.tablesetitem('LIST1', row, 0, global.stocks.symbol);
qtgui.tablesetitem('LIST1', row, 1, picture.format('@N$10.2', global.stocks.price));
qtgui.tablesetitem('LIST1', row, 2, global.stocks.change);
qtgui.tablesetitem('LIST1', row, 3, global.stocks.volume);

qtgui.sparkline(sparkid, '', 0, 0, 170, 22,
                global.stocks.spark, global.stocks.color, -1);
qtgui.tablecellwidget('LIST1', row, 4, sparkid);

qtgui.tablesetitem('LIST1', row, 5, picture.format('@N$10.2', global.stocks.price));

};

// ----------------------------------------------------------------------------
// Build the memory table of watchlist rows.
// Fields per row: symbol, price, change, volume, spark, color
// The “symbol” field is also declared as a maintained key, so the rows
// stay in symbol order regardless of insertion order.
// ----------------------------------------------------------------------------

global.stocks = newmemtable();
global.stocks.addkey(“symbol”);

global.stocks.symbol = “AAPL”;
global.stocks.price = 184.32;
global.stocks.change = “+1.2%”;
global.stocks.volume = “52,341,200”;
global.stocks.spark = “181.20,181.85,182.40,182.10,183.05,183.60,183.40,183.95,184.10,184.32”;
global.stocks.color = 3050327;
global.stocks.add();

AI Generated some interesting code for virtual lists. All from just the clarion help files.


DynProxyList.VLBproc        PROCEDURE(LONG row, SHORT column)
nchanges    LONG
  COMPILE('**dbgVd**',DocMgrDebug = 1)
dbgln       cstring(255)
  ! **dbgVd**
    CODE
    COMPILE('**dbgV**',DocMgrDebug = 1)
    IF DbgVlbCtr < 16 AND NOT SELF.Model &= NULL AND NOT SELF.Model.iUBSref &= NULL
       DbgVlbCtr += 1
       dbgln = 'DBG VLBproc row=' & row & ' col=' & column
       SELF.Model.iUBSref.logPush('DocManager_proxylist_debug.log')
       SELF.Model.iUBSref.logTo(dbgln)
       SELF.Model.iUBSref.logPop()
    END
    ! **dbgV**
    IF SELF.DataQ &= NULL OR SELF.Model &= NULL THEN RETURN ''; END
    CASE row
    OF -1                                          ! rows to display
        RETURN RECORDS(SELF.DataQ)
    OF -2                                          ! nominal field count
        RETURN SELF.Model.NomCount()
    OF -3                                          ! changed since last draw?
        nchanges = CHANGES(SELF.DataQ)
        IF nchanges <> SELF.ochanges
           SELF.ochanges = nchanges
           RETURN '1'
        END
        RETURN '0'
    ELSE
        GET(SELF.Model.Nom, column)                ! nominal field -> (column, role)
        IF ERRORCODE() THEN RETURN ''; END
        IF SELF.Model.Nom.NRole = ColumnDataTypes:DataItem
           RETURN SELF.ColumnDataValue(SELF.Model.Nom.NColNo, row)
        END
        ! A style field: resolve through the condition hook, passing the row's
        ! source-column data value so overrides can compute per-row rules.
        RETURN SELF.ConditionValue(SELF.Model.Nom.NColNo, SELF.Model.Nom.NRole, |
                                   SELF.ColumnDataValue(SELF.Model.Nom.NColNo, row), row)
    END

Now you might ask where did we give AI techical stuff from to do work like machine picture and create clarion DOS Style memory tables with replace able key algos.. well it was the technical documents that were not continued after Clarion Corp was sold and web site like this that AI AI researched. There are ways to get information and reading the topspeed compiler documents for accessing the CPP stuff but what is the clarion compiler written in CPP or Modula 2? Anyway this was a great site we found for AI to study.. and its still up !!! The Clarion Insider

That website is our resident documentation expert @PaulAttryde

Some of the information can be garnered from here:

Like the file extensions and who they are linked to.

.db$ Temperature debug info (Clarion Modula-2)
.dbd Debug info (Clarion Modula-2)
.dct Database dictionary (Clarion Database Developer)
.itf Interface file (JPI TopSpeed Pascal)
.mod Modula-2 source code file (Clarion Modula-2)
.red Path info (Clarion Modula-2)
.ses Session info (Clarion Modula-2)