DIRECTORY
Carets USING [ResumeCarets, SuspendCarets],
ColorWorld USING [NewContext],
Graphics USING [black, ClipBox, Context, DrawBox, DrawRope,
FontRef, Mark, NewContext, nullMark, PaintMode, Restore, Save,
Scale, SetColor, SetCP, SetDefaultFont, SetPaintMode, Translate, white],
GraphicsOps USING [Disable],
IconManager USING [selectedIcon],
Icons USING [DrawIcon],
Menus USING [],
MenusPrivate USING [DrawMenu],
Process USING [Detach, GetCurrent, MsecToTicks, Pause, Ticks],
Rope USING [ROPE],
VFonts USING [defaultFont, defaultGFont, StringWidth],
ViewerOps,
ViewerClasses,
ViewerLocks USING [CallUnderReadLock, CallUnderWriteLock, ColumnWedged, Wedged], 
ViewerSpecs,
ViewersStallNotifier,
ViewerTools USING [GetSelectedViewer];

ViewerPaintImpl: CEDAR MONITOR

IMPORTS Carets, ColorWorld, Graphics, GraphicsOps, IconManager, Icons, MenusPrivate, Process, VFonts, ViewerLocks, ViewerTools, ViewerOps, ViewerSpecs
EXPORTS ViewerOps, ViewersStallNotifier
SHARES Menus, ViewerClasses, ViewerLocks =

BEGIN OPEN Graphics, ViewerClasses, ViewerOps, ViewerSpecs;

InvisiblePaint: PUBLIC SIGNAL = CODE;

PaintDocumentHeader: PROC [viewer: Viewer, context: Context, clear: BOOL, hint: PaintHint, whatChanged: REF ANY] =
BEGIN OPEN viewer;
wbs: INTEGER = IF viewer.border THEN windowBorderSize ELSE 0;
ClipBox[context, [wx, wy, wx+ww, wy+wh]];
IF hint#menu THEN BEGIN
IF viewer.class.caption#NIL THEN BEGIN	-- client-painted caption
mark: Mark _ Save[context];
ClipBox[context, [wx+wbs, wy+wh-captionHeight-wbs, wx+ww-(2*wbs),
wy+wh-wbs]];
viewer.class.caption[viewer, context];
Restore[context, mark];
END
ELSE BEGIN
headerW: INTEGER _ VFonts.StringWidth[name];
IF viewer.saveInProgress THEN headerW _ headerW + sipW
ELSE IF viewer.newFile THEN headerW _ headerW + newFW
ELSE IF viewer.newVersion THEN headerW _ headerW + newVW;
IF viewer.link#NIL THEN headerW _ headerW + linkW;
headerW _ MIN[headerW, ww];
DrawBox[context, XYWH2Box[wx, wy+wh-captionHeight, ww, captionHeight]];
SetColor[context, white];
SetCP[context, wx+((ww-headerW)/2), wy+wh-captionHeight+4];
DrawRope[context, name];
IF viewer.saveInProgress THEN DrawRope[context, sipT]
ELSE IF viewer.newFile THEN DrawRope[context, newFT]
ELSE IF viewer.newVersion THEN DrawRope[context, newVT];
IF viewer.link#NIL THEN DrawRope[context, linkT];
END;
END;
IF menu#NIL AND hint#caption THEN BEGIN
height: INTEGER _ menu.linesUsed*menuHeight;
IF whatChanged=NIL THEN BEGIN
IF ~clear THEN BEGIN
SetColor[context, white];
DrawBox[context, XYWH2Box[wx+wbs, wy+wh-captionHeight-height,
ww-(2*wbs), height]];
END;
SetColor[context, black];
DrawBox[context, XYWH2Box[wx, wy+wh-captionHeight-height-windowBorderSize,
ww, menuBarHeight]];
END;
MenusPrivate.DrawMenu[viewer.menu, context, wx+wbs,
wy+wh-menuHeight-captionHeight, whatChanged];
END;
END;

PaintIcon: PROC [viewer: Viewer, hint: PaintHint, whatChanged: REF ANY _ NIL] = BEGIN
context: Context;
label: Rope.ROPE;

IF viewer.parent#NIL THEN RETURN;

context _ AcquireContext[viewer, FALSE];	-- all icons on b&w display

IF viewer.icon=private THEN viewer.class.paint[viewer, context, whatChanged, hint=all]

ELSE IF hint=all OR hint=caption THEN BEGIN
mark: Mark _ Save[context];	-- since Icons.DrawIcon will set clipper
IF viewer.icon=document AND (viewer.newVersion OR viewer.newFile) THEN
viewer.icon _ dirtyDocument
ELSE IF viewer.icon=dirtyDocument AND NOT (viewer.newVersion OR viewer.newFile) THEN
viewer.icon _ document;
label _ NARROW[ViewerOps.FetchProp[viewer, $IconLabel]];
IF label = NIL THEN label _ viewer.name;
Icons.DrawIcon[flavor: viewer.icon, context: context, label: label];
Restore[context, mark];
IF IconManager.selectedIcon=viewer THEN BEGIN
[] _ SetPaintMode[context, invert];
DrawBox[context, [0, 0, iconWidth, iconHeight]];
END;
END;

