DIRECTORY Carets USING [ResumeCarets, SuspendCarets], ColorWorld USING [TurnOffColor, TurnOnColor], Cursors USING [CursorType, GetCursor, SetCursor], InputFocus USING [CaptureButtons, inputEnabled, ReleaseButtons, WindowManagerTIPTable], InterminalExtra USING [InsertAction], Imager USING [black, ClipIntRectangle, Color, Context, DoSave, MaskIntRectangle, IntScaleT, SetColor, IntTranslateT, white], Menus USING [AppendMenuEntry, CreateEntry, CreateMenu, MenuEntry, Menu, MenuProc, ReplaceMenuEntry, SetGuarded], MenusPrivate USING [ClearMenu, DrawMenu, HitMenu, MarkMenu], MessageWindow USING [Append, Blink], TIPUser USING [TIPScreenCoords, TIPScreenCoordsRec], UserTerminal USING [BlinkDisplay], ViewerClasses USING [Column, ScrollOp, Viewer], ViewerMenus, ViewerOps USING [AcquireContext, ChangeColumn, CloseViewer, EnumerateViewers, EnumProc, InitialiseColorPainting, InvisiblePaint, MouseInViewer, PaintViewer, ReleaseContext], ViewerSpecs USING [captionHeight, scrollBarW, windowBorderSize], WindowManager, WindowManagerPrivate; WindowManagerImpl: CEDAR MONITOR IMPORTS Carets, ColorWorld, Cursors, Imager, InputFocus, InterminalExtra, Menus, MenusPrivate, MessageWindow, ViewerMenus, ViewerOps, UserTerminal EXPORTS WindowManager, WindowManagerPrivate SHARES InputFocus, Menus, ViewerClasses, ViewerOps = BEGIN OPEN Cursors, ViewerClasses, ViewerSpecs; Zone: TYPE = {none, menu, scroll, caption, client} ; trackingState: Zone _ none; CursorZone: PROC [v: Viewer, mousePos: TIPUser.TIPScreenCoords] RETURNS [z: Zone] = BEGIN OPEN v; RETURN[SELECT TRUE FROM parent=NIL AND column#static AND mousePos.mouseY IN [wh-captionHeight..wh] => caption, scrollable AND mousePos.mouseX IN [0..scrollBarW] AND mousePos.mouseY IN [0..ch] => scroll, menu#NIL AND mousePos.mouseY IN ((cy-wy)+ch..wh-captionHeight) => menu, ENDCASE => none ] END; ProcessWindowResults: PUBLIC PROC [self: Viewer, input: LIST OF REF ANY] = BEGIN zone: Zone; newZone: BOOL; shift, control: BOOL _ FALSE; mousePos: TIPUser.TIPScreenCoords; FOR l: LIST OF REF ANY _ input, l.rest UNTIL l = NIL DO WITH l.first SELECT FROM z: ATOM => BEGIN OPEN InputFocus; IF newZone THEN SELECT trackingState FROM -- old feedback scroll => {ReleaseButtons[]; RemoveScrollFeedback[]}; menu => {ReleaseButtons[]; MenusPrivate.ClearMenu[feedbackViewer.menu, feedbackViewer]; feedbackViewer _ NIL}; caption => {ReleaseButtons[]; RemoveCaptionFeedback[]}; ENDCASE; IF newZone THEN SELECT zone FROM -- first time stuff scroll => {CaptureButtons[ProcessWindowResults, WindowManagerTIPTable, self]; PostScrollFeedback[self]}; menu => {CaptureButtons[ProcessWindowResults, WindowManagerTIPTable, self]; feedbackViewer _ self; SetC[bullseye]}; caption => {CaptureButtons[ProcessWindowResults, WindowManagerTIPTable, self]; PostCaptionFeedback[self]; SetC[bullseye]}; ENDCASE => SetC[textPointer]; SELECT trackingState _ zone FROM -- zone specific ops scroll => SELECT z FROM $M => SetC[scrollUpDown]; $RU => HitScroll[self, mousePos.mouseY, up, shift, control]; $RD, $RM => SetC[scrollUp]; $YU => HitScroll[self, mousePos.mouseY, thumb, shift, control]; $YD, $YM => SetC[scrollRight]; $BU => HitScroll[self, mousePos.mouseY, down, shift, control]; $BD, $BM => SetC[scrollDown]; $Control => control _ TRUE; $Shift => shift _ TRUE; ENDCASE => NULL; menu => SELECT z FROM $RU => MenusPrivate.HitMenu[self.menu, self, mousePos, red, shift, control]; $BU => MenusPrivate.HitMenu[self.menu, self, mousePos, blue, shift, control]; $YU => MenusPrivate.HitMenu[self.menu, self, mousePos, yellow, shift, control]; $RM, $BM, $YM => {MenusPrivate.MarkMenu[self.menu, self, mousePos]}; $RD, $BD, $YD => MenusPrivate.MarkMenu[self.menu, self, mousePos]; $Control => control _ TRUE; $Shift => shift _ TRUE; ENDCASE => NULL; caption => SELECT z FROM $RU => MenusPrivate.HitMenu[windowMenu, self, mousePos, red, shift, control]; $BU => MenusPrivate.HitMenu[windowMenu, self, closePos, blue, FALSE, FALSE]; $YU => MenusPrivate.HitMenu[windowMenu, self, growPos, yellow, FALSE, FALSE]; $RM, $RD => MenusPrivate.MarkMenu[windowMenu, self, mousePos]; $BM, $BD => MenusPrivate.MarkMenu[windowMenu, self, closePos]; $YM, $YD => MenusPrivate.MarkMenu[windowMenu, self, growPos]; $Control => control _ TRUE; $Shift => shift _ TRUE; ENDCASE => NULL; ENDCASE; END; z: TIPUser.TIPScreenCoords => { client: BOOL _ FALSE; mousePos _ z; IF mousePos.mouseX = 0 --AND trackingState = scroll-- THEN mousePos.mouseX _ 1; IF trackingState#none THEN [self, client] _ ViewerOps.MouseInViewer[mousePos]; zone _ IF client OR self=NIL THEN none ELSE CursorZone[self, mousePos]; newZone _ trackingState#zone OR (zone=caption AND self#feedbackViewer) OR (zone=scroll AND self#feedbackViewer); }; z: REF CHAR => TRUSTED {UserTerminal.BlinkDisplay[]}; ENDCASE => NULL; ENDLOOP; END; AlterColumn: PROC [v: Viewer, mx: INTEGER] = BEGIN column: ViewerClasses.Column; right: BOOL ~ mx >= v.ww/2; column _ SELECT v.column FROM left => IF right THEN right ELSE IF colorDisplayOn THEN color ELSE right, right => IF ~right THEN left ELSE IF colorDisplayOn THEN color ELSE left, color => IF right THEN right ELSE left, ENDCASE => ERROR; ViewerOps.ChangeColumn[v, column]; END; SetC: PROC [cursor: CursorType] = INLINE {IF waitCount=0 AND GetCursor[]#cursor THEN SetCursor[cursor]}; HitScroll: PROC [v: Viewer, y: LONG INTEGER, op: ScrollOp, shift, control: BOOL] = BEGIN RemoveScrollFeedback[]; IF v.parent=NIL OR v.class.coordSys#top THEN y _ v.ch-y; -- client coords IF v.class.scroll#NIL THEN [] _ v.class.scroll[v, op, SELECT op FROM up, down => y, ENDCASE => (100*(y+1))/v.ch, -- percent shift, control]; SetC[scrollUpDown]; -- put the cursor back PostScrollFeedback[v]; END; feedbackViewer: Viewer _ NIL; visible: REF CARDINAL = NEW[CARDINAL _ 122645B]; inVisible: REF CARDINAL = NEW[CARDINAL _ 100040B]; PostScrollFeedback: PROC [v: Viewer] = BEGIN context: Imager.Context; baseY, baseX, top, bottom: INTEGER; relY1, relY2: INT; -- so won't overflow IF feedbackViewer#NIL OR v.class.scroll=NIL THEN RETURN; IF ~v.init THEN RETURN; -- avoid a race condition bug [top, bottom] _ v.class.scroll[v, query, 0]; IF top>100 OR bottom>100 THEN RETURN; Carets.SuspendCarets[]; context _ ViewerOps.AcquireContext[v.parent, v.column=color ! ViewerOps.InvisiblePaint => GOTO Punt]; IF v.parent#NIL AND v.parent.class.coordSys=top THEN BEGIN -- flip origin Imager.IntTranslateT[context, 0, v.parent.ch]; Imager.IntScaleT[context, 1, -1]; baseY _ v.parent.ch - v.wy - v.wh + (IF v.border THEN windowBorderSize ELSE 0); END ELSE baseY _ v.wy + (IF v.border THEN windowBorderSize ELSE 0); baseX _ v.wx + (IF v.border THEN windowBorderSize ELSE 0); relY1 _ baseY; relY2 _ (LONG[100-bottom]*v.ch)/100+baseY; Imager.SetColor[context, inVisible]; Imager.MaskIntRectangle[context, [baseX, relY1, scrollBarW, relY2-relY1]]; relY1 _ relY2; relY2 _ relY2 + (LONG[bottom-top]*v.ch)/100; Imager.SetColor[context, visible]; Imager.MaskIntRectangle[context, [baseX, relY1, scrollBarW, relY2-relY1]]; Imager.SetColor[context, inVisible]; Imager.MaskIntRectangle[context, [baseX, relY2, scrollBarW, baseY+v.ch-relY2]]; ViewerOps.ReleaseContext[context]; feedbackViewer _ v; Carets.ResumeCarets[]; EXITS Punt => {feedbackViewer _ NIL; Carets.ResumeCarets[]}; END; RemoveScrollFeedback: PROC = BEGIN context: Imager.Context; baseX, baseY: INTEGER; IF feedbackViewer=NIL THEN RETURN; Carets.SuspendCarets[]; context _ ViewerOps.AcquireContext[feedbackViewer.parent, feedbackViewer.column=color ! ViewerOps.InvisiblePaint => GOTO Punt]; IF feedbackViewer.parent#NIL AND feedbackViewer.parent.class.coordSys=top THEN BEGIN Imager.IntTranslateT[context, 0, feedbackViewer.parent.ch]; Imager.IntScaleT[context, 1, -1]; baseY _ feedbackViewer.parent.ch - feedbackViewer.wy - feedbackViewer.wh + (IF feedbackViewer.border THEN windowBorderSize ELSE 0); END ELSE baseY _ feedbackViewer.wy + (IF feedbackViewer.border THEN windowBorderSize ELSE 0); baseX _ feedbackViewer.wx + (IF feedbackViewer.border THEN windowBorderSize ELSE 0); Imager.SetColor[context, Imager.white]; Imager.MaskIntRectangle[context, [baseX, baseY, scrollBarW, feedbackViewer.ch]]; ViewerOps.ReleaseContext[context]; GOTO Punt; EXITS Punt => {feedbackViewer _ NIL; Carets.ResumeCarets[]}; END; DrawCaptionMenu: PUBLIC ENTRY PROC [v: Viewer, guard: BOOL] = {ENABLE UNWIND => NULL; InternalDrawCaptionMenu[v, guard]}; InternalDrawCaptionMenu: INTERNAL PROC [v: Viewer, guard: BOOL] = BEGIN OPEN v; context: Imager.Context; DrawCaption: PROC = BEGIN x, y: INTEGER; x _ wx+windowBorderSize; y _ wy+wh-captionHeight; Imager.ClipIntRectangle[context, [x, y, ww-(2*windowBorderSize),captionHeight]]; Imager.SetColor[context, Imager.white]; Imager.MaskIntRectangle[context, [x, y, ww, captionHeight]]; Imager.SetColor[context, Imager.black]; IF guard THEN Menus.SetGuarded[destroyEntry, guardDestroy OR (newVersion AND link=NIL AND ~saveInProgress)]; MenusPrivate.DrawMenu[windowMenu, context, x, y]; END; IF feedbackViewer#v OR iconic OR ~visible THEN RETURN; context _ ViewerOps.AcquireContext[parent, column=color ! ViewerOps.InvisiblePaint => GOTO Punt]; Imager.DoSave[context, DrawCaption]; ViewerOps.ReleaseContext[context]; EXITS Punt => NULL; END; PostCaptionFeedback: ENTRY PROC [v: Viewer] = BEGIN ENABLE UNWIND => NULL; IF feedbackViewer#v THEN BEGIN -- remove old IF feedbackViewer#NIL THEN MenusPrivate.ClearMenu[windowMenu, feedbackViewer, FALSE]; feedbackViewer _ v; END; InternalDrawCaptionMenu[v, TRUE]; END; RemoveCaptionFeedback: ENTRY PROC = BEGIN ENABLE UNWIND => NULL; IF feedbackViewer#NIL THEN BEGIN MenusPrivate.ClearMenu[windowMenu, feedbackViewer, FALSE]; ViewerOps.PaintViewer[feedbackViewer, caption]; feedbackViewer _ NIL; END; END; waitCount: PUBLIC INTEGER _ 0; WaitCursor: PUBLIC ENTRY PROC [cursor: Cursors.CursorType _ hourGlass] = BEGIN ENABLE UNWIND => NULL; IF InputFocus.inputEnabled THEN SetCursor[cursor]; waitCount _ waitCount + 1; END; UnWaitCursor: PUBLIC ENTRY PROC = BEGIN ENABLE UNWIND => NULL; waitCount _ MAX[0, waitCount - 1]; IF waitCount=0 THEN RestoreCursor[]; END; RestoreCursor: PUBLIC PROC = TRUSTED {IF InputFocus.inputEnabled THEN InterminalExtra.InsertAction[[contents: deltaMouse[[0,0]]]]}; StartColorViewers: PUBLIC PROC [screenPos: WindowManager.ScreenPos, bitsPerPixel: CARDINAL] = BEGIN IF colorDisplayOn THEN StopColorViewers[]; colorDisplayOn _ ColorWorld.TurnOnColor[bitsPerPixel, (screenPos=left)]; IF ~colorDisplayOn THEN BEGIN MessageWindow.Append["Sorry, you don't have a color display.", TRUE]; MessageWindow.Blink[]; RETURN; END; ViewerOps.InitialiseColorPainting[]; Menus.ReplaceMenuEntry[windowMenu, tNopEntry, tColorEntry]; growPos^ _ [growEntry.xPos+1, FALSE, 0]; closePos^ _ [closeEntry.xPos+1, FALSE, 0]; END; StopColorViewers: PUBLIC PROC = BEGIN DoColorViewer: ViewerOps.EnumProc = BEGIN IF v.column=color THEN BEGIN ViewerOps.CloseViewer[v]; ViewerOps.ChangeColumn[v, left]; END; END; IF ~colorDisplayOn THEN RETURN; ViewerOps.EnumerateViewers[DoColorViewer]; ColorWorld.TurnOffColor[]; colorDisplayOn _ FALSE; Menus.ReplaceMenuEntry[windowMenu, tColorEntry, tNopEntry]; growPos^ _ [growEntry.xPos+1, FALSE, 0]; closePos^ _ [closeEntry.xPos+1, FALSE, 0]; END; BuildWindowMenus: PROC = BEGIN windowMenu _ Menus.CreateMenu[]; Menus.AppendMenuEntry[windowMenu, destroyEntry _ Menus.CreateEntry[name: "Destroy", proc: ViewerMenus.Destroy, fork: FALSE, documentation: "Edits will be discarded..."]]; Menus.AppendMenuEntry[windowMenu, Menus.CreateEntry[name: "Adjust", proc: ViewerMenus.Adjust, fork: FALSE]]; Menus.AppendMenuEntry[windowMenu, Menus.CreateEntry[name: "Top", proc: ViewerMenus.Top, fork: FALSE]]; Menus.AppendMenuEntry[windowMenu, Menus.CreateEntry[name: "", proc: ViewerMenus.Left, fork: FALSE]]; Menus.AppendMenuEntry[windowMenu, Menus.CreateEntry[name: "", proc: ViewerMenus.Right, fork: FALSE]]; Menus.AppendMenuEntry[windowMenu, tNopEntry _ Menus.CreateEntry["", NIL]]; tColorEntry _ Menus.CreateEntry[name: "Color", proc: ViewerMenus.Color, fork: FALSE]; Menus.AppendMenuEntry[windowMenu, growEntry _ Menus.CreateEntry[name: "Grow", proc: ViewerMenus.Grow, fork: FALSE]]; Menus.AppendMenuEntry[windowMenu, closeEntry _ Menus.CreateEntry[name: "Close", proc: ViewerMenus.Close, fork: FALSE]]; growPos _ NEW[TIPUser.TIPScreenCoordsRec _ [growEntry.xPos+1, FALSE, 0]]; closePos _ NEW[TIPUser.TIPScreenCoordsRec _ [closeEntry.xPos+1, FALSE, 0]]; END; colorDisplayOn: PUBLIC BOOL _ FALSE; -- color display status windowMenu: PUBLIC Menus.Menu; destroyEntry, closeEntry, growEntry, tColorEntry, tNopEntry: Menus.MenuEntry; growPos, closePos: TIPUser.TIPScreenCoords; BuildWindowMenus[]; END. ΜWindowManagerImpl.mesa; Written by S. McGregor Edited by McGregor on August 8, 1983 1:18 pm Last Edited by: Maxwell, February 8, 1983 3:58 pm not monitored since notifier is synchronous flip origin Κ =– "cedar" style˜JšΟc.™.Jš,™,Jšœ1™1J˜šΟk ˜ Jšœžœ˜+Jšœ žœ˜-Jšœžœ$˜1Jšœ žœG˜WJšœžœ˜%Jšœžœp˜|šœžœ<˜GJ˜(—Jšœ žœ*˜J˜J˜AJ˜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šžœ˜J˜—˜Jšœžœžœ˜J˜ Jšžœžœžœ˜OJšžœžœ4˜NJš œžœžœžœžœžœ˜Gšœžœžœ˜FJšžœžœ˜)—J˜J˜—Jšœžœžœžœ˜5J˜Jšžœžœ˜Jšžœ˜—Jšžœ˜J˜—šŸ œžœžœž˜2J˜Jšœžœ˜šœ žœ ž˜Jš œžœžœžœžœžœžœ˜IJš œ žœžœžœžœžœžœ˜IJšœ žœžœžœ˜'Jšžœžœ˜—J˜"Jšžœ˜J˜—šŸœžœž˜(Jšœžœ žœžœ˜?J˜—š Ÿ œžœžœžœ žœž˜XJ˜Jš žœ žœžœžœ ˜Išžœžœžœ˜5šžœž˜J˜Jšžœ ˜'—J˜—Jšœ˜*J˜Jšžœ˜J˜—Jšœžœ˜J˜Jš œ žœžœžœžœ ˜0Jš œ žœžœžœžœ ˜2J˜šŸœžœž˜,J˜Jšœžœ˜#Jšœžœ˜'Jš žœžœžœžœžœžœ˜8Jšžœ žœžœ˜6J˜,Jšžœ žœ žœžœ˜%J˜˜;Jšœžœ˜)—š žœ žœžœžœžœ˜IJšœ.˜.Jšœ!˜!Jšœ%žœ žœžœ˜OJšž˜—Jšžœžœ žœžœ˜?Jšœžœ žœžœ˜:J˜Jšœ žœ˜*J˜$J˜JJ˜Jšœžœ˜,J˜"J˜JJ˜$J˜OJ˜"Jšœ*˜*Jšžœžœ˜˜^J˜—šŸœžœžœ%˜CJšœžœž˜Jšžœžœ˜*J˜Hšžœžœž˜Jšœ?žœ˜EJšœ˜Jšžœ˜Jšžœ˜—J˜$J˜;Jšœžœ˜(Jšœ žœ˜*Jšžœ˜J˜—šŸœžœžœž˜%šœ$ž˜)šžœžœž˜J˜J˜ Jšžœ˜—Jšžœ˜—Jšžœžœžœ˜J˜*J˜Jšœžœ˜J˜;Jšœžœ˜(Jšœ žœ˜*Jšžœ˜J˜—šŸœžœž˜J˜ ˜SJšœ!žœ0˜V—˜CJšœ žœ˜(—˜@Jšœžœ˜%—˜?Jšœžœ˜&—˜?Jšœžœ˜'—JšœDžœ˜JJšœNžœ˜U˜MJšœžœ˜&—˜OJšœžœ˜'—Jšœ žœ1žœ˜IJšœ žœ2žœ˜KJšžœ˜J˜—Jšœžœžœžœ˜