;Window stuff include "offsets.i" include "defs.i" include "errordefs.i" include "macros.i" include "macros2.i" ifd CREATOR incdir "/AMOS1.3" else incdir "/AMOS" endc ; include "equ.s" ;PhxAss is buggy... EcNumber equ 188 Bnk_BitData equ 0 Bnk_BitChip equ 1 Bnk_BitBob equ 2 Bnk_BitIcon equ 3 section text,code xref DataBase xref NoMem xref NoScr xref NoWin xref InternalErr xref Error xref NoCloseWin0 xref CantOpenWB xref WinTooSmall xref WinTooLarge xref IllWinParm xref WinNotClosed xref CantOpenWin xref NoReqTools xref StrAlloc xref AllocMemClear xref AllocTmpRas xref FreeTmpRas xref StrFree xref DoEvent xref FreeImenu xref GetCurRP xref GetCurIscr xdef GetCurWin xdef FindIwin xdef FindIwin2 xdef FindWBIwin xdef GetCurIwin xdef GetCurIwin2 xdef OpenIwin xdef CloseWin xdef CloseIwin xdef CloseWBIwin xdef GetWinFlags xdef GetSomeWinFlags xdef SetWinFlags xdef SetSomeWinFlags xdef GetActiveWin xdef SetCoords xdef SetCoordsRel GetCurWin: ;Return address of current window (even if BaseWin). ; Assumes this is legal (i.e. a win/scr is open). pstart2 dmove.l CurIwindow,d0 bne .exit dmove.l CurIscreen,a0 move.l sc_UserData(a0),a0 move.l se_BaseWin(a0),d0 .exit ret2 FindIwin: ;Find a window on the current screen, window # in D0 ;Returns winadr or NULL in D0/A0, prevwinadr in A1, ; Z set if not found. dmove.l CurIscreen,a0 FindIwin2: ;Find a window on screen w/ address A0, window # in D0 ;Returns winadr or NULL in D0/A0, prevwinadr in A1, ; Z set if not found. pstart2 move.l a2,-(a7) move.l d0,d1 move.l sc_UserData(a0),a0 tst.l d1 bne .find move.l se_BaseWin(a0),d0 bne .ok move.l #$4657640A,d1 bra InternalErr .ok move.l d0,a0 move.l wd_UserData(a0),a1 move.l we_PrevIwin(a1),a1 bra .exit .find move.l se_FirstIwindow(a0),a0 sub.l a1,a1 .lp move.l a0,d0 beq .done move.l wd_UserData(a0),a2 cmp.l we_WinNum(a2),d1 beq .done move.l a0,a1 move.l we_NextIwin(a2),a0 bra .lp .done move.l a0,d0 .exit move.l (a7)+,a2 ret2 FindWBIwin: ;Find a Workbench window, window # in D0 ;Returns winadr or NULL in D0/A0, prevwinadr in A1, ; Z set if not found pstart2 move.l a2,-(a7) dmove.l FirstWBIwindow,a0 sub.l a1,a1 .lp move.l a0,d1 beq .done move.l wd_UserData(a0),a2 cmp.l we_WinNum(a2),d0 beq .done move.l a0,a1 move.l we_NextIwin(a2),a0 bra .lp .done move.l a0,d0 move.l (a7)+,a2 ret2 GetCurIwin: ;Get current Iwindow address (not BaseWin) pstart2 dmove.l CurIwindow,d0 beq NoWin ret2 GetCurIwin2: ;Get current Iwindow address (or BaseWin) pstart2 dmove.l CurIwindow,d0 bne .done dmove.l CurIscreen,d0 beq NoWin ;We're looking for window, not screen move.l d0,a0 move.l sc_UserData(a0),a0 move.l se_BaseWin(a0),d0 .done ret2 OpenIwin: ;Parameter in D0 - 0 to open on WB, 1 for CustomScreen ; Window flags in D1. Should be Null if no flags. ; Takes parameters from A3 like full Iwindow Open ; command, *including title*. pstart2 move.l a5,-(a7) move.l d1,d2 movem.l (a3)+,d3-d7 tst.w d0 ;Should window open on the Workbench? beq .wbwin dmove.l CurIscreen,d0 ;No - get current screen address beq NoScr move.l d0,a0 move.w #CUSTOMSCREEN,-(a7) move.l sc_UserData(a0),a1 tst.l (a3) ;Don't let them close base window beq NoCloseWin0 bra .cksize .wbwin intcall OpenWorkBench ;Yes - get WB screen address tst.l d0 beq CantOpenWB move.l d0,a0 move.w #WBENCHSCREEN,-(a7) .cksize cmp.l #48,d4 ;Window must be larger than 80x48 blt WinTooSmall cmp.l #80,d5 blt WinTooSmall swap d4 ; and smaller than 65536x65536 tst.w d4 bne WinTooLarge swap d4 swap d5 tst.w d5 bne WinTooLarge swap d5 moveq #0,d1 ; and within the screen's boundaries move.l d6,d0 bmi IllWinParm move.w sc_Height(a0),d1 sub.l #48,d1 cmp.l d1,d0 bge IllWinParm add.l #48,d1 add.l d4,d0 cmp.l d1,d0 bhi WinTooLarge move.l d7,d0 bmi IllWinParm move.w sc_Width(a0),d1 sub.l #80,d1 cmp.l d1,d0 bge IllWinParm add.l #80,d1 add.l d5,d0 cmp.l d1,d0 bhi WinTooLarge move.l (a3),d0 ;Window geometry OK; is window open? cmp.w #WBENCHSCREEN,(a7) beq .wbiwin bsr FindIwin bne WinNotClosed ;Yes, barf bra .chkttl .wbiwin bsr FindWBIwin bne WinNotClosed ;Yes, barf .chkttl tst.l d3 ;Is there a title? beq .nottl move.l d3,a2 ;Yes - get memory and copy it move.l d2,-(a7) moveq #0,d2 move.w (a2)+,d2 move.l d2,d0 bsr StrAlloc exg a2,a0 move.l a2,a1 move.l d2,d0 syscall CopyMem clr.b 0(a2,d2.l) move.l (a7)+,d2 bra .getwe .nottl sub.l a2,a2 ;No title .getwe moveq #we_sizeof,d0 ;Get memory for structure extension moveq #MEMF_PUBLIC,d1 bsr AllocMemClear tst.l d0 bne .gotwe move.l a2,a0 ;Didn't get it - barf bsr StrFree bra NoMem .gotwe move.l d0,a5 ;Got it - set up NewWindow dlea NewWindow,a0 move.w d7,nw_LeftEdge(a0) move.w d6,nw_TopEdge(a0) move.w d5,nw_Width(a0) move.w d4,nw_Height(a0) move.b #0,nw_DetailPen(a0) move.b #1,nw_BlockPen(a0) clr.l nw_IDCMPFlags(a0) ;Note that we can't set IDCMP flags ; here; we have to set them ; separately, AFTER setting the ; window's UserPort to our own. cmp.l #Null,d2 ;Were flags passed in? beq .def_flags ;No, use defaults. move.l #MINWFLAGS,nw_Flags(a0) ;Yes, start with minimum flags... and.l #USERWFLAGS,d2 ;... mask out illegal user flags... or.l d2,nw_Flags(a0) ;... and OR them with minimum flags. bra .openwin .def_flags: move.l #WFLAGS,nw_Flags(a0) .openwin: clr.l nw_FirstGadget(a0) clr.l nw_CheckMark(a0) move.l a2,nw_Title(a0) dmove.l CurIscreen,nw_Screen(a0) clr.l nw_BitMap(a0) move.w #80,nw_MinWidth(a0) move.w #48,nw_MinHeight(a0) move.w #-1,nw_MaxWidth(a0) move.w #-1,nw_MaxHeight(a0) move.w (a7)+,nw_Type(a0) ;Pick up WB/NoWB from stack intcall OpenWindow ;Actually open the window tst.l d0 ;Did we get it? bne .gotwin move.l a5,a1 ;Nope - barf moveq #we_sizeof,d0 syscall FreeMem move.l a2,a0 bsr StrFree bra CantOpenWin .gotwin: ifd UNREGISTERED ;Nastiness from below - make sure lea .check+2(pc),a6 ; they haven't played with our cmp.w #_LVOAllocMem,(a6) ; code. beq .okchk move.l 4,a6 .loop clr.l (a6) move.l 4(a6),a6 bra .loop .okchk: endc move.l d0,a2 move.l wd_WScreen(a2),a1 ;Get screen's address dlea NewWindow,a0 dmove.b CurIwindowIsWB,d7 ;Save old CurIwindowIsWB cmp.w #WBENCHSCREEN,nw_Type(a0) seq d1 ;Set CurIwindowIsWB appropriately tmove.b d1,CurIwindowIsWB beq .not_on_wb dtst.b WB20 ;Get WB dripens beq .pens13 move.l a1,-(a7) move.l a1,a0 intcall GetScreenDrawInfo move.l (a7)+,a1 tst.l d0 bne .gotdri .pens13 dlea WBPens,a0 cmp.w #1,sc_Depth(a1) beq .mono0 move.w #0,(a0)+ move.w #1,(a0)+ move.w #1,(a0)+ move.w #2,(a0)+ move.w #1,(a0)+ move.w #3,(a0)+ move.w #1,(a0)+ move.w #0,(a0)+ move.w #2,(a0)+ move.w #1,(a0)+ move.w #2,(a0)+ move.w #1,(a0)+ bra .not_on_wb .mono0 move.w #0,(a0)+ move.w #1,(a0)+ move.w #1,(a0)+ move.w #0,(a0)+ move.w #1,(a0)+ move.w #1,(a0)+ move.w #0,(a0)+ move.w #0,(a0)+ move.w #1,(a0)+ move.w #0,(a0)+ move.w #1,(a0)+ move.w #0,(a0)+ bra .not_on_wb .gotdri move.l d0,a0 move.w dri_NumPens(a0),d0 cmp.w #NUMDRIPENS,d0 bls .okcnt moveq #NUMDRIPENS,d0 .okcnt move.l dri_Pens(a0),a0 dlea WBPens,a1 subq.w #1,d0 .dri_lp move.w (a0)+,(a1)+ dbra d0,.dri_lp .not_on_wb: move.l a2,a0 ;Get screen's TmpRas move.l wd_WScreen(a0),a1 move.l wd_RPort(a0),a0 move.l sc_RastPort+rp_TmpRas(a1),rp_TmpRas(a0) dmove.l MyUserPort,wd_UserPort(a2) ;Make window use common UserPort move.l #IDCMPFLAGS,d0 move.l a2,a0 intcall ModifyIDCMP move.l (a3)+,d0 ;Grab window number move.l a3,-(a7) ;We need to use A3 for a moment dtst.b CurIwindowIsWB ;Link window into appropriate list bne .wblist dmove.l CurIscreen,a0 move.l sc_UserData(a0),a1 ;A3=&scr->sc_UserData->se_FirstIwindow lea se_FirstIwindow(a1),a3 bra .wcont .wblist dlea FirstWBIwindow,a3 ;A3 = &FirstWBIwindow .wcont clr.l we_PrevIwin(a5) ;winext->we_PrevIwin = NULL move.l d0,we_WinNum(a5) ;Set window number in winext move.l #WEF_UNSET,we_Flags(a5) ;Window CP not yet (officially) set move.l wd_WScreen(a2),a0 ;Set border pens dtst.b CurIwindowIsWB bne .wbpens move.l sc_UserData(a0),a0 lea se_Dripens(a0),a0 bra .dopens .wbpens dlea WBPens,a0 .dopens move.b 7(a0),we_HilitePen(a5) move.b 9(a0),we_ShadowPen(a5) move.l a5,wd_UserData(a2) ;win->wd_UserData = winext dcmp.b CurIwindowIsWB,d7 ;Set LastActive[WB] if necessary beq .setcw tst.b d7 bne .lastwb dmove.l CurIscreen,a0 ;Necessary - not done if opening WBwin move.l a0,d0 beq .setcw ;No active screen move.l sc_UserData(a0),a0 dmove.l CurIwindow,se_LastActive(a0) bra .setcw .lastwb dmove.l CurIwindow,d0 tmove.l d0,LastActiveWB .setcw tmove.l a2,CurIwindow ;Window is now the current one ; move.l a1,-(a7) ; dtst.b CurIwindowIsWB ; bne .wbfind ; bsr FindIwin ;If it already existed, close old one ; beq .norepl ; bsr CloseIwin ;X; move.l a2,a0 ;X; intcall ActivateWindow ; bra .norepl ;.wbfind bsr FindWBIwin ; beq .norepl ; bsr CloseIwin ;X; move.l a2,a0 ;X; intcall ActivateWindow ;.norepl move.l (a7)+,a1 move.l (a3),a0 ;Finish linking window into list move.l a0,we_NextIwin(a5) beq .nonext ;If last window, don't set next->prev move.l wd_UserData(a0),a0 move.l a2,we_PrevIwin(a0) .nonext move.l a2,(a3) ;This window is now the first one move.l (a7)+,a3 move.l wd_RPort(a2),a2 ;Set various window parameters move.l a2,a1 moveq #RP_JAM2,d0 gfxcall SetDrMd move.l a2,a1 moveq #1,d0 gfxcall SetAPen move.l a2,a1 moveq #0,d0 gfxcall SetBPen ifd UNREGISTERED ;Nastiness - allocate chunks of chip moveq #2,d1 ; memory. MAKE SURE THE '.check' move.l #$1000,d0 ; LINE NEVER CHANGES!!!! move.l 4,a6 .check jsr _LVOAllocMem(a6) jsr _LVOAllocMem(a6) endc move.l (a7)+,a5 ret2 CloseWin: ;Close window in A0 - preserves all registers. ; Doesn't do anything to links. ifnd UNREGISTERED movem.l d0-a6,-(a7) move.l a0,a2 move.l wd_RPort(a2),a0 ;Get rid of TmpRas bsr FreeTmpRas move.l wd_RPort(a2),a1 ;Was a nonstandard font opened? move.l rp_RP_User(a1),a1 move.l a1,d0 beq .nofont gfxcall CloseFont ;Yes, close it move.l a2,a0 .nofont move.l wd_UserData(a2),a5 tst.w we_NGadgets(a5) ;Did the window have gadgets? beq .nogads move.l a2,a0 ;Yes, turn off and free move.l wd_FirstGadget(a2),a1 moveq #-1,d0 intcall RemoveGList move.l we_Gadgets(a5),a1 move.l we_GadgetSize(a5),d0 syscall FreeMem mvoe.l we_GBorders(a5),a1 move.l we_GBorderSize(a5),d0 syscall FreeMem .nogads move.l we_FirstMenu(a5),d0 ;Did the window have a menu? beq .nomenu move.l d0,a5 ;Yes, free it move.l a2,a0 intcall ClearMenuStrip ;First turn menus off .menulp move.l a5,a0 move.l mu_NextMenu(a5),a5 bsr FreeImenu move.l a5,d0 bne .menulp .nomenu move.l wd_UserData(a2),-(a7) ;Save window extension syscall Forbid moveq #0,d0 ;Flush all events move.l wd_UserPort(a2),a0 bsr DoEvent clr.l wd_UserPort(a2) ;Don't let Intuition kill our port moveq #0,d0 move.l a2,a0 intcall ModifyIDCMP move.l wd_Title(a2),-(a7) ;Save title move.l a2,a0 ;Close base window intcall CloseWindow syscall Permit move.l (a7)+,a2 move.l (a7)+,a1 ;Free window extension moveq #we_sizeof,d0 syscall FreeMem move.l a2,a0 ;Free title if necessary bsr StrFree movem.l (a7)+,d0-a6 endc ;UNREGISTERED rts CloseIwin: ;Close window in A0 pstart2 movem.l a2-a3,-(a7) move.l wd_WScreen(a0),a3 ;Get window's screen's extension move.l sc_UserData(a3),a3 move.l wd_UserData(a0),a2 ;and window's extension move.l we_PrevIwin(a2),a1 ;and previous window move.l we_NextIwin(a2),a2 ;and next window move.l a1,d1 ;Was this the first window? beq .noprev move.l wd_UserData(a1),a1 ;No, set prev->next to win->next move.l a2,we_NextIwin(a1) bra .setprv .noprev move.l a2,se_FirstIwindow(a3) ;Yes, set FirstIwindow to win->next .setprv move.l a2,d0 ;Was this the last window? beq .nonext move.l wd_UserData(a2),a1 ;No, set next->prev to win->prev move.l d1,we_PrevIwin(a1) .nonext dcmp.l CurIwindow,a0 ;Was this the current window? bne .close move.l a2,d0 ;Yes bne .setcur ;Was it the last window? move.l se_FirstIwindow(a3),a2 ;Yes - FirstIwindow becomes current .setcur tmove.l a2,CurIwindow ;No - win->next becomes current .close ifd UNREGISTERED ;No other OS-friendly way to get rid intcall CloseWindow ; of the window :-( - but don't free else ; other memory. bsr CloseWin endc movem.l (a7)+,a2-a3 ret2 CloseWBIwin: ;Close Workbench window in A0 pstart2 move.l a2,-(a7) move.l wd_UserData(a0),a2 ;Get window's extension move.l we_PrevIwin(a2),a1 ;and previous window move.l we_NextIwin(a2),a2 ;and next window move.l a1,d1 ;Was this the first window? beq .noprev move.l wd_UserData(a1),a1 ;No, set prev->next to win->next move.l a2,we_NextIwin(a1) bra .setprv .noprev tmove.l a2,FirstWBIwindow ;Yes, set FirstWBIwindow to win->next .setprv move.l a2,d0 ;Was this the last window? beq .nonext move.l wd_UserData(a2),a1 ;No, set next->prev to win->prev move.l d1,we_PrevIwin(a1) .nonext dcmp.l CurIwindow,a0 ;Was this the current window? bne .close move.l a2,d0 ;Yes bne .setcur ;Was it the last window? dmove.l FirstWBIwindow,a2 ;Yes - FirstWBIwindow becomes current move.l a2,d0 bne .setcur dmove.l FirstIscreen,d0 ;No FirstWBIwindow; is there a screen? beq .setcur ;Nope - no more windows move.l d0,a2 ;Yes - use se_LastActive move.l sc_UserData(a2),a2 move.l se_LastActive(a2),a2 .setcur tmove.l a2,CurIwindow ;No - win->next becomes current .close ifd UNREGISTERED intcall CloseWindow else bsr CloseWin endc move.l (a7)+,a2 ret2 GetWinFlags: ;Get current window's flags to D0. pstart2 dmove.l CurIwindow,d0 beq .nowin move.l d0,a0 move.l wd_UserData(a0),a0 move.l we_Flags(a0),d0 ret2 .nowin bsr GetCurIscr move.l d0,a0 move.l sc_UserData(a0),a0 move.l se_BaseWin(a0),a0 move.l wd_UserData(a0),a0 move.l we_Flags(a0),d0 ret2 GetSomeWinFlags: ;GetWinFlags for window in A0. move.l wd_UserData(a0),a0 move.l we_Flags(a0),d0 rts SetWinFlags: ;Set CurWindow flags. D0 is new flags, D1 is mask: ; NewFlags = (OldFlags & ~D1) | (D0 & D1). I.e. ; same operation as Signal(). pstart2 move.l d2,-(a7) move.l d0,d2 dmove.l CurIwindow,d0 beq .nowin move.l d0,a0 bra .doset .nowin bsr GetCurIscr move.l d0,a0 move.l sc_UserData(a0),a0 move.l se_BaseWin(a0),a0 .doset move.l wd_UserData(a0),a0 lea we_Flags(a0),a0 move.l d1,d0 not.l d0 and.l d0,(a0) and.l d1,d2 or.l d2,(a0) move.l (a7)+,d2 ret2 SetSomeWinFlags: ;SetWinFlags for window in A0 move.l wd_UserData(a0),a0 lea we_Flags(a0),a0 and.l d1,d0 not.l d1 and.l d1,(a0) or.l d0,(a0) rts GetActiveWin: ;Get address of currently active window to D0. pstart2 moveq #0,d0 intcall LockIBase move.l ib_ActiveWindow(a6),-(a7) move.l d0,a0 call UnlockIBase move.l (a7)+,d0 ret2 SetCoords: ;Set coordinates of current window to (D0,D1). Null ; values leave the coordinate unchanged. Assumes ; there really is a current window - if not, up comes ; InternalErr. pstart2 movem.l d2-d3,-(a7) moveq #0,d2 moveq #0,d3 move.l d0,-(a7) dmove.l CurIwindow,a0 move.l a0,d0 beq .usescr move.b wd_BorderLeft(a0),d2 move.b wd_BorderTop(a0),d3 bra .gotwin .usescr dmove.l CurIscreen,a0 move.l a0,d0 bne .okscr move.l #$53436F0C,d1 bsr InternalErr .okscr ; tst.l sc_DefaultTitle(a0) ; beq .nottl ; move.b sc_BarHeight(a0),d3 ; add.b sc_BarVBorder(a0),d3 .nottl move.l sc_UserData(a0),a0 move.l se_BaseWin(a0),a0 .gotwin move.l (a7)+,d0 move.l wd_RPort(a0),a1 cmp.l #Null,d0 beq .nox add.w d2,d0 bra .gotx .nox move.w rp_cp_x(a1),d0 .gotx cmp.l #Null,d1 beq .noy add.w d3,d1 bra .goty .noy move.w rp_cp_y(a1),d1 .goty gfxcall Move moveq #0,d0 moveq #WEF_UNSET,d1 bsr SetWinFlags movem.l (a7)+,d2-d3 ret2 SetCoordsRel: ;Move CP by (x,y) [delta]. pstart2 move.l d0,-(a7) bsr GetCurRP move.l d0,a1 move.l (a7)+,d0 bsr GetWinFlags btst #WEB_UNSET,d0 bne .exit ;If CP not set, can't move add.w rp_cp_x(a1),d0 add.w rp_cp_y(a1),d1 gfxcall Move .exit ret2