ReleaseContext[context];
END;

SetIconLabel: PUBLIC PROC [viewer: Viewer, label: Rope.ROPE] = BEGIN
ViewerOps.AddProp[viewer, $IconLabel, label];
END;

RecursivelyPaintViewers: PROC [viewer: Viewer, hint: PaintHint, clearClient: BOOL,
clear: BOOL, rect: PaintRectangle, whatChanged: REF ANY] = BEGIN OPEN viewer;
vx, vy: INTEGER;
context: Context _ NIL;
bitmapY: INTEGER _ 0;

FOR v: Viewer _ viewer, v.parent UNTIL v=NIL DO	-- visibility test
IF v.parent#NIL THEN BEGIN
IF (v.wy+v.wh < 0) OR (v.wy > v.parent.ch) THEN RETURN;
IF (v.ww+v.ww < 0) OR (v.wx > v.parent.cw) THEN RETURN;
END
ENDLOOP;

IF hint#client THEN BEGIN
ENABLE UNWIND => IF context#NIL THEN ReleaseContext[context];
context _ AcquireContext[parent, viewer.column=color];
IF ~viewer.visible OR viewer.destroyed THEN SIGNAL InvisiblePaint;
IF clearClient AND ~clear AND hint=all THEN BEGIN
SetColor[context, white];
DrawBox[context, XYWH2Box[wx, wy, ww, wh]];
SetColor[context, black];
clear _ TRUE;
END;
IF border AND hint=all THEN BEGIN
wbs: INTEGER ~ windowBorderSize;
DrawBox[context, XYWH2Box[wx, wy, ww, wbs]];
DrawBox[context, XYWH2Box[wx, wy, wbs, wh]];
DrawBox[context, XYWH2Box[wx+ww-wbs, wy, wbs, wh]];
DrawBox[context, XYWH2Box[wx, wy+wh-wbs, ww, wbs]];
END;
IF parent=NIL AND viewer.column#static 
THEN PaintDocumentHeader[viewer, context, clear, hint, whatChanged];
ReleaseContext[context];
END;

IF hint=all OR hint=client THEN BEGIN
ENABLE UNWIND => IF context#NIL THEN ReleaseContext[context];
context _ NIL; context _ AcquireContext[viewer, viewer.column=color];
IF ~viewer.visible OR viewer.destroyed THEN SIGNAL InvisiblePaint;
IF rect#NIL AND class.bltContents = none THEN clearClient _ TRUE;
IF clearClient AND ~clear THEN BEGIN
SetColor[context, white];
DrawBox[context, [0, 0, cw, ch]];
SetColor[context, black];
IF rect # NIL THEN whatChanged _ NIL;
rect _ NIL;
clear _ TRUE;
END;
IF class.paint#NIL THEN class.paint[viewer, context, whatChanged, clear];
ReleaseContext[context];
END;

IF rect # NIL AND viewer.parent = NIL THEN {  
IF viewer.cx >= rect.x AND (viewer.cx + viewer.cw <= rect.x + rect.w) AND
viewer.cy >= rect.y AND (viewer.cy + viewer.ch <= rect.y + rect.h) THEN RETURN};

IF hint=all OR hint=client OR clear THEN
FOR v: Viewer _ viewer.child, v.sibling UNTIL v=NIL DO
IF rect # NIL THEN { -- don't paint if it is completely within the blt 
-- map to the coodinate system that rect uses
IF viewer.class.coordSys = top 
THEN [vx, vy] _ ViewerOps.UserToScreenCoords[viewer, v.wx, v.wy+v.wh]
ELSE [vx, vy] _ ViewerOps.UserToScreenCoords[viewer, v.wx, v.wy];
IF vx >= rect.x AND (vx + v.ww <= rect.x + rect.w) AND
vy >= rect.y AND (vy + v.wh <= rect.y + rect.h) THEN LOOP};
RecursivelyPaintViewers[v, all, FALSE, clear, rect, whatChanged];
ENDLOOP;

END;

