<<>> <> <> <> <> <<>> DIRECTORY AbbrevExpand USING [Validate, ValidateAll], Ascii USING [Lower], Atom USING [MakeAtomFromRefText], FS USING [ComponentPositions, Error, ExpandName], FSBackdoor USING [CreateEvent, NextCreateEvent], MessageWindow USING [Append, Blink], NodeStyleValidate USING [ValidateStyle, ValidateStyles], Process USING [Detach], RefText USING [AppendRope, ObtainScratch, ReleaseScratch], Rope USING [Cat, Equal, Fetch, Length, ROPE, Run], TEditDocument USING [TEditDocumentData], TEditDocumentPrivate USING [DoLoadFile], UserProfile USING [CallWhenProfileChanges, ProfileChangedProc], ViewerClasses USING [Viewer], ViewerForkers USING [ForkPaint], ViewerLocks USING [CallUnderViewerTreeLock], ViewerOps USING [EnumerateChildren, EnumerateViewers, EnumProc]; TiogaFileWatcherImpl: CEDAR PROGRAM IMPORTS AbbrevExpand, Ascii, Atom, FS, FSBackdoor, MessageWindow, NodeStyleValidate, Process, RefText, Rope, TEditDocumentPrivate, UserProfile, ViewerForkers, ViewerLocks, ViewerOps = BEGIN ROPE: TYPE = Rope.ROPE; highestVersion: CARDINAL ~ CARDINAL.LAST; ExtensionType: TYPE = {nil, tip, style, abbreviations}; Info: TYPE = RECORD[ name: ROPE ¬ NIL, -- full FName len: INT ¬ 0, -- length of name, omitting version part baseStart: INT ¬ 0, -- index of start of base name baseLen: INT ¬ 0, -- length of base name version: CARDINAL ¬ highestVersion, -- version number type: ExtensionType ¬ nil -- extension type ]; LowerCaseAtom: PROC[rope: ROPE, start, len: INT] RETURNS [atom: ATOM ¬ NIL] ~ { scratch: REF TEXT ~ RefText.ObtainScratch[100]; text: REF TEXT ~ RefText.AppendRope[to: scratch, from: rope, start: start, len: len]; FOR i: NAT IN [0..text.length) DO text[i] ¬ Ascii.Lower[text[i]] ENDLOOP; atom ¬ Atom.MakeAtomFromRefText[text]; RefText.ReleaseScratch[scratch]; }; ParseFileName: PROC[name: ROPE] RETURNS[info: Info ¬ []] = { cp: FS.ComponentPositions; [fullFName: name, cp: cp] ¬ FS.ExpandName[name ! FS.Error => GOTO Fail]; info.name ¬ name; -- full name info.len ¬ cp.ext.start+cp.ext.length; -- length up to end of extension info.baseStart ¬ cp.base.start; info.baseLen ¬ cp.base.length; IF cp.ver.length>0 THEN { -- parse version number start: INT ~ cp.ver.start; len: INT ~ cp.ver.length; version: CARDINAL ¬ 0; FOR i: INT IN[start..start+len) DO version ¬ version*10+(name.Fetch[i]-'0); ENDLOOP; info.version ¬ version; }; IF cp.ext.length>0 THEN { -- look for special extensions start: INT ~ cp.ext.start; len: INT ~ cp.ext.length; MatchExtension: PROC[x: ROPE] RETURNS[BOOL] = { RETURN[Rope.Length[x]=len AND Rope.Run[s1: name, pos1: start, s2: x, case: FALSE]=len] }; SELECT TRUE FROM MatchExtension["tip"] => info.type ¬ tip; MatchExtension["style"] => info.type ¬ style; MatchExtension["abbreviations"] => info.type ¬ abbreviations; ENDCASE; }; EXITS Fail => RETURN; }; NamesMatch: PROC[a, b: Info] RETURNS[BOOL] = { RETURN[a.len=b.len AND Rope.Run[s1: a.name, s2: b.name, case: FALSE]>=a.len]; }; autoStyleLoad: BOOL ¬ TRUE; <