IMPLEMENTATION MODULE FrameManager; (* * REPERTOIRE * Release 1.6 * By Charles Bradford and Cole Brecheen * (c) Copyright 1985-1992 PMI * Green Bay, Wisconsin * All rights reserved * (414) 468-6040 * * $Header: D:/logfiles/mods/frameman.mov 1.5 10 Mar 1991 15:27:50 coleb $ * *) (* IMPORT Diagnostics; *) IMPORT ErrorManager; IMPORT FramePainter; IMPORT GenLists; IMPORT Hash; IMPORT ListUtils; IMPORT Rectangles; IMPORT ScrnTypes; IMPORT SYSTEM; IMPORT VWindows; VAR Initialized : BOOLEAN; (* The idea here is that we have a list of windows, each of which has a list of active DisplayFrames (pointers to DisplayFrameRecs) in the position immediately following it. A DisplayFrame's position in the window list indicates how it is stacked --position 1 means it is in the foreground, and each position after that means it is farther into the background *) CONST FrameCode = 65529; WindowCode = 65528; (* arbitrary *) VAR WindowListInitialized : BOOLEAN; WindowList: GenLists.GenList; PROCEDURE CleanUp(); BEGIN (* Diagnostics.diagS( 'About to DisposeList', '' ); *) GenLists.DisposeList( WindowList ); END CleanUp; PROCEDURE AddWindow( TheWindow: VWindows.AWindowHandle ); VAR ActiveFrameList : GenLists.GenList; BEGIN IF NOT WindowListInitialized THEN GenLists.NewList( WindowList ); WindowListInitialized := TRUE; ErrorManager.AddTermProc( CleanUp ); END; IF ListUtils.ObjectSpot( TheWindow, WindowList, 1, 65535 ) > 0 THEN (*TheWindow is already in WindowList. We don't complain about redundant adds because most frames will be associated with the same window, and we don't want InitDisplayFrame to have to worry about whether a window has already been added. *) RETURN; END; GenLists.NewList( ActiveFrameList ); GenLists.ListInsert( ActiveFrameList, GenLists.ListCode, WindowList, 1 ); GenLists.ListInsert( TheWindow, WindowCode, WindowList, 1 ); END AddWindow; PROCEDURE DeleteWindow( TheWindow: VWindows.AWindowHandle ); VAR ActiveFrameList : GenLists.GenList; spot : CARDINAL; BEGIN spot := ListUtils.ObjectSpot( TheWindow, WindowList, 1, 65535 ); IF spot > 0 THEN GenLists.ListDelete( WindowList, spot, 2 ); END; END DeleteWindow; PROCEDURE GetAssociatedFrames( TheWindow: VWindows.AWindowHandle; VAR FrameList: GenLists.GenList ); VAR spot: CARDINAL; BEGIN spot := ListUtils.ObjectSpot( TheWindow, WindowList, 1, 65535 ); IF spot > 0 THEN GenLists.GetChildList( WindowList, spot + 1, FrameList ); IF GenLists.Initialized( FrameList ) THEN RETURN; END; END; ErrorManager.WARN( "You're missing a call to AddWindow somewhere" ); END GetAssociatedFrames; PROCEDURE FrameIsInForeGround( TheFrame: ScrnTypes.DisplayFrame ); VAR ActiveFrameList : GenLists.GenList; spot: CARDINAL; BEGIN GetAssociatedFrames( TheFrame^.WindowHandle, ActiveFrameList ); spot := ListUtils.ObjectSpot( TheFrame, ActiveFrameList, 1, 65535 ); IF spot = 0 THEN ErrorManager.WARN( 'Frame not active' ); END; (* Now move TheFrame to the front of ActiveFrameList. *) IF spot # 1 THEN GenLists.ListDelete( ActiveFrameList, spot, 1 ); GenLists.ListInsert( TheFrame, FrameCode, ActiveFrameList, 1 ); END; END FrameIsInForeGround; PROCEDURE GetFrameFromList( list: GenLists.GenList; spot: CARDINAL; VAR frame: ScrnTypes.DisplayFrame ); VAR TypeCode: CARDINAL; BEGIN GenLists.GetElmt( list, spot, frame, TypeCode ); IF TypeCode # FrameCode THEN ErrorManager.WARN( 'Error in frame list' ); END; END GetFrameFromList; PROCEDURE FrameActivated( TheFrame: ScrnTypes.DisplayFrame ); VAR ActiveFrameList : GenLists.GenList; spot : CARDINAL; BEGIN GetAssociatedFrames( TheFrame^.WindowHandle, ActiveFrameList ); spot := ListUtils.ObjectSpot( TheFrame, ActiveFrameList, 1, 65535 ); IF spot > 0 THEN (* TheFrame is already in the list. *) RETURN; END; GenLists.ListInsert( TheFrame, FrameCode, ActiveFrameList, 1 ); END FrameActivated; PROCEDURE FrameDeactivated( TheFrame: ScrnTypes.DisplayFrame ); VAR ActiveFrameList : GenLists.GenList; spot : CARDINAL; BEGIN GetAssociatedFrames( TheFrame^.WindowHandle, ActiveFrameList ); spot := ListUtils.ObjectSpot( TheFrame, ActiveFrameList, 1, 65535 ); IF spot = 0 THEN (* TheFrame is not in the list. *) RETURN; END; GenLists.ListDelete( ActiveFrameList, spot, 1 ); END FrameDeactivated; PROCEDURE GetFrameCoords( TheFrame: ScrnTypes.DisplayFrame; VAR rect: Rectangles.ARectangle ); BEGIN Rectangles.DefineRectangle( rect, TheFrame^.startcol + 1, TheFrame^.startrow + 1, TheFrame^.endcol + 1, TheFrame^.endrow + 1 ) END GetFrameCoords; PROCEDURE IsFrameObscured( TheFrame: ScrnTypes.DisplayFrame ): BOOLEAN; VAR FrameRect, tmprect, intersection : Rectangles.ARectangle; ActiveFrameList : GenLists.GenList; ListEnd, cnt, spot : CARDINAL; TmpFrame : ScrnTypes.DisplayFrame; BEGIN GetAssociatedFrames( TheFrame^.WindowHandle, ActiveFrameList ); spot := ListUtils.ObjectSpot( TheFrame, ActiveFrameList, 1, 65535 ); IF spot = 0 THEN (* The frame itself has got to be in the list. *) ErrorManager.WARN( 'Error in frame list' ); RETURN FALSE; ELSIF spot = 1 THEN (* We return if it's 1 because, if the system is working, a frame that's at the top of the list will never be obscured *) RETURN FALSE; END; GetFrameCoords( TheFrame, FrameRect ); ListEnd := GenLists.ListLength( ActiveFrameList ); FOR cnt := 1 TO (spot - 1) DO GetFrameFromList( ActiveFrameList, cnt, TmpFrame ); GetFrameCoords( TmpFrame, tmprect ); IF Rectangles.RectsIntersect( FrameRect, tmprect, intersection ) THEN RETURN TRUE; END; END; RETURN FALSE; END IsFrameObscured; PROCEDURE EraseFrame( TheFrame: ScrnTypes.DisplayFrame ); VAR FrameRect, tmprect, intersection : Rectangles.ARectangle; ActiveFrameList : GenLists.GenList; ListEnd, cnt, spot : CARDINAL; TmpFrame : ScrnTypes.DisplayFrame; BEGIN FrameIsInForeGround( TheFrame ); FrameDeactivated( TheFrame ); GetFrameCoords( TheFrame, FrameRect ); GetAssociatedFrames( TheFrame^.WindowHandle, ActiveFrameList ); ListEnd := GenLists.ListLength( ActiveFrameList ); (* If FrameRect is wholly within an unobscured frame, redraw that frame. *) FOR cnt := 1 TO ListEnd DO GetFrameFromList( ActiveFrameList, cnt, TmpFrame ); GetFrameCoords( TmpFrame, tmprect ); IF (NOT IsFrameObscured( TmpFrame )) AND (Rectangles.RectIsInside( FrameRect, tmprect ) ) THEN FramePainter.RedrawArea( TmpFrame, FrameRect.col1, FrameRect.row1, FrameRect.col2, FrameRect.row2 ); RETURN END; END; (* otherwise clearpart(rec), then start from bottom and call redrawarea for each frame that extends into rec *) VWindows.SetBackColor( TheFrame^.WindowHandle, VWindows.BackColor(TheFrame^.WindowHandle) ); VWindows.SetMonoAttr( TheFrame^.WindowHandle, VWindows.MonoAttr(TheFrame^.WindowHandle) ); VWindows.ClearPart( TheFrame^.WindowHandle, FrameRect.col1, FrameRect.row1, FrameRect.col2, FrameRect.row2 ); cnt := ListEnd; WHILE cnt >= 1 DO GetFrameFromList( ActiveFrameList, cnt, TmpFrame ); GetFrameCoords( TmpFrame, tmprect ); IF Rectangles.RectsIntersect( FrameRect, tmprect, intersection ) THEN FramePainter.RedrawArea( TmpFrame, intersection.col1, intersection.row1, intersection.col2, intersection.row2 ); END; DEC( cnt ); END; END EraseFrame; PROCEDURE RestoreWholeWindow( TheWindow: VWindows.AWindowHandle ); VAR ActiveFrameList : GenLists.GenList; ListEnd, cnt: CARDINAL; TmpFrame: ScrnTypes.DisplayFrame; BEGIN GetAssociatedFrames( TheWindow, ActiveFrameList ); VWindows.SetBackColor( TheWindow, VWindows.BackColor(TheWindow) ); VWindows.SetMonoAttr( TheWindow, VWindows.MonoAttr(TheWindow) ); VWindows.ClearPart( TheWindow, 1, 1, VWindows.EndCol(TheWindow), VWindows.EndRow(TheWindow) ); ListEnd := GenLists.ListLength( ActiveFrameList ); cnt := ListEnd; WHILE cnt >= 1 DO GetFrameFromList( ActiveFrameList, cnt, TmpFrame ); FramePainter.RedrawArea( TmpFrame, TmpFrame^.startcol + 1, TmpFrame^.startrow + 1, TmpFrame^.endcol + 1, TmpFrame^.endrow + 1 ); (* Corrected 3 Nov 88 thanks to John McMonagle; was 0,0,0,0 in 1.5c *) DEC( cnt ); END; END RestoreWholeWindow; PROCEDURE Init(); BEGIN IF Initialized THEN RETURN; ELSE Initialized := TRUE; END; WindowListInitialized := FALSE; (* Diagnostics.Init(); *) ErrorManager.Init(); FramePainter.Init(); GenLists.Init(); Hash.Init(); ListUtils.Init(); Rectangles.Init(); ScrnTypes.Init(); VWindows.Init(); END Init; BEGIN Initialized := FALSE; Init(); END FrameManager.