; ; win.s ; ; Window event dispatching (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:sapphire GET sapphire:suballoc GET sapphire:event ;----- Main code ------------------------------------------------------------ AREA |Sapphire$$Code|,CODE,READONLY ; --- win__addToList --- ; ; On entry: R0 == window handle ; R1 == pointer to routine to call ; R2 == R10 value to call routine ; R3 == R12 value to call routine with ; R4 == pointer to list head to use ; ; On exit: R0-R4 preserved ; ; Use: Adds a rountine to the given list. Later added ; routines are called first win__addToList ROUT STMFD R13!,{R0-R4,R14} ;Stack some registers ; --- Allocate a block --- MOV R0,#list__size ;Size to allocate BL sub_alloc ;Allocate the block BVS %01 ;Branch ahead if error ; --- Fill the block in --- LDR R1,[R4] ;Get the list head STR R1,[R0,#list__next] ;Store in next field STR R0,[R4] ;Store new block at head LDMIA R13,{R1-R4} ;Get parameters STMIB R0,{R1-R4} ;Store them in the block ; --- And return to user --- LDMFD R13!,{R0-R4,R14} ;Load back link BICS PC,R14,#V_flag ;Return without error ; --- Barf if an error occured --- 01 ADD R13,R13,#4 ;Skip over R0 LDMFD R13!,{R1-R4,R14} ;Branch if error ORRS PC,R14,#V_flag ;Return with error LTORG ; --- win__removeFromList --- ; ; On entry: R0 == window handle ; R1 == pointer to routine to called ; R2 == R10 value routine is called with ; R3 == R12 value routine is called with ; R4 == pointer to list head to use ; ; On exit: All registers/flags preserved ; ; Use: Removes a routine from the given list. All values are ; compared. win__removeFromList ROUT STMFD R13!,{R0-R10,R12,R14} ; --- Find the block --- MOV R5,#0 ;The previous pointer MOV R12,R4 ;Remember where the head is LDR R4,[R4] ;Get the head of the list 01 TEQ R4,#0 ;Are we at the end? LDMEQFD R13!,{R0-R10,R12,PC}^ ;Yes -- return LDR R9,[R4],#4 ;Get the next pointer LDMIA R4,{R6-R8,R10} ;Load data from the block CMP R6,R0 ;Are handles/R4 the same? CMPEQ R7,R1 ;Yes -- and routines to call? CMPEQ R8,R2 ;Yes -- R10 value? CMPEQ R10,R3 ;Yes -- R12 value? SUBNE R5,R4,#4 ;If no, remember previous MOVNE R4,R9 ;...get list pointer BNE %01 ;...and keep looking ; --- So now the block has been found --- SUB R0,R4,#4 ;Put the block in R0 MOV R1,#list__size ;Get the size BL sub_free ;Free the block CMP R5,#0 ;Was there a previous block STREQ R9,[R12,#0] ;No -- store next blk in head STRNE R9,[R5,#0] ;Yes -- store in prev next ^ ; --- And return to the user --- LDMFD R13!,{R0-R10,R12,PC}^ LTORG ; --- win_eventHandler --- ; ; On entry: R0 == window handle ; R1 == pointer to routine to call ; R2 == R10 value to call routine with ; R3 == R12 value to call routine with ; ; On exit: May return an error ; ; Use: Adds a routine to the event handler list. Later added ; routines are called first. The event handing routine ; must preserve all the registers, but may alter the carry ; flag. If it returns with carry set, then no more event ; handlers, OR post-filters, will be called. EXPORT win_eventHandler win_eventHandler ROUT STMFD R13!,{R4,R9,R14} ;Save some registers ; --- Be careful not to alter flags --- WSPACE win__wSpace,R9 ;Get my workspace pointer ADR R4,win__eHandlers ;Get the event handlers BL win__addToList ;Add the routine to the list LDMFD R13!,{R4,R9,PC} ;Return cunningly ; --- win_removeEventHandler --- ; ; On entry: R0 == window handle ; R1 == pointer to routine called ; R2 == R10 value routine is called with ; R3 == R12 value routine is called with ; ; On exit: -- ; ; Use: Removes a routine to the event handler list. EXPORT win_removeEventHandler win_removeEventHandler ROUT STMFD R13!,{R4,R9,R14} ;Stack some registers WSPACE win__wSpace,R9 ;Get my workspace pointer ADR R4,win__eHandlers ;Get the event handlers BL win__removeFromList ;Remove routine from the list LDMFD R13!,{R4,R9,PC}^ ;Load registers LTORG ; --- win_swapWindow --- ; ; On entry: R0 == old window handle ; R1 == new window handle ; ; On exit: -- ; ; Use: Searches for all the event handlers for window R0, and ; changes the window handle for R1. This is designed for ; situations in wihich a window has been deleted and ; recreated. EXPORT win_swapWindow win_swapWindow ROUT STMFD R13!,{R0-R3,R9,R14} ;Stack some registers WSPACE win__wSpace,R9 ;Get my workspace pointer LDR R2,win__eHandlers ;Get my event handlers list 10 TEQ R2,#0 ;Are we at the end BEQ %20win_swapWindow ;Yes -- jump ahead LDMIA R2,{R3,R14} ;Load some information TEQ R14,R0 ;Are window handles the same STREQ R1,[R2,#list__wHandle] ;Yes -- store new window hnd MOV R2,R3 ;Put next handler in R2 B %10win_swapWindow ;Try another handler 20 LDMFD R13!,{R0-R3,R9,PC}^ ;Return to caller LTORG ; --- win_windowDeleted --- ; ; On entry: R0 == window handle ; ; On exit: -- ; ; Use: Removes all the event handlers associated with the given ; window handle. It is intended to be used when a window ; has been deleted. EXPORT win_windowDeleted win_windowDeleted ROUT STMFD R13!,{R0-R5,R9,R14} ;Stack some registers WSPACE win__wSpace,R9 ;Get my workspace pointer ; --- Find the block --- MOV R5,#0 ;The previous pointer LDR R2,win__eHandlers ;Get the event handlers 01 TEQ R2,#0 ;Are we at the end? LDMEQFD R13!,{R0-R5,R9,PC}^ ;Yes -- return LDMIA R2,{R3,R4} ;Get next/handle CMP R4,R0 ;Are handles the same? MOVNE R5,R2 ;If no, remember previous MOVNE R2,R3 ;...get list pointer BNE %01win_windowDeleted ;...and keep looking ; --- So now the block has been found --- MOV R0,R2 ;Put the block in R0 MOV R1,#list__size ;Get the size BL sub_free ;Free the block CMP R5,#0 ;Was there a previous block ADREQ R14,win__eHandlers ;No -- point to list head STREQ R3,[R14,#0] ;No -- store next blk in head STRNE R3,[R5,#0] ;Yes -- store in prev next ^ ; --- Now search for the next one --- MOV R2,R3 ;Put the next block in R2 B %01win_windowDeleted ;And keep on searching LTORG ; --- win_unknownHandler --- ; ; On entry: R0 == pointer to routine to call ; R1 == R4 value to call routine with ; R2 == R10 value to call routine with ; R3 == R12 value to call routine with ; ; On exit: May return an error ; ; Use: Adds a rountine to the event handler list. Later added ; routines are called first. The event handing routine ; must preserve all the registers, but may alter the carry ; flag. If it returns with carry set, then no more event ; handlers, OR post-filters, will be called. EXPORT win_unknownHandler win_unknownHandler ROUT STMFD R13!,{R4,R9,R14} ;Save some registers ; --- Be careful not to alter flags --- WSPACE win__wSpace,R9 ;Get my workspace pointer ADR R4,win__uHandlers ;Get the unknowns list BL win__addToList ;Add the routine to the list LDMFD R13!,{R4,R9,PC} ;Return cunningly ; --- win_removeUnknownHandler --- ; ; On entry: R0 == pointer to routine called ; R1 == R4 value routine is called with ; R2 == R10 value routine is called with ; R3 == R12 value routine is called with ; ; On exit: -- ; ; Use: Removes a routine to the unknown handler list. EXPORT win_removeUnknownHandler win_removeUnknownHandler ROUT STMFD R13!,{R4,R9,R14} ;Stack some registers WSPACE win__wSpace,R9 ;Get my workspace pointer ADR R4,win__uHandlers ;Get the event handlers BL win__removeFromList ;Remove routine from the list LDMFD R13!,{R4,R9,PC}^ ;Load registers LTORG ; --- win__dispatchUnknown --- ; ; On entry: R0 == reason code returned from Wimp_Poll ; R1 == pointer to block ; R12 == pointer to workspace ; ; On exit: R0-R1 preserved ; C Clear if the event is not claimed, Set otherwise win__dispatchUnknown ROUT ; --- Note --- ; ; At this point, we've already got R2-R5, R9, R10, R12 ; and R14 on the stack. ; --- Go through the handlers list --- 02 ADDS R0,R0,#0 ;Clear carry flag LDR R2,win__uHandlers ;Get my event handlers list 10 TEQ R2,#0 ;Are we at the end BEQ %20 ;Yes -- jump ahead LDMIA R2,{R2-R4,R10,R12} ;Load parameters to pass MOV R14,PC ;Set return address MOV PC,R3 ;Branch to handler BCC %10 ;Try next handler 20 LDMFD R13!,{R2-R5,R9,R10,R14} ;Load registers ORRCSS PC,R14,#C_flag ;... and return BICCCS PC,R14,#C_flag LTORG win__dispatchEvents ROUT STMFD R13!,{R2-R5,R9,R10,R14} ;Stack some registers MOV R9,R12 ;Put my workspace in R9 ; --- Messages need special attention --- CMP R0,#17 ;Is this User_Message? CMPNE R0,#18 ;Or User_Message_Recorded? BEQ %30 ;Yes -- off we go then ; --- If it's some weird kind of message --- CMP R0,#13 ;Highest event I know BGT win__dispatchUnknown ;Too high -- unknown then ; --- Find the table and get window handle offset --- ADR R14,win__eventTbl ;Point to the table LDRB R5,[R14,R0] ;Get offset for this event CMP R5,#255 ;Is this event `unknown'? BEQ win__dispatchUnknown ;Yes -- call unknown list CMP R5,#254 ;Is it broadcastable? LDRNE R5,[R1,R5] ;Get the window handle MOVEQ R5,#&40000000 ;Or set up for broadcast ; --- Go through the handlers list --- 05 ADDS R0,R0,#0 ;Clear carry flag LDR R2,win__eHandlers ;Get my event handlers list 10 TEQ R2,#0 ;Are we at the end BEQ %20 ;Yes -- jump ahead LDMIA R2,{R2,R3,R4,R10,R12} ;Load parameters to pass TEQ R5,R3 ;Are window handles the same TEQNE R5,#&40000000 ;Or is this a broadcast? BNE %10 ;No -- try another handler MOV R14,PC ;Set return address MOV PC,R4 ;Branch to handler BCC %10 ;Try next handler 20 LDMFD R13!,{R2-R5,R9,R10,R14} ;Load the registers BICCCS PC,R14,#C_flag ;Return with carry clear ORRCSS PC,R14,#C_flag ;... or with carry set ; --- Now try unknowns if I'm not claiming the message --- 30 LDR R2,[R1,#16] ;Get message code ADR R14,win__msgTbl ;Point to message table 00 LDMIA R14!,{R3,R4} ;Load code and offset CMP R2,R3 ;Does the code match? LDREQ R5,[R1,R4] ;Yes -- load window handle BEQ %05 ;And continue going CMP R3,#-1 ;Is this the end yet? BNE %b00 ;No -- keep going then ; --- See if it's broadcastable --- ADR R14,win__broadTbl ;Point to the table 00 LDR R3,[R14],#4 ;Load the message code CMP R2,R3 ;Do we have a match? MOVEQ R5,#&40000000 ;Yes -- signal broadcast BEQ %05 ;And dispatch appropriately CMP R3,#-1 ;Is this the end yet? BNE %b00 ;No -- keep on going B win__dispatchUnknown ;Unknown event -- dispatch it DCB 0 ;Hint_Received win__eventTbl DCB 255 ;Null DCB 0 ;Redraw DCB 0 ;Open DCB 0 ;Close DCB 0 ;Leave window DCB 0 ;Enter window DCB 12 ;Mouse click DCB 255 ;Drag event DCB 0 ;Key press DCB 255 ;Menu choice DCB 0 ;Scroll request DCB 0 ;Lose caret DCB 0 ;Gain caret DCB 255 ;Poll word nonzero ALIGN win__msgTbl DCD &1, 20 ;DataSave DCD &3, 20 ;DataLoad DCD &502, 32 ;HelpRequest DCD &11, 20 ;Dragging (drag'n'drop) DCD -1, -1 win__broadTbl DCD &9 ;PaletteChange DCD &400C1 ;ModeChange DCD &400CF ;FontChange DCD -1 LTORG ; --- win_init --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Initialises the win system. EXPORT win_init win_init ROUT STMFD R13!,{R0,R1,R9,R14} ;Stack some registers WSPACE win__wSpace,R9 ;Get my workspace ; --- Are we already initialised? --- LDR R0,win__flags ;Get my flags TST R0,#win__INITED ;Are we initialised? LDMNEFD R13!,{R0,R1,R9,PC}^ ;Yes -- return ORR R0,R0,#win__INITED ;Set initialised flag STR R0,win__flags ;And store them back ; --- Clear rest of workspace --- MOV R0,#0 ;Zero some registers STR R0,win__eHandlers ;Clear event handlers list STR R0,win__uHandlers ;Clear unknown list ; --- Initialise event system --- BL event_init ;Initialise event system ; --- Set up a post filter for the win system --- ADR R0,win__dispatchEvents ;Call this routine MOV R1,R9 ;Put my workspace in R12 BL event_postFilter ;Add it to post-filter list ; --- That's it now --- LDMFD R13!,{R0,R1,R9,PC}^ ;Return LTORG win__wSpace DCD 0 ;My workspace pointer ;----- Workspace ------------------------------------------------------------ ^ 0,R9 win__wStart # 0 win__flags # 4 ;Flags win__INITED EQU (1<<0) ;I've been initialised win__eHandlers # 4 ;Event handler list win__uHandlers # 4 ;Unknown event handlers win__wSize EQU {VAR}-win__wStart ; --- list structure --- ^ 0 list__next # 4 ;The next block list__wHandle # 4 ;The window handle list__proc # 4 ;Handler code list__r10 # 4 ;R12 to call with list__r12 # 4 ;R12 to call with list__size # 0 AREA |Sapphire$$LibData|,CODE,READONLY DCD win__wSize ;Workspace size DCD win__wSpace ;Workspace pointer DCD 0 ;Scratchpad size DCD win_init ;Initialisation code ;----- That's all, folks ---------------------------------------------------- END