PaintViewer: PUBLIC PROC [viewer: Viewer, hint: PaintHint _ client, clearClient: BOOL _ TRUE,
whatChanged: REF ANY _ NIL] = BEGIN
LocalPaintViewer: PROC  = {
ENABLE ABORTED => {Carets.ResumeCarets[]; CONTINUE};
rect: PaintRectangle;
IF ~viewer.visible OR viewer.destroyed THEN RETURN;
IF viewer.iconic THEN {PaintIcon[viewer, hint, whatChanged]; RETURN};
Carets.SuspendCarets[];
IF ISTYPE[whatChanged, PaintRectangle] THEN rect _ NARROW[whatChanged];
RecursivelyPaintViewers[viewer, hint, clearClient AND ~(hint=menu OR hint=caption),
FALSE, rect, whatChanged ! InvisiblePaint => CONTINUE];
Carets.ResumeCarets[]};
ViewerLocks.CallUnderReadLock[LocalPaintViewer, viewer ! ViewerLocks.Wedged => CONTINUE];
END;


PaintVector: TYPE = REF PaintVectorRec;
PaintVectorRec: TYPE = RECORD [
next: PaintVector _ NIL,
viewer: Viewer _ NIL,
inUse: BOOL _ FALSE,
resetOnRelease: BOOL _ FALSE,
color: BOOL _ FALSE,
mark: Graphics.Mark _ nullMark,
process: UNSAFE PROCESS _ NIL,
context: Context _ NIL,
previous: PaintVector _ NIL];

nVectors: CARDINAL = 5;
usedVectors: CARDINAL _ 0;
PaintVectorAvailable: CONDITION;
paintingLock: CARDINAL _ 0;

vectorRoot: PaintVector _ NIL;
colorVector: PaintVector _ NIL;

Init: ENTRY PROC = BEGIN
new: PaintVector;
FOR n: CARDINAL IN [0..nVectors) DO
new _ NEW[PaintVectorRec];
new.context _ NewContext[];
SetDefaultFont[new.context, VFonts.defaultGFont];
new.next _ vectorRoot;
IF vectorRoot#NIL THEN vectorRoot.previous _ new;
vectorRoot _ new;
ENDLOOP;
newFW _ VFonts.StringWidth[newFT];
newVW _ VFonts.StringWidth[newVT];
linkW _ VFonts.StringWidth[linkT];
sipW _ VFonts.StringWidth[sipT];
colorVector _ NEW[PaintVectorRec];
colorVector.color _ TRUE;
END;

colorInit: BOOL _ FALSE;

InitialiseColorPainting: PUBLIC PROC = BEGIN
ColorCriticalInit: ENTRY PROC = BEGIN
colorVector.context _ ColorWorld.NewContext[];
SetDefaultFont[colorVector.context, VFonts.defaultGFont];
colorInit _ TRUE;
END;
ColorCriticalInit[];
ViewerOps.GreyScreen[0, 0, 9999, 9999, TRUE, FALSE];
END;

ZapVector: INTERNAL PROC [p: PaintVector] = BEGIN
oldContext: Context _ p.context;
p.context _ IF p.color THEN ColorWorld.NewContext[] ELSE NewContext[];
Graphics.SetDefaultFont[p.context, VFonts.defaultGFont];
p.viewer _ NIL;
p.inUse _ FALSE;
p.process _ NIL;
p.mark _ nullMark;
IF ~p.color THEN usedVectors _ usedVectors - 1;
GraphicsOps.Disable[oldContext];	-- smash old
BROADCAST PaintVectorAvailable;
END;

UnWedgePainter: PUBLIC ENTRY PROC [process: PROCESS, kind: ATOM] = BEGIN
ENABLE UNWIND => NULL;
IF colorVector.inUse AND colorVector.process=process THEN ZapVector[colorVector]
ELSE FOR p: PaintVector _ vectorRoot, p.next UNTIL p=NIL DO
IF p.inUse AND p.process=process THEN ZapVector[p];
ENDLOOP;
END;

UnWedge: ENTRY PROC [process: PROCESS, kind: ATOM] = BEGIN
IF colorVector.inUse THEN ZapVector[colorVector]
ELSE FOR p: PaintVector _ vectorRoot, p.next UNTIL p=NIL DO
IF p.inUse THEN ZapVector[p];
ENDLOOP;
usedVectors _ 0;	-- make sure
paintingLock _ 0;	-- make sure
BROADCAST PaintVectorAvailable;
END;

DisablePainting: PUBLIC ENTRY PROC [wait: BOOL _ TRUE] = BEGIN
ENABLE UNWIND => NULL;
InternalDisablePainting[wait];
END;
InternalDisablePainting: INTERNAL PROC [wait: BOOL _ TRUE] = INLINE BEGIN
IF wait THEN
WHILE usedVectors#0 OR colorVector.inUse DO WAIT PaintVectorAvailable; 
ENDLOOP;
paintingLock _ paintingLock+1;
END;

EnablePainting: PUBLIC ENTRY PROC = BEGIN
ENABLE UNWIND => NULL;
InternalEnablePainting[];
END;
InternalEnablePainting: INTERNAL PROC = INLINE BEGIN
IF paintingLock#0 THEN paintingLock _ paintingLock-1;
IF paintingLock=0 THEN BROADCAST PaintVectorAvailable;
END;

