DIRECTORY
Atom USING [DottedPairNode],
Basics USING [UnsafeBlock],
BasicTime USING [earliestGMT, GetClockPulses, GMT, Now, Period, Pulses, PulsesToMicroseconds],
Commander USING [CommandProc],
ComputeServerServer USING [Register],
Convert USING [RopeFromInt, RopeFromReal],
FS USING [ComponentPositions, Error, ExpandName, GetName, OpenFileFromStream, StreamOpen],
IO USING [CharsAvail, GetChar, PutChar, PutRope, SetLength, STREAM, UnsafePutBlock],
NodeStyle USING [Ref],
ProcessProps USING [AddPropList],
PutGet USING [FromFile],
Rope USING [Cat, Concat, Equal, Fetch, Index, Length, ROPE, Substr],
SafeStorage USING [ReclaimCollectibleObjects],
SirPress USING [CursorObject, CursorObjectRec, CursorProc],
TEditInput USING [FreeTree],
TextNode USING [LastLocWithin, LocNumber, Ref],
TSJaMPageBuilder USING [RunPageBuilder],
TSObject USING [ItemList],
TSOutput USING [Close, Handle],
TSOutputPress USING [CreateWithCursor],
TSTranslate USING [FontNotFound, ProgressProc, TreeToVlist],
TSViewer USING [Tool, ToolRec],
UserProfile USING [Boolean],
ViewerTools USING [SetContents];
=
BEGIN
OPEN TSViewer;
ROPE: TYPE = Rope.ROPE;
cursorData: TYPE = REF cursorDataObject;
cursorDataObject:
TYPE =
RECORD [
out: IO.STREAM ← NIL,
lastSendTime: BasicTime.GMT ← BasicTime.earliestGMT,
lastPulse: BasicTime.Pulses ← 0
];
ShowMessage:
ENTRY
PROCEDURE [out:
IO.
STREAM, prefix:
CHAR, msg:
ROPE] = {
ENABLE UNWIND => NULL;
out.PutChar[prefix];
out.PutRope[msg];
out.PutChar['$];
};
CreateOutputHandle:
PROCEDURE [tool: Tool, node: TextNode.Ref,
cursorObject: SirPress.CursorObject]
RETURNS [outputHandle: TSOutput.Handle] = {
stream: IO.STREAM ← FS.StreamOpen[GetPressName[tool], $create];
inputLength: INT ← TextNode.LocNumber[TextNode.LastLocWithin[node], 0];
stream.SetLength[MIN[1024, inputLength+inputLength-inputLength/3]];
tool.pressName ← FS.GetName[FS.OpenFileFromStream[stream]].fullFName;
IF node=NIL THEN ERROR;
outputHandle ← TSOutputPress.CreateWithCursor[
stream: stream,
documentName: tool.currentName,
cursorObject: cursorObject
];
};
GetPressName:
PROCEDURE [tool: Tool]
RETURNS [pressName:
ROPE] = {
nameLen: INT ← 0;
cp: FS.ComponentPositions; dirOmitted: BOOL;
[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 {
ViewerTools.SetContents[tool.serverMsg, ""]
}
};
CursorProc:
ENTRY SirPress.CursorProc =
CHECKED {
ENABLE UNWIND => NULL;
cursor: cursorData = NARROW[clientData];
out: IO.STREAM = cursor.out;
block: Basics.UnsafeBlock;
now: BasicTime.GMT = BasicTime.Now[];
nowPulse: BasicTime.Pulses = BasicTime.GetClockPulses[];
IF bits =
NIL
OR BasicTime.Period[cursor.lastSendTime, now] > 0
OR BasicTime.PulsesToMicroseconds[nowPulse - cursor.lastPulse] > 200000
THEN {
cursor.lastSendTime ← now;
cursor.lastPulse ← nowPulse;
IF bits = NIL THEN out.PutRope["c$"]
ELSE {
out.PutChar['b];
block ← [LOOPHOLE[bits], 0, 32];
out.UnsafePutBlock[block];
out.PutChar['$];
};
};
};
RemoteTSetterProc: Commander.CommandProc = {
tool: Tool ← NEW[ToolRec ← [tempPress: UserProfile.Boolean["Hardcopy.TemporaryPressFiles"], stop: FALSE]];
aborted: BOOL;
lastProgressReported: REAL ← -2.0;
IsAborted:
PROC
RETURNS [
BOOL] = {
IF cmd.in.CharsAvail[] > 0
THEN {
inChar: CHAR ;
inChar ← cmd.in.GetChar[];
IF inChar = 's THEN tool.stop ← TRUE;
};
RETURN[tool.stop];
};
ProgressProc:
ENTRY TSTranslate.ProgressProc = {
ENABLE UNWIND => NULL;
IF progress > lastProgressReported + 1.0
THEN {
realString: ROPE ← Rope.Cat["p", Convert.RopeFromReal[from: progress, precision: 3, useE: FALSE], "$"];
lastProgressReported ← progress;
cmd.out.PutRope[realString];
IF cmd.in.CharsAvail[] > 0
THEN {
inChar: CHAR ;
inChar ← cmd.in.GetChar[];
IF inChar = 's THEN tool.stop ← TRUE;
};
IF tool.stop THEN ERROR ABORTED;
};
};
galley: TSObject.ItemList;
style: NodeStyle.Ref;
outputHandle: TSOutput.Handle ← NIL;
names: ROPE ← cmd.commandLine;
IF names.Substr[0, 3].Equal["-t "]
THEN {
tool.tempPress ← TRUE;
names ← names.Substr[3];
}
ELSE tool.tempPress ← FALSE;
WHILE names.Length[] > 0
AND ~tool.stop
DO
ENABLE TSTranslate.FontNotFound => {
msg ← Rope.Cat["Unable to find font ", fontName, "; position including comment nodes = ", Convert.RopeFromInt[location]];
tool.stop ← TRUE;
GOTO Quit
};
errorMsg: ROPE ← NIL;
end: INT;
node: TextNode.Ref;
IF names.Fetch[0] = '
THEN {
names ← names.Substr[1];
LOOP;
};
end ← names.Index[0," "];
tool.currentName ← names.Substr[0, end];
names ← names.Substr[end];
node ← PutGet.FromFile[tool.currentName !
FS.Error => {errorMsg ← error.explanation; CONTINUE}];
IF errorMsg =
NIL
THEN {
cursor: cursorData ← NEW[cursorDataObject];
cursor.out ← cmd.out;
cursor.lastPulse ← BasicTime.GetClockPulses[];
IF outputHandle =
NIL
THEN
outputHandle ← CreateOutputHandle[tool, node,
NEW[SirPress.CursorObjectRec ← [cursorProc: CursorProc, clientData: cursor]]];
ShowMessage[cmd.out, 'm, Rope.Concat[IF tool.singleOutputFile THEN "Typesetting member " ELSE "Typesetting ", tool.currentName]];
{
FormatFile:
PROC ~ {
[galley, style] ← TSTranslate.TreeToVlist[node, ProgressProc];
aborted ← TSJaMPageBuilder.RunPageBuilder[
galley: galley,
style: style,
output: outputHandle,
abortCheckProc: IsAborted,
documentName: tool.currentName
! ABORTED => { aborted ← TRUE; }]
};
wd: Rope.ROPE ← ExtractWorkingDirectory[tool.currentName];
ProcessProps.AddPropList[propList: LIST[NEW[Atom.DottedPairNode ← [$WorkingDirectory, wd]]], inner: FormatFile];
};
tool.stop ← tool.stop OR aborted;
TEditInput.FreeTree[node];
SafeStorage.ReclaimCollectibleObjects[];
}
ELSE ShowMessage[cmd.out, 'e, errorMsg];
ENDLOOP;
IF outputHandle # NIL THEN outputHandle.Close;
EXITS Quit => {}
};
ExtractWorkingDirectory:
PROC [fileName: Rope.
ROPE]
RETURNS [wd: Rope.
ROPE]~ {
fullFName: Rope.ROPE;
cp: FS.ComponentPositions;
[fullFName, cp] ← FS.ExpandName[fileName];
wd ← Rope.Substr[fullFName, 0, cp.base.start];
};
ComputeServerServer.Register[
key: "RemoteTSetter",
proc: RemoteTSetterProc
];