<<>> <> <> <> <> <> <> <> DIRECTORY Atom, BackStop, Commander, FS, IconRegistry, IO, List, MessageWindow, Rope, SystemNames, TextReplace, UserProfile, ViewerClasses, ViewerEvents, ViewerLocks, ViewerOps; IconHacks: CEDAR PROGRAM IMPORTS Atom, BackStop, Commander, FS, IconRegistry, IO, List, MessageWindow, Rope, SystemNames, TextReplace, UserProfile, ViewerEvents, ViewerLocks, ViewerOps = BEGIN ROPE: TYPE ~ Rope.ROPE; LOR: TYPE ~ LIST OF ROPE; myKey: REF ¬ Atom.MakeAtom["the label created by IconHacks"]; hackLabels, hackIcons: BOOL ¬ FALSE; subst: TextReplace.RopeMap ¬ NIL; pairs: TextReplace.PairList ¬ NIL; Hackit: PROC [viewer: ViewerClasses.Viewer, event: ViewerEvents.ViewerEvent, before: BOOL] RETURNS [abort: BOOL ¬ FALSE] --ViewerEvents.EventProc-- ~ { HackLabel: PROC ~ { name: ROPE ~ viewer.name; label: ROPE ¬ name; IF event # close OR List.Assoc[myKey, viewer.props] # viewer.label THEN RETURN; IF NOT hackLabels THEN {viewer.label ¬ NIL; RETURN}; {cache: LOR ¬ WITH List.Assoc[key: subst, aList: viewer.props] SELECT FROM x: LOR => x, ENDCASE => NIL; IF cache # NIL AND cache.rest # NIL AND cache.rest.rest = NIL AND cache.first = viewer.name THEN {viewer.label ¬ cache.rest.first; RETURN}; label ¬ subst.Apply[label]; cache ¬ LIST[name, label]; viewer.props ¬ List.PutAssoc[subst, cache, List.PutAssoc[myKey, label, viewer.props]]; viewer.label ¬ label; }}; HackIcon: PROC ~ { IF hackIcons AND viewer.parent=NIL AND viewer.file#NIL THEN { Icon: PROC [r1, r2: ROPE ¬ NIL] RETURNS [found: BOOL] ~ { iconName ¬ UserProfile.Token[key: Rope.Cat["IconHacks.", r1, r2]]; RETURN [iconName#NIL] }; cp: FS.ComponentPositions; fullFName, extension, iconName: ROPE; [cp: cp, fullFName: fullFName] ¬ FS.ExpandName[name: viewer.file]; extension ¬ Rope.Substr[base: fullFName, start: cp.ext.start, len: cp.ext.length]; SELECT TRUE FROM viewer.newVersion AND Icon["DirtyIcon.", extension] => {}; Icon["Icon.", extension] => {}; viewer.newVersion AND (iconName ¬ IconRegistry.IsRegistered[Rope.Concat["Dirty", extension]].name)#NIL => {}; (iconName ¬ IconRegistry.IsRegistered[extension].name)#NIL => {}; viewer.newVersion AND Icon["DefaultDirtyIcon"] => {}; Icon["DefaultIcon"] => {}; ENDCASE => iconName ¬ iconName; IF iconName#NIL THEN { viewer.icon ¬ IconRegistry.GetIcon[iconName: iconName, default: viewer.icon]; IF event#close THEN ViewerOps.PaintViewer[viewer, caption] ELSE viewer ¬ viewer; } ELSE hackIcons ¬ hackIcons; } ELSE viewer ¬ viewer; }; BackStopped: PROC ~ { HackLabel[]; HackIcon[]; RETURN}; WithLock: PROC ~ { IF lastMsg.Length[] > 0 THEN lastErr ¬ lastMsg; lastMsg ¬ BackStop.Call[inner: BackStopped]; RETURN}; IF event=close OR viewer.iconic THEN ViewerLocks.CallUnderWriteLock[WithLock, viewer] ELSE event ¬ event; RETURN}; lastErr, lastMsg: ROPE ¬ NIL; NoteProfile: PROC [reason: UserProfile.ProfileChangeReason] --UserProfile.ProfileChangedProc-- ~ { user: ROPE ~ SystemNames.UserName[]; asRope: ROPE ~ UserProfile.Line["IconHacks.LabelSubstitutions", "defaults"]; in: IO.STREAM ~ IO.RIS[asRope]; head, tail: TextReplace.PairList ¬ NIL; DO ENABLE IO.EndOfStream => { MessageWindow.Append["Syntax error in IconHacks.LabelSubstitutions profile entry", TRUE]; EXIT}; [] ¬ in.SkipWhitespace[]; IF in.EndOf[] THEN EXIT; {find: ROPE ~ GetToken[in]; this: TextReplace.PairList; IF find.Equal["defaults", FALSE] THEN { this ¬ LIST[ ["/Cedar/", "c/", TRUE], ["/Cedar10.1/", "c/", TRUE], ["/PCedar2.0/", "pc/", TRUE], [SystemNames.SimpleHomeDirectory[], "~/", TRUE, FALSE, TRUE], [".mesa", ".m", TRUE, FALSE, TRUE], [".config", ".c", TRUE, FALSE, TRUE] ] <> <<[" ('$&) :", ":"],>> <<[" ('$&) WD = ~$~$ :", ":"],>> <<["[Cedar7.0]", "dc]", TRUE],>> <<["[CedarChest7.0]", "dcc]", TRUE],>> <<["/pseudo/cedarchest7.0/", "dcc/", TRUE],>> <<["/pseudo/cedar7.0/", "dc/", TRUE],>> <<["[PCedar2.0]", "pc]", TRUE],>> <<["/pseudo/pcedar2.0/", "pc/", TRUE],>> <<[Rope.Cat["/pseudo/", SystemNames.ReleaseDir["cedar", current], "/"], "c/", TRUE],>> <<[Rope.Cat["/", SystemNames.ReleaseDir["Cedar", current], "/"], "c/", TRUE],>> <<[SystemNames.SimpleHomeDirectory[], "~/", TRUE, FALSE, TRUE],>> <<["Telephone Directory:", "TD", TRUE],>> <<[".mesa", ".m", TRUE, FALSE, TRUE],>> <<[".config", ".c", TRUE, FALSE, TRUE] ]>> } ELSE { literal, ignoreCase: BOOL ¬ TRUE; word: BOOL ¬ FALSE; sense: BOOL ¬ TRUE; UNTIL MyBreak[in.PeekChar[]]=sepr DO switch: CHAR ~ in.GetChar[]; SELECT switch FROM '- => sense ¬ FALSE; '+ => sense ¬ TRUE; 'l => literal ¬ sense; 'p => literal ¬ NOT sense; 'w => word ¬ sense; 'c => ignoreCase ¬ NOT sense; <<'b => addBounds ¬ sense;>> ENDCASE => MessageWindow.Append[IO.PutFR["Invalid IconsHacks switch %c after %g", [character[switch]], [rope[find]] ], TRUE]; ENDLOOP; this ¬ LIST[[find, GetToken[in], literal, word, ignoreCase]]; }; IF tail = NIL THEN head ¬ this ELSE tail.rest ¬ this; FOR tail ¬ this, tail.rest WHILE tail.rest # NIL DO NULL ENDLOOP; tail ¬ tail}ENDLOOP; subst ¬ TextReplace.RopeMapFromPairs[pairs ¬ head]; hackLabels ¬ UserProfile.Boolean[key: "IconHacks.HackLabels", default: FALSE]; hackIcons ¬ UserProfile.Boolean[key: "IconHacks.HackIcons", default: FALSE]; }; GetToken: PROC [in: IO.STREAM] RETURNS [token: ROPE] ~ { [] ¬ in.SkipWhitespace[]; token ¬ SELECT in.PeekChar[] FROM '" => in.GetRopeLiteral[], ENDCASE => in.GetTokenRope[MyBreak].token; }; MyBreak: PROC [char: CHAR] RETURNS [IO.CharClass] --IO.BreakProc-- ~ { RETURN [SELECT char FROM IN [0C .. ' ] => sepr, ENDCASE => other]; }; ListHacksCmd: PROC [cmd: Commander.Handle] RETURNS [result: REF ¬ NIL, msg: ROPE ¬ NIL] --Commander.CommandProc-- ~ { FOR pl: TextReplace.PairList ¬ pairs, pl.rest WHILE pl#NIL DO cmd.out.PutFL["\"%q\" => \"%q\" %g %g %g %g\n", LIST[ [rope[pl.first.match]], [rope[pl.first.replace]], [boolean[pl.first.literal]], [boolean[pl.first.word]], [boolean[pl.first.ignoreCase]] ]]; ENDLOOP; RETURN}; hreg: ViewerEvents.EventRegistration ¬ ViewerEvents.RegisterEventProc[Hackit, close]; regs: LIST OF ViewerEvents.EventRegistration ¬ LIST[ ViewerEvents.RegisterEventProc[proc: Hackit, event: close, before: TRUE], ViewerEvents.RegisterEventProc[proc: Hackit, event: save, before: FALSE], ViewerEvents.RegisterEventProc[proc: Hackit, event: edit, before: FALSE]]; UserProfile.CallWhenProfileChanges[NoteProfile]; Commander.Register["IconHacksList", ListHacksCmd, "lists the icon label substitutions"]; END.