<> <> DIRECTORY BasicTime, IO, IODefs, Menus, MessageWindow, Process, Rope, ViewerClasses, ViewerEvents, ViewerIO, ViewerOps; IODefsImpl: CEDAR MONITOR IMPORTS IO, Menus, MessageWindow, Process, ViewerEvents, ViewerIO, ViewerOps EXPORTS IODefs = BEGIN log: PUBLIC IO.STREAM _ NIL; WriteString: PUBLIC PROC [s: Rope.ROPE] = {Log[].PutRope[s ! IO.Error => {ResetLog[]; RETRY}]}; WriteLine: PUBLIC PROC [s: Rope.ROPE] = {Log[].PutF["%g\n", IO.rope[s] ! IO.Error => {ResetLog[]; RETRY}]}; WriteChar: PUBLIC PROC [c: CHARACTER] = {Log[].PutChar[c ! IO.Error => {ResetLog[]; RETRY}]}; WriteDecimal: PUBLIC PROC [n: INT] = {Log[].PutF["%g", IO.int[n] ! IO.Error => {ResetLog[]; RETRY}]}; WriteReal: PUBLIC PROC [r: REAL] = {Log[].PutF["%g", IO.real[r] ! IO.Error => {ResetLog[]; RETRY}]}; PrintTime: PUBLIC PROC [msg: Rope.ROPE _ NIL] = {Log[].PutF["%g %g\n", IO.rope[msg], IO.time[] ! IO.Error => {ResetLog[]; RETRY}]}; PostIt: PUBLIC ENTRY PROC [s: Rope.ROPE] = {ENABLE UNWIND => NULL; postee _ s; CheckStop[]}; Log: PROC RETURNS [ IO.STREAM ] = BEGIN WHILE log = NIL DO menuEntry: Menus.MenuEntry = Menus.CreateEntry[name: "STOP!", proc: NoticeStop, guarded: TRUE]; viewer: ViewerClasses.Viewer; doStop _ FALSE; log _ ViewerIO.CreateViewerStreams[name: "MPC Log", backingFile: "MPC.log"].out; viewer _ ViewerIO.GetViewerFromStream[log]; [] _ Menus.InsertMenuEntry[menu: viewer.menu, entry: menuEntry]; ViewerOps.PaintViewer[viewer, menu]; [] _ ViewerEvents.RegisterEventProc[proc: CloseOutputStream, event: destroy, filter: viewer]; log.PutF["MPC.log of %g...\n\n", IO.time[]]; ENDLOOP; CheckStop[]; RETURN[log]; END; doStop: BOOL _ FALSE; CheckStop: PROC = {IF doStop THEN {doStop _ FALSE; ERROR ABORTED}}; NoticeStop: PROC [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift, control: BOOL _ FALSE] -- Menus.ClickProc -- = {doStop _ TRUE}; CloseOutputStream: PROC [viewer: ViewerClasses.Viewer, event: ViewerEvents.ViewerEvent, before: BOOL] RETURNS [abort: BOOL _ FALSE] -- ViewerEvents.EventProc -- = {ResetLog[]}; ResetLog: PROC = {IF log # NIL THEN log.Close[ ! IO.Error => CONTINUE ]; log _ NIL}; postee: Rope.ROPE _ NIL; posteeReady: CONDITION; Poster: ENTRY PROC = BEGIN ENABLE UNWIND => NULL; lastPostee: Rope.ROPE _ NIL; DO IF log#NIL THEN log.Flush[ ! IO.Error => CONTINUE ]; IF postee # NIL OR lastPostee # NIL THEN BEGIN MessageWindow.Append[message: postee, clearFirst: TRUE]; lastPostee _ postee; postee _ NIL; END; WAIT posteeReady; ENDLOOP; END; TRUSTED BEGIN Process.InitializeCondition[condition: @posteeReady, ticks: Process.SecondsToTicks[2]]; Process.Detach[FORK Poster[]]; END; END.