Adds the per-user High-Water Mark API to TMessageBase:
function SupportsHWM: boolean;
function GetHWM(const UserName: AnsiString): longint;
procedure SetHWM(const UserName: AnsiString; MsgNum: longint);
procedure MapUser(const UserName: AnsiString; UserId: longint);
property ActiveUser: AnsiString;
GetHWM returns -1 when the format has no HWM mechanism, the user
isn't registered (number-keyed formats), or no HWM has been set
for that user yet.
Two-flavour native dispatch:
- Name-keyed backends (JAM, later Squish/Wildcat) override
DoGetHWMByName / DoSetHWMByName.
- Number-keyed backends (later Hudson/GoldBase/EzyCom) override
DoGetHWMById / DoSetHWMById; caller must register name->id via
MapUser first.
Auto-bump: when ActiveUser is non-empty, ReadMessage compares the
just-read msg.num to GetHWM(ActiveUser); if higher, calls SetHWM.
Never decrements -- reading a lower-numbered message is a no-op.
Default off (ActiveUser = '').
JAM implementation:
- Adds .JLR (lastread) handling to TJamBase: lazy open via
EnsureLrStream, GetLastRead/GetHighRead/SetLastRead methods,
proper Close cleanup.
- TJamMessageBase wires DoGetHWMByName / DoSetHWMByName to
CalcUserCRC + GetLastRead / SetLastRead. SetHWM also keeps
HighReadMsg monotonic.
Coverage map (this milestone):
- JAM: native ✓
- Squish, Hudson, GoldBase, EzyCom, Wildcat: -1 (planned 0.3.1/2)
- PCBoard, MSG, PKT: -1 (no HWM in spec)
Tests: tests/test_hwm.pas covers SupportsHWM, set/get round-trip,
persistence across Open/Close, auto-bump via ActiveUser (advances),
auto-bump never decrements, MSG/PKT correctly return -1, Hudson
returns -1 even after MapUser (until 0.3.1 lands the impl). 7/7
new tests pass; full suite 38/38 across 9 programs.
Recommended caller pattern:
base.ActiveUser := 'NetReader';
for i := 0 to base.MessageCount - 1 do begin
base.ReadMessage(i, msg);
{ process msg ... HWM auto-tracks the high-water for NetReader }
end;