-- TEditTouchupImpl.mesa, last edit by Paxton on May 23, 1983 11:27 am
Last Edited by: Maxwell, January 6, 1983 11:38 am
DIRECTORY
TEditTouchup,
Process USING [Ticks, MsecToTicks, SetTimeout],
Rope USING [ROPE],
TEditDocument USING [SpinAndLock, TEditDocumentData, Unlock],
TextNode USING [Ref],
TEditLocks USING [Lock, LockRef, Unlock, WaitingForWrite];
TEditTouchupImpl: CEDAR MONITOR
IMPORTS TEditDocument, TEditLocks, Process
EXPORTS TEditTouchup = BEGIN
fullUpdate: PUBLIC REF ANY ← $Update;
refresh: PUBLIC REF ANY ← $Refresh;
RefreshOver: PUBLIC ENTRY PROC = { ENABLE UNWIND => NULL; BROADCAST refreshOver };
LockAfterScroll: PUBLIC PROC [tdd: TEditDocument.TEditDocumentData, who: Rope.ROPE]
RETURNS [ok: BOOL] = { RETURN [LockAfter[tdd, who, TRUE]] };
LockAfterRefresh: PUBLIC PROC [tdd: TEditDocument.TEditDocumentData, who: Rope.ROPE]
RETURNS [ok: BOOL] = { RETURN [LockAfter[tdd, who, FALSE]] };
LockAfter: PROC [tdd: TEditDocument.TEditDocumentData, who: Rope.ROPE, scroll: BOOL]
RETURNS [ok: BOOL] = {
lock: TEditLocks.LockRef;
doc: TextNode.Ref;
WaitForRefresh: ENTRY PROC RETURNS [BOOL] = {
ENABLE UNWIND => NULL;
If scroll, then wait for ~tdd.dirty and tdd.scroll=no which means have done scroll.
count: NAT ← 0;
WHILE tdd.dirty AND (~scroll OR tdd.scroll=no) DO -- wait for refresh to finish
IF (count ← count+1) > 5 THEN RETURN [FALSE]; -- don't wait more than 5 seconds
IF TEditLocks.WaitingForWrite[lock] THEN RETURN [FALSE]; -- change of plans
Refresh will not complete because of pending edit. Must release read lock so edit can take place.
IF tdd.invisible THEN RETURN [FALSE];
Never will be refreshed.
WAIT refreshOver; -- let refresh complete first
ENDLOOP;
RETURN [TRUE] };
[] ← TEditDocument.SpinAndLock[tdd, "LockAfterRefresh1"]; -- lock it before read tdd.text
doc ← tdd.text;
TEditDocument.Unlock[tdd]; -- need to unlock it again so refresh can take place while we wait
IF doc=NIL THEN RETURN [FALSE]; -- hasn't been initialized?
lock ← TEditLocks.Lock[doc, who, read];
must do this before acquire monitor lock
IF ~WaitForRefresh[] THEN { TEditLocks.Unlock[doc]; RETURN [FALSE] };
[] ← TEditDocument.SpinAndLock[tdd, "LockAfterRefresh2"];
IF tdd.text # doc THEN { -- it changed while we had tdd unlocked
TEditLocks.Unlock[doc]; TEditDocument.Unlock[tdd]; RETURN [FALSE] };
RETURN [TRUE];
};
UnlockAfterRefresh: PUBLIC PROC [tdd: TEditDocument.TEditDocumentData] = {
IF tdd.text#NIL THEN TEditLocks.Unlock[tdd.text]; TEditDocument.Unlock[tdd] };
refreshOver: CONDITION;
aLittleWhile: Process.Ticks = Process.MsecToTicks[1000];
TRUSTED {Process.SetTimeout[@refreshOver, aLittleWhile]}; -- recheck for refresh over every second
END.