; ; dbx.numWrite.s ; ; Numeric writable icons (MDW) ; ; © 1994 Straylight ; ;----- Standard header ------------------------------------------------------ GET libs:header GET libs:swis ;----- External dependencies ------------------------------------------------ GET sapphire:dbox GET sapphire:keyMap GET sapphire:string GET sapphire:dbx.dbx GET sapphire:dbx._dbxMacs ;----- Main code ------------------------------------------------------------ AREA |Sapphire$$Code|,CODE,READONLY ; --- numWrite --- ; ; Control data: +0 == minimum value ; +4 == maximum value ; +8 ; ; Workspace: +0 ; ; Flags: -- ; ; Use: Control type for numeric writable icons. EXPORT numWrite numWrite ROUT DBXWS 0 ;No need for workspace DCD dbxMask_key ;Interested in keypresses STMFD R13!,{R0-R7,R14} ;Save lots of registers MOV R6,R2 ;Keep the new character safe MOV R0,R10 ;And the dialogue box handle BL dbox_getField ;Read the current contents MOV R7,R2 ;Keep this pointer ; --- Find out where the caret is --- SUB R13,R13,#24 ;Make space for caret block MOV R1,R13 ;Point at this block SWI Wimp_GetCaretPosition ;Find where the caret is LDR R5,[R13,#20] ;Load the icon index ; --- Find out if this keypress is interesting --- CMP R5,#0 ;Is the cursor at the start? LDREQB R14,[R7,#0] ;Yes -- get the first byte CMPEQ R14,#'-' ;Is it a minus sign? BEQ %50numWrite ;Yes -- disallow it then SUB R14,R6,#'0' ;Convert keypress to digit CMP R14,#10 ;Is it a proper digit? BCC %10numWrite ;Yes -- deal with it then SUB R14,R6,#key_k0 ;Try again with keypad CMP R14,#10 ;Is it a proper digit? SUBCC R6,R6,#key_k0-'0' ;Yes -- convert to ASCII BCC %10numWrite ;Yes -- deal with it then CMP R6,#'-' ;Is is a `-' sign? CMPNE R6,#key_kMinus ;Or the one on the keypad? MOVEQ R6,#'-' ;Either -- make it a `-' BNE %50numWrite ;No -- ignore it then LDR R3,[R9,#0] ;Load the minimum value CMP R3,#0 ;Does it allow negative nos? BGE %50numWrite ;No -- ignore it then CMP R5,#0 ;Is the cursor at the start? BNE %50numWrite ;No -- ignore it then ; --- We've got a character to insert --- 10numWrite MOV R2,R7 ;Point at the icon's text MOV R7,#0 ;An initial index 20numWrite CMP R7,R5 ;Is this the caret position? MOVEQ R14,R6 ;Yes -- insert my char LDRNEB R14,[R2],#1 ;Otherwise load from icon STRB R14,[R11,R7] ;Save in position CMP R14,#32 ;Is there more to go? ADDGE R7,R7,#1 ;Increment the index BGE %20numWrite ;Yes -- go round again SUB R7,R7,#1 ;This is the original length ; --- Fill the icon in nicely --- MOV R2,R11 ;Point to my nice new string BL numWrite__read ;Convert it to an integer MOV R6,R2 ;Take a copy of this value LDR R1,[R13,#28] ;Load the icon number LDMIA R9,{R3,R4} ;Load the boundary values SUB R4,R4,R3 ;Get the range size SUB R14,R2,R3 ;Subtract the bottom end CMP R14,R4 ;Is the value in range? MOVLS R0,R10 ;Yes -- get dialogue handle MOVLS R2,R11 ;Point at the string I made BLLS dbox_setField ;And just write the string BLHI numWrite__set ;Otherwise set the value MOVHI R6,R2 ;If changed, copy value BL dbx_sendEvent ;Send the user an event ; --- Move the caret on --- MOV R0,R10 ;Get the dialogue handle BL dbox_getField ;Find the text address MOV R0,R2 ;Point to the buffer BL str_len ;Find the string length SUBS R14,R0,R7 ;Find the length difference BEQ %40numWrite ;No movement -- forget it ADD R5,R5,R14 ;Move caret position on 1 CMP R5,R0 ;Is the caret in range? LDMLSIA R13,{R0-R4} ;Load rest of caret state SWILS Wimp_SetCaretPosition ;Set this as the new pos ; --- Pass an event to the user --- MOV R0,#numWrite_event ;Get the event number MOV R2,#numWrite_change ;The value has been changed MOV R3,R6 ;Pass the value in R3 BL dbx_sendEvent ;Pass the event on 40numWrite ADD R13,R13,#24 ;Restore the stack now LDMFD R13!,{R0-R7,R14} ;Unstack the registers ORRS PC,R14,#C_flag ;I used the character ; --- Handle a weird character --- 50numWrite ADD R13,R13,#24 ;Restore the stack ; --- Make sure it's an arrow key --- TST R6,#&100 ;Is the top bit set? BEQ %90numWrite ;No -- just return then BIC R6,R6,#&130 ;Ignore modifier bits CMP R6,#key_Tab-&100 ;Is it tab? CMPNE R6,#key_sTab-&100 ;Or is it shift-tab? CMPNE R6,#key_Up-&100 ;Or any of the cursor keys? CMPNE R6,#key_Down-&100 CMPNE R6,#key_cUp-&100 ;Or maybe with control CMPNE R6,#key_cDown-&100 BNE %90numWrite ;No -- just return then LDR R1,[R13,#4] ;Load the icon number MOV R0,R10 ;Get my dialogue handle BL numWrite_read ;Read the current value BL numWrite__set ;Set this as the new value MOV R0,#numWrite_event ;Get my event code MOV R3,R2 ;Pass value in R3 MOV R2,#numWrite_move ;The cursor has moved BL dbx_sendEvent ;Send the user an event 90numWrite LDMFD R13!,{R0-R7,R14} ;Unstack the registers BICS PC,R14,#C_flag ;Let someone else have it LTORG ; --- numWrite_set --- ; ; On entry: R0 == dialogue box handle ; R1 == icon number within dialogue ; R2 == value to set in the icon ; ; On exit: R2 == value actually set ; ; Use: Writes the specified numeric value into the given writable ; icon. The icon must be a dbx control with numWrite type ; for this to work. EXPORT numWrite_set numWrite_set ROUT STMFD R13!,{R0,R1,R8-R10,R14} ;Save some registers MOV R10,R0 ;Keep the dialogue handle BL dbx_findData ;Look up all the dbx info BL numWrite__set ;Do the actual work LDMFD R13!,{R0,R1,R8-R10,PC}^ ;Return to caller LTORG ; --- numWrite__set --- ; ; On entry: R1 == icon handle to set it in ; R2 == value to set ; R9 == pointer to minimum and maximum values ; R10 == dialogue box handle ; ; On exit: R2 == actual value set ; ; Use: Forces the given value between the limits for the icon ; and writes it into the specified icon. numWrite__set STMFD R13!,{R0-R2,R14} ;Save some registers ; --- Force the value in range --- LDMIA R9,{R0,R1} ;Load min and max values CMP R2,R0 ;Is it big enough? MOVLT R2,R0 ;No -- make it bigger then CMP R2,R1 ;Is it small enough? MOVGT R2,R1 ;No -- make it smaller then STR R2,[R13,#8] ;Return this modified value ; --- Translate it into a string --- MOV R0,R2 ;Get value in R0 now MOV R1,R11 ;Build string in scratchpad MOV R2,#256 ;Specify the scratchpad size SWI OS_ConvertInteger4 ;Convert it to a string ; --- Write it into the icon --- MOV R2,R0 ;Point at my nice new string LDR R1,[R13,#4] ;Load the icon handle back MOV R0,R10 ;Get the dialogue handle BL dbox_setField ;And write it into the icon LDMFD R13!,{R0-R2,PC}^ ;Return to caller LTORG ; --- numWrite_read --- ; ; On entry: R0 == dialogue box handle ; R1 == icon handle ; ; On exit: CC if icon contains a valid integer, and ; R2 == value shown in the icon ; else CS and ; R2 == 0 ; ; Use: Reads the numeric value within the icon specifed. EXPORT numWrite_read numWrite_read ROUT STMFD R13!,{R14} ;Save the link register BL dbox_getField ;Find the icon string BL numWrite__read ;Convert it to an integer LDMFD R13!,{PC} ;Return it and the flags LTORG ; --- numWrite__read --- ; ; On entry: R2 == pointer to a string ; ; On exit: R2 == integer represented by string and CC or 0 and CS ; ; Use: Converts a string showing a decimal integer to the value ; it represents. numWrite__read ROUT STMFD R13!,{R0,R1,R14} ; --- Set up some initial values --- MOV R0,R2 ;Point to the string start MOV R1,#0 ;Not found any digits yet MOV R2,#0 ;A good accumulator ; --- Check for a leading sign --- LDRB R14,[R0],#1 ;Load a byte from the string CMP R14,#'-' ;Is it a `-' sign? ORREQ R1,R1,#1 ;Set the `negative' bit LDREQB R14,[R0],#1 ;Yes -- load another byte ; --- Now read bytes from the string --- ; ; We stop as soon as we find a character which isn't a ; digit. 10 SUB R14,R14,#'0' ;Convert to an integer CMP R14,#10 ;Is it in range? BCS %20numWrite__read ;No -- that's it then TST R1,#1 ;Is the number negative? ADD R2,R2,R2,LSL #2 ;Multiply by 5 ADDEQ R2,R14,R2,LSL #1 ;If +ve, double and add new RSBNE R2,R14,R2,LSL #1 ;Otherwise, subtract it ORR R1,R1,#2 ;Say we read something good LDRB R14,[R0],#1 ;Load a new byte B %10numWrite__read ;Go round the loop again ; --- Return the value --- 20 TST R1,#2 ;Was the number valid? LDMFD R13!,{R0,R1,R14} ;Restore the registers ORREQS PC,R14,#C_flag ;No -- set C as error warning BICNES PC,R14,#C_flag ;Otherwise clear it LTORG ; --- numWrite_bump --- ; ; On entry: R0 == dialogue box handle ; R1 == icon handle ; R2 == increment to apply to it ; ; On exit: R2 == updated value in the icon ; ; Use: Adjusts the value in a writable icon by a given increment. EXPORT numWrite_bump numWrite_bump ROUT STMFD R13!,{R0,R1,R3,R14} ;Save some registers MOV R3,R2 ;Look after the increment BL numWrite_read ;Read the current value ADDCC R2,R2,R3 ;If valid, apply increment BL numWrite_set ;And write the value back LDMFD R13!,{R0,R1,R3,PC}^ ;Return to caller LTORG ;----- Constants ------------------------------------------------------------ numWrite_event EQU &80000004 ;R1 == icon number changed ;R2 == subreason code ;R3 == new value of icon numWrite_change EQU 0 ;Subreason -- number changed numWrite_move EQU 1 ;Subreason -- cursor moved ;----- That's all, folks ---------------------------------------------------- END