DIRECTORY FS USING [ComponentPositions, Error, ExpandName], Rope USING [ROPE, Run, SkipTo], ViewerClasses USING [Viewer], ViewerEvents USING [EventProc, EventRegistration, ViewerEvent], ViewerPrivate USING [Severity], UserProfile USING [Boolean, GetProfileName, ProfileChanged]; ViewerEventsImpl: CEDAR MONITOR IMPORTS FS, Rope, UserProfile EXPORTS ViewerEvents, ViewerPrivate = BEGIN ROPE: TYPE = Rope.ROPE; EventProcs: TYPE = LIST OF RECORD[proc: ViewerEvents.EventProc, filter: REF, before: BOOL]; ArrayEventProcs: TYPE = ARRAY ViewerEvents.ViewerEvent OF EventProcs; eventProcs: REF ArrayEventProcs _ NEW[ArrayEventProcs _ ALL[NIL]]; Error: PUBLIC SIGNAL [severity: ViewerPrivate.Severity _ fatal, msg: Rope.ROPE _ NIL] = CODE; UserErrorQuery: PUBLIC ENTRY PROC RETURNS [continue: BOOL _ FALSE] = TRUSTED { ENABLE UNWIND => NULL; IF UserProfile.Boolean["Viewers.WorldSwapDebug", FALSE] THEN RETURN [FALSE]; }; RegisterEventProc: PUBLIC ENTRY PROC [proc: ViewerEvents.EventProc, event: ViewerEvents.ViewerEvent, filter: REF _ NIL, before: BOOL _ TRUE] RETURNS [ViewerEvents.EventRegistration] = { RETURN [eventProcs[event] _ CONS[[proc, filter, before], eventProcs[event]]]; }; UnRegisterEventProc: PUBLIC ENTRY PROC [proc: ViewerEvents.EventRegistration, event: ViewerEvents.ViewerEvent] = { newHead: EventProcs _ NIL; newTail: EventProcs _ NIL; FOR each: EventProcs _ eventProcs[event], each.rest WHILE each # NIL DO IF proc # each THEN { new: EventProcs _ LIST[each.first]; IF newTail # NIL THEN newTail.rest _ new ELSE newHead _ new; newTail _ new; }; ENDLOOP; eventProcs[event] _ newHead; }; GetHead: ENTRY PROC [event: ViewerEvents.ViewerEvent] RETURNS [EventProcs] = { RETURN [eventProcs[event]]; }; ProcessEvent: PUBLIC PROC [event: ViewerEvents.ViewerEvent, viewer: ViewerClasses.Viewer, before: BOOL] RETURNS [abort: BOOL _ FALSE] = { FOR l: EventProcs _ GetHead[event], l.rest UNTIL l=NIL DO IF l.first.before = before THEN { filter: REF _ l.first.filter; IF filter = NIL OR filter = viewer OR (viewer # NIL AND filter = viewer.class.flavor) THEN { proc: ViewerEvents.EventProc _ l.first.proc; IF proc # NIL THEN abort _ proc[viewer, event, before ! ABORTED => {abort _ TRUE; EXIT}].abort; IF abort THEN RETURN; }; }; ENDLOOP; }; NoticeProfileChanges: ViewerEvents.EventProc = { IF viewer # NIL THEN { ENABLE FS.Error => GOTO GiveUp; name1: ROPE _ FS.ExpandName[viewer.file].fullFName; bang1: INT _ Rope.SkipTo[name1, 0, "!"]; name2: ROPE _ FS.ExpandName[UserProfile.GetProfileName[]].fullFName; bang2: INT _ Rope.SkipTo[name2, 0, "!"]; IF bang1 # 0 AND bang1 = bang2 AND Rope.Run[name1, 0, name2, 0, FALSE] = bang1 THEN UserProfile.ProfileChanged[edit]; EXITS GiveUp => NULL; }; }; [] _ RegisterEventProc[NoticeProfileChanges, save, $Text, FALSE]; END. NViewerEventsImpl.mesa Copyright c 1985, 1986 by Xerox Corporation. All rights reserved. Doug Wyatt, March 30, 1985 2:48:18 pm PST Russ Atkinson (RRA) May 6, 1986 11:57:28 pm PDT Exports to ViewerPrivate RRA: formerly used to query user as to whether or not to continue when an uncaught error occurs in a paint or TIP notification procedure (not currently used, perhaps this entire module should go away). Exports to ViewerEvents Monitorized CONS onto the head of the list. We don't check for duplicates, and the unique key passed back is the new entry itself. Copy the previous list without the given entry. We copy this to avoid needing to monitorize ProcessEvent (who needs the hassle, after all). This guarantees that the sampling is atomic. Notice that we do not have to monitorize this processing since the sampling of GetHead[event] is atomic and the list is never changed by smashing elements. User profile handling [viewer: ViewerClasses.Viewer, event: ViewerEvent, before: BOOL] RETURNS[abort: BOOL _ FALSE] The profile is the same (except for version info), so notify about a change Κƒ– "Mesa" style˜codešœ™Kšœ Οmœ7™BK™)K™/K˜šΟk ˜ Kšžœžœ)˜1Kšœžœžœ˜Kšœžœ ˜Kšœ žœ-˜?Kšœžœ ˜Kšœ žœ+˜<——K˜šΠblœžœž˜Kšžœžœ˜Kšžœ˜#Kšœž˜—˜Kšžœžœžœ˜Kš œ žœžœžœžœ'žœ žœ˜[Kšœžœžœžœ ˜EKš œ žœžœžœžœ˜B—K˜šœ™K˜Kš œžœžœ6žœžœžœ˜]K˜šΟnœžœžœžœžœ žœžœžœ˜NK™ΙKšžœžœžœ˜Kš žœ/žœžœžœžœ˜LKšœ˜K˜——šœ™K˜š œžœžœžœJžœžœ žœžœžœ%˜ΊKšœ žœs™ƒKšžœžœ-˜MKšœ˜K˜—š œžœžœžœL˜rKšœŒ™ŒKšœžœ˜Kšœžœ˜šžœ1žœžœž˜Gšžœ žœ˜Kšœžœ ˜#Kšžœ žœžœžœ˜