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
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 => {
Execute all the commands found within the selection
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 {
end of typescript, backup to before %
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.
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