DisablePaintingUnWedged: INTERNAL PROC [wait: BOOL _ TRUE] = INLINE BEGIN
AllWedged: INTERNAL PROC RETURNS[BOOL] = INLINE BEGIN
IF colorVector.inUse THEN BEGIN
IF colorVector.viewer=NIL THEN RETURN[FALSE]; -- context = screen
IF ~ViewerLocks.ColumnWedged[color].wedged THEN RETURN[FALSE];
END;
FOR p: PaintVector _ vectorRoot, p.next UNTIL p=NIL DO
IF ~p.inUse THEN LOOP;
IF p.viewer = NIL THEN RETURN[FALSE]; -- context = screen
IF ~ViewerLocks.ColumnWedged[ViewerColumn[p.viewer]].wedged THEN RETURN[FALSE];
ENDLOOP;
RETURN[TRUE];
END;

IF wait THEN
WHILE usedVectors#0 OR colorVector.inUse DO 
IF AllWedged[] THEN EXIT ELSE WAIT PaintVectorAvailable; 
ENDLOOP;
paintingLock _ paintingLock+1;
END;

WaitForPaintingToFinish: PUBLIC ENTRY PROC = BEGIN
WHILE usedVectors#0 AND colorVector.inUse DO WAIT PaintVectorAvailable ENDLOOP;
END;

ResetPaintCache: PUBLIC ENTRY PROC [viewer: Viewer _ NIL, wait: BOOL _ TRUE] = BEGIN
ENABLE UNWIND => NULL;
DisablePaintingUnWedged[wait];
FOR p: PaintVector _ vectorRoot, p.next UNTIL p=NIL DO
IF p.inUse THEN BEGIN
IF p.viewer = NIL OR ~ViewerLocks.ColumnWedged[ViewerColumn[p.viewer]].wedged 
THEN IF wait THEN RETURN WITH ERROR fatalViewersError;
p.resetOnRelease _ TRUE;
END
ELSE IF p.viewer#NIL THEN BEGIN
ResetContext[p.context];
p.viewer _ NIL;
END;
ENDLOOP;
IF colorVector.context#NIL THEN BEGIN
IF colorVector.inUse AND ~ViewerLocks.ColumnWedged[color].wedged THEN BEGIN
IF wait THEN RETURN WITH ERROR fatalViewersError;
colorVector.resetOnRelease _ TRUE;
END
ELSE IF colorVector.viewer#NIL THEN BEGIN
ResetContext[colorVector.context];
colorVector.viewer _ NIL;
END;
END;
InternalEnablePainting[];
END;

fatalViewersError: ERROR = CODE;

ReleaseContext: PUBLIC ENTRY PROC [free: Context] = BEGIN
ENABLE UNWIND => NULL;
CleanUp: INTERNAL PROC [p: PaintVector] = BEGIN
Restore[free, p.mark];	-- throw away any client changes
p.inUse _ FALSE;
p.mark _ nullMark;
IF ~p.color THEN {IF usedVectors=0 THEN RETURN WITH ERROR fatalViewersError
ELSE usedVectors _ usedVectors-1};
IF p.resetOnRelease THEN BEGIN
ResetContext[p.context];
p.viewer _ NIL;
p.resetOnRelease _ FALSE;
END;
p.process _ NIL;
BROADCAST PaintVectorAvailable;
END;
IF free=NIL THEN RETURN WITH ERROR fatalViewersError;
IF free=colorVector.context THEN CleanUp[colorVector]
ELSE FOR p: PaintVector _ vectorRoot, p.next UNTIL p=NIL DO
IF free=p.context THEN {CleanUp[p]; EXIT};
ENDLOOP;
END;

AcquireContext: PUBLIC ENTRY PROC [viewer: Viewer, color: BOOL _ FALSE]
RETURNS [allocated: Context] = BEGIN
ENABLE UNWIND => NULL;
bestFit: PaintVector;
nil: BOOL _ FALSE;

MakeFirst: INTERNAL PROC [pv: PaintVector] = INLINE BEGIN	-- LRU caching scheme
IF pv=vectorRoot THEN RETURN;
pv.previous.next _ pv.next;
IF pv.next#NIL THEN pv.next.previous _ pv.previous;
pv.next _ vectorRoot;
vectorRoot.previous _ pv;
vectorRoot _ pv;
END;

IF color THEN BEGIN
IF ~colorInit THEN ERROR fatalViewersError;
WHILE colorVector.inUse OR paintingLock#0 DO WAIT PaintVectorAvailable; ENDLOOP;
IF viewer#NIL AND (~viewer.visible OR viewer.destroyed) THEN
SIGNAL InvisiblePaint;	-- someone got changed while waiting in the loop above
bestFit _ colorVector;
END

