; ; pane.s ; ; Pane handling facilities (TMA) ; ; © 1994-1998 Straylight ; ;----- Licensing note ------------------------------------------------------- ; ; This file is part of Straylight's Sapphire library. ; ; Sapphire is free software; you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation; either version 2, or (at your option) ; any later version. ; ; Sapphire is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with Sapphire. If not, write to the Free Software Foundation, ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;----- Standard header ------------------------------------------------------ GET libs:header GET libs:swis ;----- External dependencies ------------------------------------------------ GET sapphire:alloc GET sapphire:event GET sapphire:screen GET sapphire:sapphire GET sapphire:suballoc GET sapphire:tspr ;----- Main code ------------------------------------------------------------ AREA |Sapphire$$Code|,CODE,READONLY ; --- pane_add --- ; ; On entry: R0 == window handle of parent window ; R1 == icon handle in parent window ; R2 == window handle of pane window ; ; On exit: May return an error ; ; Use: This call registers a pane to be associated with the given ; window. The pane is always opened to fit exactly within ; the given icon -- border widths are taken into account ; if there are scroll bars etc. ; ; You must call pane_closed if the parent window is closed, ; since there is no way for pane to trap this occurence. EXPORT pane_add pane_add ROUT STMFD R13!,{R0-R4,R12,R14} ;Stack some registers WSPACE pane__wSpace ;Locate my workspace ; --- First, we must scan to see if the parent ; window is already registered MOV R4,R0 ;Preserve parent handle BL pane__windowBlock ;Find the window block CMP R0,#0 ;Is there one? MOVNE R3,R0 ;Yes -- point to it BNE %50pane_add ;And add in the pane ; --- The window isn't registered --- 10 MOV R0,#wl__size ;Allocate this much memory BL sub_alloc ;Get it then SWIVS OS_GenerateError ;...and generate error LDR R3,ws__wList ;Load first window defn STR R3,[R0,#wl__next] ;Store as next pointer CMP R3,#0 ;Is there any more? STRNE R0,[R3,#wl__prev] ;Yes -- update prev pointer MOV R3,#0 ;A NULL pointer STR R3,[R0,#wl__prev] ;No previous for new block STR R3,[R0,#wl__pList] ;No pane list yet MOV R3,R0 ;Put pointer in R3 STR R4,[R3,#wl__wHandle] ;Store parent window handle STR R3,ws__wList ;Store at list head ; --- R3 points to the window list block --- 50 MOV R0,#pl__size ;Allocate this much memory BL sub_alloc ;Go on then SWIVS OS_GenerateError ;...and generate error LDR R4,[R3,#wl__pList] ;Load first pane defn STR R4,[R0,#pl__next] ;Store as next pointer CMP R4,#0 ;Is there any more? STRNE R0,[R4,#pl__prev] ;Yes -- update prev pointer MOV R14,#0 ;A NULL pointer STR R14,[R0,#pl__prev] ;No previous for new block STR R1,[R0,#pl__iHandle] ;Store the icon handle STR R2,[R0,#pl__wHandle] ;Store the window handle STR R0,[R3,#wl__pList] ;Store at list head ; --- Return to caller --- LDMFD R13!,{R0-R4,R12,PC}^ ;Return LTORG ; --- pane_remove --- ; ; On entry: R0 == window handle for which pane was registered ; R1 == window handle of the pane window itself ; ; On exit: -- ; ; Use: Removes the pane from the given window. This call will ; close the given pane, but will not actually delete it ; (ie. with a Wimp_DeleteWindow). EXPORT pane_remove pane_remove ROUT STMFD R13!,{R0-R5,R12,R14} ;Stack some registers WSPACE pane__wSpace ;Locate my workspace BL pane__windowBlock ;Find the window block CMP R0,#0 ;Is there one? BEQ %90pane_remove ;No -- remove MOV R3,R0 ;Put pointer in R3 ; --- Remove the pane from the window list --- 50 LDR R4,[R3,#wl__pList] ;Get the first entry 55 CMP R4,#0 ;Is there a pane definition? BEQ %90pane_remove ;No -- return LDR R5,[R4,#pl__wHandle] ;Get the pane handle CMP R5,R1 ;Is this the one we want LDRNE R4,[R4,#wl__next] ;No -- get next in list BNE %55pane_remove ;...and keep looking ; --- We have now found the pane block --- ADD R1,R4,#pl__wHandle ;Point to the window handle SWI XWimp_CloseWindow ;Close the window LDR R1,[R4,#pl__prev] ;Get the previous pointer LDR R2,[R4,#pl__next] ;And the next pointer CMP R2,#0 ;Is there a next field? STRNE R1,[R2,#pl__prev] ;Yes -- update previous CMP R1,#0 ;Is there a previous field STRNE R2,[R1,#pl__next] ;Yes -- update next field STREQ R2,[R3,#wl__pList] ;No -- store next as head MOV R0,R4 ;Point to the block MOV R1,#pl__size ;It's this big BL sub_free ;Free the block LDR R1,[R3,#wl__pList] ;Get the pane list CMP R1,#0 ;Is there one? MOVEQ R0,R3 ;No -- point to window block BLEQ pane__removeWindow ;...remove the definition ; --- Return to caller --- 90 LDMFD R13!,{R0-R5,R12,PC}^ ;Return LTORG ; --- pane__removeWindow --- ; ; On entry: R0 == pointer to window block ; ; On exit: -- ; ; Use: Removes the give window block from the list. All associated ; panes are removed too. pane__removeWindow ROUT STMFD R13!,{R0-R3,R14} ;Stack some registers MOV R3,R0 ;Keep a pointer to this block LDR R2,[R3,#wl__pList] ;Get the first pane block CMP R2,#0 ;Is there one? BEQ %10pane__removeWindow ;No -- free window block 00 ADD R1,R2,#pl__wHandle ;Point to the window handle MOV R14,R2 ;Get block pointer in R14 LDR R2,[R2,#pl__next] ;Get next pointer SWI XWimp_CloseWindow ;Close the window MOV R0,R14 ;Block pointer in R0 MOV R1,#pl__size ;It's this big BL sub_free ;Free the block CMP R2,#0 ;Are there more blocks? BNE %00pane__removeWindow ;Yes -- remove next pane too ; --- Remove the window block --- 10 LDR R1,[R3,#wl__prev] ;Get the previous pointer LDR R2,[R3,#wl__next] ;And the next pointer CMP R2,#0 ;Is there a next field? STRNE R1,[R2,#wl__prev] ;Yes -- update previous CMP R1,#0 ;Is there a previous field STRNE R2,[R1,#wl__next] ;Yes -- update next field STREQ R2,ws__wList ;No -- store next as head MOV R0,R3 ;Point to the block MOV R1,#wl__size ;It's this big BL sub_free ;And free it LDMFD R13!,{R0-R3,PC}^ ;Return to caller LTORG ; --- pane_closed --- ; ; On entry: R0 == window handle of parent ; ; On exit: -- ; ; Use: Informs pane that a parent window has closed. ; All associated panes are then closed. EXPORT pane_closed pane_closed ROUT STMFD R13!,{R0-R2,R12,R14} ;Stacks some registers WSPACE pane__wSpace ;Locate workspace BL pane__windowBlock ;Find the block CMP R0,#0 ;Is there one? BEQ %90pane_closed ;No -- return LDR R2,[R0,#wl__pList] ;Get the first pane pointer 00pane_closed ADD R1,R2,#pl__wHandle ;Point to the window handle SWI XWimp_CloseWindow ;Close the window LDR R2,[R2,#pl__next] ;Get the next pane CMP R2,#0 ;Is there one? BNE %00pane_closed ;Yes -- close it then 90pane_closed LDMFD R13!,{R0-R2,R12,PC}^ ;Return to caller LTORG ; --- pane_deleted --- ; ; On entry: R0 == window handle of parent ; ; On exit: -- ; ; Use: Informs pane that a parent window has been deleted. ; All associated panes are then closed, and there ; registration with the pane library module is ; terminated. EXPORT pane_deleted pane_deleted ROUT STMFD R13!,{R0-R3,R12,R14} ;Stacks some registers WSPACE pane__wSpace ;Locate workspace BL pane__windowBlock ;Find the block CMP R0,#0 ;Is there one? BLNE pane__removeWindow ;Yes -- remove definitions LDMFD R13!,{R0-R3,R12,PC}^ ;Return to caller LTORG ; --- pane__windowBlock --- ; ; On entry: R0 == window handle ; ; On exit: R0 == pointer to window block ; ; Use: Find the window block associated with the given ; window handle. If it is not found, 0 is returned. pane__windowBlock ROUT STMFD R13!,{R1,R2,R14} ;Stack some registers MOV R1,R0 ;Keep the window handle LDR R0,ws__wList ;Load first window defn 00 CMP R0,#0 ;Is there one? BEQ %90pane__windowBlock ;No -- return LDR R2,[R0,#wl__wHandle] ;Get the window handle CMP R2,R1 ;Is this the one we want? BEQ %90pane__windowBlock ;Yes -- return LDR R0,[R0,#wl__next] ;Get the next in list B %00pane__windowBlock ;And keep looking 90 LDMFD R13!,{R1,R2,PC}^ ;Return to caller LTORG ; --- pane_swap --- ; ; On entry: R0 == window handle of parent window ; R1 == icon handle within parent window ; R2 == window handle of new pane ; ; On exit: -- ; ; Use: This call will replace the pane in associated with icon R1 ; in window R0, with the pane in R2. ; ; The exisiting pane is closed, and the new pane is ; opened in it's place. No error is generated if the existing ; pane does not exist; this allows the caller to delete the ; window before doing the swap. EXPORT pane_swap pane_swap ROUT STMFD R13!,{R0-R3,R12,R14} ;Stack some registers WSPACE pane__wSpace ;Locate my workspace BL pane__windowBlock ;Find the window block CMP R0,#0 ;Is there one? BEQ %90pane_swap ;No -- return ; --- Find the pane in the pane window list --- LDR R3,[R0,#wl__pList] ;Get the first entry 00 CMP R3,#0 ;Is there a pane definition? BEQ %90pane_swap ;No -- return LDR R14,[R3,#pl__iHandle] ;Get the icon handle CMP R14,R1 ;Is this the one we want LDRNE R3,[R3,#wl__next] ;No -- get next in list BNE %00pane_swap ;...and keep looking ; --- Do the swap --- MOV R14,R0 ;Preserve R0 ADD R1,R3,#pl__wHandle ;Point to the window handle SWI XWimp_CloseWindow ;Close it STR R2,[R3,#pl__wHandle] ;Store the new window handle SUB R13,R13,#36 ;Get a block LDR R0,[R14,#wl__wHandle] ;Get parent handle STR R0,[R13,#0] ;Store it in the block MOV R1,R13 ;Point to the block SWI Wimp_GetWindowState ;Get the window state MOV R2,R1 ;Put state in R2 MOV R0,R14 ;The window block MOV R1,R3 ;Point to the pane block MOV R3,R2 ;Now put state in R3 BL pane__open ;Open the new pane ADD R13,R13,#36 ;Reclaim my stack 90pane_swap LDMFD R13!,{R0-R3,R12,PC}^ ;Return to caller LTORG ; --- pane_open --- ; ; On entry: R0 == window handle ; ; On exit: -- ; ; Use: Opens all the panes associated with the given window. EXPORT pane_open pane_open ROUT STMFD R13!,{R0-R3,R12,R14} ;Stack some registers WSPACE pane__wSpace ;Load my workspace pointer BL pane__windowBlock ;Find the window block CMP R0,#0 ;Is there one? BEQ %90pane_open ;No -- return ; --- Find the pane in the pane window list --- SUB R13,R13,#36 ;Get a block LDR R14,[R0,#wl__wHandle] ;Get the window handle STR R14,[R13,#0] ;Store in the block MOV R1,R13 ;Point to the block MOV R2,R0 ;Preserve R0 SWI Wimp_GetWindowState ;Get the window state MOV R0,R2 ;Get R0 back MOV R3,R1 ;Put state in R3 LDR R1,[R0,#wl__pList] ;Get the first entry 00pane_open BL pane__open ;Open the pane LDR R1,[R1,#pl__next] ;Get next pane CMP R1,#0 ;Is there one? BNE %00pane_open ;Yes -- keep looping ADD R13,R13,#36 ;Get stack back 90pane_open LDMFD R13!,{R0-R3,R12,PC}^ ;Return to caller LTORG ; --- pane__open --- ; ; On entry: R0 == pointer to window block ; R1 == pointer to pane block ; R3 == pointer to parent window state ; ; On exit: -- ; ; Use: Opens the pane in the right place. pane__open ROUT STMFD R13!,{R0-R9,R14} ;Stack some more registers MOV R4,R0 ;Preserve window block MOV R6,R1 ;Preserve R1 BL screen_justChangedMode ;Due to a mode change? MOVCS R1,R3 ;Point to open window block BLCS tspr_adjustBox ;Adjust the box LDR R5,[R3,#28] ;Get the back value CMP R5,#-2 ;Opening at the back? MOVEQ R1,R3 ;Yes -- point to the block SWIEQ Wimp_OpenWindow ;Open the window SWIEQ Wimp_GetWindowState ;Get the window state MOV R2,R6 ;Get R1 back again SUB R13,R13,#36 ;Get me a block LDR R14,[R2,#pl__wHandle] ;Get pane window handle STR R14,[R13,#0] ;Store in the block MOV R1,R13 ;Point to the block SWI Wimp_GetWindowState ;Get the window state LDR R9,[R13,#32] ;Load the window's flags SUB R13,R13,#40 ;Get another block LDR R14,[R4,#wl__wHandle] ;Get parent handle STR R14,[R13,#0] ;Store the handle LDR R14,[R2,#pl__iHandle] ;Get the icon handle STR R14,[R13,#4] ;Store that too MOV R1,R13 ;Point to the block SWI Wimp_GetIconState ;Get the icon state ADD R1,R13,#8 ;Point to coordinates LDMIA R1,{R5-R8} ;Get the icon coordinates ADD R13,R13,#40 ;Point at window state LDR R0,[R3,#4] ;Visible area x0 coord LDR R1,[R3,#16] ;Visible area y1 coord ADD R5,R0,R5 ;Make icon coords screen rel. ADD R6,R1,R6 ADD R7,R0,R7 ADD R8,R1,R8 STMFD R13!,{R2-R4} ;Preserve registers BL screen_getInfo ;Get screen information ADD R0,R0,#screen_dx ;Point to the pixel sizes LDMIA R0,{R3,R4} ;Load the pixel sizes BL tspr_borderWidths ;Get the border widths TST R9,#&0f000000 ;Is there a title bar? SUBNE R8,R8,R0 ;Yes -- correct y1 coord SUBEQ R8,R8,R4 ;No -- subtract pixel size TST R9,#&10000000 ;Is there a vertical bar? SUBNE R7,R7,R1 ;Yes -- correct x1 coord SUBEQ R7,R7,R3 ;No -- subtract pixel size TST R9,#&40000000 ;Is there a horizontal bar? ADDNE R6,R6,R2 ;Yes -- correct y0 coord ADDEQ R6,R6,R4 ;No -- add pixel size ADD R5,R5,R3 ;Add pixel size to x0 LDMFD R13!,{R2-R4} ;Get registers back again 10pane__open STMIB R13,{R5-R8} ;Store new coorinates LDR R5,[R3,#28] ;Get behind value to use LDR R6,[R13,#0] ;And the pane handle CMP R6,R5 ;Are they the same? STRNE R5,[R13,#28] ;No -- Store it in the block STR R6,[R3,#28] ;New behind for parent window MOV R1,R13 ;Point to the block SWI Wimp_OpenWindow ;Open the pane window ADD R13,R13,#36 ;Reclaim stack LDMFD R13!,{R0-R9,PC}^ ;Return to caller LTORG ; --- pane__fakeHandler --- ; ; On entry: R0 == event type ; R1 == event block ; ; On exit: CC ; ; Use: Although this is called as a fake handler, it does not ; generate fake event. Instead, it is used to trap ; open window event before any handler can claim them. This ; allows the panes to be moved automatically. pane__fakeHandler ROUT TEQ R0,#2 ;Open window request? MOVNES PC,R14 ;No -- return PDQ STMFD R13!,{R0,R14} ;Stack some registers LDR R0,[R1,#0] ;Get the window handle BL pane__windowBlock ;Find out if it's registered CMP R0,#0 ;Is there a block LDMEQFD R13!,{R0,PC}^ ;No -- return ; --- We are moving a window with panes in it --- STMFD R13!,{R1,R3} ;Stack some more registers MOV R3,R1 ;Put window state in R3 LDR R1,[R0,#wl__pList] ;Get the first pane 00 BL pane__open ;Open the given pane ; --- Keep looking for more panes --- LDR R1,[R1,#pl__next] ;Get the next pane CMP R1,#0 ;Is there one? BNE %00pane__fakeHandler ;Yes -- move it then LDMFD R13!,{R1,R3} ;Get back first lot LDMFD R13!,{R0,PC}^ ;And return LTORG ; --- pane_init --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Initialises the pane unit. EXPORT pane_init pane_init ROUT STMFD R13!,{R0,R1,R12,R14} ;Stack some registers WSPACE pane__wSpace ;Locate my workspace ; --- Set up a fake handler --- BL event_init ;Initialise event ADR R0,pane__fakeHandler ;Call this routine MOV R1,R12 ;With this R12 value BL event_fakeHandler ;Add in the handler ; --- Initalise some workspace --- MOV R0,#0 ;A nice NULL word STR R0,ws__wList ;No window list yet LDMFD R13!,{R0,R1,R12,PC}^ ;Return to caller LTORG pane__wSpace DCD 0 ;----- Workspace layout ----------------------------------------------------- ; --- Window list --- ^ 0 wl__next # 4 ;The next window in list wl__prev # 4 ;The previous window in list wl__wHandle # 4 ;The window handle wl__pList # 4 ;List of panes wl__size # 0 ;The size of this structure ; --- Pane list --- ^ 0 pl__next # 4 ;The next pane in the list pl__prev # 4 ;The previous pane in list pl__wHandle # 4 ;The window handle of pane pl__iHandle # 4 ;Icon handle in window pl__size # 0 ;The size of this structure ; --- The workspace --- ^ 0,R12 ws__start # 0 ;Workspace start ws__wList # 4 ;The window list ws__size EQU {VAR}-ws__start ;Workspace size AREA |Sapphire$$LibData|,CODE,READONLY DCD ws__size ;Workspace size DCD pane__wSpace ;Workspace pointer DCD 0 ;Scratchpad size DCD pane_init ;Initialisation code ;----- That's all, folks ---------------------------------------------------- END