<> 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 = BEGIN 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; }; <> Commander.Register["Remember", Remember, "Register a reminder. Form is: Remember ... at time"]; TRUSTED {Process.Detach[FORK PostRemindButton[]]}; END.