ELSE BEGIN
UNTIL usedVectors<nVectors AND paintingLock=0 DO WAIT PaintVectorAvailable; ENDLOOP;
IF viewer#NIL AND (~viewer.visible OR viewer.destroyed) THEN
SIGNAL InvisiblePaint;	-- someone got changed while waiting in the loop above
FOR p: PaintVector _ vectorRoot, p.next UNTIL p=NIL DO
IF p.inUse THEN LOOP;
IF viewer=p.viewer THEN {bestFit _ p; EXIT}
ELSE IF p.viewer=NIL THEN {bestFit _ p; nil _ TRUE}
ELSE IF ~nil THEN bestFit _ p;
ENDLOOP;
usedVectors _ usedVectors+1;
MakeFirst[bestFit];
END;

bestFit.inUse _ TRUE;
TRUSTED {bestFit.process _ Process.GetCurrent[]};
SetContext[viewer, bestFit];
bestFit.mark _ Save[allocated _ bestFit.context];	-- protect context
END;

SetContext: INTERNAL PROC [viewer: Viewer, paintVector: PaintVector] = BEGIN
pViewer: Viewer = paintVector.viewer;
pContext: Context = paintVector.context;

RecursivelyPushParent: INTERNAL PROC [viewer: Viewer] = BEGIN
IF viewer.parent#NIL THEN RecursivelyPushParent[viewer.parent];
PushContext[viewer, pContext]
END;

SELECT TRUE FROM	-- try to efficiently set up client context
pViewer=viewer			=> NULL;
viewer=NIL				=> ResetContext[pContext];
pViewer=viewer.parent	=> PushContext[viewer, pContext];
pViewer=NIL				=> RecursivelyPushParent[viewer];
pViewer.destroyed		=> {ResetContext[pContext]; RecursivelyPushParent[viewer]};
pViewer.parent=viewer	=> PopContext[pContext];
pViewer.parent=viewer.parent	=> {PopContext[pContext]; PushContext[viewer, pContext]};
ENDCASE					=> {ResetContext[pContext]; RecursivelyPushParent[viewer]};

paintVector.viewer _ viewer;
END;

PushContext: INTERNAL PROC [viewer: Viewer, context: Context] = BEGIN OPEN viewer;
invertCoords: BOOL = IF viewer.parent=NIL THEN viewer.class.coordSys=top
ELSE viewer.class.coordSys#viewer.parent.class.coordSys;
[] _ Save[context];
IF viewer.iconic THEN BEGIN
IF wy+wh > openBottomY THEN ClipIcon[context];
ClipBox[context, XYWH2Box[wx, wy, ww, wh]];
Translate[context, wx, wy];
END
ELSE IF invertCoords THEN BEGIN
ClipBox[context, XYWH2Box[cx, cy, cw, ch]];
Translate[context, cx, cy+ch];
Scale[context, 1, -1];
END
ELSE BEGIN
ClipBox[context, XYWH2Box[cx, cy, cw, ch]];
Translate[context, cx, cy];
END;
END;

PopContext: INTERNAL PROC [context: Context] = INLINE BEGIN
Restore[context];
END;

ResetContext: INTERNAL PROC [context: Context] = INLINE BEGIN
screen: Mark = LOOPHOLE[0];
Restore[context, screen];
END;

InvertForMenus: PUBLIC PROC [viewer: Viewer, x,y: INTEGER, w,h: INTEGER] = BEGIN
context: Context;
context _ AcquireContext[viewer.parent, viewer.column=color];
[] _ SetPaintMode[context, invert];
DrawBox[context, ViewerOps.XYWH2Box[viewer.wx+x, y, MIN[w,viewer.ww-x], h]];
ReleaseContext[context];
END;

ClipIcon: PROC [context: Context] = BEGIN
ClipOpenViewer: ViewerOps.EnumProc = BEGIN
IF ~v.iconic AND (v.column=right OR v.column=left) THEN
Graphics.ClipBox[context, [v.wx, v.wy, v.wx+v.ww, v.wy+v.wh], TRUE];
END;
ViewerOps.EnumerateViewers[ClipOpenViewer];
END;

BlinkIcon: PUBLIC PROC [viewer: Viewer, count, interval: NAT] = BEGIN
IF interval >= 1000 THEN interval _ interval/1000;
IF viewer.offDeskTop THEN ViewerOps.ChangeColumn[viewer, left];
IF count = 1 THEN BlinkProcess[viewer, count, interval]
ELSE TRUSTED {Process.Detach[FORK BlinkProcess[viewer, count, interval]]};
END;

