ReminderOpsImpl.mesa; Edited by Teitelman on June 22, 1983 9:49 am
DIRECTORY
Commander USING [Register, CommandProc, Handle],
CommandProcOps USING [EventFailed],
IO USING [STREAM, Flush, SkipOver, RIS, WhiteSpace, GetToken],
IOExtras USING [GetLine],
Menus USING [AppendMenuEntry, ReplaceMenuEntry, MenuEntry, FindEntry, ClickProc, CreateEntry, Menu],
MessageWindow USING [Append, Blink],
PeanutWindow USING [AddCommand],
Process USING [Pause, Detach, SecondsToTicks],
ReminderDefs USING [Error, Parameter, ReadParameters, RegisterEvent],
ReminderDefsPrivate USING [peanutUser, walnutUser],
Rope USING [ROPE, Cat, Concat, Equal, Find, Substr, Length],
Runtime USING [IsBound],
TiogaOps USING [SaveSelB, SelectPoint, ViewerDoc, FirstChild, FindWord, RestoreSelB, Location, GetSelection, GetRope, Ref, Parent],
ViewerIO USING [CreateMessageWindowStream],
WalnutDisplayerOps USING [GetMsgName, msgMenu, msgMenuAvailable],
ViewerTools USING [GetSelectionContents],
ViewerClasses USING [Viewer]
;
ReminderOpsImpl: CEDAR PROGRAM
IMPORTS Commander, CommandProcOps, IO, IOExtras, Menus, MessageWindow, PeanutWindow, Process, Rope, ReminderDefs, ReminderDefsPrivate, Runtime, TiogaOps, ViewerIO, ViewerTools, WalnutDisplayerOps
SHARES ReminderDefsPrivate
ROPE: TYPE = Rope.ROPE;
Remember: Commander.CommandProc = {
err, offender: ROPE;
h: IO.STREAM = IO.RIS[cmd.commandLine];
token, line: ROPE;
parameters: LIST OF REF ReminderDefs.Parameter;
i: INT;
token ← h.GetToken[IO.WhiteSpace];
IF Rope.Equal[token, "to",
FALSE]
THEN {
-- more aesthetic for reminder to say phone mumble then to phone mumble.
h.SkipOver[IO.WhiteSpace];
line ← IOExtras.GetLine[h];
}
ELSE line ← Rope.Concat[token, IOExtras.GetLine[h]];
{
ENABLE ReminderDefs.Error =>
{
IF ec = timeRopeFormatError THEN err ← ""
ELSE IF ec = formatError THEN err ← "Format Error: "
ELSE IF ec = timeNotSpecified THEN err ← "No Time Specified"
ELSE REJECT;
offender ← msg;
GOTO Out;
};
IF (i ← Rope.Find[line, "/"]) # -1
THEN {
parameters ← ReminderDefs.ReadParameters[IO.RIS[Rope.Substr[base: line, start: i + 1]]];
line ← Rope.Substr[base: line, len: i];
};
ReminderDefs.RegisterEvent[parameters: parameters, scanThis: line, out: cmd.out];
EXITS Out => NULL;
};
IF err # NIL THEN CommandProcOps.EventFailed[handle: cmd, msg: Rope.Concat[err, offender], offender: offender] ;
};
stream: IO.STREAM ← NIL;
RemindProc: Menus.ClickProc =
TRUSTED {
viewer: ViewerClasses.Viewer = NARROW[parent];
text, messageName, err, sel: ROPE;
parameters: LIST OF REF ReminderDefs.Parameter;
i: INT;
messageName ← WalnutDisplayerOps.GetMsgName[viewer];
sel ← ViewerTools.GetSelectionContents[];
TiogaOps.SaveSelB[];
TiogaOps.SelectPoint[viewer: viewer, caret: [TiogaOps.FirstChild[TiogaOps.ViewerDoc[viewer]], 0]];
IF TiogaOps.FindWord[viewer: viewer, rope: "Subject:"]
THEN {
end: TiogaOps.Location;
i: INT;
[, , end] ← TiogaOps.GetSelection[];
text ← TiogaOps.GetRope[end.node];
text ← Rope.Substr[base: text, start: end.where + 1];
IF (i ← Rope.Find[text, "\n"]) # -1 THEN text ← Rope.Substr[base: text, len: i];
};
TiogaOps.RestoreSelB[];
IF (i ← Rope.Find[sel, "/"]) # -1
THEN {
parameters ← ReminderDefs.ReadParameters[IO.RIS[Rope.Substr[base: sel, start: i + 1]]];
sel ← Rope.Substr[base: sel, len: i];
};
IF stream = NIL THEN stream ← ViewerIO.CreateMessageWindowStream[];
ReminderDefs.RegisterEvent[
scanThis: Rope.Cat[sel, " / ", text],
parameters:
CONS[
NEW[ReminderDefs.Parameter ← [text, text]],
CONS[NEW[ReminderDefs.Parameter ← [message, messageName]], parameters]],
out: stream
! ReminderDefs.Error =>
{
SELECT ec
FROM
timeRopeFormatError => err ← Rope.Concat["TimeAndDate is ", msg];
timeNotSpecified => err ← "Specify (select) a time for the event.";
formatError => err ← Rope.Concat["Format Error: ", msg];
ENDCASE => REJECT;
CONTINUE;
};
];
IF err #
NIL
THEN {
MessageWindow.Append[err, TRUE];
MessageWindow.Blink[];
}
ELSE stream.Flush[];
};
PeanutRemindProc: Menus.ClickProc =
TRUSTED {
text, err, sel: ROPE;
parameters: LIST OF REF ReminderDefs.Parameter;
i: INT;
mailViewer: ViewerClasses.Viewer;
messageNode: TiogaOps.Ref;
start, end: TiogaOps.Location;
[mailViewer, start, end] ← TiogaOps.GetSelection[];
IF mailViewer =
NIL
OR Rope.Find[mailViewer.name, ".mail"] = -1
THEN {
MessageWindow.Append["First make a selection in the corresponding message.", TRUE];
MessageWindow.Blink[];
RETURN;
};
messageNode ← start.node;
DO
r: TiogaOps.Ref ← TiogaOps.Parent[messageNode];
IF r = NIL OR TiogaOps.Parent[r] = NIL THEN EXIT;
messageNode ← r;
ENDLOOP;
TiogaOps.SaveSelB[];
TiogaOps.SelectPoint[viewer: mailViewer, caret: [messageNode, 0]];
IF TiogaOps.FindWord[viewer: mailViewer, rope: "Subject:"]
THEN {
end: TiogaOps.Location;
i: INT;
[, , end] ← TiogaOps.GetSelection[];
text ← TiogaOps.GetRope[end.node];
text ← Rope.Substr[base: text, start: end.where + 1];
IF (i ← Rope.Find[text, "\n"]) # -1 THEN text ← Rope.Substr[base: text, len: i];
};
TiogaOps.RestoreSelB[];
sel ← ViewerTools.GetSelectionContents[];
IF Rope.Length[sel] = 1 THEN sel ← NIL;
IF (i ← Rope.Find[sel, "/"]) # -1
THEN {
parameters ← ReminderDefs.ReadParameters[IO.RIS[Rope.Substr[base: sel, start: i + 1]]];
sel ← Rope.Substr[base: sel, len: i];
};
IF stream = NIL THEN stream ← ViewerIO.CreateMessageWindowStream[]; -- first time
ReminderDefs.RegisterEvent[
scanThis: Rope.Cat[sel, " / ", text],
parameters:
CONS[
NEW[ReminderDefs.Parameter ← [text, text]],
CONS[
NEW[ReminderDefs.Parameter ←
[
message,
Rope.Cat[mailViewer.name, " ", TiogaOps.GetRope[messageNode]]
]],
parameters]],
out: stream
! ReminderDefs.Error =>
{
SELECT ec
FROM
timeRopeFormatError => err ← Rope.Concat["TimeAndDate is ", msg];
timeNotSpecified => err ← "Specify (select) a time for the event.";
formatError => err ← Rope.Concat["Format Error: ", msg];
ENDCASE => REJECT;
CONTINUE;
};
];
IF err #
NIL
THEN {
MessageWindow.Append[err, TRUE];
MessageWindow.Blink[];
}
ELSE stream.Flush[];
};
MenuEntry:
PROC [menu: Menus.Menu, name:
ROPE, proc: Menus.ClickProc] = {
entry: Menus.MenuEntry = Menus.CreateEntry[name: name, proc: proc, fork: FALSE];
oldEntry: Menus.MenuEntry = Menus.FindEntry[menu, name];
IF oldEntry = NIL THEN Menus.AppendMenuEntry[menu: menu, entry: entry]
ELSE Menus.ReplaceMenuEntry[menu: menu, oldEntry: oldEntry, newEntry: entry];
};
PostRemindButton:
PROC =
TRUSTED {
DO
IF Runtime.IsBound[WalnutDisplayerOps.GetMsgName]
AND WalnutDisplayerOps.msgMenuAvailable
THEN {
MenuEntry[WalnutDisplayerOps.msgMenu, "Remind", RemindProc];
ReminderDefsPrivate.walnutUser ← TRUE;
EXIT;
}
ELSE
IF Runtime.IsBound[PeanutWindow.AddCommand]
THEN {
PeanutWindow.AddCommand[name: "Remind", proc: PeanutRemindProc, fork: FALSE];
ReminderDefsPrivate.peanutUser ← TRUE;
EXIT;
};
Process.Pause[Process.SecondsToTicks[10]];
ENDLOOP;
};
Initialization
Commander.Register["Remember", Remember, "Register a reminder. Form is: Remember ... at time"];
TRUSTED {Process.Detach[
FORK PostRemindButton[]]};
END.