-- 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.