BlinkProcess:  PROC [viewer: Viewer, count, n: NAT] = BEGIN
howOften: Process.Ticks = Process.MsecToTicks[500];
Blink: PROC = BEGIN OPEN viewer;
context: Context;
IF NOT visible OR destroyed THEN RETURN;
context _ AcquireContext[viewer, IF iconic THEN FALSE ELSE column=color];
[] _ SetPaintMode[context, invert];
DrawBox[context, ViewerOps.XYWH2Box[0, 0, viewer.ww, viewer.wh]];
Process.Pause[Process.MsecToTicks[400]];
DrawBox[context, ViewerOps.XYWH2Box[0, 0, viewer.ww, viewer.wh]];
ReleaseContext[context];
Process.Pause[Process.MsecToTicks[350]];	-- so can be called back-to-back
END;

DO
ViewerLocks.CallUnderWriteLock[Blink, viewer];
IF count = 1 THEN RETURN;
IF count > 0 THEN count _ count - 1;
FOR i: NAT IN [0..2*n) DO  -- blink every n seconds, but wake up every half second.
Process.Pause[howOften];
IF viewer.destroyed OR ~viewer.iconic 
OR viewer = ViewerTools.GetSelectedViewer[] THEN RETURN;
ENDLOOP;
ENDLOOP;
END;


newVT: Rope.ROPE = "  [New Version]";
newVW: INTEGER;

newFT: Rope.ROPE = "  [New File]";
newFW: INTEGER;

linkT: Rope.ROPE = "  [Split]";
linkW: INTEGER;

sipT: Rope.ROPE = "  [Saving...]";
sipW: INTEGER;

Init[];

ViewerOps.GreyScreen[0, 0, 9999, 9999, FALSE, FALSE];

END.


