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: ROPE ← NIL;
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:
BOOL ←
FALSE, row:
INTEGER ← 0, clientData:
REF
ANY ←
NIL, copy:
BOOL ←
FALSE, documentation:
ROPE ←
NIL, guarded:
BOOL ←
FALSE] = {
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:
BOOLEAN ←
TRUE] = {
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: NAT ← MAX[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:
BOOLEAN ←
TRUE] = {
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: ROPE ← NIL;
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: BOOLEAN ← TRUE;
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: ROPE ← NIL;
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.STREAM ← FS.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: ROPE ← NIL;
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.STREAM ← IO.RIS[cmd.commandLine];
serverName: ROPE ← GetName[stream];
files: ROPE ← NIL;
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.