DIRECTORY Commander USING [CommandProc, Handle, Register], CommanderBackdoor USING [AdamOrEve], EditedStream USING [UnAppendBufferChars], IO USING [STREAM], Menus USING [AppendMenuEntry, CreateEntry, FindEntry, MenuEntry, MenuProc, ReplaceMenuEntry], Rope USING [Fetch, Find, ROPE, Substr], TiogaOps USING [GetRope, GetSelection, Location], UserProfile USING [CallWhenProfileChanges, ProfileChangedProc, Token], ViewerClasses USING [Viewer], ViewerIO USING [GetBuffer, GetViewerFromStream], ViewerOps USING [BlinkDisplay, EnumerateViewers, EnumProc, PaintViewer], ViewerTools USING [SetSelection]; RedoButtonImpl: CEDAR PROGRAM IMPORTS Commander, CommanderBackdoor, EditedStream, Menus, Rope, TiogaOps, UserProfile, ViewerIO, ViewerOps, ViewerTools = BEGIN ROPE: TYPE = Rope.ROPE; RopeList: TYPE = LIST OF ROPE; redoButtonName: ROPE; LineTerminatorChar: CHAR = 12C; NoteProfile: UserProfile.ProfileChangedProc= { redoButtonName ¬ UserProfile.Token["RedoButton.RedoButtonName", "Redo"]; }; Blink: PROC = {ViewerOps.BlinkDisplay[]}; Redo: Menus.MenuProc = { ScanAndStuff: PROC = { exec: ViewerClasses.Viewer ~ NARROW[parent]; cmdList, cmdListTail: LIST OF REF ANY ¬ NIL; SELECT mouseButton FROM red, yellow => { tsRope: ROPE; start, end: INT; startLoc, endLoc: TiogaOps.Location; selectionViewer: ViewerClasses.Viewer; [selectionViewer, startLoc, endLoc, , , ] ¬ TiogaOps.GetSelection[]; IF NOT selectionViewer = exec THEN { --force selection into command window ViewerTools.SetSelection[exec, NIL]; [selectionViewer, startLoc, endLoc, , , ] ¬ TiogaOps.GetSelection[]; }; tsRope ¬ TiogaOps.GetRope[startLoc.node]; start ¬ startLoc.where; IF Rope.Find[tsRope, "%", start] = -1 THEN { start ¬ start-1; WHILE Rope.Fetch[tsRope, start]#'% DO start ¬ start-1; ENDLOOP; start ¬ start-1; }; WHILE Rope.Fetch[tsRope, start]#'% DO start ¬ start-1; ENDLOOP; --back up to "%" preceeding command of interest WHILE start+2 < endLoc.where DO rope: ROPE; end ¬ start ¬ start+2; WHILE Rope.Fetch[tsRope, end]#LineTerminatorChar DO end ¬ end+1; ENDLOOP; --forward to CR rope ¬ Rope.Substr[tsRope, start, end-start+1]; IF cmdListTail = NIL THEN cmdList ¬ cmdListTail ¬ LIST[rope] ELSE cmdListTail ¬ cmdListTail.rest ¬ LIST[rope]; start ¬ end; WHILE Rope.Fetch[tsRope, start]#'% DO start ¬ start+1; ENDLOOP; ENDLOOP; }; blue => { cmdList ¬ LIST["History -d 10\n"]; }; ENDCASE => ERROR; ViewerTools.SetSelection[exec, NIL]; BackupToPrompt[cmd]; exec.class.notify[exec, cmdList]; }; cmd: Commander.Handle ~ NARROW[clientData]; ScanAndStuff[! ANY => {Blink[]; CONTINUE}]; }; Greet: PROC [v: ViewerClasses.Viewer, cmd: Commander.Handle, paint: BOOL] = { Add: PROC [me: Menus.MenuEntry, name: ROPE] = { old: Menus.MenuEntry = Menus.FindEntry[v.menu, name]; IF old = NIL THEN Menus.AppendMenuEntry[v.menu, me] ELSE Menus.ReplaceMenuEntry[v.menu, old, me]; }; IF v = NIL THEN RETURN; Add[Menus.CreateEntry[name: redoButtonName, proc: Redo, fork: FALSE, clientData: cmd], redoButtonName]; IF paint THEN ViewerOps.PaintViewer[v, menu]; }; BackupToPrompt: PROC [cmd: Commander.Handle] ={ inStream: IO.STREAM ¬ cmd.in; bufferContents: REF TEXT ¬ ViewerIO.GetBuffer[inStream]; IF bufferContents # NIL AND bufferContents.length > 0 AND bufferContents[bufferContents.length - 1] # LineTerminatorChar THEN { FOR n: NAT DECREASING IN [0..bufferContents.length) DO IF bufferContents[n] = LineTerminatorChar THEN { EditedStream.UnAppendBufferChars[ stream: inStream, nChars: bufferContents.length - n - 1]; EXIT; } REPEAT FINISHED => EditedStream.UnAppendBufferChars[stream: inStream, nChars: LAST[NAT]]; ENDLOOP; }; }; AttachMenuItemsToExecs: PROC = { PerViewer: ViewerOps.EnumProc = { Greet[v, NIL, TRUE]; }; ViewerOps.EnumerateViewers[PerViewer]; }; RedoButtonCmd: Commander.CommandProc ~ { ancestorCmdHandle: Commander.Handle ¬ CommanderBackdoor.AdamOrEve[cmd]; WITH ViewerIO.GetViewerFromStream[ancestorCmdHandle.err] SELECT FROM viewer: ViewerClasses.Viewer => Greet[viewer, ancestorCmdHandle, TRUE]; ENDCASE => RETURN [$Failure, "Can't find CommanderViewer for Redo button"]; }; UserProfile.CallWhenProfileChanges[NoteProfile]; Commander.Register[key: "RedoButton", proc: RedoButtonCmd, doc: "Registers CommanderViewer menu button for redoing the last command."]; END. t RedoButtonImpl.mesa Copyright Σ 1985, 1986, 1987, 1992 by Xerox Corporation. All rights reserved. McGregor on August 17, 1983 5:09 pm Michael Plass on March 12, 1985 12:53:14 pm PST Tim Diebert: May 7, 1992 12:02 pm PDT Michael Plass, January 22, 1987 8:20:01 am PST Last Edited by: Gasbarro March 11, 1986 11:30:15 am PST Last tweaked by Mike Spreitzer on August 18, 1988 12:44:16 pm PDT Mike Spreitzer, March 5, 1987 10:19:12 am PST Eric Nickell, October 22, 1987 8:36:01 am PDT Bertrand Serlet August 31, 1986 9:35:24 pm PDT Rick Beach, January 2, 1987 3:16:07 pm PST Theimer, March 29, 1990 2:02 pm PST Execute all the commands found within the selection end of typescript, backup to before % CHANGE LOG Rick Beach, June 14, 1986 3:03:45 pm PDT cosmetic changes to procedure types and names. changes to: RedoCmd added capability to execute all commands within selection ΚI–(cedarcode) style•NewlineDelimiter ™code™Kšœ ΟeœC™NKšœ#™#K™/K™%K™.K™7K™AK™-K™-K™.K™*K™#K™—šΟk ˜ Kšœ žœ!˜0Kšœžœ ˜$Kšœ žœ˜)Kšžœžœžœ˜KšœžœR˜]Kšœžœžœ ˜'Kšœ žœ#˜1Kšœ žœ5˜FKšœžœ ˜Kšœ žœ"˜0Kšœ žœ9˜HKšœ žœ˜!—K˜KšΠlnœžœž˜Kšžœq˜xšœž˜K˜Kšžœžœžœ˜Kš œ žœžœžœžœ˜K˜Kšœžœ˜K˜Kšœžœ˜K˜šΟn œ#˜.K˜HK˜—K˜š œžœ˜)K˜—š œ˜š  œžœ˜Kšœžœ ˜,Kš œžœžœžœžœžœ˜,šžœ ž˜˜Kšœ3™3Kšœžœ˜ Kšœ žœ˜K˜$Kšœ&˜&K˜DšžœžœžœΟc%˜JKšœžœ˜$K˜DK˜—K˜)K˜šžœ$žœ˜,Kšœ%™%K˜Kšžœžœžœ˜?K˜K˜—Kšžœžœžœ‘/˜ošžœž˜Kšœžœ˜ K˜Kšžœ,žœœ žœ‘˜YK˜/šžœžœž˜Kšœžœ˜"—šž˜Kšœ!žœ˜,—K˜ Kšžœžœžœ˜?Kšžœ˜—K˜—˜ Kšœ žœ˜"K˜—Kšžœžœ˜—Kšœžœ˜$K˜Kšœ!˜!Kšœ˜—Kšœžœ ˜+Kšœžœžœ˜+Kšœ˜—K˜š œžœ9žœ˜Mš œžœžœ˜/Kšœ5˜5šžœž˜ Kšžœ"˜&Kšžœ)˜-—K˜—Kšžœžœžœžœ˜Kšœ>žœ$˜gKšžœžœ ˜-K˜—K˜K˜š œžœ˜/Kšœ žœžœ ˜Kšœžœžœ ˜8š žœžœžœžœ@žœ˜š žœžœž œžœž˜6šžœ(žœ˜0K˜[Kšžœ˜K˜—Kšž˜Kšžœ?žœžœ˜RKšžœ˜—K˜—K˜K˜—š œžœ˜ š  œ˜!Kšœ žœžœ˜Kšœ˜—Kšœ&˜&Kšœ˜—K˜˜(K˜Gšžœ5žœž˜DKšœAžœ˜GKšžœžœ:˜K—K˜—K˜Kšœ0˜0K˜K˜‡—K˜K˜Kšžœ˜K™Kšžœž™ ™(K™.Kšœ Οrœ:™M——…—ž[