-- File: WalnutSendOpsImpl.mesa
-- Contents: More procs for WalnutSend
-- Created by Willie-Sue, December 13, 1983

-- Last Edited by: Willie-Sue, December 13, 1983 2:04 pm

DIRECTORY
GVAnswer USING [MakeHeader],
Menus,
IO,
Rope,
RopeIO USING [GetRope],
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,
  GVAnswer,
Menus,
RopeIO, TiogaOps,
ViewerOps,
WalnutSendInternal, WalnutSendOps
EXPORTS
WalnutSendInternal, WalnutSendOps
SHARES Menus =

BEGIN OPEN WalnutSendOps, WalnutSendInternal;

-- ************************************************************************
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
  { SenderReport[IO.PutFR[
    "\nSyntax error in line previous to line containing pos %g (in message being answered)",
     IO.int[errorIndex]]];
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];
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];
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: INTLAST[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.