; ; dbox.s ; ; Dialogue box handling (MDW) ; ; © 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:akbd GET sapphire:alloc GET sapphire:event GET sapphire:keyMap GET sapphire:help GET sapphire:hour GET sapphire:msgs GET sapphire:sapphire GET sapphire:string GET sapphire:subAlloc GET sapphire:template GET sapphire:transWin GET sapphire:win GET sapphire:winUtils ;----- Creating and deleting dialogue boxes --------------------------------- AREA |Sapphire$$Code|,CODE,READONLY ; --- dbox_create --- ; ; On entry: R0 == pointer to dialogue template name ; ; On exit: R0 == dialogue box handle for the dialogue ; May return an error ; ; Use: Creates a dialogue box from a template definition. EXPORT dbox_create dbox_create ROUT STMFD R13!,{R1-R3,R14} ;Save some registers ; --- Locate the template and copy it --- MOV R3,R0 ;Keep name pointer safe MOV R1,#0 ;No template created yet BL template_find ;Find the actual definition MOVVC R2,R0 ;Keep this pointer MOVVS R2,#1 ;Otherwise assume shared rsc MOV R0,R3 ;Point at the name again BL template_copy ;And create the copy I use MOVVC R1,R0 ;Look after the copy ; --- Now create a dialogue box around it --- BLVC dbox_fromDefn ;Create dbox from window def STRVC R2,[R0,#dbox__template] ;Store the template pointer LDMVCFD R13!,{R1-R3,R14} ;Unstack the registers BICVCS PC,R14,#V_flag ;And return errorless ; --- Tidy up aftet an error MOV R2,R0 ;Look after this MOVS R0,R1 ;Get the template pointer BLNE template_free ;Maybe we free it MOVNE R0,R2 ;If not, get error back ADDEQ R2,R2,#4 ;Otherwise find error text ADREQ R0,dbox__createErr ;Point to my skeleton error BLEQ msgs_error ;Translate and substitute LDMFD R13!,{R1-R3,R14} ;Restore registers ORRS PC,R14,#V_flag ;Return the error LTORG ; --- dbox_fromEmbedded --- ; ; On entry: R0 == pointer to an embedded template ; ; On exit: R0 == dialogue box handle ; May return an error ; ; Use: Creates a dialogue box from an embedded template definition. EXPORT dbox_fromEmbedded dbox_fromEmbedded ROUT STMFD R13!,{R1,R2,R14} ;Save some registers MOV R1,#0 ;Clear template pointer BL template_embedded ;Copy the template MOVVC R1,R0 ;Look after this BLVC dbox_fromDefn ;Create the dialogue box MOVVC R14,#1 ;Mark as a template STRVC R14,[R0,#dbox__template] ;So it gets freed properly LDMVCFD R13!,{R1,R2,R14} ;Restore registers BICVCS PC,R14,#V_flag ;And return with no error MOV R2,R0 ;Look after this MOVS R0,R1 ;Get the template pointer BLNE template_free ;Maybe we free it MOVNE R0,R2 ;If not, get error back ADDEQ R2,R2,#4 ;Otherwise find error text ADREQ R0,dbox__createErr ;Point to my skeleton error BLEQ msgs_error ;Translate and substitute LDMFD R13!,{R1,R2,R14} ;Restore registers ORRS PC,R14,#V_flag ;Return the error LTORG ; --- dbox_fromDefn --- ; ; On entry: R0 == pointer to a window definition ; ; On exit: R0 == dialogue box handle for the dialogue ; May return an error ; ; Use: Creates a dialogue box from an immediate window definition, ; rather than a template. There are several things you need ; to be aware of when you use this call to create a dialogue ; box: ; ; * The window definition is not copied, but used directly ; for the duration the dialogue box exists. It must ; not move for this duration. When the dialogue is ; destroyed, you can release the memory for the definition, ; although this is your responsibility. ; ; * The indirected data is not copied either, so you'll have ; to copy it yourself if you want multiple dialogues from ; the same window definition. ; ; * The window definition and the indirected data must both ; be writable. EXPORT dbox_fromDefn dbox_fromDefn ROUT STMFD R13!,{R1-R3,R10,R14} ;Save some registers away ; --- Obtain a dbox block from the heap --- MOV R3,R0 ;Look after the definition MOV R0,#dbox__blockSize ;Find out how much I need BL alloc ;Allocate the memory BLCS alloc_error ;If it failed, find error msg BCS %99dbox_fromDefn ;... and quit if no memory ; --- Now start filling in the structure --- STR R3,[R0,#dbox__defn] ;Store the copy pointer away MOV R2,#0 ;Start zeroing things STR R2,[R0,#dbox__proc] ;No event handler yet STR R2,[R0,#dbox__flags] ;Dialogue box has no flags STR R2,[R0,#dbx__defn] ;Dbox not nabbed by dbx yet STR R2,[R0,#dbox__template] ;No template definition MOV R2,#-1 ;No embedded title icon STR R2,[R0,#dbox__title] ;So store it away MOV R10,R0 ;Keep this pointer safe ; --- Now we need to create a window --- MOV R1,R3 ;Point to the window defn SWI XWimp_CreateWindow ;Create the window BVS %98dbox_fromDefn ;If it failed, tidy up STR R0,[R10,#dbox__window] ;Store the window handle ; --- Now register our event handler for it --- ADR R1,dbox__events ;Point to my event handler MOV R2,R10 ;Pass the dialogue box handle WSPACE dbox__wSpace,R3 ;And my workspace pointer BL win_eventHandler ;Register the event handler BVS %97dbox_fromDefn ;If that failed, tidy up ; --- Now return the dialogue box handle --- MOV R0,R10 ;Return pointer to my block LDMFD R13!,{R1-R3,R10,R14} ;Restore the registers BICS PC,R14,#V_flag ;Return with no errors ; --- Tidy up after unfortunate events --- 97dbox_fromDefn MOV R3,R0 ;Keep error pointer ADD R1,R10,#dbox__window ;Point to the window handle SWI Wimp_DeleteWindow ;Delete the duff window MOV R0,R3 ;Restore error pointer 98dbox_fromDefn MOV R2,R0 ;Keep error pointer MOV R0,R10 ;Point to the block BL free ;Free it up -- it's useless MOV R0,R2 ;Restore error pointer 99dbox_fromDefn ADD R2,R0,#4 ;Point to the error message ADR R0,dbox__createErr ;Point to my skeleton error BL msgs_error ;Translate and substitute LDMFD R13!,{R1-R3,R10,R14} ;Restore registers ORRS PC,R14,#V_flag ;Return the error dbox__createErr DCD 1 DCB "dboxCRTERR",0 ; --- dbox_destroy --- ; ; On entry: R0 == dialogue box handle ; ; On exit: -- ; ; Use: Destroys a dialogue box, freeing all the memory it took ; up etc. EXPORT dbox_destroy dbox_destroy ROUT STMFD R13!,{R0,R1,R10,R14} ;Save some registers MOV R10,R0 ;Get the dialogue handle ; --- Make sure the dialogue's been closed --- BL dbox_close ;Close the dialogue box MOV R0,#dbEvent_lifeCycle ;Send a lifecycle message MOV R1,#dblc_destroy ;Dialogue will be destroyed BL dbox__dispatch ;Send the message ; --- Remove the event handler --- LDR R0,[R10,#dbox__window] ;Find the window handle BL win_windowDeleted ;Window doesn't need handling ; --- Delete the window --- ADD R1,R10,#dbox__window ;Point to the window handle SWI Wimp_DeleteWindow ;Delete the window ; --- Free the template copy --- LDR R14,[R10,#dbox__template] ;Load the template address CMP R14,#0 ;Is there one defined? LDRNE R0,[R10,#dbox__defn] ;Point to the template copy BLNE template_free ;Free it up now ; --- Free the dialogue block --- MOV R0,R10 ;Point to the dbox block BL free ;Free its memory up ; --- Return to caller --- LDMFD R13!,{R0,R1,R10,PC}^ ;Return to caller ;----- The event handler --------------------------------------------------- ; --- dbox__events --- ; ; On entry: R0 == the event code that happened ; R1 == pointer to the event data ; R10 == dialogue box it happened to ; ; On exit: CS if we handled the event, CC otherwise ; ; Use: Handles various events for a dialogue box dbox__events ROUT ; --- Dispatch the event to the right place --- STR R10,dbox__eventDbox ;Remember this handle CMP R0,#9 ;Is it a sensible event? BGE %00dbox__events ;No -- check for messages ADD PC,PC,R0,LSL #2 ;Yes -- dispatch to handler ; --- Event dispatch table --- B dbox__hint ;Hint for the hint bar MOVS PC,R14 ;Null event B dbox__redraw ;Redraw window request B dbox__open ;Open window request B dbox__close ;Close window request B dbox__enterLeave ;Pointer leaving window B dbox__enterLeave ;Pointer entering window B dbox__mouse ;Mouse clicked MOVS PC,R14 ;Drag event B dbox__keyPress ;Key pressed ; --- Handle a message --- 00dbox__events CMP R0,#17 ;User message CMPNE R0,#18 ;Rubber message (bouncy!) MOVNES PC,R14 ;No -- return unhandled B dbox__message ;Handle the message event ; --- dbox__dispatch --- ; ; On entry: R0 == the (dbox-style) event code to dispatch ; R1-R7 == any additional arguments that want passing along ; R10 == the dialogue box to send the event to ; ; On exit: CS or CC from the event handler ; ; Use: Dispatches an event to the event handler associated with the ; dialogue box, and returns its response. dbox__dispatch ROUT STMFD R13!,{R8-R10,R12,R14} ;Save lots of registers MOV R9,R10 ;Pass dialogue handle in R9 ADDS R0,R0,#0 ;Clear the carry flag LDMIB R10,{R8,R10,R12} ;Get the event handler stuff TEQ R8,#0 ;Is there an event handler? MOVNE R14,PC ;Set up return address MOVNE PC,R8 ;Call the event handler LDMFD R13!,{R8-R10,R12,R14} ;Restore the registers ORRCSS PC,R14,#C_flag ;Return CS if it returned CS BICCCS PC,R14,#C_flag ;Return CC if it returned CC LTORG ; --- dbox__checkIcon --- ; ; On entry: R1 == icon handle ; R10 == dialogue box handle ; ; On exit: R1 == icon handle or -1 if it was shaded ; ; Use: Translates an icon handle to the window background if it ; is shaded, for passing to event handlers. dbox__checkIcon ROUT STMFD R13!,{R0,R14} ;Save some registers MOV R0,R1 ;Move icon handle along BL dbox__icon ;Find the icon definition LDR R14,[R0,#16] ;Load the icon flags TST R14,#&00400000 ;Is the icon shaded? MOVNE R1,#-1 ;Yes -- return background STR R1,dbox__eventIcon ;Store in workspace LDMFD R13!,{R0,PC}^ ;Return to caller LTORG ; --- dbox__hint --- ; ; On entry: R0 == -1 ; R1 == pointer to hint event block ; ; On exit: C set if handled ; ; Use: Sends a hint event to the dbox handler dbox__hint ROUT STMFD R13!,{R0-R2,R14} ;Save some registers MOV R0,#dbEvent_hint ;The event code ADD R2,R1,#4 ;Point to the string BL dbox__dispatch ;Send it to the handler LDMFD R13!,{R0-R2,PC} ;Return with its flags LTORG ; --- dbox__redraw --- ; ; On entry: R0 == 1 ; R1 == pointer to window handle ; ; On exit: C set ; ; Use: Redraws a window using Sculptrix dbox__redraw ROUT STMFD R13!,{R0,R2,R3,R14} ;Save some registers ; --- Start the redraw operation --- SWI Wimp_RedrawWindow ;Start the redraw CMP R0,#0 ;Is it over already? BEQ %10dbox__redraw ;Yes -- skip to the end ; --- Set up Sculptrix's sprite area --- LDR R0,[R10,#dbox__defn] ;Find the window definition LDR R0,[R0,#64] ;Load the sprite area pointer SWI XSculptrix_SetSpriteArea ;Set up the sprite area ; --- Do any bits that need doing --- 00dbox__redraw LDR R2,[R1,#4] ;Get the window left position ADD R0,R1,#16 ;Point to the top position LDMIA R0,{R0,R3,R14} ;Load top, and scroll posns SUB R2,R2,R3 ;Convert to find origin x SUB R3,R0,R14 ;Convert to find origin y MOV R0,#dbEvent_redraw ;Give user a redraw event BL dbox__dispatch ;Send it to the handler BCS %01dbox__redraw ;If it claimed it, skip ahead LDR R0,[R10,#dbox__title] ;Get the embedded title icon CMP R0,#-1 ;Has it been defined? MOVNE R0,R10 ;Give it the dialogue box BLNE dbox_renderTitle ;Yes -- render it nicely SWI XSculptrix_RedrawWindow ;Get Sculptrix to do its bit 01dbox__redraw SWI Wimp_GetRectangle ;Get the next rectangle CMP R0,#0 ;Is this the end yet? BNE %00dbox__redraw ;No -- do the rest ; --- That's it, then --- 10dbox__redraw LDMFD R13!,{R0,R2,R3,R14} ;Unstack all the registers ORRS PC,R14,#C_flag ;Set carry and return LTORG ; --- dbox__open --- ; ; On entry: R0 == 2 ; R1 == pointer to window open block ; ; On exit: C set ; ; Use: This just opens the window. Later, it may do clever things ; with panes. dbox__open SWI Wimp_OpenWindow ;Open the window ORRS PC,R14,#C_flag ;Set carry and return ; --- dbox__close --- ; ; On entry: R0 == 3 ; R1 == pointer to the window handle ; ; On exit: C set ; ; Use: Passes a close event to the user dialogue box handler. dbox__close STMFD R13!,{R0,R14} ;Save some registers MOV R0,#dbEvent_close ;The close event code BL dbox__dispatch ;Pass it to the handler LDMFD R13!,{R0,R14} ;Unstack all the registers ORRS PC,R14,#C_flag ;Set carry and return ; --- dbox__mouse --- ; ; On entry: R0 == 6 ; R1 == pointer to mouse status block ; ; On exit: C set if we understood the event, C clear otherwise ; ; Use: Passes a click event to the dbox event handler. dbox__mouse ROUT STMFD R13!,{R0-R2,R9,R14} ;Save some registers MOV R9,R1 ;Keep the event pointer LDR R1,[R9,#8] ;Get the button status TST R1,#&5 ;Is it Select or Adjust? BNE %10dbox__mouse ;Yes -- handle it nicely TST R1,#&50 ;Is it a drag event? BNE %20dbox__mouse ;Yes -- handle it nicely TST R1,#&2 ;Is it a menu click? LDMEQFD R13!,{R0-R2,R9,PC}^ ;No -- we're clueless then ; --- The user clicked Menu --- LDR R1,[R9,#16] ;Get the icon handle out MOV R0,#dbEvent_menu ;Give it a menu click BL dbox__checkIcon ;Handle icon shadedness BL dbox__dispatch ;Give it to the user B %80dbox__mouse ;And return C set ; --- The user clicked Select or Adjust --- 10dbox__mouse LDR R1,[R9,#16] ;Get the icon handle out BL dbox__checkIcon ;Handle icon shadedness MOV R0,R1 ;Return icon number as event LDR R1,[R9,#8] ;Load the button state again BL dbox__dispatch ;Dispatch the event out BCS %80dbox__mouse ;If handled, skip this bit MOV R1,R0 ;Get the icon handle in R1 MOV R0,R10 ;And dialogue handle in R0 BL dbox_radio ;Handle magic radio buttons LDR R0,[R10,#dbox__flags] ;Get this dialogue's flags TST R0,#dbFlag__drag ;Is the move on drag bit on? BEQ %80dbox__mouse ;No -- skip this bit out SUB R13,R13,#56 ;Make a drag info block LDR R0,[R10,#dbox__window] ;Get the window handle STR R0,[R13,#0] ;Store the window handle MOV R0,#1 ;Move the window STR R0,[R13,#4] ;Store the drag type MOV R1,R13 ;Point to the block SWI Wimp_DragBox ;Start the window moving ADD R13,R13,#56 ;Reclaim the stack space B %80dbox__mouse ;Skip ahead to claim event ; --- The user dragged an icon --- 20dbox__mouse LDR R1,[R9,#16] ;Get the icon handle out BL dbox__checkIcon ;Handle shadiness nicely MOV R2,R1 ;Move handle to right place LDR R1,[R9,#8] ;Load button status again MOV R0,#dbEvent_drag ;Give handler a drag event BL dbox__dispatch ;And pass it to the handler B %80dbox__mouse ;And claim the event ; --- Finish everything off nicely --- 80dbox__mouse LDMFD R13!,{R0-R2,R9,R14} ;Restore the registers ORRS PC,R14,#C_flag ;Claim the event nicely LTORG ; --- dbox__enterLeave --- ; ; On entry: R0 == 4 for leaving, 5 for entering ; ; On exit: -- ; ; Use: Informs dialogue handlers that pointer has entered or left ; a window. dbox__enterLeave ROUT STMFD R13!,{R0,R14} ;Save some registers ADD R0,R0,#dbEvent_leave-4 ;Convert to appropriate event BL dbox__dispatch ;Send it to the handler LDMFD R13!,{R0,PC}^ ;And return to caller LTORG ; --- dbox__keyPress --- ; ; On entry: R0 == 8 ; R1 == pointer to caret block ; ; On exit: C clear ; ; Use: Handles key events for a dialogue box dbox__keyPress ROUT STMFD R13!,{R0-R3,R14} ;Save some registers ; --- Send the event to the user --- LDR R2,[R1,#4] ;Get the icon handle STR R2,dbox__eventIcon ;Store it in workspace LDR R0,[R1,#24] ;Get the key code BL akbd_translate ;Mangle for extended keyset MOV R1,R0 ;Move into right register MOV R0,#dbEvent_key ;Key event code BL dbox__dispatch ;Send it to the user BCS %50dbox__keyPress ;If processed, skip ahead ; --- Now see if it's one of ours --- CMP R1,#&100 ;Is it an extended code? BGE %20dbox__keyPress ;Yes -- skip forward CMP R1,#key_Return ;Is it a return? MOVEQ R0,#dbEvent_OK ;Yes -- give out an OK event BEQ %10dbox__keyPress ;Send it on its way CMP R1,#key_Esc ;Or maybe an escape MOVEQ R0,#dbEvent_cancel ;Yes -- give a Cancel event BEQ %10dbox__keyPress ;Send it on its way 00 LDMFD R13!,{R0-R3,PC}^ ;Forget it -- don't know ; --- Send a key event on --- 10 MOV R1,#4 ;Pretend Select was pressed BL dbox__dispatch ;Send it to the client B %50dbox__keyPress ;Now we've done the deed... 11 MOV R1,#1 ;Pretend Adjust was pressed BL dbox__dispatch ;Send it to the client B %50dbox__keyPress ;Now we've done the deed... ; --- Handle an extended key --- 20 AND R2,R1,#&FF ;Leave the bottom byte ; --- Straight cursor keys --- MOV R0,#0 CMP R2,#key_kEnter-256 MOVEQ R0,#dbEvent_OK BEQ %10dbox__keyPress CMP R2,#key_sReturn-256 CMPNE R2,#key_skEnter-256 MOVEQ R0,#dbEvent_OK BEQ %11dbox__keyPress CMP R2,#key_sEsc-256 MOVEQ R0,#dbEvent_cancel BEQ %11dbox__keyPress CMP R2,#key_Up-256 CMPNE R2,#key_sTab-256 MOVEQ R1,#-1 BEQ %40dbox__keyPress CMP R2,#key_Down-256 CMPNE R2,#key_Tab-256 MOVEQ R1,#+1 BEQ %40dbox__keyPress ; --- Control cursor keys --- MOV R0,#1 CMP R2,#key_cUp-256 MOVEQ R1,#+1 BEQ %40dbox__keyPress ; --- Cursor up --- CMP R2,#key_cDown-256 MOVEQ R1,#-1 BEQ %40dbox__keyPress ; --- Nothing worth knowing about --- B %00dbox__keyPress ; --- Actually do a cursor move --- 40 BL dbox__moveCaret ;Do the cursor move ; --- Return and claim the keypress --- 50 LDMFD R13!,{R0-R3,R14} ORRS PC,R14,#C_flag LTORG ; --- dbox__message --- ; ; On entry: R0 == 17 or 18 ; R1 == pointer to message data ; ; On exit: C set if the event was handled, or clear otherwise ; ; Use: Handles messages sent to dialogue boxes. dbox__message ROUT STMFD R13!,{R0-R4,R9,R14} ;Save some registers MOV R9,R1 ;Point to the event block LDR R14,[R9,#16] ;Get the message type number CMP R14,#1 ;Is it a save message? CMPNE R14,#3 ;Or a load message? BEQ %10dbox__message ;Yes -- handle them the same MOV R0,#&500 ;&502 is a help request ORR R0,R0,#&002 ;Build the full number CMP R14,R0 ;Is it a help request? LDMNEFD R13!,{R0-R4,R9,PC}^ ;No -- we don't understand ; --- Handle help requests for the dbox --- LDR R1,[R9,#36] ;Obtain the icon handle BL dbox__checkIcon ;Handle icon shadiness MOV R0,#dbEvent_help ;Pass a help request on BL dbox__dispatch ;Send it to the client B %80dbox__message ;Skip on and claim the event ; --- Handle save and load events --- 10dbox__message CMP R14,#1 ;Is it a save message? MOVEQ R0,#dbEvent_save ;Yes -- give a save event MOVNE R0,#dbEvent_load ;No -- give a load event LDR R1,[R9,#24] ;Get the icon handle BL dbox__checkIcon ;Handle icon shadiness LDR R2,[R9,#40] ;Get filetype in R2 ADD R3,R9,#44 ;Point to filename with R3 LDR R4,[R9,#36] ;Estimated size in R4 BL dbox__dispatch ;Send the message on B %80dbox__message ;Skip on and claim the event ; --- We did something, so claim event --- 80dbox__message LDMFD R13!,{R0-R4,R9,R14} ;Restore all the registers ORRS PC,R14,#C_flag ;Return, claiming the event LTORG ;----- Locating icons ------------------------------------------------------- ; --- dbox__find --- ; ; On entry: R0 == icon number to start from or -1 ; R1 == AND mask for flags ; R2 == flags word to match ; R3 == direction to scan in (either +1 or -1 unless you're ; very odd) ; R10 == dialogue box handle ; ; On exit: R0 == icon number of found icon or -1 ; Other registers preserved ; ; Use: Locates an icon within a window with flags that match the ; ones given. Note that icon definitions within the cached ; window definition are scanned, not icons in their actual ; current state. ; ; Searching from icon `-1' means to start from one end and ; keep looking until you've gone through all of them. ; Otherwise, the scan starts from the icon *after* the one ; specified in R0 on entry. ; ; The return value is the number of the first icon that ; matched the specification, or -1 if none of them matched. dbox__find ROUT STMFD R13!,{R4-R6,R14} ;Save some registers ; --- Find the cached window defintion --- LDR R4,[R10,#dbox__defn] ;Locate the definition ; --- Work out a sensible scanning start position --- CMP R0,#-1 ;Extremity requested? ADDNE R0,R0,R3 ;No -- skip over start icon BNE %00dbox__find ;And skip past this bit CMP R3,#0 ;Is the increment positive? MOVGT R0,#0 ;Yes -- start from 0 LDRLT R0,[R4,#84] ;No -- load the icon count SUBLT R0,R0,#1 ;And bump down -- zero index ; --- Now work out when to stop scanning --- 00dbox__find CMP R3,#0 ;What's the increment again? BEQ %02dbox__find ;If it's silly, find nothing LDRGT R5,[R4,#84] ;Positive -- stop at the SUBGT R5,R5,#1 ;...number of icons -1 ; --- A few other pre-scan bits --- AND R2,R2,R1 ;Make sure flags aren't silly ADD R6,R4,#88 ;Point to icon number 0 ADD R6,R6,R0,LSL #5 ;Point to the right icon ; --- The main scanning loop --- ; ; The comparison at the end is slightly tricky. It works ; on the basis that if R3>0, the condition is that R0>R5, ; and if R3<0, the condition is that R0<0. Each of these ; double-barrelled conditions can be done in two ARM ; instructions, and both together, complete with branches ; can be done in 6. ; ; Rather oddly, we start with the termination condition. 01dbox__find CMP R3,#0 ;What's the increment like? CMPLT R0,#0 ;Check not gone too low BLT %02dbox__find ;Yes -- exit the loop CMP R3,#0 ;Check increment again CMPGT R0,R5 ;Check not gone too high BGT %02dbox__find ;Yes -- exit the loop ; --- Now see if we got a match --- LDR R14,[R6,#16] ;Get icon flags for this one AND R14,R14,R1 ;Apply the AND mask to them CMP R14,R2 ;Is this a match? LDMEQFD R13!,{R4-R6,PC}^ ;Yes -- return to caller ; --- Set up for the next one --- ADD R0,R0,R3 ;Move the icon number on ADD R6,R6,R3,LSL #5 ;And bump icon pointer too B %01dbox__find ;Jump back to the loop start ; --- We failed to find it -- return -1 --- 02dbox__find MOV R0,#-1 ;Return funny failure value LDMFD R13!,{R4-R6,PC}^ ;Return to caller LTORG ; --- dbox__icon --- ; ; On entry: R0 == icon number wanted ; R10 == dialogue box block pointer ; ; On exit: R0 == pointer to numbered icon's definition ; ; Use: Locates an icon definition given its number dbox__icon STMFD R13!,{R14} ;Save link register a bit LDR R14,[R10,#dbox__defn] ;Find window definition ADD R14,R14,#88 ;Point to the first icon ADD R0,R14,R0,LSL #5 ;Add R0*32 to point to icon LDMFD R13!,{PC}^ ;Return to caller nicely ;----- Main initialisation -------------------------------------------------- ; --- dbox_init --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Initialises the dbox system. EXPORT dbox_init dbox_init ROUT STMFD R13!,{R12,R14} ;Save a load of registers WSPACE dbox__wSpace ;Find my workspace ; --- Make sure I'm not running yet --- LDR R14,dbox__wFlags ;Get hold of my flags word TST R14,#dbFlag__inited ;Am I running yet? LDMNEFD R13!,{R12,PC}^ ;Yes -- return immediately ; --- Set up the flags nicely --- MOV R14,#dbFlag__inited ;I am initialised now STR R14,dbox__wFlags ;Save my flags back again MOV R14,#0 ;Zero some workspace bits STR R14,dbox__clickList ;Nothing on the click list BL win_init ;Make sure win's awake BL transWin_init ;And also for transWin LDMFD R13!,{R12,PC}^ ;Return to caller LTORG dbox__wSpace DCD 0 ;----- Opening and closing dialogue boxes ----------------------------------- ; --- dbox_open --- ; ; On entry: R0 == dialogue box handle ; R1 == how to open the dialogue box ; Other registers depend on R1, and are described at the end ; of this header file ; ; On exit: -- ; ; Use: Displays the dialogue box on the screen in the given manner. EXPORT dbox_open dbox_open ROUT STMFD R13!,{R0-R6,R10,R12,R14} WSPACE dbox__wSpace ;Locate my workspace MOV R10,R0 ;Move the dbox handle away ; --- Is this a submenu request? --- ADDS R0,R0,#0 ;Clear the C flag TST R1,#dbOpen_nonSub ;Do we ignore this? BLEQ transWin_subWaiting ;No -- waiting for a submenu? BCS %60dbox_open ;Yes -- open as a submenu ; --- Now work out how to open it --- LDR R6,[R10,#dbox__flags] ;Get the dialogue's flags TST R1,#dbOpen_persist ;Is this a persistent dbox? BICEQ R6,R6,#dbFlag__static ;No -- clear static flag ORRNE R6,R6,#dbFlag__static ;Yes -- set static flag MOV R4,R1 ;Look after open style ; --- Read the dialogue's position --- SUB R13,R13,#36 ;Enough for a window block LDR R0,[R10,#dbox__window] ;Get the window handle STR R0,[R13,#0] ;Store it in the block MOV R1,R13 ;Point to the window handle SWI Wimp_GetWindowState ;Read in the information ; --- Move the dialogue box to the right position --- BIC R0,R4,#dbOpen_persist + dbOpen_nonSub BL winUtils_setPosition ;Position the window nicely TST R6,#dbFlag__static ;Is it static? BEQ %40dbox_open ;No -- skip ahead a bit ; --- Open a persistent dialogue box --- SWI Wimp_OpenWindow ;Open the window ADD R13,R13,#36 ;Reclaim the stack space ; --- If the window was already open, quit now --- TST R6,#dbFlag__open ;Is the dialogue box open BNE %80dbox_open ;Yes -- skip past this bit ; --- Now find out if there's a caret to handle --- MOV R0,#-1 ;Start searching from start MOV R1,#&0000E000 ;Find all Writable icons MOV R2,#&0000E000 ;Only check button type bits MOV R3,#+1 ;Search forwards BL dbox__find ;Find the icon CMP R0,#-1 ;Is there a writable icon? BICEQ R6,R6,#dbFlag__rCaret ;Don't have to restore caret BEQ %10dbox_open ;No -- skip ahead ; --- Read the old caret position --- ADD R1,R10,#dbox__oldCaret ;Point to old caret block SWI Wimp_GetCaretPosition ;Read the current position LDR R0,[R10,#dbox__window] ;Get the dialogue window MOV R1,#-1 ;In no particular icon MOV R2,#&ff000000 ;Quite a long way away ORR R2,R2,#&00ff0000 MOV R3,#0 ;Doesn't really matter MOV R4,#&02000000 ;Hide caret, make it small MOV R5,#-1 ;No index into icon, please SWI Wimp_SetCaretPosition ;Set the caret's position ORR R6,R6,#dbFlag__rCaret ;Remember to restore caret ; --- That's it, so finish things off --- 10dbox_open B %80dbox_open ;Perform wrapping-up actions ; --- Open as a transient menu --- 40dbox_open LDR R1,[R10,#dbox__window] ;Get the window handle ready SWI Wimp_CreateMenu ;Create it as a menu :-/ BIC R6,R6,#dbFlag__rCaret ;Don't restore the caret ADD R13,R13,#36 ;Reclaim the stack we used MOV R0,R1 ;Get the window handle again BL transWin_register ;This is transient window B %80dbox_open ;Perform wrapping-up actions ; --- Open in the correct submenu position --- 60dbox_open LDR R0,[R10,#dbox__window] ;Load the window handle BL transWin_openSub ;And display as submenu LDR R6,[R10,#dbox__flags] ;Read the dialogue box flags BIC R6,R6,#dbFlag__static :OR: dbFlag__rCaret ; --- Wrap everything up now --- 80dbox_open ORR R6,R6,#dbFlag__open ;The window is at last open STR R6,[R10,#dbox__flags] ;Store the flags away now MOV R0,#dbEvent_lifeCycle ;A lifecycle event MOV R1,#dblc_open ;Box has opened BL dbox__dispatch ;Send a message LDMFD R13!,{R0-R6,R10,R12,PC}^ LTORG ; --- dbox_close --- ; ; On entry: R0 == dialogue box handle ; ; On exit: -- ; ; Use: Closes a dialogue box, by clearing the current menu if ; necessary. EXPORT dbox_close dbox_close ROUT STMFD R13!,{R0-R6,R10,R12,R14} ;Save some registers away WSPACE dbox__wSpace ;Locate my workspace MOV R10,R0 ;Move dbox handle away ; --- First things first -- check it's open --- LDR R6,[R10,#dbox__flags] ;Get the dialogue's flags TST R6,#dbFlag__open ;Is the open flag on? BEQ %80dbox_close ;No -- skip forward ; --- Now restore the caret if needs be --- ; ; Try not to be overly upset if we can't put the caret back. ; After all, the window may have closed by now. An X SWI ; is called for, and we ignore V on exit. TST R6,#dbFlag__rCaret ;Does caret need restoring? BEQ %00dbox_close ;No -- skip forwards ADD R0,R10,#dbox__oldCaret ;Point to old caret block LDMIA R0,{R0-R5} ;Load the old caret state SWI XWimp_SetCaretPosition ;And try to put it back ; --- Now handle transientness properly --- 00dbox_close TST R6,#dbFlag__static ;Is this a static dialogue? LDREQ R0,[R10,#dbox__window] ;Yes -- find the window BLEQ transWin_close ;And close it ADDNE R1,R10,#dbox__window ;Point to the window handle SWINE Wimp_CloseWindow ;Close the window now BIC R6,R6,#dbFlag__open :OR: dbFlag__rCaret STR R6,[R10,#dbox__flags] ;Store flags away again ; --- Send a lifecycle warning --- MOV R0,#dbEvent_lifeCycle ;Get the event code MOV R1,#dblc_close ;Box has closed BL dbox__dispatch ;Send the event 80dbox_close LDMFD R13!,{R0-R6,R10,R12,PC}^ ;Return to caller LTORG ; --- dbox_writePos --- ; ; On entry: R0 == dialogue box handle ; ; On exit: -- ; ; Use: Saves the dialogue's current position so that it will be ; opened here the next time it is created. If the dialogue ; box was created from a template, the template is updated. ; Otherwise, the new state is written back to the definition ; supplied to dbox_fromDefn. EXPORT dbox_writePos dbox_writePos ROUT STMFD R13!,{R0-R5,R10,R14} ;Save a load of registers MOV R10,R0 ;Keep the dialogue handle SUB R13,R13,#36 ;Make space on the stack LDR R14,[R10,#dbox__window] ;Get the dialogue's window STR R14,[R13,#0] ;Save in the block MOV R1,R13 ;Point to the block SWI Wimp_GetWindowState ;Get the window's position LDMIB R13,{R0-R5} ;Load pos and scroll settings LDR R14,[R10,#dbox__template] ;Find the template address CMP R14,#0 ;Is it actually there? CMPNE R14,#1 ;Check for embedded templates LDREQ R14,[R10,#dbox__defn] ;No -- just use definition STMIA R14,{R0-R5} ;Yes -- save them for later ADD R13,R13,#36 ;Reclaim the used stack space LDMFD R13!,{R0-R5,R10,PC}^ ;Return to caller LTORG ;----- Caret handling functions --------------------------------------------- ; --- dbox__viewIcon --- ; ; On entry: R0 == an icon number ; R10 == dialogue box handle ; ; On exit: -- ; ; Use: Scrolls the given dialogue box so that the specified icon ; is visible. The icon is assumed to be in the same position ; as it was when it was created. ; ; This is translated fairly literally from the STEEL code ; in dbox__nextWritable. dbox__viewIcon ROUT STMFD R13!,{R0-R9,R14} ;Save a load of registers ; --- Locate the icon definition --- BL dbox__icon ;Find the icon position MOV R9,R0 ;Keep a pointer to it ; --- Find the window position --- SUB R13,R13,#36 ;Make space for a window def LDR R14,[R10,#dbox__window] ;Find the dbox's window hnd STR R14,[R13,#0] ;Store it in the block MOV R1,R13 ;Point to the block SWI Wimp_GetWindowState ;Find the window information ; --- Now read the window scroll positions --- LDMIB R13,{R0-R5} ;Load window visible coords SUB R0,R2,R0 ;R0 == window width SUB R1,R3,R1 ;R1 == window height ADD R2,R4,R0 ;R2 == window right hand side SUB R3,R5,R1 ;R3 == window bottom edge ;R4 == window left hand side ;R5 == window top edge LDMIA R9,{R6-R8,R14} ;Load icon coordinates nicely SUB R6,R6,#24 ;Add a bit of extra around SUB R7,R7,#24 ADD R8,R8,#24 ADD R14,R14,#24 ; --- Bodge the scroll positions until icon is visible --- ; ; This section is fairly self-explanatory, and the comments ; are very dull. CMP R7,R3 ADDLT R5,R7,R1 CMP R14,R5 MOVGT R5,R14 CMP R6,R4 MOVLT R4,R6 CMP R8,R2 SUBGT R4,R8,R0 ; --- Now store the scroll offsets back and reopen --- ADD R1,R13,#20 ;Point to scroll offsets STMIA R1,{R4,R5} ;Store them back in the block MOV R1,R13 ;Point to the block SWI Wimp_OpenWindow ;Now open the window nicely ; --- Reclaim the stack and return --- ADD R13,R13,#36 LDMFD R13!,{R0-R9,PC}^ ;Return to caller LTORG ; --- dbox__moveCaret --- ; ; On entry: R0 == 0 to move relative to current input focus ; 1 to move absolute (for ctrl cursor keys) ; R1 == direction to move in (+1 or -1, if you've any sense) ; R10 == dialogue box handle ; ; On exit: -- ; ; Use: Moves the caret between writable icons, responding to cursor ; key presses. dbox__moveCaret ROUT STMFD R13!,{R0-R5,R14} ;Save a few registers ; --- Find out where the cursor is --- SUB R13,R13,#24 ;Make way for a caret block MOV R1,R13 ;Point to it SWI Wimp_GetCaretPosition ;Find the caret nicely ; --- Check this is the right window --- LDMIA R13,{R0,R5} ;Get the input focus window LDR R14,[R10,#dbox__window] ;Get dialogue box window ADD R13,R13,#24 ;Reclaim that stack space CMP R0,R14 ;Do they match nicely? LDMNEFD R13!,{R0-R5,PC}^ ;No -- return to caller ; --- Now set up a search for the icon --- LDMIA R13,{R0,R3} ;Get the stacked start pos CMP R0,#0 ;Is it a zero? MOVNE R0,#-1 ;No -- start from one end MOVEQ R0,R5 ;Yes -- start from current ; --- Load the icon flags to search for --- MOV R2,#&0000E000 ;Find writable icons ORR R1,R2,#&00400000 ;Also check shaded bit BL dbox__find ;Find the icon nicely CMP R0,#-1 ;Did it find one? BLEQ dbox__find ;No -- search from one end ; --- Now it's come up with the goods --- CMP R0,#-1 ;Did it fail this time? CMPNE R0,R5 ;Or just come back again? LDMEQFD R13!,{R0-R5,PC}^ ;Yes -- nothing doing then ; --- Scroll to make icon visible --- BL dbox__viewIcon ;Scroll the window nicely ; --- Set the caret position nicely --- MOV R1,R0 ;Icon number to R1 BL dbox__fieldLen ;Find the string length MOV R5,R0 ;This is icon text index MOV R4,#-1 ;Calculate things for me LDR R0,[R10,#dbox__window] ;Get the window handle SWI Wimp_SetCaretPosition ;Move the caret nicely now LDMFD R13!,{R0-R5,PC}^ ;Return to caller at last LTORG ;----- Selecting and shading icons ------------------------------------------ ; --- dbox_select --- ; ; On entry: R0 == dialogue box handle ; R1 == icon number ; R2 == 0 to deselect the icon, 1 to select it, 2 to toggle ; its current selected state ; ; On exit: -- ; ; Use: Selects or deselects the specified icon in the Acorn sense ; (i.e. by flipping its selected bit). The state is only ; changed if required, to reduce flicker. EXPORT dbox_select dbox_select ROUT STMFD R13!,{R0-R2,R14} ;Save some registers away ; --- Find the old state --- SUB R13,R13,#40 ;Make space for an icon block LDR R0,[R0,#dbox__window] ;Get the window handle STMIA R13,{R0,R1} ;Save the handles away MOV R1,R13 ;Point to the block SWI Wimp_GetIconState ;Find out about the icon ; --- Find out the current selection state --- LDR R14,[R13,#24] ;Load the flags word AND R14,R14,#&00200000 ;Clear all but the select bit CMP R2,#1 ;Are we to select the icon? MOVEQ R2,#&00200000 ;Yes -- set the select bit CMP R2,#2 ;Are we to toggle it? EOREQ R2,R14,#&00200000 ;Yes -- toggle it then ; --- Make sure we need to do something --- CMP R2,R14 ;Are the states the same? ADDEQ R13,R13,#40 ;Yes -- restore the stack LDMEQFD R13!,{R0-R2,PC}^ ;And return right now ; --- Now change the icon state --- ADD R0,R13,#8 ;Point to the flags masks MOV R14,#&00200000 ;Clear only the selected bit STMIA R0,{R2,R14} ;Save the masks in the block SWI Wimp_SetIconState ;Set the state nicely ADD R13,R13,#40 ;Restore the stack nicely LDMFD R13!,{R0-R2,PC}^ ;Return to caller LTORG ; --- dbox_shade --- ; ; On entry: R0 == dialogue box handle ; R1 == icon number ; R2 == 0 to unshade the icon, 1 to shade it, 2 to toggle its ; current shaded state ; ; On exit: -- ; ; Use: Makes the icon look dimmer, to indicate that it is not ; available. It uses its own shading algorithms, rather than ; the WindowManager's, so there are some things you must watch ; out for: ; ; * Don't use any other method of shading icons ; ; * Don't assume that a shaded icon isn't going to give you ; events. At the user level, this should have been tidied ; up, but at the Sapphire level, it's still a problem. ; There is a routine in winUtils which will tell you if an ; icon is shaded. ; ; This routine has been written so that it only flickers icons ; when they actually need it. EXPORT dbox_shade dbox_shade ROUT STMFD R13!,{R0-R6,R10,R14} ;Save a load of registers ; --- Make sure we need to do something --- MOV R10,R0 ;Look after the dbox handle MOV R0,R1 ;Get the original icon handle BL dbox__icon ;Find my cached icon defn MOV R4,R0 ;Look after this pointer LDR R6,[R4,#16] ;Load the icon's flags AND R5,R6,#&00400000 ;Leave only the selected bit ; --- Work out what needs to be done --- CMP R2,#1 ;Do we have to shade it? MOVEQ R2,#&00400000 ;Yes -- set the bit CMP R2,#2 ;Do we have to toggle it? EOREQ R2,R5,#&00400000 ;Yes -- get the toggled state ; --- Now quit if there's nothing to do --- CMP R2,R5 ;Are they the same now? LDMEQFD R13!,{R0-R6,R10,PC}^ ;Yes -- return right now ; --- Find the old state from the icon --- LDR R0,[R10,#dbox__window] ;Get the window handle SUB R13,R13,#40 ;Make way for an icon block STMIA R13,{R0,R1} ;Save window and icon handles MOV R1,R13 ;Point to the block SWI Wimp_GetIconState ;Get the icon information LDR R5,[R13,#24] ;Get the current icon flags ; --- Now process the cached flags nicely --- ; ; We can just flip the bit now, because we know it must be ; different to its old state. EOR R6,R6,#&00400000 ;Toggle the flag STR R6,[R4,#16] ;Store it back in the block ; --- Now work out exactly what we have to do --- TST R6,#&00400000 ;Are we meant to be shading? BEQ %50dbox_shade ;No -- unshade nicely ; --- Lots of messing about with bitmasks --- ; ; We need to change the icon colours, the button type and ; the ESG number for text icons, and the shaded bit for ; sprite icons. If there's a sprite, or nothing at all, then ; we set the shaded bit. If there's text and a sprite, then ; we /don't/ do the text hacking if anti-aliased fonts are ; being used, since everything looks nasty. MOV R0,#8 ;Read the font handle SWI XWimp_ReadSysInfo ;Read the handle then MOVVS R0,#0 ;Unknown -- not supported AND R14,R5,#3 ;Get the contents bits TST R14,#2 ;Do we have a sprite? CMPNE R0,#0 ;And is there a font? TSTEQ R5,#&40 ;Or is the icon anti-aliased? BICNE R14,R14,#1 ;Yes -- clear text bit then CMP R14,#1 ;Is it text only? ORRNE R5,R5,#&00400000 ;No -- set the shaded bit TST R14,#1 ;Does it contain text? BICNE R5,R5,#&0f100000 ;Clear foreg colour and ESG 5 BICNE R5,R5,#&000ff000 ;Clear ESG and button type ORRNE R5,R5,#&02100000 ;Set foreg and ESG bit 5 ORRNE R5,R5,#&000f0000 ;Set ESG to 31, leave btype MOV R14,#-1 ;Clear all the flags bits ADD R0,R13,#8 ;Point to flags masks STMIA R0,{R5,R14} ;Store them in the block MOV R1,R13 ;Point to the block again SWI Wimp_SetIconState ;And `shade' the icon ; --- Now make sure the caret's not in it --- LDMIA R1,{R2,R3} ;Get the window and icon SWI Wimp_GetCaretPosition ;Find where the caret is LDMIA R1,{R4,R5} ;Get the focus window and icn CMP R2,R4 ;Check the windows match CMPEQ R3,R5 ;And check the icons match BNE %80dbox_shade ;If not, skip ahead a bit ; --- Now kick the caret into cyberspace --- LDMIA R1,{R0-R5} ;Load the caret registers MOV R1,#-1 ;Kick caret out of icon MOV R2,#&ff000000 ;Quite a long way away ORR R2,R2,#&00ff0000 SWI Wimp_SetCaretPosition ;Set the new caret position B %80dbox_shade ;Tidy everything up ; --- Now handle unshading -- this is easy :-/ --- 50dbox_shade BIC R6,R6,#&f000000f ;Clear some bits BIC R6,R6,#&00e00000 ;Clear some more bits BIC R6,R6,#&00000ff0 ;Clear yet more bits BIC R5,R5,#&0f500000 ;Clear another load of bits BIC R5,R5,#&000ff000 ;And the last load of bits ORR R5,R5,R6 ;Now merge them all together MOV R14,#-1 ;Update all of the flags ADD R0,R13,#8 ;Point to the flags masks STMIA R0,{R5,R14} ;Save the masks away SWI Wimp_SetIconState ;Now flicker the icon ; --- Tidy everything up finally --- 80dbox_shade ADD R13,R13,#40 ;Restore the stack position LDR R0,[R10,#dbox__defn] ;Find the window definition LDR R0,[R0,#64] ;Load the sprite area pointer SWI XSculptrix_SetSpriteArea ;Set the sprite area up LDR R1,[R13,#4] ;Get the icon handle back LDR R0,[R10,#dbox__window] ;Get the window handle SWI XSculptrix_UpdateIcon ;And redraw the 3D border LDMFD R13!,{R0-R6,R10,PC}^ ;Return to caller LTORG ; --- dbox_selectMany --- ; ; On entry: R0 == dialogue box handle ; R1 == pointer to icon handle list, -1 terminated ; R2 == select action (0 == unselect, 1 == select, 2 == toggle) ; ; On exit: -- ; ; Use: Changes the select state of a group of icons. EXPORT dbox_selectMany dbox_selectMany ROUT STMFD R13!,{R1,R3,R14} ;Save some registers MOV R3,R1 ;Remember this pointer 00 LDR R1,[R3],#4 ;Load next icon handle CMP R1,#-1 ;Is it the end of the list? BLNE dbox_select ;No -- then do the select BNE %b00 ;And loop round again LDMFD R13!,{R1,R3,PC}^ ;And return to caller LTORG ; --- dbox_shadeMany --- ; ; On entry: R0 == dialogue box handle ; R1 == pointer to icon handle list, -1 terminated ; R2 == shade action (0 == unshade, 1 == shade, 2 == toggle) ; ; On exit: -- ; ; Use: Changes the shade state of a group of icons. EXPORT dbox_shadeMany dbox_shadeMany ROUT STMFD R13!,{R1,R3,R14} ;Save some registers MOV R3,R1 ;Remember this pointer 00 LDR R1,[R3],#4 ;Load next icon handle CMP R1,#-1 ;Is it the end of the list? BLNE dbox_shade ;No -- then do the select BNE %b00 ;And loop round again LDMFD R13!,{R1,R3,PC}^ ;And return to caller LTORG ; --- dbox_isSelected --- ; ; On entry: R0 == dialogue box handle ; R1 == icon number ; ; On exit: CS if the icon is selected, CC otherwise ; ; Use: Returns whether an icon is currently selected. EXPORT dbox_isSelected dbox_isSelected ROUT STMFD R13!,{R0,R1,R14} ;Save the registers away SUB R13,R13,#40 ;Make space for an icon block LDR R0,[R0,#dbox__window] ;Load the dialogue's window STMIA R13,{R0,R1} ;Store them in the block MOV R1,R13 ;Point to the block SWI Wimp_GetIconState ;Get the icon information LDR R14,[R13,#24] ;Load the icon flags ADD R13,R13,#40 ;Recover the stack space TST R14,#&00200000 ;Check the selected bit LDMFD R13!,{R0,R1,R14} ;Load the saved registers ORRNES PC,R14,#C_flag ;If flag set, return with CS BICEQS PC,R14,#C_flag ;Otherwise, clear carry LTORG ; --- dbox_radio --- ; ; On entry: R0 == dialogue box handle ; R1 == icon handle ; ; On exit: -- ; ; Use: Checks to see if the icon is a radio button as defined by ; Sapphire, i.e. button type 3 (debounced) and non-zero ESG. ; If it is, it selects it, and deselects all other icons with ; this ESG. EXPORT dbox_radio dbox_radio ROUT STMFD R13!,{R0-R4,R9,R10,R14} ;Save some registers MOV R10,R0 ;Get the dialogue handle MOV R9,R1 ;Look after the icon number ; --- Locate the icon and check it's a radio button --- MOV R0,R1 ;Icon in R0 for dbox__icon BL dbox__icon ;Find the icon definition LDR R14,[R0,#16] ;Load the icon flags AND R4,R14,#&0000f000 ;Leave only the button type CMP R4,#&00003000 ;Make sure it's Debounced LDMNEFD R13!,{R0-R4,R9,R10,PC}^ ;No -- return right now ANDS R4,R14,#&001f0000 ;Leave only the ESG CMPNE R4,#&001f0000 ;Or 31 (i.e. it's shaded) LDMEQFD R13!,{R0-R4,R9,R10,PC}^ ;Yes -- return right now ; --- The ESG is now in R4 -- process it --- MOV R0,#-1 ;Start from the beginning 00dbox_radio MOV R1,#&001f0000 ;Mask out all but the ESG MOV R2,R4 ;Move ESG in to test it MOV R3,#+1 ;Search forwards nicely BL dbox__find ;Get the next matching icon CMP R0,#-1 ;None found? LDMEQFD R13!,{R0-R4,R9,R10,PC}^ ;Return to caller then MOV R1,R0 ;Icon number in R1 required MOV R0,R10 ;Dialogue box handle in R0 CMP R1,R9 ;Is this the clicked icon? MOVEQ R2,#1 ;Yes -- select it MOVNE R2,#0 ;No -- deselect it BL dbox_select ;Change its selection state MOV R0,R1 ;Start search where we left B %00dbox_radio ;And loop round again LTORG ;----- Clicking and unclicking icons ---------------------------------------- ; --- dbox_slab --- ; ; On entry: R0 == dialogue box handle ; R1 == icon handle ; ; On exit: May return an error ; ; Use: Slabs an icon in properly, to give visual feedback when you ; click it. EXPORT dbox_slab dbox_slab ROUT STMFD R13!,{R0-R2,R12,R14} ;Save some registers away WSPACE dbox__wSpace ;Find my workspace pointer ; --- Allocate a new block --- MOV R0,#20 ;Make space for a new block BL sub_alloc ;Try to allocate the block BVS %90dbox_slab ;If it failed, skip forward ; --- Link the block into the list --- LDR R14,dbox__clickList ;Load the old list head STR R0,dbox__clickList ;Store this block as new head STR R14,[R0,#0] ;And store link to next one ; --- Now actually slab the icon --- ADD R2,R0,#4 ;Point to slab descriptor LDR R0,[R13,#0] ;Get the saved dbox handle LDR R0,[R0,#dbox__window] ;Get the window handle SWI XSculptrix_SlabIcon ;Slab the icon in nicely LDMFD R13!,{R0-R2,R12,PC}^ ;Return to caller ; --- Tidy up after an error --- 90dbox_slab ADD R13,R13,#4 ;Skip past stacked R0 LDMFD R13!,{R1,R2,R12,R14} ;Load the saved registers ORRS PC,R14,#V_flag ;Set V flag on exit LTORG ; --- dbox_unslab --- ; ; On entry: -- ; ; On exit: CS if there are no more slabbed icons after this one, CC ; if there are more left. ; ; Use: Unslabs an icon slabbed with dbox_slab. Icons are unslabbed ; in reverse order to that in which they were slabbed. The ; carry flag is returned as an indication of whether there ; are any more icons left in the list -- you can unslab all ; icons in one go by doing: ; ; BL dbox_unslab ; SUBCC PC,PC,#12 ;Avoids a label! ; ; It is recommended that, if you are going to close a window, ; you unslab icons within it *after* you close, but before you ; actually destroy it, e.g. ; ; LDR R0,my_dbox ; BL dbox_close ; BL dbox_unslab ; BL dbox_destroy EXPORT dbox_unslab dbox_unslab ROUT STMFD R13!,{R0-R2,R12,R14} ;Save some registers away WSPACE dbox__wSpace ;Find my workspace pointer LDR R1,dbox__clickList ;Find the last slabbed icon ; --- Get the descriptor to free --- CMP R1,#0 ;Is there one at all? LDMEQFD R13!,{R0-R2,R12,R14} ;No -- restore the registers ORREQS PC,R14,#C_flag ;And return with C set ; --- Unslab the icon and unlink the block --- ; ; Make sure the hourglass stays off all this time. ADD R2,R1,#4 ;Point to the slab descriptor SUB R13,R13,#8 ;Make an hourglass status blk MOV R0,R13 ;Point to the block BL hour_suspend ;Save the old state a while SWI XSculptrix_UnslabIcon ;Unslab the icon nicely BL hour_resume ;Resume the hourglass now ADD R13,R13,#8 ;And restore the stack LDR R2,[R1,#0] ;Get the next field out STR R2,dbox__clickList ;Store it as the new head ; --- Free the block now --- MOV R0,R1 ;Point to the slab block MOV R1,#20 ;suballoc wants the size BL sub_free ;Free the block again ; --- Now return the status to the user --- CMP R2,#0 ;Was the next block null? LDMFD R13!,{R0-R2,R12,R14} ;Restore all the registers ORREQS PC,R14,#C_flag ;Yes -- return and set C BICNES PC,R14,#C_flag ;No -- return and clear C LTORG ;----- Messing with dialogue box fields ------------------------------------- ; --- dbox__fieldLen --- ; ; On entry: R1 == icon number ; R10 == dialogue box handle ; ; On exit: R0 == length of the text in the icon ; ; Use: Returns the length of the field in the given icon dbox__fieldLen ROUT STMFD R13!,{R1,R14} ;Save some registers ; --- Find the icon definition --- SUB R13,R13,#40 ;Make space for icon block LDR R0,[R10,#dbox__window] ;Get the window handle STMIA R13,{R0,R1} ;Store handles in block MOV R1,R13 ;Point at the block SWI Wimp_GetIconState ;Find the *current* icon info ; --- Get the icon flags and find the data --- LDR R0,[R13,#24] ;Load the flags word ANDS R0,R0,#1<<8 ;Check indir flag (clever) BEQ %10dbox__fieldLen ;Yes -- skip ahead a bit ; --- Handle indirectedness --- LDR R0,[R13,#28] ;Load the icon data pointer ADD R13,R13,#40 ;Reclaim the stack block LDMFD R13!,{R1,R14} ;Unstack the registers B str_len ;Find the string length ; --- Handle nonindirectedness --- ; ; We know at this point that R0 is 0, because we used ANDS ; not TST above. This is a pointless optimisation. 10 ADD R1,R13,#28 ;Point to the data string 11 LDRB R14,[R1],#1 ;Get a byte from the string CMP R14,#' ' ;Is it the end yet? BLT %12dbox__fieldLen ;Yes -- skip forward ADD R0,R0,#1 ;Bump on the counter CMP R0,#12 ;Is it maximum length yet? BLT %11dbox__fieldLen ;No -- skip back again ; --- Return the calculated length --- 12 ADD R13,R13,#40 ;Reclaim the stack again LDMFD R13!,{R1,PC}^ ;Return to caller LTORG ; --- dbox_setField --- ; ; On entry: R0 == dialogue box handle ; R1 == icon number to write to (may be -1 for title) ; flags in top byte if not -1: ; dbFlag_dots (bit 31) == add `...' if text overflows ; R2 == pointer to string to use ; ; On exit: -- ; ; Use: Writes the string specified into the indirection buffer ; for the given icon. If the icon is not indirected, an ; error is generated. If the indirected buffer is too small, ; the string is shortened by chopping off the beginning or ; the end, according to the setting of the icon's right ; justify flag. ; ; The icon is only flickered if the text has actually changed. ; The caret is moved correctly if it is within the icon to ; prevent it `falling off' the end and deleting the validation ; string, or being positioned incorrectly in centred icons if ; the length changes. ; ; Note that this routine requires a string to already be in ; the buffer, and doesn't perform any substitution or other ; transformations. This helps to prevent buffer full errors ; and similar problems. EXPORT dbox_setField dbox_setField ROUT STMFD R13!,{R0-R5,R14} ;Stash registers away ; --- Handle the title bar nicely --- CMP R1,#-1 ;Does he want the title? BEQ %30dbox_setField ;Yes -- jump ahead to do it ; --- Find out about the icon --- AND R4,R1,#&FF000000 ;Get the flag bits out BIC R1,R1,#&FF000000 ;Leave just the icon number LDR R0,[R0,#dbox__window] ;Get the dbox's window handle SUB R13,R13,#40 ;Make space for icon block STMIA R13,{R0,R1} ;Store the info in it MOV R1,R13 ;Point to the icon block SWI Wimp_GetIconState ;Get the icon's information ; --- Make sure we can change the text --- LDR R1,[R13,#24] ;Get the icon's flags TST R1,#&100 ;Check the indirected bit BEQ %80dbox_setField ;It's an error if it's clear ; --- Now find how much we actually have to copy --- LDR R5,[R13,#36] ;Get the buffer length SUB R5,R5,#1 ;Take terminator into account MOV R0,R2 ;Point to the string to copy BL str_len ;Find out how long it is SUBS R0,R0,R5 ;Find out the difference BICLE R4,R4,#(1<<31) ;If it fits, don't add dots BLE %00dbox_setField ;And skip ahead TST R1,#1<<9 ;Is it right aligned? ADDNE R2,R2,R0 ;Yes, chop off front ORRNE R4,R4,#1 ;And set a flag to remember ; --- Copy the text into the buffer --- 00dbox_setField LDR R0,[R13,#28] ;Find the buffer address MOV R3,#0 ;Count the length too 10dbox_setField CMP R5,R3 ;How much space left in buff? MOVLE R1,#0 ;None -- pretend null char LDRGTB R1,[R2],#1 ;Get a byte from the string CMP R1,#' ' ;Is it a control char? MOVLO R1,#0 ;Yes -- say it's a zero BLO %15dbox_setField ;And don't bother with dots ; --- Handle ellipsis generation --- TST R4,#(1<<31) ;Do we put the ellipsis in? BEQ %15dbox_setField ;No -- skip ahead then TST R4,#1 ;Are we right-justified? ADDNE R14,R3,#1 ;Yes -- just get the length SUBEQ R14,R5,R3 ;Otherwise find what's left CMP R14,#4 ;Are we within three? MOVLO R1,#'.' ;Yes -- put in a dot then ; --- Return to normality --- 15dbox_setField LDRB R14,[R0],#1 ;Get one from the buffer CMP R14,#' ' ;Same for the buffer char MOVLO R14,#0 CMP R1,R14 ;Are they different ORRNE R4,R4,#2 ;Yes -- remember this STRNEB R1,[R0,#-1] ;And store the different char CMP R1,#0 ;Is that end of the string? ADDNE R3,R3,#1 ;No -- bump the length on BNE %10dbox_setField ;And go round for another ; --- We've copied the string -- now update the icon --- TST R4,#2 ;Is the string different? BEQ %20dbox_setField ;No -- skip ahead MOV R1,#0 STR R1,[R13,#8] ;The EOR mask for setstate STR R1,[R13,#12] ;The BIC mask for setstate MOV R1,R13 ;Point to the block SWI Wimp_SetIconState ;Flicker the icon nastily ; --- Now check for the caret --- SWI Wimp_GetCaretPosition ;Find out where the caret is LDMIA R13,{R2,R4} ;Get the window and icon ADD R0,R13,#40 ;Point past this block LDMIA R0,{R0,R1} ;Get the old dbox and icon LDR R0,[R0,#dbox__window] ;Get the window handle CMP R0,R2 ;Do the window handles match? CMPEQ R1,R4 ;And the icon handles? BNE %20dbox_setField ;No -- skip ahead ; --- Push the caret back a little --- LDR R5,[R13,#20] ;Get the caret index CMP R5,R3 ;Is this bigger than new len? MOVGT R5,R3 ;Yes -- trim the index ; --- Now put the caret in the right place --- MOV R2,#-1 ;Don't set the x coord MOV R3,#-1 ;Don't set the y coord MOV R4,#-1 ;Don't set the height SWI Wimp_SetCaretPosition ;Put the caret in its place ; --- Return nicely --- 20dbox_setField ADD R13,R13,#40 ;Reclaim that temporary space LDMFD R13!,{R0-R5,PC}^ ;Return to caller ; --- Caller wants to update the title bar --- 30dbox_setField LDR R14,[R0,#dbox__defn] ;Load the window definition LDR R5,[R14,#56] ;Load the title bar's flags TST R5,#&00000100 ;Check the indirected bit BEQ %80dbox_setField ;If clear, generate the error LDR R1,[R14,#72] ;Load the buffer pointer LDR R2,[R0,#dbox__window] ;Load the window handle LDR R0,[R13,#8] ;Load the string pointer BL winUtils_setTitle ;And set the title string LDMFD R13!,{R0-R5,PC}^ ;Return to caller ; --- Icon wasn't indirected --- 80dbox_setField ADR R0,dbox__nind ;Point to error BL msgs_error ;Translate the message SWI OS_GenerateError dbox__nind DCD 1 DCB "dboxNIND",0 LTORG ; --- dbox_getField --- ; ; On entry: R0 == dialogue box handle ; R1 == icon number to interrogate ; ; On exit: R0, R1 preserved ; R2 == pointer to the icon text ; ; Use: Returns a pointer to the text associated with an icon. ; Note that if the icon is *not* indirected, the text will ; be copied into the scratchpad. Otherwise you get a pointer ; to the actual indirected data. You shouldn't write to the ; string returned at all -- dbox_setField is specially ; designed to do that sort of thing very well (i.e. not ; flickering the text unless it has to, truncating if it's too ; long, and handling the caret correctly). You *are* allowed ; to zero terminate the string if you want to, though. ; ; Despite all the PRM's assurances to the contrary, chances ; are the text will be terminated by some weird control char, ; so you'll have to handle this, and not just assume it's ; going to be null-terminated. ; ; Note: The indirected case is immensely quick -- just load a ; pointer. The non-indirected case has been optimised as much ; as possible. EXPORT dbox_getField dbox_getField ROUT STMFD R13!,{R0,R1,R10,R14} ;Save some registers ; --- Find the icon defintion --- MOV R10,R0 ;Keep dialogue box handle MOV R0,R1 ;Put icon handle in R0 BL dbox__icon ;Find icon definition ; --- Find out about indirectedness --- LDR R14,[R0,#16] ;Load the icon flags word TST R14,#1<<8 ;Is the bit set? LDRNE R2,[R0,#20] ;Yes -- load the pointer LDMNEFD R13!,{R0,R1,R10,PC}^ ;And return ; --- Copy the text to the scratchpad --- ADD R0,R0,#20 ;Point to the text string LDMIA R0,{R0,R1,R14} ;Load the 12 bytes of text STMIA R11,{R0,R1,R14} ;Store them in scratchpad MOV R0,#0 ;Zero terminate nicely STRB R0,[R11,#12] ;In case string is too long MOV R2,R11 ;Point to string in scratch LDMFD R13!,{R0,R1,R10,PC}^ ;Return to caller LTORG ;---- Other utility functions ----------------------------------------------- ; --- dbox_eventHandler --- ; ; On entry: R0 == dialogue box handle ; R1 == pointer to handler routine ; R2 == value to pass to handler in R10 ; R3 == value to pass to handler in R12 ; ; On exit: R0 preserved ; R1 == pointer to old handler ; R2 == old R10 value ; R3 == old R12 value ; ; Use: Sets up an event handler for a dialogue box, and returns ; the previous one. If the pointer to handler is 0, there is ; no dialogue box event handler. EXPORT dbox_eventHandler dbox_eventHandler ROUT STMFD R13!,{R4-R6,R14} ;Save some registers LDR R14,[R0,#dbx__defn] ;Load the dbx pointer CMP R14,#0 ;Is there a dbx definition? ADDEQ R14,R0,#dbox__proc ;Point to the correct user... ADDNE R14,R0,#dbx__proc ;... handler LDMIA R14,{R4-R6} ;Load the old values out STMIA R14,{R1-R3} ;Store the new ones in MOV R1,R4 ;Move the old values to... MOV R2,R5 ;... the correct registers... MOV R3,R6 ;... for returning LDMFD R13!,{R4-R6,PC}^ ;Return to caller LTORG ; --- dbox_renderTitle --- ; ; On entry: R0 == dialogue box handle ; R1 == pointer to redraw block ; ; On exit: -- ; ; Use: Renders a dialogue box's embedded title if there is one. EXPORT dbox_renderTitle dbox_renderTitle ROUT STMFD R13!,{R0-R3,R10,R14} ;Save a load of registers MOV R10,R0 ;Move the handle into R10 LDR R0,[R10,#dbox__title] ;Get the icon number out CMP R0,#-1 ;Check there really is one LDMEQFD R13!,{R0-R3,R10,PC}^ ;Return to caller if not BL dbox__icon ;Find the icon pointer MOV R2,#0 ;Group box type 0, please LDR R3,[R10,#dbox__defn] ;Find the window definition LDR R3,[R3,#72] ;Get the actual data pointer SWI XSculptrix_PlotGroupBox ;Draw the group box LDMFD R13!,{R0-R3,R10,PC}^ ;Return to caller now LTORG ; --- dbox_setEmbeddedTitle --- ; ; On entry: R0 == dialogue box handle ; R1 == icon which should contain the embedded title ; ; On exit: -- ; ; Use: Declares a given dialogue box as requiring an embedded title ; (rather than the one the WindowManager put on). EXPORT dbox_setEmbeddedTitle dbox_setEmbeddedTitle STR R1,[R0,#dbox__title] ;Store the icon number MOVS PC,R14 ; --- dbox_setClickDrag --- ; ; On entry: R0 == dialogue box handle ; ; On exit: -- ; ; Use: Sets a given dialogue box so that the user can move it by ; dragging from any part of the window, not just the title ; bar. EXPORT dbox_setClickDrag dbox_setClickDrag STMFD R13!,{R14} ;Save a register LDR R14,[R0,#dbox__flags] ;Load the flags word ORR R14,R14,#dbFlag__drag ;Set the click-drag flag STR R14,[R0,#dbox__flags] ;Save the flags back again LDMFD R13!,{PC}^ ;Return to caller ; --- dbox_hasTitle --- ; ; On entry: R0 == dialogue box handle ; ; On exit: CS if the dialogue box has a title bar, CC if not ; ; Use: Informs the caller whether the dialogue box has a title bar. ; This is mainly useful for other library sections which ; conditionally add in embedded titles etc. EXPORT dbox_hasTitle dbox_hasTitle ROUT STMFD R13!,{R14} ;Save a register LDR R14,[R0,#dbox__defn] ;Load the window definition LDR R14,[R14,#28] ;Load the window flags TST R14,#1<<31 ;Using new gadget flags? BEQ %10dbox_hasTitle ;No -- skip to handle this TST R14,#1<<26 ;Test the title bar flag B %20dbox_hasTitle ;And skip the other test 10dbox_hasTitle TST R14,#1<<0 ;Test the old-fashioned bit 20dbox_hasTitle LDMFD R13!,{R14} ;Restore the register I saved ORRNES PC,R14,#C_flag ;If bit set, return carry BICEQS PC,R14,#C_flag ;Otherwise clear carry LTORG ; --- dbox_window --- ; ; On entry: R0 == dialogue box handle ; ; On exit: R0 == the dialogue box's window handle ; ; Use: Returns the Wimp window handle associated with a dialogue ; box. This may be useful if you want to perform lowlevel ; Wimp operation on it, or to subclass it using win. EXPORT dbox_window dbox_window LDR R0,[R0,#dbox__window] ;Load the window handle MOVS PC,R14 ;Return to caller ; --- dbox_help --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Adds a help line to the current help message, read by ; scanning the icon to which the help was sent for an `H' ; validation string. EXPORT dbox_help dbox_help ROUT STMFD R13!,{R0-R4,R10,R12,R14} ;Save some registers WSPACE dbox__wSpace ;Find my workspace quickly LDR R10,dbox__eventDbox ;Find the helpful dbox LDR R0,dbox__eventIcon ;Find the icon too CMP R0,#0 ;Is it a sensible number? BLT %99dbox_help ;No -- skip to the end ; --- Locate the validation string --- BL dbox__icon ;Find the icon definition MOV R1,#'H' ;Find `H' validation commands MOV R2,#0 ;Start from the beginning BL winUtils_findValid ;Find the validation string BCC %99dbox_help ;If not there, skip to end ; --- Copy the message tag to scratchpad --- MOV R0,R11 ;Point to scratchpad MOV R1,#0 ;We are not escaped yet ADD R2,R2,#1 ;Skip past `H' character 10dbox_help LDRB R14,[R2],#1 ;Get the next byte CMP R14,#'\' ;Is it a backslash? CMPEQ R1,#0 ;Make sure it's not escaped MOVEQ R1,#1 ;Yes -- escape next char BEQ %10dbox_help ;And loop for next char CMP R14,#' ' ;Is it a control character MOVLT R14,#0 ;Yes -- terminate string CMP R14,#';' ;Is it validation string end? CMPEQ R1,#0 ;Make sure it's not escaped MOVEQ R14,#0 ;Yes -- terminate string STRB R14,[R0],#1 ;Store character in buffer CMP R14,#0 ;Was that the end? BNE %10dbox_help ;No -- try for another one ; --- Send the message to !Help --- MOV R0,R11 ;Point to buffer start again BL msgs_lookup ;Lookup the message tag BL help_add ;Add it to the help message 99dbox_help LDMFD R13!,{R0-R4,R10,R12,PC}^ ;No -- return right now LTORG ;----- Useful constants ----------------------------------------------------- ; --- Ways of opening dialogue boxes --- ^ 0 dbOpen_current # 1 ;In its current position dbOpen_centre # 1 ;Centred on the screen dbOpen_pointer # 1 ;Centred over the pointer dbOpen_givenY # 1 ;At a given height on screen ; R2 == y coordinate to open dbOpen_trans EQU &00 ;Make the dbox transient dbOpen_persist EQU &80 ;Make the dbox persistent dbOpen_nonSub EQU &40 ;Don't open as a submenu ; --- Dialogue box event codes --- dbEvent_close EQU -2 ;The user closed the dialogue ;C flag ignored on exit dbEvent_help EQU -3 ;The user wants some help ;R1 == icon number ;C flag ignored on exit dbEvent_OK EQU -4 ;The user clicked OK ;R1 == mouse button status ;C flag ignored on exit dbEvent_cancel EQU -5 ;The user clicked Cancel ;R1 == mouse button status ;C flag ignored on exit dbEvent_redraw EQU -6 ;Redraw a single rectangle ;R1 == pointer to redraw blk ;R2,R3 == coords of origin ;CS => don't do default draw dbEvent_menu EQU -7 ;User clicked Menu button ;R1 == icon handle clicked ;C flag ignored on exit dbEvent_drag EQU -8 ;User dragged an icon ;R1 == mouse button status ;R2 == icon handle dragged ;C flag ignored on exit dbEvent_save EQU -9 ;User wants to import data ;R1 == icon handle dropped on ;R2 == filetype of data ;R3 == pointer to filename ;R4 == estimated file size ;C flag ignored on exit dbEvent_load EQU -10 ;User wants to load data ;R1 == icon handle dropped on ;R2 == filetype of data ;R3 == pointer to filename ;R4 == estimated file size ;C flag ignored on exit dbEvent_key EQU -11 ;User pressed a key ;R1 == key code received ;R2 == icon handle with caret ;CC => unknown keypress ;Key code has been translated dbEvent_hint EQU -12 ;Received a hint message ;R2 == pointer to hint string dbEvent_enter EQU -13 ;Pointer has entered window dbEvent_leave EQU -14 ;Pointer has left window dbEvent_lifeCycle EQU -15 ;Interesting points in cycle ;R1 == life cycle code ; --- Life cycle codes --- ^ 0 dblc_create # 1 ;Creation (used by dbx) dblc_open # 1 ;Opening dblc_close # 1 ;Closing dblc_destroy # 1 ;Destruction ; --- Other values --- dbFlag_dots EQU (1<<31) ;Add dots if text overflows ; in dbox_setField ;----- Dialogue box data structure ------------------------------------------ ^ 0 dbox__window # 4 ;The real window handle dbox__proc # 4 ;Pointer to event handler dbox__R10 # 4 ;Magic handle for event proc dbox__R12 # 4 ;Workspace for event proc dbox__oldCaret # 24 ;Caret position to restore dbox__defn # 4 ;Pointer to window template dbox__template # 4 ;Pointer to original template dbox__title # 4 ;Embedded title icon number dbox__flags # 4 ;Various interesting flags dbx__proc # 4 ;Pointer to user event proc dbx__R10 # 4 ;Object pointer for user proc dbx__R12 # 4 ;Workspace for user proc dbx__defn # 4 ;Pointer to control def block dbox__blockSize # 0 ;Size of the above block dbFlag__open EQU (1<<0) ;Dialogue box is on-screen dbFlag__static EQU (1<<1) ;Dialogue box is static dbFlag__rCaret EQU (1<<2) ;We have to restore the caret dbFlag__drag EQU (1<<3) ;Clicking window starts move ;----- Workspace ------------------------------------------------------------ ^ 0,R12 dbox__wStart # 0 dbox__wFlags # 4 ;Various magic flags for me dbox__clickList # 4 ;List of button slabbings dbox__eventDbox # 4 ;Dbox last event happened to dbox__eventIcon # 4 ;Icon number from last event dbFlag__inited EQU (1<<0) ;The dbox system is running dbox__wSize EQU {VAR}-dbox__wStart AREA |Sapphire$$LibData|,CODE,READONLY DCD dbox__wSize DCD dbox__wSpace DCD 16 DCD dbox_init ;----- That's all, folks ---------------------------------------------------- END