CycleThruErrorLog.mesa
Copyright Ó 1989, 1991 by Xerox Corporation. All rights reserved.
David Goldberg April 27, 1989 1:31:01 pm PDT
Theimer, March 14, 1990 6:38 pm PST
Willie-s, June 22, 1992 6:09 pm PDT
Michael Plass, January 14, 1992 9:39 am PST
DIRECTORY
Commander,
CommanderOps,
FileViewerOps,
FileViewerOpsBackdoor,
Menus USING [MouseButton],
MessageWindow USING [Append, Blink, Clear],
NodeAddrs USING [PutTextAddr, GetTextAddr, TextAddrNotFound],
RefTab USING [Fetch, Create, Ref, Store],
Rope,
TEditSelectionOps USING [ShowGivenPositionRange],
TextNode USING [BadArgs, Location, LocWithin, Ref, LocOffset],
TiogaOps USING [FirstChild, Location, SetSelection, SelectionError, ViewerDoc],
TiogaMenuOps,
ViewerClasses USING [Viewer],
ViewerTools USING [GetContents];
CycleThruErrorLog: CEDAR PROGRAM
IMPORTS Commander, CommanderOps, FileViewerOps, FileViewerOpsBackdoor, MessageWindow, NodeAddrs, RefTab, Rope, TEditSelectionOps, TextNode, TiogaOps, TiogaMenuOps, ViewerTools
= BEGIN OPEN FileViewerOpsBackdoor;
ROPE: TYPE = Rope.ROPE;
Viewer: TYPE = ViewerClasses.Viewer;
ErrorLocRec: TYPE = RECORD[node: TextNode.Ref, uniq: REF INT, start, end: TiogaOps.Location, nxt, prev: ErrorLoc];
ErrorLoc: TYPE = REF ErrorLocRec;
ErrListRec: TYPE = RECORD[root: TextNode.Ref, headLoc, curLoc: ErrorLoc];
ErrList: TYPE = REF ErrListRec; -- ErrList is a pointer to a doubly linked list of ErrLoc's
Errlog operations
CycleThruErrorLog: ErrorLogProc = {
PROC[log: Viewer, repeat: BOOLEAN, clientData: REF ANYNIL, parent: Viewer,
mouseButton: Menus.MouseButton ← red, shift, control: BOOLFALSE];
any: REF ANY;
errList: ErrList;
found: BOOLEAN;
viewer: Viewer = NARROW[parent];
count: INT;
loc: TextNode.Location;
if viewer is split, need to check all splits
FOR v: ViewerClasses.Viewer ¬ parent, v.link UNTIL v = NIL DO
[found, any] ¬ RefTab.Fetch[viewerTable, v];
IF found OR v.link = parent THEN EXIT;
ENDLOOP;
IF ~found OR ~repeat THEN {
errList ¬ NEW[ErrListRec];
MakeErrList[errList, log, viewer];
[] ¬ RefTab.Store[viewerTable, parent, errList];
}
ELSE {
errList ¬ NARROW[any];
};
IF control THEN
IF mouseButton = red THEN {
FileViewerOps.RemoveErrorLog[viewer.file];
RETURN;
}
ELSE { -- new errlog file
errList ¬ NEW[ErrListRec];
MakeErrList[errList, log, viewer];
[] ¬ RefTab.Store[viewerTable, parent, errList];
};
WHILE TRUE DO {
ENABLE {
NodeAddrs.TextAddrNotFound, TextNode.BadArgs => {
IF mouseButton = yellow THEN {
MessageWindow.Append["Position of first error has been erased!", TRUE];
MessageWindow.Blink[];
GOTO done
}
ELSE LOOP;
};
};
IF errList = NIL OR errList.headLoc = NIL THEN RETURN;
IF mouseButton = red THEN {
IF errList.curLoc = NIL THEN errList.curLoc ¬ errList.headLoc
ELSE IF errList.curLoc.nxt # NIL THEN errList.curLoc ¬ errList.curLoc.nxt
ELSE {MessageWindow.Append["At last error", TRUE]; MessageWindow.Blink[]; RETURN;};
}
ELSE IF mouseButton = blue THEN {
IF errList.curLoc = NIL THEN errList.curLoc ¬ errList.headLoc
ELSE IF errList.curLoc.prev # NIL THEN errList.curLoc ¬ errList.curLoc.prev
ELSE {MessageWindow.Append["At first error", TRUE]; MessageWindow.Blink[]; RETURN;};
}
ELSE errList.curLoc ¬ errList.headLoc;
MessageWindow.Clear[];
[loc.node, loc.where] ¬ NodeAddrs.GetTextAddr[errList.curLoc.node, errList.curLoc.uniq];
count ¬ TextNode.LocOffset[TextNode.LocWithin[errList.root, 0, 1, TRUE], loc, 1, TRUE];
TiogaOps.SetSelection[log, errList.curLoc.start, errList.curLoc.end
! TiogaOps.SelectionError => {
MakeErrList[errList, log, viewer];
GOTO done;
} ];
TiogaMenuOps.Normalize[log];
TEditSelectionOps.ShowGivenPositionRange[
viewer: viewer,
selectionId: feedback,
posI: count, posF: count+2,
skipCommentNodes: TRUE,
pendingDelete: FALSE]
EXITS
done => RETURN;
};
RETURN;
ENDLOOP;
};
MakeErrList: PROC[errList: ErrList, log, viewer: ViewerClasses.Viewer] = {
i, prevStart: INT ¬ 0;
pos, this: INT;
vRope: ROPE;
prevloc, curloc: ErrorLoc;
loc: TextNode.Location;
root, vRopeNode: TextNode.Ref;
TiogaMenuOps.Reset[log];
vRope ¬ ViewerTools.GetContents[log];
root ¬ TiogaOps.ViewerDoc[viewer];
vRopeNode ¬ TiogaOps.FirstChild[TiogaOps.ViewerDoc[log]];
errList.root ¬ root;
errList.headLoc ¬ NIL;
DO
ch: CHAR;
this ¬ Rope.Find[vRope, "[", i];
IF this < 0 THEN EXIT;
pos ¬ 0;
i ¬ this;
DO
ch ¬ Rope.Fetch[vRope, i ¬ i + 1];
IF ch IN ['0 .. '9] THEN pos ¬ (pos *10 ) + ORD[ch] - ORD['0]
ELSE EXIT;
ENDLOOP;
IF ( ch # '] ) OR ( i = this + 1 ) THEN LOOP; -- skip []
curloc ¬ NEW[ErrorLocRec];
curloc.start ¬ [vRopeNode, this];
curloc.end ¬ [vRopeNode, i];
prevStart ¬ this;
loc ¬ TextNode.LocWithin[n: root, count: pos, break: 1, skipCommentNodes: TRUE];
IF errList.headLoc = NIL THEN { errList.headLoc ¬ curloc; prevloc ¬ NIL };
curloc.prev ¬ prevloc;
curloc.nxt ¬ NIL;
curloc.node ¬ loc.node;
curloc.uniq ¬ NEW[INT ¬ i]; -- This could be new of anything
NodeAddrs.PutTextAddr[loc.node, curloc.uniq, loc.where];
IF prevloc # NIL THEN prevloc.nxt ¬ curloc;
prevloc ¬ curloc;
ENDLOOP;
errList.curLoc ¬ NIL;
};
Commander procs
ActivateErrorLogProc: Commander.CommandProc = {
[cmd: Commander.Handle] RETURNS [result: REF ANYNIL, msg: ROPENIL]
sourceFileName: Rope.ROPE;
args: LIST OF Rope.ROPE ← CommandTool.ParseToList[cmd: cmd, switchChar: ' ].list;
args: LIST OF Rope.ROPE ¬ CommanderOps.ParseToList[cmd: cmd].list;
IF args = NIL THEN RETURN [$Failure, "Usage: ActivateErrorLog filename"];
IF args.rest # NIL THEN RETURN [$Failure, "Usage: ActivateErrorLog filename"];
sourceFileName ¬ Rope.Concat[args.first, ".mesa"];
FileViewerOps.ShowLog[sourceFileName];
FileViewerOps.AttachErrorLog[sourceFileName];
};
UnRegisterErrorLogProc: Commander.CommandProc ~
{ UnregisterErrorLogProc[CycleThruErrorLog] };
Initialization
viewerTable: RefTab.Ref; 
viewerTable ¬ RefTab.Create[];
RegisterErrorLogProc[CycleThruErrorLog, NIL];
Commander.Register[
key: "ActivateErrorLog",
proc: ActivateErrorLogProc,
doc: "Brings up a file and adds an errlog button."];
Commander.Register[
key: "ErrorLogParsers.UnRegister",
proc: UnRegisterErrorLogProc];
END.