-- File: WalnutSendOpsImpl.mesa
-- Contents: More procs for WalnutSend
-- Created by Willie-Sue, December 13, 1983
-- Last Edited by: Willie-Sue, May 1, 1984 4:47:57 pm PDT
DIRECTORY
GVAnswer USING [MakeHeader],
Menus,
IO,
Rope,
RopeIO USING [GetRope],
RuntimeError USING [BoundsFault],
TiogaOps USING [ Pattern, Ref, Location,
CreateSimplePattern,
GetSelection, InsertRope, SelectDocument, SelectPoint,
SelectionRoot, SelectionSearch, SetSelection, ToPrimary],
ViewerOps,
ViewerClasses,
ViewerTools,
WalnutSendInternal,
WalnutSendOps;
WalnutSendOpsImpl:
CEDAR
MONITOR
IMPORTS
IO, Rope, RuntimeError,
GVAnswer,
Menus,
RopeIO, TiogaOps,
ViewerOps,
WalnutSendInternal, WalnutSendOps
EXPORTS
WalnutSendInternal, WalnutSendOps
SHARES Menus =
BEGIN OPEN WalnutSendOps, WalnutSendInternal;
-- ************************************************************************
nullIndex: INT = LAST[INT];
Answer:
PUBLIC
PROC[msgHeaders:
ROPE, who: Viewer←
NIL]
RETURNS [v: Viewer] =
BEGIN
notOk: BOOL;
errorIndex: INT;
answer: ROPE;
answerForm: WalnutSendOps.Form;
AnswerGetChar: PROC[pos: INT] RETURNS[CHAR] = {RETURN[msgHeaders.Fetch[pos]]};
[notOk, answer, errorIndex]← GVAnswer.MakeHeader[AnswerGetChar, msgHeaders.Length[],
simpleUserName, defaultRegistry];
IF notOk
THEN
{ start, end:
INT← errorIndex;
BEGIN
ENABLE RuntimeError.BoundsFault => {start← 0; end← 1;
CONTINUE};
IF start = nullIndex THEN start← 0
ELSE
{UNTIL msgHeaders.Fetch[start] = '\n DO start← start - 1; ENDLOOP;
start← start + 1};
IF end = nullIndex THEN end← start + 1
ELSE
{UNTIL msgHeaders.Fetch[end] = '\n DO end← end + 1; ENDLOOP;
end← end - 1};
END;
IF who # NIL THEN ShowErrorFeedback[who, start, end];
SenderReport[
IO.PutFR[
"\nSyntax error in line starting at pos %g (in message being answered)",
IO.int[start]]];
RETURN };
answerForm ←
NEW[ WalnutSendOps.FormRec ←
[formText: answerText, fields: ParseAnswerHeader[answer] ] ];
v← BuildSendViewer[TRUE, FALSE, answerForm, who];
ClearFileAssoc[v];
GrabFocus[v];
END;
ParseAnswerHeader: PROC[header: ROPE] RETURNS[fields: LIST OF ROPE] =
{ HeaderLines: ARRAY[0..3] OF Rope.ROPE;
startPos: INT ← Rope.Find[header, ": ", 0];
endOfLine: INT ← Rope.Find[header, "\n", startPos];
FOR i: INT IN [0..3] DO
HeaderLines[i] ← Rope.Substr[header, startPos+2, endOfLine-startPos-2];
startPos ← Rope.Find[header, ": ", endOfLine];
IF startPos = -1 THEN EXIT ELSE endOfLine ← Rope.Find[header, "\n", startPos]
ENDLOOP;
RETURN[ LIST[ HeaderLines[0], HeaderLines[1], HeaderLines[2], HeaderLines[3] ] ] };
Forward: PUBLIC PROC[msg: Viewer, who: Viewer← NIL] RETURNS[v: Viewer] =
TRUSTED
BEGIN
forwardForm: WalnutSendOps.Form =
NEW[WalnutSendOps.FormRec ← [formText: forwardText, fields: NIL]];
messagePattern: TiogaOps.Pattern = TiogaOps.CreateSimplePattern["ForwardedMessage"];
headerPattern: TiogaOps.Pattern = TiogaOps.CreateSimplePattern["MessageHeader"];
pstart, pend: TiogaOps.Location;
root: TiogaOps.Ref;
found: BOOL;
v← BuildSendViewer[TRUE, FALSE, forwardForm, who];
ClearFileAssoc[v];
TiogaOps.SelectDocument[v];
root ← TiogaOps.SelectionRoot[];
pstart ← TiogaOps.Location[ root, 0 ];
TiogaOps.SelectPoint[ v, pstart ];
found ← TiogaOps.SelectionSearch[pattern: headerPattern];
IF found THEN
{ [ ,pstart, pend, , , ] ← TiogaOps.GetSelection[];
TiogaOps.SetSelection[viewer: v, start: pstart, end: pend,
level: word, pendingDelete: TRUE];
TiogaOps.InsertRope[ msg.name ] };
found ← TiogaOps.SelectionSearch[pattern: messagePattern];
IF NOT found THEN RETURN;
[ ,pstart, pend, , , ] ← TiogaOps.GetSelection[];
TiogaOps.SetSelection[ viewer: v, start: pstart, end: pend, level: node, pendingDelete: TRUE ];
TiogaOps.SelectDocument[ viewer: msg, which: secondary ];
TiogaOps.ToPrimary[];
UnsetNewVersion[v];
GrabFocus[v]
END;
ClearFileAssoc: PUBLIC PROC[v: Viewer] =
BEGIN
IF v.file # NIL THEN v.file← NIL;
v.name← sendCaption;
ViewerOps.PaintViewer[v, caption];
END;
SenderNewVersion: PUBLIC PROC[viewer: Viewer] =
BEGIN OPEN Menus;
menu: Menus.Menu = viewer.menu;
firstForm: Menus.MenuEntry = Menus.GetLine[formsMenu, 0];
getEntry: Menus.MenuEntry← Menus.FindEntry[menu, "Get"];
IF getEntry # NIL THEN Menus.SetGuarded[getEntry, TRUE];
getEntry← Menus.FindEntry[menu, "Default"];
IF getEntry # NIL THEN Menus.SetGuarded[getEntry, TRUE];
getEntry← Menus.FindEntry[menu, "PrevMsg"];
IF getEntry # NIL THEN Menus.SetGuarded[getEntry, TRUE];
FOR i: Menus.MenuLine IN [1..5) DO
thisLine: Menus.MenuEntry = Menus.GetLine[menu, i];
IF thisLine = NIL THEN EXIT;
IF Rope.Equal[thisLine.name, firstForm.name] THEN
FOR entry: MenuEntry ← thisLine, entry.link UNTIL entry = NIL DO
SetGuarded[entry, TRUE]
ENDLOOP;
ENDLOOP;
ViewerOps.PaintViewer[viewer, menu]; -- show as guarded
viewer.newVersion← TRUE;
END;
UnsetNewVersion: PUBLIC PROC[viewer: Viewer] =
BEGIN OPEN Menus;
menu: Menu = viewer.menu;
firstForm: Menus.MenuEntry = Menus.GetLine[formsMenu, 0];
getEntry: Menus.MenuEntry← Menus.FindEntry[menu, "Get"];
IF getEntry # NIL THEN Menus.SetGuarded[getEntry, FALSE];
getEntry← Menus.FindEntry[menu, "Default"];
IF getEntry # NIL THEN Menus.SetGuarded[getEntry, FALSE];
getEntry← Menus.FindEntry[menu, "PrevMsg"];
IF getEntry # NIL THEN Menus.SetGuarded[getEntry, FALSE];
FOR i: Menus.MenuLine IN [1..5) DO
thisLine: Menus.MenuEntry = Menus.GetLine[menu, i];
IF thisLine = NIL THEN EXIT;
IF Rope.Equal[thisLine.name, firstForm.name] THEN
FOR entry: MenuEntry ← thisLine, entry.link UNTIL entry = NIL DO
SetGuarded[entry, FALSE]
ENDLOOP;
ENDLOOP;
ViewerOps.PaintViewer[viewer, menu]; -- show as unguarded
viewer.newVersion← FALSE;
ViewerOps.PaintViewer[viewer, caption];
END;
-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
TiogaTextFromStrm: PUBLIC PROC[strm: IO.STREAM, startPos: INT← 0, len: INT← LAST[INT]]
RETURNS[contents: TiogaContents] =
-- returns NIL IF endOfStream encountered during read
BEGIN ENABLE IO.EndOfStream => GOTO TooShort;
fulltext: ROPE;
formatPos: INT;
strm.SetIndex[startPos];
IF len = LAST[INT] THEN len ← strm.GetLength[] - startPos;
fulltext← RopeIO.GetRope[strm, len];
contents← NEW[ViewerTools.TiogaContentsRec];
IF (formatPos← fulltext.Find["\000\000"]) < 0 THEN -- no formatting
{ contents.contents← fulltext; RETURN};
contents.contents← fulltext.Substr[len: formatPos];
contents.formatting← fulltext.Substr[formatPos];
EXITS TooShort => RETURN[NIL];
END;
END.