��p��ViewerPaintImpl.mesa; written by S. McGregor
Edited by McGregor on May 2, 1983 11:11 am
Edited by Maxwell, June 3, 1983 8:23 am
Last Edited by: Pausch, June 20, 1983 10:40 pm
IF flavor is private then client wants to draw the icon
do we need to paint any of the children?
recursively paint children
these guys should be painted in reverse order for correct overlaps
call from debugger
broadcast since all are likely to be free
assumes interesting paints already in progress
RFP: altered to keep box within the viewer for partially visible buttons
clips for overlapping top level windows given valid Context and Viewer
Êi��–"Mesa" style˜�JšÏc,™,Jš*™*J™'J™.šÏk	˜	Jšœžœ˜+Jšœžœ˜šœ	žœ-˜;J˜>J˜H—Jšœžœ˜Jšœžœ˜!Jšœžœ˜Jšœžœ˜Jšœ
žœ˜Jšœžœ1˜>Jšœžœžœ˜Jšœžœ*˜6J˜
J˜Jšœžœ@˜QJšœ˜J˜Jšœžœ˜&J˜�—Jšœž
˜J˜�Jšžœ˜–Jšžœ ˜'Jšžœ$˜*J˜�Jšžœžœ1˜;J˜�Jšœžœžœžœ˜%J˜�š
Ïnœžœ+žœ žœžœ˜rJšžœžœ˜Jš	œžœžœžœžœ˜=J˜)šžœžœž˜š	žœžœžœžœ˜@J˜˜AJ˜—J˜&J˜Jšž˜—šžœž˜
Jšœ	žœ˜,Jšžœžœ˜6Jšžœžœžœ˜5Jšžœžœžœ˜9Jšžœ
žœžœ˜2Jšœ
žœ˜J˜GJ˜J˜;J˜Jšžœžœ˜5Jšžœžœžœ˜4Jšžœžœžœ˜8Jšžœ
žœžœ˜1Jšžœ˜—Jšžœ˜—š	žœžœžœžœž˜'Jšœžœ˜,šžœ
žœžœž˜šžœžœž˜J˜˜=J˜—Jšžœ˜—J˜˜JJ˜—Jšžœ˜—˜3J˜-—Jšžœ˜—Jšžœ˜J˜�—šŸ	œžœ0žœžœžœž˜UJ˜Jšœžœ˜J˜�Jšžœžœžœžœ˜!J˜�Jšœ!žœ˜DJ˜�Jš7™7Jšžœžœ;˜VJ˜�š	žœžœ
žœžœž˜+Jšœ(˜Dšžœžœžœž˜FJ˜—šžœžœžœžœžœž˜TJ˜—Jšœžœ*˜8Jšžœ	žœžœ˜(J˜DJ˜šžœ!žœž˜-J˜#J˜0Jšžœ˜—Jšžœ˜J˜�—J˜Jšžœ˜—J˜�š	Ÿœžœžœžœž˜DJ˜-Jšžœ˜J˜�—šŸœžœ0žœ˜RJšœžœ%žœžœžœžœ˜MJšœžœ˜Jšœžœ˜Jšœ	žœ˜J˜�š	žœžœžœžœ˜Bšžœ
žœžœž˜Jšžœžœžœžœ˜7Jšžœžœžœžœ˜7Jšž˜—Jšžœ˜—J˜�šžœ
žœž˜Jš
žœžœžœ	žœžœ˜=J˜6Jšžœžœžœžœ˜Bš	žœ
žœžœ
žœž˜1J˜J˜+J˜Jšœžœ˜
Jšžœ˜—šžœžœ
žœž˜!Jšœžœ˜ J˜,J˜,J˜3J˜3Jšžœ˜—šžœžœžœ˜'Jšžœ@˜D—J˜Jšžœ˜J˜�—šžœ
žœ
žœž˜%Jš
žœžœžœ	žœžœ˜=Jšœ
žœ8˜EJšžœžœžœžœ˜BJš
žœžœžœžœžœ˜Ašžœ
žœžœž˜$J˜J˜!J˜Jšžœžœžœžœ˜%Jšœžœ˜Jšœžœ˜
Jšžœ˜—Jšžœ
žœžœ2˜IJ˜Jšžœ˜J˜�—Jšœ(™(šžœžœžœžœžœ˜.šžœžœ,ž˜IJšœžœ,žœžœ˜P——J˜�Jš™šžœ
žœ
žœž˜(JšB™Bšžœ%žœžœž˜6šžœžœžœ2˜GJš-˜-šžœ˜JšžœA˜EJšžœ=˜A—šžœžœ ž˜6Jšœ
žœ žœžœ˜;——Jšœ žœ˜AJšžœ˜J˜�——Jšžœ˜J˜�—š
Ÿœžœžœ9žœžœ˜]Jšœ
žœžœžœž˜#šŸœžœ˜Jšžœžœžœ˜4J˜Jšžœžœžœžœ˜3Jšžœžœ(žœ˜EJ˜Jšžœžœžœžœ˜Gšœ2žœ
žœ˜SJšžœ(žœ˜7—Jšœ˜—JšœOžœ˜YJšžœ˜J˜�J˜�—Jšœ
žœžœ˜'šœžœžœ˜Jšœžœ˜Jšœžœ˜Jšœžœžœ˜Jšœžœžœ˜Jšœžœžœ˜J˜Jšœ	žœžœ˜Jšœžœ˜Jšœžœ˜J˜�—Jšœ
žœ˜Jšœ
žœ˜Jšœž	œ˜ Jšœžœ˜J˜�Jšœžœ˜Jšœžœ˜J˜�šŸœžœžœž˜J˜šžœžœžœž˜#Jšœžœ˜J˜J˜1J˜Jšžœžœžœ˜1J˜Jšžœ˜—J˜"J˜"J˜"J˜ Jšœžœ˜"Jšœžœ˜Jšžœ˜J˜�—Jšœžœžœ˜J˜�šŸœžœžœž˜,šŸœžœžœž˜%J˜.J˜9Jšœžœ˜Jšžœ˜—J˜Jšœ'žœžœ˜4Jšžœ˜J˜�—šŸ	œžœžœž˜1J˜ Jšœžœ	žœžœ˜FJ˜8Jšœžœ˜Jšœ
žœ˜Jšœžœ˜J˜Jšžœ
žœ˜/Jšœ!˜-Jšž	œ˜Jšžœ˜J˜�—š
Ÿœžœžœžœžœžœž˜HJšžœžœžœ˜Jšžœžœžœ˜Pš	žœžœ%žœžœž˜;Jšžœ	žœžœ˜3Jšžœ˜—Jšžœ˜J˜�—šŸœžœžœžœžœž˜:Jš™Jšžœžœ˜0š	žœžœ%žœžœž˜;Jšžœ	žœ˜Jšžœ˜—Jšœ˜Jšœ˜Jšž	œ˜Jšžœ˜J˜�—š
Ÿœžœžœžœžœžœž˜>Jšžœžœžœ˜J˜Jšžœ˜š
Ÿœžœžœžœžœžœž˜Išžœž˜Jšžœžœžœžœ˜GJšžœ˜J˜—Jšžœ˜J˜�——š	Ÿœžœžœžœž˜)Jšžœžœžœ˜J˜Jšžœ˜š	Ÿœžœžœžœž˜4Jšžœžœ˜5Jš)™)Jšžœžœž	œ˜6Jšžœ˜——J˜�š
Ÿœžœžœžœžœžœž˜Iš
Ÿ	œžœžœžœžœžœž˜5šžœžœž˜Jšžœžœžœžœžœ˜AJšžœ)žœžœžœ˜>Jšžœ˜—šžœ%žœžœž˜6Jšžœ
žœžœ˜Jšžœžœžœžœžœ˜9Jšžœ:žœžœžœ˜OJšžœ˜—Jšžœžœ˜
Jšžœ˜J˜�—šžœž˜šžœžœžœ˜,Jš
žœ
žœžœžœžœ˜9—Jšžœ˜J˜—Jšžœ˜J˜�—š	Ÿœžœžœžœž˜2Jš.™.Jš
žœžœžœžœžœ˜OJšžœ˜J˜�—šŸœžœžœžœžœžœžœž˜TJšžœžœžœ˜J˜šžœ%žœžœž˜6šžœ	žœž˜šžœžœžœ:˜NJš
žœžœžœžœžœ˜6—Jšœžœ˜Jšž˜—š	žœžœ
žœžœž˜J˜Jšœžœ˜Jšžœ˜—Jšžœ˜—šžœžœžœž˜%šžœžœ'žœž˜KJš
žœžœžœžœžœ˜1Jšœžœ˜"Jšž˜—š	žœžœžœžœž˜)J˜"Jšœžœ˜Jšžœ˜—Jšžœ˜—J˜Jšžœ˜J˜�—Jšœžœžœ˜ J˜�š	Ÿœžœžœžœž˜9Jšžœžœžœ˜šŸœžœžœž˜/Jšœ ˜7Jšœ
žœ˜J˜šžœ
žœžœžœžœžœžœ˜KJšžœ˜"—šžœžœž˜J˜Jšœžœ˜Jšœžœ˜Jšžœ˜—Jšœžœ˜Jšž	œ˜Jšžœ˜—Jšžœžœžœžœžœžœ˜5Jšžœžœ˜5š	žœžœ%žœžœž˜;Jšžœžœžœ˜*Jšžœ˜—Jšžœ˜J˜�—šŸœžœžœžœžœžœ˜GJšžœž˜$Jšžœžœžœ˜J˜Jšœžœžœ˜J˜�šŸ	œžœžœžœžœ˜OJšžœžœžœ˜J˜Jšžœ	žœžœ ˜3J˜J˜J˜Jšžœ˜J˜�—šžœžœž˜Jšžœžœžœ˜+Jš
žœžœžœžœžœ˜Pš	žœžœžœžœž˜<Jšžœ6˜M—J˜Jšž˜J˜�—šžœž˜
Jš
žœžœžœžœžœ˜Tš	žœžœžœžœž˜<Jšžœ6˜M—šžœ%žœžœž˜6Jšžœ	žœžœ˜Jšžœžœžœ˜+Jš
žœžœ
žœžœžœ˜3Jšžœžœžœ
˜Jšžœ˜—J˜J˜Jšžœ˜J˜�—Jšœžœ˜Jšžœ*˜1J˜Jšœ2˜DJšžœ˜J˜�—šŸ
œžœžœ.ž˜LJ˜%J˜(J˜�šŸœžœžœž˜=Jšžœžœžœ&˜?J˜Jšžœ˜J˜�—šžœžœžœ+˜<Jšœžœ˜Jšœžœ˜(J˜7Jšœžœ%˜0JšœN˜NJšœ.˜.J˜VJšžœ@˜GJ˜�—J˜Jšžœ˜J˜�—š
Ÿœžœžœ&žœžœ˜Rš	œžœžœžœžœ˜HJšžœ4˜8—J˜šžœžœž˜Jšžœžœ˜.J˜+J˜Jšž˜—šžœžœžœž˜J˜+J˜J˜Jšž˜—šžœž˜
J˜+J˜Jšžœ˜—Jšžœ˜J˜�—š	Ÿ
œžœžœžœž˜;J˜Jšžœ˜J˜�—š	Ÿœžœžœžœž˜=Jšœžœ˜J˜Jšžœ˜J˜�—šŸœžœžœžœžœž˜PJ˜J˜=J˜#JšœH™HJ˜LJ˜Jšžœ˜J˜�—šŸœžœž˜)JšF™Fšœ%ž˜*šžœžœžœž˜7Jšœ>žœ˜D—Jšžœ˜—J˜+Jšžœ˜J˜�—šŸ	œžœ#žœž˜EJ˜2Jšžœžœ&˜?Jšžœžœ&˜7Jšžœžœžœ)˜JJšžœ˜J˜�—šŸœžœžœž˜;Jšœ3˜3šŸœžœž
œ˜ J˜Jš
žœžœ	žœžœžœ˜(Jš	œ!žœžœžœžœ˜IJ˜#J˜AJ˜(J˜AJ˜Jšœ) ˜IJšžœ˜J˜�—šž˜J˜.Jšžœžœžœ˜Jšžœžœ˜$š	žœžœžœ
žœ8˜SJšœ˜šžœžœ˜&Jšžœ*žœžœ˜8—Jšžœ˜—Jšžœ˜—Jšžœ˜J˜�—J˜�Jšœžœ˜%Jšœžœ˜J˜�Jšœžœ˜"Jšœžœ˜J˜�Jšœžœ˜Jšœžœ˜J˜�Jšœžœ˜"Jšœžœ˜J˜�J˜J˜�Jšœ'žœžœ˜5J˜�Jšžœ˜J˜�J˜�—�…—����Ej��_C��