TSViewerImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Michael Plass, April 25, 1985 1:22:42 pm PST
Rick Beach, June 3, 1985 2:11:22 pm PDT
Bob Hagmann November 22, 1985 11:53:46 am PST
DIRECTORY
Ascii USING [CR, SP, TAB],
Buttons USING [ButtonProc, Create],
Commander USING [CommandProc, Handle, Register],
CommandTool USING [DoCommand],
Containers USING [ChildXBound],
Convert USING [Error, IntFromRope, RopeFromInt],
FileNames USING [CurrentWorkingDirectory],
FS USING [ComponentPositions, Delete, EnumerateForNames, Error, ExpandName, NameProc],
Icons USING [DrawIcon, IconFlavor, NewIconFromFile],
Imager USING [DoSaveAll, MaskRectangleI, SetColor],
ImagerBackdoor USING [invert],
IO USING [CharClass, EndOf, EndOfStream, GetLineRope, GetTokenRope, IDProc, PutChar, PutRope, RIS, STREAM],
Labels USING [Create, Set],
Menus USING [CreateEntry, CreateMenu, GetNumberOfLines, InsertMenuEntry, Menu, MenuEntry, MenuProc],
PieViewers USING [Create, Set],
PressPrinter USING [Abort, CurrentProgress, CurrentState, CurrentStateMessage, Handle, IsAPressFile, ProgressProc, SendPressFile, State],
PressScreen USING [NewPressName, PressScreen, Side],
PrincOps USING [],
PrincOpsUtils USING [],
Process USING [CheckForAbort, Detach, Pause, priorityBackground, SecondsToTicks, SetPriority, Ticks],
PseudoCursors USING [Create],
Rope USING [Cat, Concat, Equal, Fetch, Find, IsEmpty, Length, ROPE, Substr],
RuntimeError USING [UNCAUGHT],
SafeStorage USING [ReclaimCollectibleObjects],
TSFormat USING [FormatOneOutputFile],
TSGlue USING [],
TSOutput USING [Handle],
TSViewer USING [RemoteOrLocalState, Tool, ToolRec],
UserCredentials USING [Get],
UserProfile USING [Boolean, Token],
ViewerClasses USING [AdjustProc, PaintProc, Viewer, ViewerClass, ViewerClassRec],
ViewerOps USING [AddProp, CreateViewer, DestroyViewer, EnumerateViewers, EnumProc, EstablishViewerPosition, FetchProp, FetchViewerClass, PaintViewer, RegisterViewerClass, SetMenu, SetOpenHeight],
ViewerPrivate USING [selectedIcon],
ViewerSpecs USING [captionHeight, iconHeight, iconWidth, menuHeight, scrollBarW, windowBorderSize],
ViewerTools USING [GetContents, GetSelectedViewer, InhibitUserEdits, MakeNewTextViewer, SetContents, SetSelection];
TSViewerImpl: CEDAR MONITOR
IMPORTS Buttons, Commander, CommandTool, Containers, Convert, FileNames, FS, Imager, ImagerBackdoor, Icons, IO, Labels, Menus, PieViewers, PressPrinter, PressScreen, Process, PseudoCursors, Rope, RuntimeError, SafeStorage, TSFormat, UserCredentials, UserProfile, ViewerOps, ViewerPrivate, ViewerSpecs, ViewerTools
EXPORTS TSViewer
= BEGIN OPEN TSViewer;
ROPE: TYPE = Rope.ROPE;
indent: INTEGER = 4;
longIndent: INTEGER = 128;
baseline: INTEGER = 16;
rightIcon: Icons.IconFlavor ← Icons.NewIconFromFile["TSetter.icons", 0];
leftIcon: Icons.IconFlavor ← Icons.NewIconFromFile["TSetter.icons", 2];
NewButton: Menus.MenuProc = {
IF mouseButton=yellow THEN ShowMessage[NARROW[clientData], doc[New]]
ELSE {
selectedViewer: ViewerClasses.Viewer ← ViewerTools.GetSelectedViewer[];
server: ROPENIL;
server ← IF selectedViewer = NIL OR selectedViewer.class.get = NIL THEN NIL
ELSE NARROW[selectedViewer.class.get[selectedViewer, $SelChars !
RuntimeError.UNCAUGHT => CONTINUE]];
IF server.Length < 2 THEN server ← NIL;
[] ← NewTool[server];
};
};
doc: REF ARRAY MenuCode OF ROPE ← InitDoc[];
MenuCode: TYPE = {New, RightScreen, Screen, LeftScreen, All, Print, Get, StopSending, Stop, Pause};
InitDoc: PROCEDURE RETURNS [d: REF ARRAY MenuCode OF ROPE] = {
d ← NEW[ARRAY MenuCode OF ROPE];
d[New] ← "New: Create a new typesetter tool for selected server.";
d[RightScreen] ← ">: Print the right side of the screen.";
d[Screen] ← "Screen: Print the whole screen.";
d[LeftScreen] ← "<: Print the left side of the screen.";
d[All] ← "All: Print all the documents in one press file.";
d[Print] ← "Print: Print the documents named above.";
d[Get] ← "Get: Add selected documents to the document queue.";
d[StopSending] ← "StopSending: Abort transmission to the printer.";
d[Stop] ← "Stop: Stop typesetting as soon as possible.";
d[Pause] ← "Pause: Stop typesetting at end of current document.";
};
NewTool: PUBLIC ENTRY PROCEDURE [server: ROPE, feedBack: IO.STREAMNIL]
RETURNS [Tool] = {
ENABLE UNWIND => NULL;
data: Tool ← NEW[ToolRec ← [stop: FALSE, feedBack: feedBack]];
curY: INTEGER ← indent/2;
NextY: PROCEDURE RETURNS [y:NAT] = {y ← curY ← curY+baseline};
container: ViewerClasses.Viewer ←
ViewerOps.CreateViewer[
flavor: $TSetter,
info: [name: IF server.Length = 0 THEN "TSetter" ELSE server,
column: right, scrollable: FALSE
],
paint: FALSE
];
menu: Menus.Menu ← Menus.CreateMenu[];
InsertMenuEntry: PROCEDURE [name: ROPE,
proc: Menus.MenuProc, fork: BOOLFALSE, row: INTEGER ← 0,
copy: BOOLFALSE, documentation: ROPENIL, guarded: BOOLFALSE] = {
menuEntry: Menus.MenuEntry ~ Menus.CreateEntry[name: name, proc: proc, clientData: data, documentation: documentation, fork: fork, guarded: guarded];
Menus.InsertMenuEntry[menu, menuEntry];
};
InsertMenuEntry[name: "New", proc: NewButton, fork: FALSE, documentation: doc[New]];
InsertMenuEntry[name: ">", proc: RightScreenButton, fork: TRUE,
documentation: doc[RightScreen]];
InsertMenuEntry[name: "Screen", proc: ScreenButton, fork: TRUE,
documentation: doc[Screen]];
InsertMenuEntry[name: "<", proc: LeftScreenButton, fork: TRUE,
documentation: doc[LeftScreen]];
InsertMenuEntry[name: "All", proc: AllButton, fork: FALSE, documentation: doc[All]];
InsertMenuEntry[name: "Print", proc: PrintButton, fork: FALSE, documentation: doc[Print]];
InsertMenuEntry[name: "Get", proc: GetSelectionButton, fork: FALSE,
documentation: doc[Get]];
InsertMenuEntry[name: "StopSending", proc: StopSendingButton, fork: FALSE, documentation: doc[StopSending]];
InsertMenuEntry[name: "Stop", proc: StopButton, fork: FALSE, documentation: doc[Stop] ];
InsertMenuEntry[name: "Pause", proc: PauseButton, fork: FALSE, documentation: doc[Pause]];
ViewerOps.SetMenu[container, menu];
data.nameButton ← Buttons.Create[
info:[name: "Documents: ", wx: indent, wy: curY, parent: container, border: FALSE],
clientData: data,
proc: NameButton,
fork: FALSE,
paint: FALSE,
documentation: "Select the document name window. The right button empties it first."
];
PlaceChild[data.nameButton, 0, 0, TRUE];
data.nameBox ← ViewerTools.MakeNewTextViewer[
info:[wx: data.nameButton.wx + data.nameButton.ww, wy: curY+1, ww: 4*72, wh: data.nameButton.wh,
parent: container, scrollable: TRUE, border: FALSE],
paint: FALSE
];
PlaceChild[data.nameBox, 0, 0, FALSE];
Containers.ChildXBound[container, data.nameBox]; -- Let the text box grow to the right
data.pie ← PieViewers.Create[parent: container, x: indent, y: NextY[]];
PlaceChild[data.pie, 1, 0, TRUE];
data.miniDisplay ← PseudoCursors.Create[parent: container, x: indent+20, y: curY];
PlaceChild[data.miniDisplay, 1, 0, TRUE];
data.messageBox ← ViewerTools.MakeNewTextViewer[
info: [wx: indent + 40, wy: curY, ww: 350, wh: 16, parent: container, scrollable: TRUE, border: TRUE],
paint: FALSE
];
PlaceChild[data.messageBox, 1, 0, FALSE];
ViewerTools.InhibitUserEdits[data.messageBox];
data.serverName ← server;
data.serverPie ← PieViewers.Create[parent: container, x: indent, y: NextY[], total: 1.0];
PlaceChild[data.serverPie, 2, 0, TRUE];
data.serverMsg ← ViewerTools.MakeNewTextViewer[
info: [wx: indent + 40, wy: curY, ww: 350, wh: 16, parent: container, scrollable: TRUE, border: TRUE],
paint: FALSE
];
PlaceChild[data.serverMsg, 2, 0, FALSE];
ViewerTools.InhibitUserEdits[data.serverMsg];
data.copiesBox ← Buttons.Create[
info:[name: "Copies: ", wx: indent, wy: NextY[], parent: container, border: FALSE],
clientData: data,
proc: CopiesButton,
fork: FALSE,
paint: FALSE,
documentation: "Set the number of copies. Gets reset to 1 after each file is sent."
];
PlaceChild[data.copiesBox, 3, 0, TRUE];
data.copiesBox ← ViewerTools.MakeNewTextViewer[
info:[wx: data.copiesBox.wx + data.copiesBox.ww, wy: curY+1, ww: 72, wh: data.nameButton.wh,
parent: container, scrollable: FALSE, border: FALSE],
paint: FALSE
];
PlaceChild[data.copiesBox, 3, 0, TRUE];
data.remoteBox ← Buttons.Create[
info:[name: "Remote or Local: ", wx: longIndent , wy: curY, parent: container, border: FALSE],
clientData: data,
proc: RemoteOrLocalButton,
fork: FALSE,
paint: FALSE
];
PlaceChild[data.remoteBox, 3, 0, TRUE];
data.remoteBox ← Labels.Create[
info:[name: "best performance", wx: data.remoteBox.wx+data.remoteBox.ww , wy: curY, parent: container, border: FALSE],
paint: FALSE
];
data.remoteState ← bestPerformance;
PlaceChild[data.remoteBox, 3, 0, TRUE];
data.tempPressLabel ← Buttons.Create[
info:[name: "Temporary Press Files: ", wx: indent , wy: NextY[], parent: container, border: FALSE],
clientData: data,
proc: TempPressButton,
fork: FALSE,
paint: FALSE
];
PlaceChild[data.tempPressLabel, 3, 1, TRUE];
data.tempPressLabel ← Labels.Create[
info:[name: "FALSE", wx: data.tempPressLabel.wx+data.tempPressLabel.ww , wy: curY, parent: container, border: FALSE],
paint: FALSE
];
PlaceChild[data.tempPressLabel, 3, 1, TRUE];
TempPress[data, UserProfile.Boolean["Hardcopy.TemporaryPressFiles"]];
Containers.ChildXBound[container, data.copiesBox];
ViewerTools.SetContents[data.copiesBox, "1"];
ViewerOps.SetOpenHeight[container, curY+indent/2+baseline];
ViewerOps.PaintViewer[container, all];
ShowMessage[data, "Ready"];
RETURN [data]
};
PositionInfoRec: TYPE = RECORD [
nVar: NAT, -- number of stretchy children above this one
nFixed: NAT, -- number of fixed-height children above this one
fixed: BOOLEAN -- true if this child is fixed in height
];
PlaceChild: PROCEDURE [viewer: ViewerClasses.Viewer, nVar, nFixed: NAT,
fixed: BOOLEANTRUE] = {
ViewerOps.AddProp[viewer, $TSViewerPositionInfo, NEW[PositionInfoRec ←
[nVar, nFixed, fixed]]];
};
SetViewerPosition: PROCEDURE [viewer: ViewerClasses.Viewer, x,y,w,h: INTEGER] = {
OPEN viewer;
vbs: INTEGER = IF border THEN ViewerSpecs.windowBorderSize ELSE 0;
wx ← x; wy ← y; ww ← w; wh ← h;
ch ← wh - (vbs+vbs) - (IF column=static OR parent#NIL THEN 0 ELSE ViewerSpecs.captionHeight);
IF menu#NIL THEN ch ← ch - (Menus.GetNumberOfLines[menu]*ViewerSpecs.menuHeight);
cx ← wx + vbs + (IF scrollable THEN ViewerSpecs.scrollBarW ELSE 0);
cy ← wy + vbs;
cw ← ww - (cx-wx) - vbs;
};
TSViewerAdjust: ViewerClasses.AdjustProc = {
varbaseline: NATMAX[baseline, (self.ch-indent-2*baseline)/3];
FOR v: ViewerClasses.Viewer ← self.child, v.sibling UNTIL v=NIL DO
WITH ViewerOps.FetchProp[v, $TSViewerPositionInfo] SELECT FROM
positionInfo: REF PositionInfoRec => {
ViewerOps.EstablishViewerPosition[viewer: v, x: v.wx,
y: varbaseline*positionInfo.nVar + baseline*positionInfo.nFixed + indent/2,
w: v.ww,
h: IF positionInfo.fixed THEN baseline ELSE varbaseline
];
};
ENDCASE => NULL;
ENDLOOP;
};
TSViewerPaint: ViewerClasses.PaintProc = {
drawIcon: PROC ~ {
Icons.DrawIcon[flavor: IF self.column = left THEN leftIcon ELSE rightIcon,
context: context, x: 0, y: 0,
label: self.name];
};
IF self.iconic THEN {
Imager.DoSaveAll[context, drawIcon];
IF ViewerPrivate.selectedIcon=self THEN {
Imager.SetColor[context, ImagerBackdoor.invert];
Imager.MaskRectangleI[context, 0, 0, ViewerSpecs.iconWidth, ViewerSpecs.iconHeight];
}
};
};
ShowMessage: PROCEDURE [tool: Tool, msg: ROPE] = {
tool.messageLog ← msg ← tool.messageLog.Cat["\n", msg];
ViewerTools.SetContents[tool.messageBox, msg];
[] ← tool.messageBox.class.scroll[tool.messageBox, thumb, 100];
};
StopButton: Menus.MenuProc = {
tool: Tool ← NARROW[clientData];
tool.selfDestruct ← FALSE;
IF mouseButton=yellow THEN ShowMessage[tool, doc[Stop]]
ELSE Stop[tool]
};
Stop: PUBLIC ENTRY PROCEDURE [tool: Tool] = {ENABLE UNWIND => NULL;
tool.stop ← TRUE;
};
PauseButton: Menus.MenuProc = {
tool: Tool ← NARROW[clientData];
tool.selfDestruct ← FALSE;
IF mouseButton=yellow THEN ShowMessage[tool, doc[Pause]]
ELSE Pause[tool]
};
Pause: PUBLIC ENTRY PROCEDURE [tool: Tool] = {ENABLE UNWIND => NULL;
tool.pause ← TRUE;
};
StopSendingButton: Menus.MenuProc = {
tool: Tool ← NARROW[clientData];
tool.selfDestruct ← FALSE;
IF mouseButton=yellow THEN ShowMessage[tool, doc[StopSending]]
ELSE StopSending[tool]
};
StopSending: PUBLIC ENTRY PROCEDURE [tool: Tool] = {ENABLE UNWIND => NULL;
tool.stopSending ← TRUE;
};
NameButton: ENTRY Buttons.ButtonProc = {ENABLE UNWIND => NULL;
tool: Tool ← NARROW[clientData];
tool.selfDestruct ← FALSE;
IF mouseButton = blue THEN ViewerTools.SetContents[tool.nameBox, ""];
ViewerTools.SetSelection[tool.nameBox];
};
Copies: PUBLIC PROCEDURE [tool: Tool, copies: NAT] = {
ViewerTools.SetContents[tool.copiesBox, Convert.RopeFromInt[copies]];
};
CopiesButton: Buttons.ButtonProc = {
tool: Tool ← NARROW[clientData];
tool.selfDestruct ← FALSE;
IF mouseButton = blue THEN ViewerTools.SetContents[tool.copiesBox, ""];
ViewerTools.SetSelection[tool.copiesBox];
};
TempPress: PUBLIC PROCEDURE [tool: Tool, temporaryPressFiles: BOOLEAN] = {
tool.tempPress ← temporaryPressFiles;
Labels.Set[tool.tempPressLabel, IF tool.tempPress THEN "TRUE" ELSE "FALSE"];
};
TempPressButton: Buttons.ButtonProc = {
tool: Tool ← NARROW[clientData];
tool.tempPress ← NOT tool.tempPress;
tool.selfDestruct ← FALSE;
Labels.Set[tool.tempPressLabel, IF tool.tempPress THEN "TRUE" ELSE "FALSE"];
};
RemoteOrLocalButton: Buttons.ButtonProc = {
tool: Tool ← NARROW[clientData];
currentOption: ROPE;
tool.selfDestruct ← FALSE;
currentOption ← ViewerTools.GetContents[tool.remoteBox];
tool.remoteState ← IF tool.remoteState = TSViewer.RemoteOrLocalState.LAST THEN TSViewer.RemoteOrLocalState.FIRST ELSE tool.remoteState.SUCC;
Labels.Set[tool.remoteBox, SELECT tool.remoteState FROM
bestPerformance => "best performance",
localOnly => "local only",
remoteOnly => "remote only"
ENDCASE => "???"];
};
GetNames: ENTRY PROCEDURE [tool: Tool] RETURNS [gotIt: BOOLEANTRUE, names: LIST OF ROPE ← NIL] = {
ENABLE UNWIND => NULL;
rope: ROPE ~ ViewerTools.GetContents[tool.nameBox];
length: NAT ~ rope.Length;
i, start: NAT ← 0;
c: CHAR;
currentName: LIST OF ROPE;
IF tool.pause OR tool.stop THEN
{tool.process ← NIL; NOTIFY tool.idle; RETURN[FALSE, NIL]};
names ← CONS[NIL, NIL];
currentName ← names;
DO
WHILE i<length AND ((c ← rope.Fetch[i]) = Ascii.SP OR c=Ascii.CR OR c=Ascii.TAB OR c=', OR c=';)
DO i ← i+1 ENDLOOP;
start ← i;
UNTIL i>=length OR (c ← rope.Fetch[i]) = Ascii.SP OR c=Ascii.CR OR c=Ascii.TAB OR c=', OR c=';
DO i ← i+1 ENDLOOP;
IF i-start <= 0 THEN EXIT;
currentName.rest ← CONS[rope.Substr[start: start, len: i-start], NIL];
currentName ← currentName.rest;
WHILE i<length AND ((c ← rope.Fetch[i]) = Ascii.SP OR c=Ascii.CR OR c=Ascii.TAB OR c=', OR c=';)
DO i ← i+1 ENDLOOP;
IF i >= length OR ~tool.singleOutputFile THEN EXIT;
ENDLOOP;
ViewerTools.SetContents[tool.nameBox, rope.Substr[start: i]];
names ← names.rest;
IF names = NIL OR names.first.IsEmpty[] THEN {
tool.process ← NIL;
NOTIFY tool.idle;
RETURN[FALSE, NIL];
};
};
FindFileViewer: PROC[file: Rope.ROPE]
RETURNS[viewer: ViewerClasses.Viewer] = {
FindViewer: ViewerOps.EnumProc = {
IF Rope.Find[v.file, file, 0, FALSE] = 0
THEN {viewer ← v; RETURN[FALSE]}
ELSE RETURN[TRUE];
};
ViewerOps.EnumerateViewers[FindViewer];
};
WaitUntilSaved: PROC [fileName: Rope.ROPE, tool: Tool] = {
viewer: ViewerClasses.Viewer ← NIL;
viewer ← FindFileViewer[fileName];
IF viewer # NIL AND viewer.newVersion THEN {
SomeSaveInProgress: PROC RETURNS[ans: BOOLFALSE] = CHECKED {
v: ViewerClasses.Viewer ← viewer;
IF viewer.saveInProgress THEN RETURN[TRUE];
WHILE (v ← v.link) # NIL AND (v # viewer) DO
IF v.saveInProgress THEN RETURN[TRUE];
ENDLOOP;
};
IF NOT SomeSaveInProgress[] THEN {
IF tool.feedBack = NIL THEN {
ShowMessage[tool, Rope.Cat["***Please save ", viewer.name, ". . . \n"]];
}
ELSE {
tool.feedBack.PutRope[Rope.Cat["***Please save ", viewer.name, ". . . \n"]];
};
};
UNTIL SomeSaveInProgress[]
DO
Process.Pause[Process.SecondsToTicks[1]];
Process.CheckForAbort[];
ENDLOOP;
IF SomeSaveInProgress[] THEN {
IF tool.feedBack = NIL THEN {
ShowMessage[tool, Rope.Cat["***Waiting for ", viewer.name, " to finish being saved. . . "]];
}
ELSE {
tool.feedBack.PutRope[Rope.Cat["***Waiting for ", viewer.name, " to finish being saved. . . "]];
};
};
WHILE SomeSaveInProgress[] DO
TRUSTED {
Process.Pause[Process.SecondsToTicks[1]];
Process.CheckForAbort[];
};
ENDLOOP;
IF tool.feedBack = NIL THEN ShowMessage[tool, "ok\n"]
ELSE tool.feedBack.PutRope["ok\n"];
};
};
InsureSaved: PROC [tool: Tool, names: LIST OF ROPE] = {
wDir: ROPE = FileNames.CurrentWorkingDirectory[];
FOR loopNames: LIST OF ROPE ← names, loopNames.rest UNTIL loopNames = NIL DO
currentName: ROPE = loopNames.first;
WaitUntilSaved[
IF Rope.Find[currentName, ">"] < 0 AND Rope.Find[currentName, "/"] < 0
THEN FS.ExpandName[currentName, wDir].fullFName
ELSE currentName,
tool];
ENDLOOP;
};
GetPressName: PROCEDURE [tool: Tool] RETURNS [pressName: ROPE] = {
nameLen: INT ← 0;
cp: FS.ComponentPositions; dirOmitted: BOOLEAN;
[tool.currentName, cp, dirOmitted] ← FS.ExpandName[tool.currentName];
IF tool.currentName.Substr[cp.ext.start, cp.ext.length].Equal["Tioga", FALSE] THEN
pressName ← tool.currentName.Substr[cp.base.start, cp.base.length]
ELSE pressName ← tool.currentName.Substr[cp.base.start, cp.ext.start+cp.ext.length-cp.base.start];
IF tool.singleOutputFile THEN pressName ← pressName.Concat[".etc"];
pressName ← pressName.Concat[".press"];
IF cp.server.length = 0 THEN {
pressName ← tool.currentName.Substr[0, cp.base.start].Concat[pressName];
};
IF tool.tempPress THEN pressName ← pressName.Concat["$"];
IF pressName.Equal[tool.pressName] THEN {
WaitForSendIdle[tool];
ViewerTools.SetContents[tool.serverMsg, ""]
}
};
PrintButton: Menus.MenuProc = {
tool: Tool ← NARROW[clientData];
tool.selfDestruct ← FALSE;
IF mouseButton=yellow THEN ShowMessage[tool, doc[Print]]
ELSE Print[tool]
};
Print: PUBLIC ENTRY PROCEDURE [tool: Tool] = {
ENABLE UNWIND => NULL;
tool.pause ← tool.stop ← tool.stopSending ← FALSE;
IF tool.process=NIL THEN TRUSTED {Process.Detach[tool.process ← FORK TypesetProcess[tool]]};
};
AllButton: Menus.MenuProc = {
tool: Tool ← NARROW[clientData];
tool.selfDestruct ← FALSE;
IF mouseButton=yellow THEN ShowMessage[tool, doc[All]]
ELSE PrintAll[tool]};
PrintAll: PUBLIC PROCEDURE [tool: Tool] = {
tool.singleOutputFile ← TRUE;
Print[tool];
};
LeftScreenButton: Menus.MenuProc = {
tool: Tool ← NARROW[clientData];
tool.selfDestruct ← FALSE;
IF mouseButton=yellow THEN ShowMessage[tool, doc[LeftScreen]]
ELSE Screen[tool, leftSide]
};
ScreenButton: Menus.MenuProc = {
tool: Tool ← NARROW[clientData];
tool.selfDestruct ← FALSE;
IF mouseButton=yellow THEN ShowMessage[tool, doc[Screen]]
ELSE Screen[tool, bothSides]
};
RightScreenButton: Menus.MenuProc = {
tool: Tool ← NARROW[clientData];
tool.selfDestruct ← FALSE;
IF mouseButton=yellow THEN ShowMessage[tool, doc[RightScreen]]
ELSE Screen[tool, rightSide]
};
Screen: PUBLIC PROCEDURE [tool: Tool, side: PressScreen.Side] = {
pressName: ROPE;
TRUSTED {pressName ← PressScreen.NewPressName[]};
IF tool.tempPress THEN pressName ← pressName.Concat["$"];
TRUSTED {PressScreen.PressScreen[pressName, side]};
ShowMessage[tool, pressName.Concat[" completed"]];
IF NOT tool.debug AND NOT tool.stop AND tool.serverName.Length # 0 THEN {
tool.pressName ← pressName;
StartSending[tool];
};
};
TypesetProcess: PROCEDURE [tool: Tool] = {
didNothing: BOOLEANTRUE;
gotIt: BOOLEAN;
names: LIST OF ROPE;
outputHandle: TSOutput.Handle ← NIL;
TRUSTED {Process.SetPriority[Process.priorityBackground]};
WHILE ([gotIt: gotIt, names: names] ← GetNames[tool]).gotIt DO
didNothing ← FALSE;
IF tool.singleOutputFile THEN {
tool.currentName ← names.first;
ShowMessage[tool, tool.currentName];
tool.pressName ← GetPressName[tool];
IF PressPrinter.IsAPressFile[tool.currentName] THEN {
tool.pressName ← tool.currentName;
IF NOT tool.debug AND NOT tool.stop AND tool.serverName.Length # 0 THEN
StartSending[tool];
}
ELSE {
InsureSaved[tool, names];
TSFormat.FormatOneOutputFile[tool, names ! ABORTED => CONTINUE];
IF NOT tool.debug AND NOT tool.stop AND tool.serverName.Length # 0 THEN StartSending[tool];
};
}
ELSE { -- the "All" button means to format to one output file
currentList: LIST OF ROPECONS[NIL, NIL];
currentListTail: LIST OF ROPE ← currentList;
tool.pressName ← NIL ;
FOR n: LIST OF ROPE ← names, n.rest UNTIL n = NIL DO
tool.currentName ← n.first;
IF tool.pressName = NIL THEN tool.pressName ← GetPressName[tool];
ShowMessage[tool, tool.currentName];
IF PressPrinter.IsAPressFile[tool.currentName] THEN {
IF currentList.rest # NIL THEN {
currentList ← currentList.rest;
TSFormat.FormatOneOutputFile[tool, currentList ! ABORTED => CONTINUE];
IF NOT tool.debug AND NOT tool.stop AND tool.serverName.Length # 0 THEN StartSending[tool];
};
currentList ← CONS[NIL, NIL];
currentListTail ← currentList;
ShowMessage[tool, tool.currentName];
tool.pressName ← tool.currentName;
IF NOT tool.debug AND NOT tool.stop AND tool.serverName.Length # 0 THEN
StartSending[tool];
tool.pressName ← NIL;
}
ELSE {
ShowMessage[tool, tool.currentName];
InsureSaved[tool, names];
currentListTail.rest ← CONS[n.first, NIL];
currentListTail ← currentListTail.rest;
};
ENDLOOP;
IF currentList.rest # NIL THEN {
currentList ← currentList.rest;
TSFormat.FormatOneOutputFile[tool, currentList ! ABORTED => CONTINUE];
IF NOT tool.debug AND NOT tool.stop AND tool.serverName.Length # 0 THEN StartSending[tool];
};
};
ENDLOOP;
SafeStorage.ReclaimCollectibleObjects[];
tool.singleOutputFile ← FALSE;
IF didNothing THEN ShowMessage[tool, "Ready"];
IF tool.selfDestruct THEN WaitForSendIdle[tool];
IF tool.stop OR tool.stopSending THEN tool.selfDestruct ← FALSE;
IF tool.selfDestruct THEN ViewerOps.DestroyViewer[tool.messageBox.parent];
};
QueueRequest: PUBLIC ENTRY PROCEDURE [tool: Tool, documentName: ROPE] = {
ENABLE UNWIND => NULL;
queue: ROPE ← ViewerTools.GetContents[tool.nameBox];
IF queue.Length = 0 THEN queue ← documentName
ELSE queue ← queue.Cat[" ", documentName];
ViewerTools.SetContents[tool.nameBox, queue];
};
GetSelectionButton: Menus.MenuProc = {
tool: Tool ← NARROW[clientData, Tool];
tool.selfDestruct ← FALSE;
IF mouseButton=yellow THEN ShowMessage[tool, doc[Get]]
ELSE {
selectedViewer: ViewerClasses.Viewer ← ViewerTools.GetSelectedViewer[];
sourceName: ROPENIL;
sourceName ← IF selectedViewer = NIL OR selectedViewer.class.get = NIL THEN NIL
ELSE NARROW[selectedViewer.class.get[selectedViewer, $SelChars !
RuntimeError.UNCAUGHT => CONTINUE]];
IF sourceName.Length <=1 THEN {
IF (selectedViewer = NIL) THEN
{ShowMessage[tool, "Selection not in text viewer"]; sourceName ← NIL}
ELSE sourceName ← selectedViewer.name;
};
QueueRequest[tool, sourceName];
};
};
WaitForIdle: PUBLIC ENTRY PROCEDURE [tool: Tool] = {
ENABLE UNWIND => NULL;
WHILE tool.process # NIL DO WAIT tool.idle ENDLOOP;
WHILE tool.serverProcess # NIL DO WAIT tool.serverIdle ENDLOOP;
};
WaitForSendIdle: PUBLIC ENTRY PROCEDURE [tool: Tool] = {
ENABLE UNWIND => NULL;
WHILE tool.serverProcess # NIL DO WAIT tool.serverIdle ENDLOOP;
};
StartSending: PROCEDURE [tool: Tool] = {
IF tool.serverName.Equal["*"] THEN DoShowPress[tool.pressName]
ELSE MonitoredStartSending[tool];
};
MonitoredStartSending: ENTRY PROCEDURE [tool: Tool] = {
ENABLE UNWIND => NULL;
UNTIL tool.serverProcess = NIL DO WAIT tool.serverIdle ENDLOOP;
TRUSTED {Process.Detach[tool.serverProcess ← FORK SendingProcess[tool, tool.pressName]]};
};
FinishSending: ENTRY PROCEDURE [tool: Tool] = {
ENABLE UNWIND => NULL;
tool.serverProcess ← NIL;
BROADCAST tool.serverIdle;
ViewerTools.SetContents[tool.copiesBox, "1"]; -- should set it to one here only if there is nothing more to print, but I didn't figure out how to determine that yet...
};
SendingProcess: PROCEDURE [tool: Tool, pressName: ROPE] = {
ENABLE ABORTED => {FinishSending[tool]; GOTO Quit};
prevMsg: ROPENIL;
AbortablePause: PROC [seconds: CARDINAL] ~ {
oneSecond: Process.Ticks ~ Process.SecondsToTicks[1];
THROUGH [0..seconds] DO
IF tool.stopSending THEN GO TO Aborted;
Process.Pause[oneSecond];
ENDLOOP;
EXITS
Aborted => DisplayMsg["Transmission aborted"];
};
DisplayMsg: PROC [rope: ROPE] ~ {
IF prevMsg # rope THEN {
ViewerTools.SetContents[tool.serverMsg, ViewerTools.GetContents[tool.serverMsg].Cat["\n",rope]];
[] ← tool.serverMsg.class.scroll[tool.serverMsg, thumb, 100];
The line cache in Tioga 1 is global and used by both scrolling and selection.
Invalidate it as a good citizen (guess scrolling was never expected to be asynchronous)
TEditSelection.InvalidateLineCache[];
};
prevMsg ← rope;
};
tryAgain: BOOLFALSE;
progressProc: PressPrinter.ProgressProc = {
state: PressPrinter.State ~ handle.CurrentState;
PieViewers.Set[tool.serverPie, 1.0-handle.CurrentProgress];
IF tryAgain=FALSE OR state#aborted THEN DisplayMsg[handle.CurrentStateMessage];
IF state=serverBusy OR state=serverTimeout THEN {tryAgain ← TRUE; handle.Abort};
IF tool.stopSending THEN {tryAgain ← FALSE; handle.Abort};
};
copies: INT ← 1;
copies ← MAX[0, Convert.IntFromRope[ViewerTools.GetContents[tool.copiesBox] ! Convert.Error => CONTINUE]];
IF copies > 0 THEN {
printedBy: ROPE ← UserProfile.Token["Hardcopy.PrintedBy", ""];
DO
tryAgain ← FALSE;
[] ← PressPrinter.SendPressFile[
fileName: pressName,
server: tool.serverName,
progressProc: progressProc,
copies: copies,
userName: IF printedBy.Length = 0 THEN UserCredentials.Get[].name ELSE printedBy
];
IF NOT tryAgain THEN EXIT;
AbortablePause[30];
ENDLOOP;
};
IF TemporaryName[pressName] THEN {
FS.Delete[pressName ! FS.Error => {
DisplayMsg[error.explanation];
CONTINUE
}];
};
FinishSending[tool];
EXITS Quit => {}
};
TemporaryName: PROC [rope: ROPE] RETURNS [BOOL] ~ {
fullFName: ROPE;
cp: FS.ComponentPositions;
[fullFName, cp] ← FS.ExpandName[rope];
RETURN [fullFName.Fetch[cp.ext.start+cp.ext.length-1] = '$]
};
GetName: PROC [stream: IO.STREAM] RETURNS [name: ROPE] ~ {
name ← NIL;
name ← IO.GetTokenRope[stream, IO.IDProc ! IO.EndOfStream => CONTINUE].token;
};
FileNameBreakProc: PROC [char: CHAR] RETURNS [IO.CharClass] = {
IF char = ' OR char = '  OR char = ', OR char = '; OR char = '\n THEN RETURN [sepr];
RETURN [other];
};
GetFileName: PROC [stream: IO.STREAM] RETURNS [name: ROPE] ~ {
name ← NIL;
name ← IO.GetTokenRope[stream, FileNameBreakProc ! IO.EndOfStream => CONTINUE].token;
};
GetLine: PROC [stream: IO.STREAM] RETURNS [line: ROPE] ~ {
line ← NIL;
line ← IO.GetLineRope[stream ! IO.EndOfStream => CONTINUE];
};
DoShowPress: PROC [pressFileName: ROPE] ~ {
[] ← CommandTool.DoCommand[Rope.Concat["ShowPress ", pressFileName], NIL];
};
TSetterExecCommand: Commander.CommandProc = {
tool: Tool;
stream: IO.STREAMIO.RIS[cmd.commandLine];
serverName: ROPE ← GetName[stream];
files: ROPENIL;
WHILE NOT IO.EndOf[stream] DO
token: ROPE ← GetFileName[stream];
IF token # NIL THEN {
ENABLE FS.Error => {IF error.group=user THEN {cmd.out.PutRope[error.explanation]; cmd.out.PutChar['\n]; CONTINUE} ELSE REJECT};
CatProc: FS.NameProc = {
files ← files.Cat[" ", fullFName];
RETURN[TRUE];
};
IF token.Find["*"] = -1 THEN [] ← CatProc[FS.ExpandName[token].fullFName]
ELSE {
IF token.Find["!"] = -1 THEN token ← token.Concat["!H"];
FS.EnumerateForNames[pattern: token, proc: CatProc];
};
};
ENDLOOP;
IF serverName.Length=0 THEN serverName ← UserProfile.Token["Hardcopy.PressPrinter", ""];
tool ← NewTool[serverName];
IF files.Length > 0 THEN {tool.selfDestruct ← TRUE; QueueRequest[tool, files]};
Print[tool];
};
tSViewerClass: ViewerClasses.ViewerClass =
NEW[ViewerClasses.ViewerClassRec ← ViewerOps.FetchViewerClass[$Container]^];
tSViewerClass.paint ← TSViewerPaint;
tSViewerClass.adjust ← TSViewerAdjust;
tSViewerClass.icon ← private;
tSViewerClass.bltH ← none;
tSViewerClass.bltV ← none;
ViewerOps.RegisterViewerClass[$TSetter, tSViewerClass];
Commander.Register[
key: "TSetter",
proc: TSetterExecCommand,
doc: "Create a typesetter viewer for specified server, and use it to print listed documents"
];
END.
CHANGE LOG
Michael Plass, September 15, 1982 9:53 am. ENABLE UNWIND => NULL.
Michael Plass, September 15, 1982 10:51 am. Changed Rope.SP, etc, to refer to Ascii.
Michael Plass, September 15, 1982 10:51 am. Removed "Clover" default.
Michael Plass, September 15, 1982 11:54 am. Fixed it so unknown font message is not obliterated.
Michael Plass, September 15, 1982 12:07 pm. Revised calculation of press file names.
Michael Plass, September 15, 1982 12:13 pm. Replaced ! ANY with ! SafeStorage.NarrowFault.
Michael Plass, September 16, 1982 1:01 pm. Revised creation of press files.
Michael Plass, November 1, 1982 11:30 am. Converted to Tioga fomatting, made cursorProc and progressProc SAFE
Michael Plass, November 12, 1982 3:22 pm. Made some of the windows scrollable and growable.
Michael Plass, November 15, 1982 3:08 pm. Added StopSending and Screen buttons.
Michael Plass, November 17, 1982 9:28 am. Fixed screen buttons to reset the stopSending bit.
Michael Plass, November 17, 1982 11:35 am. Added calls to SafeStorage.
Michael Plass, November 18, 1982 10:45 am. Added yellow-button documentation.
Michael Plass, December 10, 1982 4:19 pm. Added clientData to New menu item.
Michael Plass, December 10, 1982 4:18 pm. Added ExecCommand.
Michael Plass, December 10, 1982 5:33 pm. Added selfDestuct
changes to: ToolRec, StopButton, PauseButton, StopSendingButton, NameButton, CopiesButton, TempPress, TempPressButton, GetFirstName, PrintButton, AllButton, LeftScreenButton, ScreenButton, RightScreenButton, TypesetProcess, GetSelectionButton, ExecCommand
Michael Plass, December 10, 1982 6:17 pm. Bug fix in TypesetProcess
John Maxwell, January 20, 1983 1:54 pm.
changes to: TSViewerImpl, Print, Screen, TypesetProcess, FormatOneFile, StartSending, ExecCommand
Michael Plass, March 10, 1983 8:30 am. changes to: rightIcon, leftIcon, InitDoc, NewTool
Michael Plass, May 2, 1983 9:05 am. Removed uses of UserExec, fixed bug in GetFirstName.
Michael Plass, May 27, 1983 11:15 am. Changed so foo.tioga produces foo.press., IMPORTS
Edited on May 27, 1983 11:11 am, by Beach
changes to: TSViewerPaint to force a clear viewer when adjusting the viewer sizes.
Edited on June 1, 1983 9:40 am, by Beach
changes to: tSViewerClass, TSViewerPaint, TSViewerPaint
Edited on June 20, 1983 3:56 pm, by Beach
changes to: SendingProcess to use Hardcopy.PrintedBy if its defined in the user profile.
Edited on August 10, 1983 5:24 pm, by Beach
changes to: DIRECTORY, IMPORTS, TSViewerPaint
Edited on August 12, 1983 2:39 pm, by Beach
changes to: ToolRec, NewTool, TSetterExecCommand, PressScreenTool, PressScreenToolRec, NewPressScreenTool, NextY (local of NewPressScreenTool), FlashImageButton, SelectedImageButton, WholeScreenButton, RightColumnButton, LeftColumnButton, MagnificationFactorButton, SetCornersButton, BlackBorder, PageMarginButton, PressScreenExecCommand, Commander, Commander, mode, BoxAdjustNotify, Clip (local of BoxAdjustNotify), BlackBorder
Edited on August 15, 1983 2:52 pm, by Beach
changes to: DIRECTORY, IMPORTS, InsertMenuEntry, FlashImageButton, SelectedImageButton, WholeScreenButton, RightColumnButton, LeftColumnButton, ReadScreenCorners, ConvertRopeToReal, vaTIP, NewPressScreenTool, TSetterExecCommand, Commander, }, Screen, MenuCode, NewTool, NewTool, ToolRec, InsertMenuEntry (local of NewTool), ToolRec, GetPressName
Edited on August 18, 1983 12:46 pm, by Beach
changes to: TSViewerPaint
Edited on August 19, 1983 12:56 pm, by Beach
changes to: NewTool, InsertMenuEntry (local of NewTool)
Edited on October 26, 1983 9:08 am, by Beach
changes to: DIRECTORY, IMPORTS, progressProc (local of SendingProcess)
Michael Plass, December 7, 1983 12:36 pm: Cedar 5 conversion (FS, Convert, UserCredentials, IO.GetTokenRope, IO.GetLineRope)
Michael Plass, December 12, 1983 2:11 pm: Carried local directory name from input file to output file.
Michael Plass, February 21, 1984 9:46:50 am PST: Fixed file-name-on-header bug.
Rick Beach, May 3, 1985 2:04:22 pm PDT
changes to: SendingProcess increased pause before retrying to send to a busy or timed-out server from 2 seconds to 60 seconds, moved the code to reset the copies box from FinishSending to the end of the TypesetProcess loop.
Rick Beach, May 3, 1985 8:30:33 pm PDT
changes to: progressProc (local of SendingProcess), SendingProcess, AbortablePause (local of SendingProcess), DisplayMsg (local of SendingProcess), DIRECTORY, =, FinishSending
Bob Hagmann May 20, 1985 1:31:57 pm PDT
changes to: NewTool, cursorProc, =, DIRECTORY, IMPORTS, WaitUntilSaved, InsureSaved, WaitUntilSaved, GetNames, GetFirstName, Screen
Bob Hagmann November 21, 1985 4:40:47 pm PST
added RemoteOrLocalButton to handle Summoner options
changes to: NewTool, RemoteOrLocalButton
Bob Hagmann November 22, 1985 11:53:46 am PST
changes to: NewTool