TSetterStarter.mesa
Created by Sindhu, October 18, 1985 5:45:22 pm PST
Pradeep Sindhu October 21, 1985 9:49:01 pm PDT
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 [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];
TSetterStarter: 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;
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: 4*72, wh: data.nameButton.wh,
parent: container, scrollable: FALSE, border: FALSE],
paint: FALSE
];
PlaceChild[data.copiesBox, 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"];
};
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 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]]};
tool.process ← NIL;
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];
};
DragomanStartTSetter: 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: "DragomanStartTSetter",
proc: DragomanStartTSetter,
doc: "Starts a single Dragoman simulation of TSetter"
];
END.