DIRECTORY Buttons, Commander, CommanderOps, Convert, Rope, IO, Menus, SimpleFeedback, TiogaOps, ViewerClasses, ViewerTools; TopButton: CEDAR PROGRAM IMPORTS Buttons, Commander, CommanderOps, Convert, IO, Rope, SimpleFeedback, TiogaOps, ViewerTools ~ BEGIN ROPE: TYPE ~ Rope.ROPE; ButtonImplRef: TYPE = REF ButtonImplObject; ButtonImplObject: TYPE = RECORD [ name: ROPE, def: ROPE, button: Buttons.Button ¬ NIL ]; DoButtonProc: TYPE = PROC [br: ButtonImplRef]; topButtonList: LIST OF ButtonImplRef ¬ NIL; TopButton: Commander.CommandProc ~ { s: IO.STREAM = IO.RIS[cmd.commandLine]; br: ButtonImplRef; button: Buttons.Button; name: ROPE = (IO.GetCedarTokenRope[s]).token; cmdline: ROPE = IO.GetRope[s]; br ¬ NEW[ButtonImplObject ¬ [name: name, def: cmdline]]; button _ Buttons.Create[info: [name: name], proc: TopButtonImpl, clientData: br, paint: FALSE]; Buttons.SetDisplayStyle[button, $BlackOnWhite]; br.button _ button; topButtonList ¬ CONS[br, topButtonList]; }; SimpleTopButtonImpl: Buttons.ButtonProc ~ { msg: ROPE = CommanderOps.DoCommandRope[commandLine: NARROW[clientData], parent: NIL].out; SimpleFeedback.Append[$TopButton, oneLiner, $Feedback, msg]; }; FindTopbuttons: PROC [pattern: ROPE, doEachButton: DoButtonProc] ~ { FOR brList: LIST OF ButtonImplRef ¬ topButtonList, brList.rest UNTIL brList=NIL DO IF Rope.Match[pattern, brList.first.name, TRUE] THEN doEachButton[brList.first]; ENDLOOP; }; DestroyButtonImpl: Commander.CommandProc ~ { s: IO.STREAM = IO.RIS[cmd.commandLine]; pattern: ROPE = (IO.GetCedarTokenRope[s]).token; didDestroy: BOOL ¬ FALSE; doButton: DoButtonProc = {Buttons.Destroy[br.button]; didDestroy ¬ TRUE;}; FindTopbuttons[pattern, doButton]; IF NOT didDestroy THEN { msg: ROPE ¬ IO.PutFR1["could not find button matching `%g'.", IO.rope[pattern]]; SimpleFeedback.Append[$TopButton, oneLiner, $Feedback, msg]; }; }; ReplaceButtonImpl: Commander.CommandProc ~ { s: IO.STREAM = IO.RIS[cmd.commandLine]; name: ROPE = (IO.GetCedarTokenRope[s]).token; cmdline: ROPE = IO.GetRope[s]; didReplace: BOOL ¬ FALSE; doButton: DoButtonProc = { didReplace ¬ TRUE; br.def ¬ cmdline; }; FindTopbuttons[name, doButton]; IF NOT didReplace THEN { msg: ROPE ¬ IO.PutFR1["could not find button matching `%g'.", IO.rope[name]]; SimpleFeedback.Append[$TopButton, oneLiner, $Feedback, msg]; }; }; TopButtonImpl: Menus.ClickProc = { WITH clientData SELECT FROM br: ButtonImplRef => { def: ROPE = br.def; msg: ROPE = CommanderOps.DoCommandRope[commandLine: ButtonCommandToRope[parent, def, mouseButton, shift, control], parent: NIL].out; SimpleFeedback.Append[$TopButton, oneLiner, $Feedback, msg]; }; ENDCASE; }; ButtonCommandToRope: PROC [parent: ViewerClasses.Viewer, cmdIn: ROPE ¬ NIL, mouseButton: ViewerClasses.MouseButton ¬ red, shift, control: BOOL ¬ FALSE] RETURNS [def: ROPE] = { curSel, escaped, spaced: ROPE; viewer: ViewerClasses.Viewer ¬ NIL; start: TiogaOps.Location; viewerName: ROPE ¬ NIL; fileName: ROPE ¬ NIL; shortFileName: ROPE ¬ NIL; baseFileName: ROPE ¬ NIL; spaceFileName: ROPE ¬ NIL; shortSpaceFileName: ROPE ¬ NIL; quotedFileName: ROPE ¬ NIL; shortQuotedFileName: ROPE ¬ NIL; index: INT ¬ -1; controlRope: ROPE ¬ IF control THEN "control" ELSE "noControl"; shiftRope: ROPE ¬ IF shift THEN "shift" ELSE "noShift"; buttonRope: ROPE; SELECT mouseButton FROM red => buttonRope ¬ "left"; yellow => buttonRope ¬ "middle"; blue => buttonRope ¬ "right"; ENDCASE => ERROR; IF cmdIn = NIL THEN RETURN; def ¬ cmdIn; [viewer: viewer, start: start] ¬ TiogaOps.GetSelection[primary]; curSel ¬ ViewerTools.GetSelectionContents[]; IF viewer # NIL AND NOT viewer.destroyed AND NOT viewer.newFile THEN { root: TiogaOps.Ref ¬ TiogaOps.Root[start.node]; offset: INT ¬ TiogaOps.LocOffset[loc1: [root, 0], loc2: start, skipCommentNodes: TRUE]; index ¬ offset; viewerName ¬ viewer.file; IF viewerName = NIL THEN viewerName ¬ viewer.name; fileName ¬ viewer.file; fileName ¬ Rope.Substr[fileName, 0, Rope.SkipTo[fileName, 0, "!"]]; }; escaped ¬ Convert.RopeFromRope[from: curSel, quote: FALSE]; spaced ¬ RopeSubst[old: "\n", new: " ", base: curSel]; curSel ¬ Rope.Substr[base: curSel, start: 0, len: curSel.Index[s2: "\n"]]; fileName ¬ IF (Rope.SkipTo[s: curSel, pos: 0, skip: " \t"] = curSel.Length[]) AND (curSel.Length[] > 1) THEN curSel ELSE fileName; shortFileName ¬ GetShortName[fileName]; baseFileName ¬ GetBaseName[shortFileName]; spaceFileName ¬ IF (curSel.Length[] > 1) THEN curSel ELSE fileName; shortSpaceFileName ¬ GetShortName[spaceFileName]; quotedFileName ¬ Rope.Cat["\"", spaceFileName, "\""]; shortQuotedFileName ¬ Rope.Cat["\"", shortSpaceFileName, "\""]; IF Rope.SkipTo[def, 0, "$"] < Rope.Length[def] THEN { def ¬ RopeSubst[old: "$CurrentSelection$", new: curSel, base: def, case: TRUE]; def ¬ RopeSubst[old: "$CurrentEscapedSelection$", new: escaped, base: def, case: TRUE]; def ¬ RopeSubst[old: "$CurrentSpacedSelection$", new: spaced, base: def, case: TRUE]; def ¬ RopeSubst[old: "$FileNameSelection$", new: fileName, base: def, case: TRUE]; def ¬ RopeSubst[old: "$ShortFileNameSelection$", new: shortFileName, base: def, case: TRUE]; def ¬ RopeSubst[old: "$BaseFileNameSelection$", new: baseFileName, base: def, case: TRUE]; def ¬ RopeSubst[old: "$SpaceFileNameSelection$", new: spaceFileName, base: def, case: TRUE]; def ¬ RopeSubst[old: "$ShortSpaceFileNameSelection$", new: shortSpaceFileName, base: def, case: TRUE]; def ¬ RopeSubst[old: "$QuotedFileNameSelection$", new: quotedFileName, base: def, case: TRUE]; def ¬ RopeSubst[old: "$ShortQuotedFileNameSelection$", new: shortQuotedFileName, base: def, case: TRUE]; def ¬ RopeSubst[old: "$SelectedViewerName$", new: viewerName, base: def, case: TRUE]; def ¬ RopeSubst[old: "$ViewerPosition$", new: Convert.RopeFromInt[index, 10, FALSE], base: def, case: TRUE]; def ¬ RopeSubst[old: "$MouseButton$", new: buttonRope, base: def, case: TRUE]; def ¬ RopeSubst[old: "$ControlKey$", new: controlRope, base: def, case: TRUE]; def ¬ RopeSubst[old: "$ShiftKey$", new: shiftRope, base: def, case: TRUE]; }; RETURN [def]; }; RopeSubst: PROC [old, new, base: ROPE, case: BOOL ¬ FALSE, allOccurrences: BOOL ¬ TRUE] RETURNS [ROPE] = { lenOld: INT = old.Length[]; lenNew: INT = new.Length[]; i: INT ¬ 0; WHILE (i ¬ Rope.Find[s1: base, s2: old, case: case, pos1: i]) # -1 DO base ¬ Rope.Replace[base: base, start: i, len: lenOld, with: new]; IF ~allOccurrences THEN EXIT; i ¬ i + lenNew; ENDLOOP; RETURN[base]; }; GetShortName: PROC [path: ROPE] RETURNS [ROPE] = { len: INT ¬ Rope.Length[path]; bang: INT ¬ len; pos: INT ¬ len; WHILE pos # 0 DO np: INT ¬ pos - 1; c: CHAR ¬ Rope.Fetch[path, np]; SELECT c FROM '! => bang ¬ np; '>, '], '/ => RETURN [Rope.Substr[path, pos, bang-pos]]; ENDCASE; pos ¬ np; ENDLOOP; RETURN [Rope.Substr[path, 0, bang]]; }; GetBaseName: PROC [shortName: ROPE] RETURNS [ROPE] = { dotPos: INT ¬ Rope.Find[shortName, "."]; IF dotPos<0 THEN RETURN [shortName] ELSE RETURN [Rope.Substr[shortName, 0, dotPos]] }; Commander.Register["DestroyTopButton", DestroyButtonImpl, "Destroy all top buttons whose name match the argument (*'s permitted, case-sensitive)"]; Commander.Register["ReplaceTopButton", ReplaceButtonImpl, "Replace the command strings of those top buttons whose name match the argument"]; Commander.Register["TopButton", TopButton, "Install a new top-of-screen button. Prototype: TopButton buttonname command substitutions are: $CurrentSelection$ => replaced by the current selection up to but not including the first carriage return $CurrentEscapedSelection$ => replaced by a rope literal (minus the surrounding quotes) for the entire current selection $CurrentSpacedSelection$ => replaced by the whole current selection, with spaces substituted for newlines $FileNameSelection$ => replaced by the current selection if it appears to be a file name, otherwise replaced by the name of the selected viewer $ShortFileNameSelection$ => same as $FileNameSelection$ except that version number and directory are omitted $BaseFileNameSelection$ => same as $ShortFileNameSelection$ except that extensions are ommited $SpaceFileNameSelection$ => replaced by the current selection if it appears to be a file name (may include white space), otherwise replaced by the name of the selected viewer $ShortSpaceFileNameSelection$ => same as $SpaceFileNameSelection$ except that version number and directory are omitted $QuotedFileNameSelection$ => replaced by the current selection if it appears to be a file name (may include white space), otherwise replaced by the name of the selected viewer. The results will have double quotes around it. $ShortQuotedFileNameSelection$ => same as $QuotedFileNameSelection$ except that version number and directory are omitted. $SelectedViewerName$ => replaced by the name of the selected viewer $ViewerPosition$ => replaced by the position of the current selection in a viewer $MouseButton$ => left|middle|right $ShiftKey$ => shift|noShift $ControlKey$ control|noControl "]; END. P TopButton.mesa Copyright Σ 1986, 1990, 1992 by Xerox Corporation. All rights reserved. Bloomenthal, November 21, 1990 0:32 am PST Brent Welch December 12, 1990 12:56 pm PST Weiser, August 29, 1993 10:51 pm PDT [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] [mimics ViewerClasses.ClickProc, but with different return value] Get prefix of current selection before the first CR The curSel is the fileName if curSel is longer than one character and contains no whitespace. The curSel is the spaceFileName if curSel is longer than one character. Add quotes for the quoted version. It is likely that we have substitutions to do if old is not found in base, then value = base. if allOccurrences THEN substitute for each occurrence of old, otherwise only for first. Κp–(cedarcode) style•NewlineDelimiter ™šΟn œ™Icodešœ Οeœ=™HK™*K™*K™$K™—šΟk œ2Ÿœ>˜{K˜—K˜š œŸ ˜KšŸœ,Ÿœœ%˜b—K˜KšœŸ˜˜KšŸœŸœŸœ˜—˜KšΟb œŸœŸœ˜+š œŸœŸœ˜!KšœŸœ˜ KšœŸŸ˜ KšœŸ˜K˜K˜—šœŸœŸœ˜.K˜—šœ œŸœŸœŸœ˜+K˜—š œ˜$Kš œŸœŸœŸœŸœ˜'Kšœ˜K˜KšœŸœ˜-KšœŸœ ˜KšœŸœ0˜8Kšœ œOŸœœ˜_K˜/K˜KšœŸœ˜(—K˜—˜šœ˜+Iropeš œŸŸŸŸœDŸœœ˜YK˜=Kšœ˜K˜—šœŸœ Ÿœ!˜Dš Ÿœ ŸœŸœ,ŸœŸœŸ˜RKšŸœ(ŸœŸœ˜PKšŸœ˜—K˜K˜—šœœ˜,Kš œŸœŸœŸœŸœ˜'Kšœœ Ÿœ˜0Kšœ ŸœŸœ˜KšœCŸœ˜JK˜"šŸœŸœ Ÿœ˜Kš œŸœŸœ0Ÿœœœœœœœ˜PK˜=—K˜—K˜K˜š œ˜,Kš œŸœŸœŸœŸœ˜'Kšœœ Ÿœ˜-KšœŸœ ˜Kšœ ŸœŸœ˜˜Kšœ Ÿœ˜K˜—K˜˜šŸœŸœ Ÿœ˜Kš œŸœŸœ0Ÿœœœ˜MK˜=—K˜—K˜K˜—š œ˜"KšΠck~™~šŸœ ŸœŸ˜šœ˜KšœŸœ ˜Lš œŸŸŸŸœoŸœœ˜„K˜=K˜—KšŸœ˜—K˜—K˜šœŸœ'ŸœŸœAŸœŸœŸœŸœ˜°š‘œ‘"™AKšœŸœ˜KšœŸœ˜#Kšœ˜Kšœ ŸœŸœ˜Kšœ ŸœŸœ˜KšœŸœŸœ˜KšœŸœŸœ˜KšœŸœŸœ˜KšœŸœŸœ˜KšœŸœŸœ˜KšœŸœŸœ˜ KšœŸœ˜Kš œ ŸœŸœ Ÿœ Ÿœ ˜?Kš œ ŸœŸœŸœ Ÿœ ˜7Kšœ Ÿœ˜šŸœ Ÿ˜K˜K˜ K˜KšŸœŸœ˜—K˜KšŸœ ŸœŸœŸœ˜K˜ K˜@K˜,šŸœ ŸœŸœŸœŸœŸœŸœ˜FK˜/KšœŸœFŸœ˜WK˜K˜KšŸœŸœŸœ˜2K˜K•StartOfExpansion)[s: ROPE, pos: INT _ 0, skip: ROPE]˜CK˜—K˜Kšœ4Ÿœ˜;K˜6K™3K˜JK™]Kš œ ŸœAŸœŸœŸœ ˜‚K˜'K˜*šœG™GKšœŸœŸœŸœ ˜CK˜1—™"K˜5K˜?—K˜šŸœ-Ÿœ˜5Kšœ-™-KšœIŸœ˜OKšœQŸœ˜WKšœOŸœ˜UKšœLŸœ˜RKšœVŸœ˜\KšœTŸœ˜ZKšœVŸœ˜\Kšœ`Ÿœ˜fKšœXŸœ˜^KšœbŸœ˜hKšœOŸœ˜UKšœMŸœŸœ˜lKšœHŸœ˜NKšœHŸœ˜NKšœDŸœ˜JKšœ˜K˜—KšŸœ˜ —K˜K˜—š œŸœŸœŸœŸœŸœŸœŸœŸœ˜jšœ/™/KšœW™W—KšœŸœ˜KšœŸœ˜KšœŸœ˜ šŸœ>Ÿ˜EK˜BKšŸœŸœŸœ˜K˜KšŸœ˜—KšŸœ˜ K˜K˜—š  œŸœŸœŸœŸœ˜2KšœŸœ˜KšœŸœ˜KšœŸœ˜šŸœ Ÿ˜KšœŸœ ˜KšœŸœ˜šŸœŸ˜ K˜KšœŸœ$˜8KšŸœ˜—K˜ KšŸœ˜—KšŸœ˜$Kšœ˜K˜—š  œŸœ ŸœŸœŸœ˜6KšœŸœ˜(šŸœ ˜ KšŸœŸœ ˜KšŸœŸœ%˜0—Kšœ˜K˜—˜“K˜—K˜ŒK˜Kšœη ˜η —K˜KšŸœ˜—…—#..ξ