FileViewerOpsImpl.mesa
Copyright © 1984, 1985, 1986 by Xerox Corporation. All rights reserved.
Bob Hagmann February 6, 1985 8:20:38 am PST
Russ Atkinson (RRA) March 11, 1986 2:57:59 pm PST
DIRECTORY
FileViewerOps USING [],
FS USING [Error, ExpandName, FileInfo],
Icons USING [IconFlavor, NewIconFromFile],
IO USING [PutF1, PutRope, ROS, STREAM],
Menus USING [AppendMenuEntry, ClickProc, CreateEntry, FindEntry, MenuEntry, ReplaceMenuEntry],
MessageWindow USING [Append],
Process USING [CheckForAbort, Pause, SecondsToTicks],
Rope USING [Cat, Concat, Fetch, Find, Length, Replace, ROPE, Run],
TiogaMenuOps USING [DefaultMenus, Open],
ViewerClasses USING [Viewer],
ViewerOps USING [BlinkIcon, CreateViewer, DestroyViewer, EnumerateViewers, EnumProc, FindViewer, OpenIcon, PaintViewer];
FileViewerOpsImpl: CEDAR PROGRAM
IMPORTS FS, Icons, IO, Menus, MessageWindow, Process, Rope, TiogaMenuOps, ViewerOps
EXPORTS FileViewerOps = BEGIN
Viewer: TYPE = ViewerClasses.Viewer;
ViewerSaveStatus: TYPE = {none, old, new, saving};
ShowLog: PUBLIC PROC [fileName: Rope.ROPE, destroyIt: BOOLFALSE, createIconic: BOOLFALSE, blinkIfIconic: BOOLTRUE] = {
logViewer: ViewerClasses.Viewer ← FindFileViewer[fileName];
IF destroyIt
THEN {IF logViewer # NIL THEN ViewerOps.DestroyViewer[logViewer]}
ELSE {
IF logViewer = NIL THEN {
icon: Icons.IconFlavor;
SELECT TRUE FROM
Rope.Find[fileName, ".errlog", 0, FALSE] # -1 => icon ← typescript;
Rope.Find[fileName, ".log", 0, FALSE] # -1 => icon ← typescript;
Rope.Find[fileName, ".mesa", 0, FALSE] # -1 => icon ← needsToBeCompiled;
ENDCASE => icon ← document;
logViewer ← CreateLog[fileName, icon, createIconic]};
IF logViewer # NIL AND logViewer.iconic AND blinkIfIconic THEN ViewerOps.BlinkIcon[logViewer]};
};
WaitUntilSaved: PUBLIC PROC [fileName: Rope.ROPE, feedBack: IO.STREAMNIL] = {
lastState: ViewerSaveStatus ← none;
fileNameLen: INT ← Rope.Length[fileName ← FS.ExpandName[fileName].fullFName];
IF feedBack = NIL THEN feedBack ← IO.ROS[];
DO
state: ViewerSaveStatus ← none;
vName: Rope.ROPENIL;
innerCheck: ViewerOps.EnumProc = {
[v: ViewerClasses.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.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.ROPE] = {
errlogName: Rope.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 ← ViewerOps.FindViewer[errlogName]) # NIL DO
ViewerOps.DestroyViewer[errlog];
ENDLOOP;
};
AppendMenuEntry: PROC [viewer: Viewer, name: Rope.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.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 = {
log: Viewer;
viewer: Viewer = NARROW[parent];
name: Rope.ROPE = ErrorLogName[viewer.name];
log ← ViewerOps.FindViewer[name];
IF log = NIL
THEN log ← CreateLog[name, typescript, FALSE]
ELSE IF log.iconic
THEN ViewerOps.OpenIcon[log]
ELSE ViewerOps.PaintViewer[log, client];
};
ErrorLogName: PROC [file: Rope.ROPE] RETURNS [errlog: Rope.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.ROPE] RETURNS [viewer: Viewer] = {
FindViewer: ViewerOps.EnumProc = {
IF Rope.Find[v.file, file, 0, FALSE] = 0
THEN {viewer ← v; RETURN [FALSE]}
ELSE RETURN [TRUE];
};
ViewerOps.EnumerateViewers[FindViewer];
};
CreateLog: PROC [fileName: Rope.ROPE, icon: Icons.IconFlavor, iconic: BOOL] RETURNS [viewer: ViewerClasses.Viewer] = {
IF ~FileExists[fileName] THEN {
MessageWindow.Append[Rope.Cat[fileName, " does not exist."], TRUE];
RETURN;
};
IF iconic
THEN {
viewer ← ViewerOps.CreateViewer[flavor: $Text, info: [name: fileName, file: fileName, iconic: iconic, icon: icon]];
IF viewer # NIL THEN TiogaMenuOps.DefaultMenus[viewer];
}
ELSE {
viewer ← TiogaMenuOps.Open[fileName];
IF viewer # NIL THEN viewer.icon ← icon;
};
};
FileExists: PROC [fileName: Rope.ROPE] RETURNS [BOOL] = {
bytes: INT ← -1;
[bytes: bytes] ← FS.FileInfo[fileName ! FS.Error => CONTINUE];
RETURN [bytes >= 0];
};
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: ViewerClasses.Viewer] RETURNS [ViewerSaveStatus] = {
IF viewer # NIL AND NOT viewer.destroyed THEN {
v: ViewerClasses.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];
};
needsToBeCompiled: Icons.IconFlavor ← document;
needsToBeCompiled ← Icons.NewIconFromFile["///UserExec.icons", 9 ! FS.Error => CONTINUE];
END.