TSViewerImpl.mesa
Michael Plass, February 21, 1984 9:46:41 am PST
Last Edited by: Beach, May 7, 1984 3:46:57 pm PDT
DIRECTORY
Ascii,
Atom,
Buttons,
Commander,
CommandTool,
Containers,
Convert,
EditSpanSupport,
FS,
Graphics,
IO,
IconManager,
Icons,
Labels,
Menus,
NodeStyle,
PieViewers,
PressPrinter,
PressScreen,
PrincOps,
Process,
PseudoCursors,
PutGet,
Rope,
RuntimeError,
SafeStorage,
SirPress,
TEditDocument,
TEditInput,
TEditSelection,
TextNode,
TSTranslate,
TSGlue,
TSJaMPageBuilder,
TSObject,
TSOutput,
TSOutputPress,
TSViewer,
TSWrecker,
UserCredentials,
UserProfile,
ViewerClasses,
ViewerOps,
ViewerSpecs,
ViewerTools;
TSViewerImpl: CEDAR MONITOR
IMPORTS Buttons, Commander, CommandTool, Containers, Convert, EditSpanSupport, FS, Graphics, IconManager, Icons, IO, Labels, Menus, PieViewers, PressPrinter, PressScreen, Process, PutGet, PseudoCursors, Rope, RuntimeError, SafeStorage, TEditInput, TEditSelection, TextNode, TSJaMPageBuilder, TSTranslate, TSOutput, TSOutputPress, TSWrecker, UserCredentials, UserProfile, ViewerOps, ViewerTools EXPORTS TSViewer = {
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] RETURNS [Tool] = {
ENABLE UNWIND => NULL;
data: Tool ← NEW[ToolRec ← [stop: FALSE]];
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 ← MakeMenu[];
MakeMenu: PROCEDURE RETURNS [m: Menus.Menu] = {
m ← Menus.CreateMenu[];
InsertMenuEntry[
menu: m,
name: "New",
proc: NewButton,
fork: FALSE,
clientData: data,
documentation: doc[New]
];
InsertMenuEntry[
menu: m,
name: ">",
proc: RightScreenButton,
fork: TRUE,
clientData: data,
documentation: doc[RightScreen]
];
InsertMenuEntry[
menu: m,
name: "Screen",
proc: ScreenButton,
fork: TRUE,
clientData: data,
documentation: doc[Screen]
];
InsertMenuEntry[
menu: m,
name: "<",
proc: LeftScreenButton,
fork: TRUE,
clientData: data,
documentation: doc[LeftScreen]
];
InsertMenuEntry[
menu: m,
name: "All",
proc: AllButton,
fork: FALSE,
clientData: data,
documentation: doc[All]
];
InsertMenuEntry[
menu: m,
name: "Print",
proc: PrintButton,
fork: FALSE,
clientData: data,
documentation: doc[Print]
];
InsertMenuEntry[
menu: m,
name: "Get",
proc: GetSelectionButton,
fork: FALSE,
clientData: data,
documentation: doc[Get]
];
InsertMenuEntry[
menu: m,
name: "StopSending",
proc: StopSendingButton,
fork: FALSE,
clientData: data,
documentation: doc[StopSending]
];
InsertMenuEntry[
menu: m,
name: "Stop",
proc: StopButton,
fork: FALSE,
clientData: data,
documentation: doc[Stop]
];
InsertMenuEntry[
menu: m,
name: "Pause",
proc: PauseButton,
fork: FALSE,
clientData: data,
documentation: doc[Pause]
];
};
InsertMenuEntry: PROCEDURE [menu: Menus.Menu, name: ROPE, proc: Menus.MenuProc, fork: BOOLFALSE, row: INTEGER ← 0, clientData: REF ANYNIL, copy: BOOLFALSE, documentation: ROPENIL, guarded: BOOLFALSE] = {
menuEntry: Menus.MenuEntry ← Menus.CreateEntry[name: name, proc: proc, clientData: clientData, documentation: documentation, fork: fork, guarded: guarded];
Menus.InsertMenuEntry[menu, menuEntry];
};
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] =
BEGIN 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;
END;
TSViewerPaint: ViewerClasses.PaintProc = {
IF self.iconic THEN {
IF IconManager.selectedIcon=self THEN [] ← Graphics.Save[context];
Icons.DrawIcon[flavor: IF self.column = left THEN leftIcon ELSE rightIcon,
context: context, x: 0, y: 0,
label: self.name];
IF IconManager.selectedIcon=self THEN {
Graphics.Restore[context];
[] ← Graphics.SetPaintMode[context, invert];
Graphics.DrawBox[context, [0, 0, ViewerSpecs.iconWidth, ViewerSpecs.iconHeight]];
}}
ELSE {
varbaseline: NATMAX[baseline, (self.ch-indent-2*baseline)/3];
IF NOT clear THEN {
Graphics.SetColor[context, Graphics.white];
Graphics.DrawBox[context, Graphics.GetBounds[context]];
};
FOR v: ViewerClasses.Viewer ← self.child, v.sibling UNTIL v=NIL DO
positionInfo: REF PositionInfoRec ← NARROW[ViewerOps.FetchProp[v,$TSViewerPositionInfo]];
IF positionInfo#NIL THEN {
SetViewerPosition[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
];
};
ENDLOOP;
depend on containerPaint to reset the paint cache, since there are bound children.
containerPaint[self, context, whatChanged, clear];
};
};
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"];
};
GetFirstName: ENTRY PROCEDURE [tool: Tool] RETURNS [gotIt: BOOLEANTRUE] = {
ENABLE UNWIND => NULL;
rope: ROPE ~ ViewerTools.GetContents[tool.nameBox];
length: NAT ~ rope.Length;
i, start: NAT ← 0;
c: CHAR;
IF tool.pause OR tool.stop THEN
{tool.process ← NIL; NOTIFY tool.idle; RETURN[FALSE]};
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;
tool.currentName ← rope.Substr[start: start, len: i-start];
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;
ViewerTools.SetContents[tool.nameBox, rope.Substr[start: i]];
IF tool.currentName.Length = 0 THEN
{tool.process ← NIL; NOTIFY tool.idle; RETURN[FALSE]};
};
GetDocument: PROCEDURE [tool: Tool] RETURNS [node: TextNode.Ref] =
BEGIN
viewer: ViewerClasses.Viewer;
errorMsg: ROPENIL;
viewer ← ViewerOps.FindViewer[tool.currentName];
IF viewer = NIL OR NOT ISTYPE[viewer.data, TEditDocument.TEditDocumentData] THEN
node ← PutGet.FromFile[tool.currentName ! FS.Error => TRUSTED {errorMsg ← error.explanation; CONTINUE}]
ELSE {-- make a copy of the tree.
root: TextNode.Ref ← NARROW[viewer.data, TEditDocument.TEditDocumentData].text;
root ← TextNode.Root[
EditSpanSupport.CopySpan[ -- adds an extra root node
TextNode.MakeNodeSpan[
root,
TextNode.LastWithin[root]
]
]
.start.node
];
node ← TextNode.FirstChild[root]; -- get rid of the extra root node
node.next ← NIL; root.child ← NIL; -- to help out the garbage collector
};
IF errorMsg # NIL THEN ShowMessage[tool, errorMsg];
END;
LetterOrDigit: PROCEDURE [c: CHARACTER] RETURNS [BOOLEAN] =
{RETURN[c IN ['A .. 'Z] OR c IN ['a .. 'z] OR c IN ['0 .. '9] OR c='-]};
GetPressName: PROCEDURE [tool: Tool] RETURNS [pressName: ROPE] =
BEGIN
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, ""]
}
END;
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] =
BEGIN ENABLE UNWIND => NULL;
tool.pause ← tool.stop ← tool.stopSending ← FALSE;
IF tool.process=NIL THEN TRUSTED {Process.Detach[tool.process ← FORK TypesetProcess[tool]]};
END;
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];
};
};
cursorProc: SirPress.CursorProc = CHECKED {PseudoCursors.Set[NARROW[clientData], bits]};
TypesetProcess: PROCEDURE [tool: Tool] =
BEGIN
didNothing: BOOLEANTRUE;
outputHandle: TSOutput.Handle ← NIL;
TRUSTED {Process.SetPriority[Process.priorityBackground]};
WHILE GetFirstName[tool] DO
node: TextNode.Ref;
ShowMessage[tool, tool.currentName];
IF PressPrinter.IsAPressFile[tool.currentName] THEN {
IF outputHandle # NIL THEN {FinishUp[tool, outputHandle]; outputHandle ← NIL};
tool.pressName ← tool.currentName;
IF NOT tool.debug AND NOT tool.stop AND tool.serverName.Length # 0 THEN
StartSending[tool];
}
ELSE {
node ← GetDocument[tool];
IF node = NIL THEN {
tool.stop ← TRUE;
}
ELSE {
IF outputHandle = NIL THEN outputHandle ← CreateOutputHandle[tool, node, NEW[SirPress.CursorObjectRec ← [cursorProc: cursorProc, clientData: tool.miniDisplay]]];
FormatOneFile[tool, node, outputHandle ! ABORTED => CONTINUE];
IF NOT tool.singleOutputFile THEN {FinishUp[tool, outputHandle]; outputHandle ← NIL};
TEditInput.FreeTree[node];
TSWrecker.DestroyRef[StuffToDestroy[], NIL];
SafeStorage.ReclaimCollectibleObjects[];
};
};
didNothing ← FALSE;
ENDLOOP;
IF outputHandle # NIL THEN {FinishUp[tool, outputHandle]; outputHandle ← NIL};
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];
END;
StuffToDestroy: ENTRY PROCEDURE RETURNS [stuff: REF]= {
ENABLE UNWIND => NULL;
stuff ← TSWrecker.toDestroyAtEndOfFile;
TSWrecker.toDestroyAtEndOfFile ← NIL;
};
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 =
BEGIN
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];
};
END;
CreateOutputHandle: PROCEDURE [tool: Tool, node: TextNode.Ref, cursorObject: SirPress.CursorObject]
RETURNS [outputHandle: TSOutput.Handle] = {
stream: IO.STREAMFS.StreamOpen[tool.pressName ← GetPressName[tool], $create];
inputLength: INT ← TextNode.LocNumber[TextNode.LastLocWithin[node], 0];
stream.SetLength[MIN[1024, inputLength+inputLength-inputLength/3]];
IF node=NIL THEN ERROR;
outputHandle ← TSOutputPress.CreateWithCursor[
stream: stream,
documentName: tool.currentName,
cursorObject: cursorObject
];
};
FinishUp: PROCEDURE [tool: Tool, outputHandle: TSOutput.Handle] = {
msg: ROPE;
IF NOT tool.debug THEN msg ← tool.pressName ELSE msg ← NIL;
IF tool.stop THEN msg ← msg.Concat[" aborted"]
ELSE msg ← msg.Concat[" completed"];
outputHandle.Close;
ShowMessage[tool, msg];
IF NOT tool.debug AND NOT tool.stop AND tool.serverName.Length # 0 THEN StartSending[tool];
};
FormatOneFile: PROCEDURE [tool: Tool, node: TextNode.Ref, outputHandle: TSOutput.Handle] = {
ENABLE TSTranslate.FontNotFound => TRUSTED {
ShowMessage[tool, Rope.Cat["Unable to find font ", fontName, "; position including comment nodes = ", Convert.RopeFromInt[location]]];
tool.stop ← TRUE;
GOTO Quit
};
aborted: BOOLEAN;
isAborted: PROCEDURE RETURNS [BOOLEAN] = {RETURN[tool.stop]};
progressProc: TSTranslate.ProgressProc = {
PieViewers.Set[tool.pie, 100.0-progress];
IF tool.stop THEN ERROR ABORTED
};
galley: TSObject.ItemList;
style: NodeStyle.Ref;
IF tool.singleOutputFile THEN
ShowMessage[tool, Rope.Concat["Typesetting member ", tool.currentName]]
ELSE ShowMessage[tool, Rope.Concat["Typesetting ", tool.currentName]];
TRUSTED {
[galley, style] ← TSTranslate.TreeToVlist[node, progressProc];
aborted ← TSJaMPageBuilder.RunPageBuilder[
galley: galley,
style: style,
output: outputHandle,
abortCheckProc: isAborted,
documentName: tool.currentName
]};
tool.stop ← tool.stop OR aborted;
EXITS Quit => {}
};
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"];
};
SendingProcess: PROCEDURE [tool: Tool, pressName: ROPE] = {
ENABLE ABORTED => {FinishSending[tool]; GOTO Quit};
prevMsg: ROPENIL;
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;
};
progressProc: PressPrinter.ProgressProc = TRUSTED {
PieViewers.Set[tool.serverPie, 1.0-handle.CurrentProgress];
DisplayMsg[handle.CurrentStateMessage];
IF tool.stopSending THEN 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", ""];
[] ← PressPrinter.SendPressFile[
fileName: pressName,
server: tool.serverName,
progressProc: progressProc,
copies: copies,
userName: IF printedBy.Length = 0 THEN UserCredentials.Get[].name ELSE printedBy
];
};
IF pressName.Fetch[pressName.Length-1] = '$ THEN {
FS.Delete[pressName ! FS.Error => {
DisplayMsg[error.explanation];
CONTINUE
}];
};
FinishSending[tool];
EXITS Quit => {}
};
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]^];
containerPaint: ViewerClasses.PaintProc = tSViewerClass.paint;
tSViewerClass.paint ← TSViewerPaint;
tSViewerClass.icon ← private;
tSViewerClass.bltContents ← 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"
];
}.
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.