FileViewerOpsImpl.mesa
Copyright Ó 1984, 1985, 1986, 1987, 1991 by Xerox Corporation. All rights reserved.
Bob Hagmann February 6, 1985 8:20:38 am PST
Russ Atkinson (RRA) March 10, 1987 10:39:35 am PST
Last tweaked by Mike Spreitzer on February 16, 1988 8:57:02 am PST
David Goldberg April 27, 1989 6:48:23 pm PDT
Theimer, March 13, 1990 10:28 pm PST
Michael Plass, September 30, 1991 4:29 pm PDT
Willie-s, October 31, 1991 1:00 pm PST
DIRECTORY
FileViewerOps USING [],
FileViewerOpsBackdoor,
FS,
Icons,
IO USING [PutF1, PutRope, ROS, STREAM],
Menus USING [AppendMenuEntry, ClickProc, CreateEntry, FindEntry, MenuEntry, MouseButton, ReplaceMenuEntry],
MessageWindow USING [Append],
PFS,
PFSCanonicalNames,
Process USING [CheckForAbort, Pause, SecondsToTicks],
RefTab USING [Fetch, Create, Delete, Ref, Store],
Rope USING [Concat, Equal, Fetch, Find, Index, Length, Replace, ROPE, Run, Substr],
TiogaMenuOps USING [DefaultMenus, Load, Open],
ViewerClasses USING [Viewer],
ViewerOps USING [BlinkIcon, CreateViewer, DestroyViewer, EnumerateViewers, EnumProc, OpenIcon, PaintViewer];
FileViewerOpsImpl: CEDAR PROGRAM
IMPORTS IO, Menus, MessageWindow, PFSCanonicalNames, PFS, Process, RefTab, Rope, TiogaMenuOps, ViewerOps
EXPORTS FileViewerOps, FileViewerOpsBackdoor
= BEGIN OPEN FileViewerOpsBackdoor;
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
Viewer: TYPE = ViewerClasses.Viewer;
ViewerSaveStatus: TYPE = {none, old, new, saving};
ShowLog: PUBLIC PROC [fileName: ROPE, destroyIt: BOOL ¬ FALSE, createIconic: BOOL ¬ FALSE, blinkIfIconic: BOOL ¬ TRUE] = {
logViewer: Viewer ¬ FindFileViewer[StripVersion[fileName]];
A fresh compile occured, so remove viewer and all its splits from table
FOR v: Viewer ¬ logViewer, v.link UNTIL v = NIL DO
[] ¬ RefTab.Delete[viewerTable, v];
IF v.link = logViewer THEN EXIT;
ENDLOOP;
IF destroyIt
THEN {IF logViewer # NIL THEN ViewerOps.DestroyViewer[logViewer]}
ELSE {
icon: Icons.IconFlavor ~ SELECT TRUE FROM
Rope.Find[fileName, ".errlog", 0, FALSE] # -1 => typescript,
Rope.Find[fileName, ".log", 0, FALSE] # -1 => typescript,
Rope.Find[fileName, ".mesa", 0, FALSE] # -1 => needsToBeCompiled,
ENDCASE => document;
IF logViewer = NIL
THEN logViewer ¬ CreateLog[fileName, icon, createIconic]
ELSE logViewer ¬ SetContents[logViewer, fileName, icon, createIconic];
IF logViewer # NIL AND logViewer.iconic AND blinkIfIconic THEN ViewerOps.BlinkIcon[logViewer]};
};
StripVersion: PROC [fileName: ROPE] RETURNS [ROPE] ~ {
RETURN Rope.Substr[base: fileName, start: 0, len: fileName.Index[s2: "!"]]};
WaitUntilSaved: PUBLIC PROC [fileName: ROPE, feedBack: STREAM ¬ NIL] = {
lastState: ViewerSaveStatus ¬ none;
fileNameLen: INT ¬ Rope.Length[fileName ¬ ExpandName[fileName]];
IF feedBack = NIL THEN feedBack ¬ IO.ROS[];
DO
state: ViewerSaveStatus ¬ none;
vName: ROPE ¬ NIL;
innerCheck: ViewerOps.EnumProc = {
[v: Viewer] RETURNS [BOOL ← TRUE]
IF Rope.Run[fileName, 0, v.file, 0, FALSE] # fileNameLen THEN RETURN;
vName ¬ v.file;
state ¬ CheckViewer[v];
SELECT state FROM
new, saving => {vName ¬ v.file; RETURN [FALSE]};
ENDCASE => RETURN [TRUE];
};
Process.CheckForAbort[];
state ¬ none;
vName ¬ NIL;
ViewerOps.EnumerateViewers[innerCheck];
IF lastState # none AND state # lastState THEN IO.PutRope[feedBack, "\n"];
SELECT state FROM
none => RETURN;
lastState => {};
new => IO.PutF1[feedBack, "** Please save %g ...", [rope[vName]] ];
saving => IO.PutF1[feedBack, "** Saving %g ...", [rope[vName]] ];
ENDCASE => RETURN;
Process.CheckForAbort[! ABORTED => IO.PutRope[feedBack, "\n"]];
lastState ¬ state;
Process.Pause[Process.SecondsToTicks[1]];
ENDLOOP;
};
AttachErrorLog: PUBLIC PROC [sourceFileName: ROPE] = {
viewer: Viewer ¬ FindFileViewer[sourceFileName];
IF viewer # NIL THEN {
AppendMenuEntry[viewer, "ErrorLog", OpenErrorLog];
SetIcon[viewer: viewer, from: document, to: needsToBeCompiled]};
};
RemoveErrorLog: PUBLIC PROC [sourceFileName: ROPE] = {
errlogName: ROPE;
errlog: Viewer;
viewer: Viewer ¬ FindFileViewer[sourceFileName];
IF viewer # NIL THEN {
RemoveMenuEntry[viewer, "ErrorLog"];
SetIcon[viewer: viewer, from: needsToBeCompiled, to: document];
};
errlogName ¬ ErrorLogName[sourceFileName];
WHILE (errlog ¬ FindFileViewer[errlogName]) # NIL DO
ViewerOps.DestroyViewer[errlog];
ENDLOOP;
};
AppendMenuEntry: PROC [viewer: Viewer, name: ROPE, proc: Menus.ClickProc] = {
FOR v: Viewer ¬ viewer, v.link WHILE v # NIL DO
entry: Menus.MenuEntry ¬ Menus.FindEntry[v.menu, name];
IF entry = NIL THEN {
entry ¬ Menus.CreateEntry[name: name, proc: proc, fork: FALSE];
Menus.AppendMenuEntry[menu: v.menu, line: 0, entry: entry];
IF NOT v.iconic THEN ViewerOps.PaintViewer[v, menu];
};
IF v.link = viewer THEN EXIT;
ENDLOOP;
};
RemoveMenuEntry: PROC [viewer: Viewer, name: ROPE] = {
FOR v: Viewer ¬ viewer, v.link WHILE v # NIL DO
entry: Menus.MenuEntry ¬ Menus.FindEntry[v.menu, name];
IF entry # NIL THEN {
Menus.ReplaceMenuEntry[v.menu, entry]; -- deletes it
IF NOT v.iconic THEN ViewerOps.PaintViewer[v, menu];
};
IF v.link = viewer THEN EXIT;
ENDLOOP;
};
OpenErrorLog: Menus.ClickProc = {
PROC[parent: ViewerClasses.Viewer, clientData: REF ANY ← NIL, mouseButton: ViewerClasses.MouseButton ← red, shift: BOOL ← FALSE, control: BOOL ← FALSE]
log: Viewer;
procList: LIST OF ProcListItem;
viewer: Viewer = NARROW[parent];
name: ROPE = ErrorLogName[viewer.name];
repeat: BOOLEAN;
log ¬ FindFileViewer[name];
IF log = NIL
THEN log ¬ CreateLog[name, typescript, FALSE]
ELSE IF log.iconic
THEN ViewerOps.OpenIcon[log]
ELSE {
FOR v: ViewerClasses.Viewer ¬ parent, v.link UNTIL v = NIL DO
[found: repeat] ¬ RefTab.Fetch[viewerTable, v];
IF repeat OR v.link = parent THEN EXIT;
ENDLOOP;
procList ¬ GetProcList[];
FOR left: LIST OF ProcListItem ¬ procList, left.rest UNTIL left =NIL DO
left.first.proc[log, repeat, left.first.data, parent, mouseButton, shift, control];
ENDLOOP;
[] ¬ RefTab.Store[viewerTable, parent, parent];
}
};
RegisterErrorLogProc: PUBLIC PROC[proc: ErrorLogProc, clientData: REF ANY] = {
item: ProcListItem;
item ¬ NEW[ProcListItemRec];
item.proc ¬ proc;
item.data ¬ clientData;
procList ¬ CONS[item, procList];
};
UnregisterErrorLogProc: PUBLIC PROC[proc: ErrorLogProc] = {
prev: LIST OF ProcListItem;
IF procList.first.proc = proc THEN
procList ¬ procList.rest
ELSE {
prev ¬ procList;
FOR left: LIST OF ProcListItem ¬ procList.rest, left.rest UNTIL left = NIL DO
IF left.first.proc = proc THEN {
prev.rest ¬ left.rest;
EXIT;
};
prev ¬ prev.rest;
ENDLOOP;
};
};
GetProcList: PUBLIC PROC RETURNS [LIST OF ProcListItem] = {RETURN [procList];};
ErrorLogName: PROC [file: ROPE] RETURNS [errlog: ROPE] = {
pos: INT ¬ Rope.Length[file];
WHILE (pos ¬ pos - 1) > 0 DO
SELECT Rope.Fetch[file, pos] FROM
'. => RETURN [Rope.Replace[base: file, start: pos+1, with: "errlog"]];
'>, '], '/ => EXIT;
ENDCASE;
ENDLOOP;
RETURN [Rope.Concat[file, ".errlog"]];
};
FindFileViewer: PROC [file: ROPE] RETURNS [viewer: Viewer] = {
FindViewer: ViewerOps.EnumProc = {
IF v.class # NIL AND v.class.flavor = $Text AND Rope.Run[s1: v.file, s2: file, case: FALSE] = file.Length THEN {
viewer ¬ v;
RETURN [FALSE];
};
RETURN [TRUE];
};
file ¬ ExpandName[file];
ViewerOps.EnumerateViewers[FindViewer];
RETURN};
CreateLog: PROC [fileName: ROPE, icon: Icons.IconFlavor, iconic: BOOL]
RETURNS [viewer: Viewer] = {
fullFName: ROPE ~ ResolveName[fileName];
IF fullFName=NIL THEN {
MessageWindow.Append[Rope.Concat[fileName, " does not exist."], TRUE];
RETURN;
};
IF iconic
THEN {
viewer ¬ ViewerOps.CreateViewer[flavor: $Text, info: [name: fullFName, file: fullFName, iconic: iconic, icon: icon]];
IF viewer # NIL THEN TiogaMenuOps.DefaultMenus[viewer];
}
ELSE {
viewer ¬ TiogaMenuOps.Open[fileName];
IF viewer # NIL THEN viewer.icon ¬ icon;
};
};
SetContents: PROC [viewer: Viewer, fileName: ROPE, icon: Icons.IconFlavor, iconic: BOOL]
RETURNS [Viewer] = {
fullFName: ROPE ~ ResolveName[fileName];
IF fullFName=NIL THEN {
MessageWindow.Append[Rope.Concat[fileName, " does not exist."], TRUE];
ViewerOps.DestroyViewer[viewer];
RETURN [NIL];
};
IF Rope.Equal[fullFName, viewer.file, FALSE] THEN RETURN [viewer];
IF iconic AND viewer.iconic
THEN {
ViewerOps.DestroyViewer[viewer: viewer];
viewer ¬ ViewerOps.CreateViewer[flavor: $Text, info: [name: fullFName, file: fullFName, iconic: iconic, icon: icon]];
IF viewer # NIL THEN TiogaMenuOps.DefaultMenus[viewer];
RETURN [viewer];
}
ELSE {
TiogaMenuOps.Load[viewer, IF iconic THEN fullFName ELSE fileName];
RETURN [viewer];
};
};
ResolveName: PROC [fileName: ROPE] RETURNS [fullFName: ROPE --NIL if file doesn't exist; otherwise has version--] ~ {
bytes: INT ¬ -1;
fullFNamePath: PFS.PATH;
[fullFName: fullFNamePath, bytes: bytes] ¬ PFS.FileInfo[PFSCanonicalNames.ParseName[fileName] ! PFS.Error => CONTINUE];
RETURN [IF bytes >= 0 THEN PFSCanonicalNames.UnparseName[fullFNamePath] ELSE NIL];
};
ExpandName: PROC [fileName: ROPE] RETURNS [fullFileName: ROPE] =
BEGIN
RETURN [PFSCanonicalNames.UnparseName[PFS.AbsoluteName[PFSCanonicalNames.ParseName[fileName]]]];
END;
SetIcon: PROC [viewer: Viewer, from, to: Icons.IconFlavor] = {
IF to = unInit THEN RETURN;
FOR v: Viewer ¬ viewer, v.link WHILE v # NIL DO
IF from = unInit OR v.icon = from THEN IF v.icon # to THEN {
v.icon ¬ to;
IF v.iconic THEN ViewerOps.PaintViewer[v, all];
};
IF v.link = viewer THEN EXIT;
ENDLOOP;
};
CheckViewer: PROC [viewer: Viewer] RETURNS [ViewerSaveStatus] = {
IF viewer # NIL AND NOT viewer.destroyed THEN {
v: Viewer ¬ viewer;
IF viewer.saveInProgress THEN RETURN [saving];
WHILE (v ¬ v.link) # NIL AND (v # viewer) DO
IF v.saveInProgress THEN RETURN [saving];
ENDLOOP;
IF viewer.newVersion THEN RETURN [new];
RETURN [old];
};
RETURN [none];
};
procList: LIST OF ProcListItem;
viewerTable: RefTab.Ref;
needsToBeCompiled: Icons.IconFlavor ¬ document;
{
icon: Icons.IconFlavor;
viewerTable ¬ RefTab.Create[];
procList ¬ NIL;
icon ← Icons.NewIconFromFile["InterpreterTool.icons", 6
! FS.Error => GO TO noGood];
IF icon # unInit THEN needsToBeCompiled ← icon;
EXITS noGood => {};
};
END.