DIRECTORY Basics, BasicTime, CommanderOps USING [DoCommandRope], Convert, Icons USING [IconFlavor, NewIconFromFile], Idle USING [IsIdle], List USING [Sort, CompareProc, LORA, Remove], Menus USING [AppendMenuEntry, ClickProc, CreateEntry, CreateMenu, GetLine, GetNumberOfLines, Menu, SetLine], Process USING [Detach, Pause, SecondsToTicks], Remind, RemindReset, Rope, ViewerClasses USING [Viewer], ViewerOps USING [BlinkViewer, DestroyViewer], ViewerTools USING [MakeNewTextViewer]; RemindDelivery: CEDAR MONITOR IMPORTS Basics, BasicTime, CommanderOps, Convert, Icons, Idle, List, Menus, Process, Remind, Rope, ViewerOps, ViewerTools EXPORTS RemindReset = BEGIN OPEN Remind; ROPE: TYPE ~ Rope.ROPE; Extras: TYPE = REF ExtrasRec; ExtrasRec: TYPE = RECORD[ ringing: BOOLEAN ¬ FALSE, viewer: ViewerClasses.Viewer ¬ NIL]; ActionItem: TYPE ~ REF ActionItemPrivate; ActionItemPrivate: TYPE ~ RECORD [reminder: Reminder, meeting: Meeting]; secsPerMonth: INT ~ 86400*30; secsPerDay: INT ~ 60*60*24; insideMonitorCnt: INT ¬ 0; remindList: List.LORA ¬ NIL; remindIcon: Icons.IconFlavor ¬ Icons.NewIconFromFile["Remind.icons", 0]; Reset: PUBLIC ENTRY PROC [data: REF ANY] ~ { remindList _ NIL; NoteChange[data]; }; NoteChange: PROC [data: REF ANY] ~ TRUSTED {Process.Detach[FORK ConstructRemindList[]]}; ConstructRemindList: ENTRY PROC = { ENABLE UNWIND => NULL; newMeetList: LIST OF Meeting; newRemindList: List.LORA ¬ NIL; mt: Meeting; newMeetList ¬ ListMeetings[from: BasicTime.Now[].Update[-secsPerDay], to: BasicTime.Now[].Update[secsPerMonth]]; FOR ls: LIST OF Meeting ¬ newMeetList, ls.rest UNTIL ls = NIL DO FOR rl: RemindList ¬ ls.first.reminders, rl.rest WHILE rl#NIL DO rmd: REF ReminderRecord[alert]; lead: INT; WITH rl.first SELECT FROM x: REF ReminderRecord[alert] => rmd ¬ x; x: REF ReminderRecord[mail] => LOOP; ENDCASE => ERROR; lead ¬ BasicTime.Period[rmd.start, ls.first.start]; FOR rlOld: List.LORA ¬ remindList, rlOld.rest UNTIL rlOld = NIL DO WITH rlOld.first SELECT FROM x: ActionItem => IF x.meeting.uniqID=ls.first.uniqID THEN WITH x.reminder SELECT FROM y: REF ReminderRecord[alert] => IF BasicTime.Period[y.start, x.meeting.start]=lead THEN {rl.first.other ¬ y.other; EXIT}; y: REF ReminderRecord[mail] => NULL; ENDCASE => ERROR; x: Meeting => NULL; ENDCASE => ERROR; REPEAT FINISHED => rl.first.other ¬ NEW[ExtrasRec]; ENDLOOP; newRemindList ¬ CONS[NEW[ActionItemPrivate ¬ [rmd, ls.first]], newRemindList]; ENDLOOP; SELECT ls.first.type FROM command, protectedCmd => newRemindList ¬ CONS[ls.first, newRemindList]; none, meeting, seminar => NULL; ENDCASE => ERROR; ENDLOOP; remindList ¬ List.Sort[newRemindList, CompareUsingStartReminding]; }; CompareUsingStartReminding: List.CompareProc = { t1: BasicTime.GMT ~ StartFromRlElt[ref1]; t2: BasicTime.GMT ~ StartFromRlElt[ref2]; RETURN[Basics.CompareInt[0, BasicTime.Period[t1, t2]]]}; StartFromRlElt: PROC [rle: REF ANY] RETURNS [BasicTime.GMT] ~ { WITH rle SELECT FROM x: Meeting => RETURN[x.start]; x: ActionItem => WITH x.reminder SELECT FROM y: REF ReminderRecord[alert] => RETURN[y.start]; y: REF ReminderRecord[mail] => RETURN[y.when]; ENDCASE => ERROR; ENDCASE => ERROR}; PostReminders: PROC = { wait: INT; wait ¬ 30; DO IF NOT Idle.IsIdle[] AND insideMonitorCnt < 3 THEN TRUSTED{Process.Detach[FORK DoPostReminders[]]}; Process.Pause[Process.SecondsToTicks[wait]]; ENDLOOP; }; DoPostReminders: ENTRY PROC = { ENABLE UNWIND => NULL; start, stop, now: BasicTime.GMT; ex: Extras; str: ROPE; viewer: ViewerClasses.Viewer; remindMenu: Menus.Menu; mt: Meeting; rmd: REF ReminderRecord[alert]; cur: List.LORA; insideMonitorCnt ¬ insideMonitorCnt + 1; now ¬ BasicTime.Now[]; FOR cur ¬ remindList, cur.rest WHILE cur#NIL DO WITH cur.first SELECT FROM x: Meeting => {mt ¬ x; start ¬ mt.start}; x: ActionItem => { mt ¬ x.meeting; WITH x.reminder SELECT FROM y: REF ReminderRecord[alert] => {rmd ¬ y; start ¬ y.start; stop ¬ y.stop}; y: REF ReminderRecord[mail] => LOOP; ENDCASE => ERROR}; ENDCASE => ERROR; IF BasicTime.Period[now, start] > 0 THEN EXIT; IF cur.first=mt THEN { IF NOT (mt.type=command OR mt.type=protectedCmd) THEN ERROR; DoCommand[mt]; IF mt.repeat = once THEN remindList ¬ List.Remove[cur.first, remindList] ELSE { UpdateMeeting[mt, FirstOccurrenceAfter[mt.repeat, mt.nth, mt.start, now], FALSE]; rmd.other ¬ NEW[ExtrasRec]; }; } ELSE { ex ¬ NARROW[rmd.other]; IF BasicTime.Period[stop, now] > 0 THEN { IF mt.repeat = once THEN remindList ¬ List.Remove[cur.first, remindList] ELSE { newStart: BasicTime.GMT ~ FirstOccurrenceAfter[mt.repeat, mt.nth, start, now]; diff: INT ~ BasicTime.Period[start, newStart]; rmd.start ¬ newStart; rmd.stop ¬ BasicTime.Update[rmd.stop, diff]; rmd.other ¬ NEW[ExtrasRec]; }; } ELSE { IF ex.viewer = NIL THEN { str ¬ Rope.Cat["Time: ", Convert.RopeFromTime[mt.start], "\nDuration: ", Convert.RopeFromCard[mt.duration], " minutes\n"]; viewer ¬ ViewerTools.MakeNewTextViewer[ info: [ data: IF mt.repeat = once THEN Rope.Cat[str, "\n", mt.explanation] ELSE Rope.Cat[str, "Repeat: ", RopeFromRepetition[mt.repeat], "\n\n", mt.explanation], icon: remindIcon, name: mt.explanation] ]; remindMenu ¬ Menus.CreateMenu[]; Menus.AppendMenuEntry[menu: remindMenu, entry: Menus.CreateEntry["Blinker", ToggleBlinking, ex]]; Menus.SetLine[menu: viewer.menu, line: Menus.GetNumberOfLines[viewer.menu], entryList: Menus.GetLine[remindMenu, 0]]; ex.viewer ¬ viewer; ex.ringing ¬ TRUE; TRUSTED{Process.Detach[FORK BlinkIcon[ex, stop]]}; }; }; }; ENDLOOP; remindList ¬ List.Sort[remindList, CompareUsingStartReminding]; insideMonitorCnt ¬ insideMonitorCnt - 1; RETURN}; ToggleBlinking: Menus.ClickProc = { ex: Extras ¬ NARROW[clientData]; ex.ringing ¬ NOT ex.ringing; RETURN}; BlinkIcon: PROC[ex: Extras, stop: BasicTime.GMT] = { WHILE BasicTime.Period[BasicTime.Now[], stop] >= 0 DO Process.Pause[Process.SecondsToTicks[3]]; IF ex.ringing THEN ViewerOps.BlinkViewer[ex.viewer]; ENDLOOP; ViewerOps.DestroyViewer[ex.viewer]; }; DoCommand: PROC [mt: Meeting] = { out: ROPE; viewer: ViewerClasses.Viewer; [out,] ¬ CommanderOps.DoCommandRope[mt.explanation, NIL, NIL]; viewer ¬ ViewerTools.MakeNewTextViewer[info: [data: out, name: "Calendar command"]]; }; UpdateMeeting: PROC[meeting: Meeting, newTime: BasicTime.GMT, remindersToo: BOOL] = { diff: INT ¬ BasicTime.Period[meeting.start, newTime]; meeting.start ¬ newTime; IF remindersToo THEN FOR rl: RemindList ¬ meeting.reminders, rl.rest WHILE rl#NIL DO WITH rl.first SELECT FROM x: REF ReminderRecord[alert] => { x.start ¬ BasicTime.Update[x.start, diff]; x.stop ¬ BasicTime.Update[x.stop, diff]}; x: REF ReminderRecord[mail] => { x.when ¬ BasicTime.Update[x.when, diff]}; ENDCASE => ERROR; ENDLOOP; RETURN}; RegisterChangeProc[NoteChange, NIL, $RemindDelivery, NIL]; ConstructRemindList[]; TRUSTED { Process.Detach[FORK PostReminders[]]; }; END. l RemindDelivery.mesa Copyright Σ 1990, 1992 by Xerox Corporation. All rights reserved. David Goldberg November 13, 1989 7:59:49 pm PST Peter B. Kessler, January 17, 1990 9:11:14 pm PST Last changed by Pavel on February 12, 1990 5:40:45 pm PST Kenneth A. Pier, August 11, 1992 5:46 pm PDT Theimer, September 17, 1990 11:22 pm PDT Last tweaked by Mike Spreitzer April 30, 1992 11:47 am PDT Willie-s, May 5, 1992 2:14 pm PDT Implements the remind interface, and also contains the PostReminders proc, which runs in the background and pops up reminders Each elt is either a (protected)command Meeting or an ActionItem. The list consists of all (protected)command Meetings, and an ActionItem for every reminder. newMeetList ¬ ListMeetings[from: BasicTime.Now[], to: BasicTime.Now[].Update[secsPerMonth]]; in an attempt to get reminders processed when CalendarTool is first started and a reminder is still active, I have changed ConstructRemindList to as ListMeetings for meetings within one day previous to Now. KAP. August 11, 1992. PROC [ref1: REF ANY, ref2: REF ANY] RETURNS [Comparison] works entirely off of remindList: never looks in LoganBerry. Calls an ENTRY proc to do the real work XXX: put up or blink thing create remind window label: ShortTime[entry.time], PROC [parent: Viewer, clientData: REF ANY _ NIL, mouseButton: MouseButton _ red, shift, control: BOOL _ FALSE]; cmd: Commander.Handle _ CommanderOps.CreateFromStreams[]; Want to open the database when you rollback (no reason database will be the same as when you made the checkpoint). To accomplish this, make sure that database is closed in the checkpoint file. Κ ν•NewlineDelimiter –(cedarcode) style™codešœ™Iproc– "Cedar" stylešœ Οeœ7™BK™/K™1K™9K™,K™(K™:K™!K™—šΟk ˜ Kšœ˜Kšœ ˜ Kšœ žœ˜#Kšœ˜Kšœžœ˜*Kšœžœ ˜Kšœžœžœ ˜-Kšœžœa˜lKšœžœ!˜.Kšœ˜K˜ Kšœ˜Kšœžœ ˜Kšœ žœ˜-Kšœ žœ˜&K˜—KšΠlnœžœž˜š žœrœžœœœœž˜•K˜Kšœ}™}K™—K˜Kšžœ˜ K˜Kšžœžœžœ˜K˜Kšœžœžœ ˜šœ žœžœ˜Kšœ žœžœ˜Kšœžœ˜$K˜—Kšœ žœžœ˜)Kšœžœžœ(˜HK˜K˜Kšœžœ ˜Kšœ žœ ˜K˜Kšœžœ˜šœžœžœ˜KšœA™AKšœ[™[—K˜HK˜š Οnœžœžžœžœžœ˜,Kšœ žœ˜K˜K˜K˜—š  œžœžœžœ˜ Kšœžœžœ˜7—K˜š œžœžœ˜$Kšžœžœžœ˜Kšœ žœžœ ˜Kšœžœžœ˜K˜ K˜K™\K™εK˜pš žœžœžœ žœžœž˜@šžœ.žœžœž˜@Kšœžœ˜Kšœžœ˜ šžœ žœž˜Kšœžœ"˜(Kšœžœžœ˜$Kšžœžœ˜—K˜3š žœ žœžœ žœž˜Bšžœ žœž˜šœžœ!˜4šžœžœ žœž˜ šœžœ˜Kšžœ0˜2Kšžœžœ˜&—Kšœžœžœ˜$Kšžœžœ˜——Kšœžœ˜Kšžœžœ˜—Kšž˜Kšžœžœ ˜,Kšžœ˜—Kšœžœžœ6˜NKšžœ˜—šžœž˜Kšœ)žœ˜GKšœžœ˜Kšžœžœ˜—Kšžœ˜—K˜BKšœ˜—K˜š œ˜0Kš žœžœžœžœžœžœ ™8Kšœžœ˜)Kšœžœ˜)Kšžœ2˜8—K˜š  œžœžœžœžœ žœ˜?šžœžœž˜Kšœžœ ˜šœžœ žœž˜,Kšœžœžœ ˜0Kšœžœžœ ˜.Kšžœžœ˜—Kšžœžœ˜——K˜KšœHΟsœ™fš  œžœ˜Kšœžœ˜ K˜K˜ šž˜Kš žœžœžœžœžœžœ˜cK˜,Kšžœ˜—K˜—K˜š œžœžœ˜Kšžœžœžœ˜Kšœžœ˜ K˜ Kšœžœ˜ Kšœ˜K˜K˜ Kšœžœ˜Kšœ žœ˜K˜K˜(K˜šžœžœžœž˜/šžœ žœž˜K˜)˜K˜šžœ žœž˜KšœžœD˜JKšœžœžœ˜$Kšžœžœ˜——Kšžœžœ˜—Kšžœ"žœžœ˜.šžœžœ˜Kš žœžœžœžœžœ˜K˜TKšœ˜—K˜š  œžœ&žœžœ˜UKšœžœ,˜5K˜šžœ ˜š žœžœ-žœžœž˜Dšžœ žœž˜šœžœ˜!K˜*K˜)—šœžœ˜ K˜)—Kšžœžœ˜—Kšžœ˜——Kšžœ˜—K˜KšœΓ™ΓK˜Kšœžœžœ˜:Kšœ˜šžœ˜ Kšœžœ˜%Kšœ˜—K˜Kšžœ˜—…— *ω