chiark / gitweb /
Initial revision
[ssr] / StraySrc / Libraries / Sapphire / dbx / s / numWrite
1 ;
2 ; dbx.numWrite.s
3 ;
4 ; Numeric writable icons (MDW)
5 ;
6 ; © 1994 Straylight
7 ;
8
9 ;----- Standard header ------------------------------------------------------
10
11                 GET     libs:header
12                 GET     libs:swis
13
14 ;----- External dependencies ------------------------------------------------
15
16                 GET     sapphire:dbox
17                 GET     sapphire:keyMap
18                 GET     sapphire:string
19
20                 GET     sapphire:dbx.dbx
21                 GET     sapphire:dbx._dbxMacs
22
23 ;----- Main code ------------------------------------------------------------
24
25                 AREA    |Sapphire$$Code|,CODE,READONLY
26
27 ; --- numWrite ---
28 ;
29 ; Control data: +0 == minimum value
30 ;               +4 == maximum value
31 ;               +8
32 ;
33 ; Workspace:    +0
34 ;
35 ; Flags:        --
36 ;
37 ; Use:          Control type for numeric writable icons.
38
39                 EXPORT  numWrite
40 numWrite        ROUT
41
42                 DBXWS   0                       ;No need for workspace
43                 DCD     dbxMask_key             ;Interested in keypresses
44
45                 STMFD   R13!,{R0-R7,R14}        ;Save lots of registers
46                 MOV     R6,R2                   ;Keep the new character safe
47
48                 MOV     R0,R10                  ;And the dialogue box handle
49                 BL      dbox_getField           ;Read the current contents
50                 MOV     R7,R2                   ;Keep this pointer
51
52                 ; --- Find out where the caret is ---
53
54                 SUB     R13,R13,#24             ;Make space for caret block
55                 MOV     R1,R13                  ;Point at this block
56                 SWI     Wimp_GetCaretPosition   ;Find where the caret is
57                 LDR     R5,[R13,#20]            ;Load the icon index
58
59                 ; --- Find out if this keypress is interesting ---
60
61                 CMP     R5,#0                   ;Is the cursor at the start?
62                 LDREQB  R14,[R7,#0]             ;Yes -- get the first byte
63                 CMPEQ   R14,#'-'                ;Is it a minus sign?
64                 BEQ     %50numWrite             ;Yes -- disallow it then
65
66                 SUB     R14,R6,#'0'             ;Convert keypress to digit
67                 CMP     R14,#10                 ;Is it a proper digit?
68                 BCC     %10numWrite             ;Yes -- deal with it then
69                 SUB     R14,R6,#key_k0          ;Try again with keypad
70                 CMP     R14,#10                 ;Is it a proper digit?
71                 SUBCC   R6,R6,#key_k0-'0'       ;Yes -- convert to ASCII
72                 BCC     %10numWrite             ;Yes -- deal with it then
73                 CMP     R6,#'-'                 ;Is is a `-' sign?
74                 CMPNE   R6,#key_kMinus          ;Or the one on the keypad?
75                 MOVEQ   R6,#'-'                 ;Either -- make it a `-'
76                 BNE     %50numWrite             ;No -- ignore it then
77                 LDR     R3,[R9,#0]              ;Load the minimum value
78                 CMP     R3,#0                   ;Does it allow negative nos?
79                 BGE     %50numWrite             ;No -- ignore it then
80                 CMP     R5,#0                   ;Is the cursor at the start?
81                 BNE     %50numWrite             ;No -- ignore it then
82
83                 ; --- We've got a character to insert ---
84
85 10numWrite      MOV     R2,R7                   ;Point at the icon's text
86                 MOV     R7,#0                   ;An initial index
87 20numWrite      CMP     R7,R5                   ;Is this the caret position?
88                 MOVEQ   R14,R6                  ;Yes -- insert my char
89                 LDRNEB  R14,[R2],#1             ;Otherwise load from icon
90                 STRB    R14,[R11,R7]            ;Save in position
91                 CMP     R14,#32                 ;Is there more to go?
92                 ADDGE   R7,R7,#1                ;Increment the index
93                 BGE     %20numWrite             ;Yes -- go round again
94                 SUB     R7,R7,#1                ;This is the original length
95
96                 ; --- Fill the icon in nicely ---
97
98                 MOV     R2,R11                  ;Point to my nice new string
99                 BL      numWrite__read          ;Convert it to an integer
100                 MOV     R6,R2                   ;Take a copy of this value
101                 LDR     R1,[R13,#28]            ;Load the icon number
102                 LDMIA   R9,{R3,R4}              ;Load the boundary values
103                 SUB     R4,R4,R3                ;Get the range size
104                 SUB     R14,R2,R3               ;Subtract the bottom end
105                 CMP     R14,R4                  ;Is the value in range?
106                 MOVLS   R0,R10                  ;Yes -- get dialogue handle
107                 MOVLS   R2,R11                  ;Point at the string I made
108                 BLLS    dbox_setField           ;And just write the string
109                 BLHI    numWrite__set           ;Otherwise set the value
110                 MOVHI   R6,R2                   ;If changed, copy value
111                 BL      dbx_sendEvent           ;Send the user an event
112
113                 ; --- Move the caret on ---
114
115                 MOV     R0,R10                  ;Get the dialogue handle
116                 BL      dbox_getField           ;Find the text address
117                 MOV     R0,R2                   ;Point to the buffer
118                 BL      str_len                 ;Find the string length
119                 SUBS    R14,R0,R7               ;Find the length difference
120                 BEQ     %40numWrite             ;No movement -- forget it
121                 ADD     R5,R5,R14               ;Move caret position on 1
122                 CMP     R5,R0                   ;Is the caret in range?
123                 LDMLSIA R13,{R0-R4}             ;Load rest of caret state
124                 SWILS   Wimp_SetCaretPosition   ;Set this as the new pos
125
126                 ; --- Pass an event to the user ---
127
128                 MOV     R0,#numWrite_event      ;Get the event number
129                 MOV     R2,#numWrite_change     ;The value has been changed
130                 MOV     R3,R6                   ;Pass the value in R3
131                 BL      dbx_sendEvent           ;Pass the event on
132
133 40numWrite      ADD     R13,R13,#24             ;Restore the stack now
134                 LDMFD   R13!,{R0-R7,R14}        ;Unstack the registers
135                 ORRS    PC,R14,#C_flag          ;I used the character
136
137                 ; --- Handle a weird character ---
138
139 50numWrite      ADD     R13,R13,#24             ;Restore the stack
140
141                 ; --- Make sure it's an arrow key ---
142
143                 TST     R6,#&100                ;Is the top bit set?
144                 BEQ     %90numWrite             ;No -- just return then
145                 BIC     R6,R6,#&130             ;Ignore modifier bits
146                 CMP     R6,#key_Tab-&100        ;Is it tab?
147                 CMPNE   R6,#key_sTab-&100       ;Or is it shift-tab?
148                 CMPNE   R6,#key_Up-&100         ;Or any of the cursor keys?
149                 CMPNE   R6,#key_Down-&100
150                 CMPNE   R6,#key_cUp-&100        ;Or maybe with control
151                 CMPNE   R6,#key_cDown-&100
152                 BNE     %90numWrite             ;No -- just return then
153
154                 LDR     R1,[R13,#4]             ;Load the icon number
155                 MOV     R0,R10                  ;Get my dialogue handle
156                 BL      numWrite_read           ;Read the current value
157                 BL      numWrite__set           ;Set this as the new value
158                 MOV     R0,#numWrite_event      ;Get my event code
159                 MOV     R3,R2                   ;Pass value in R3
160                 MOV     R2,#numWrite_move       ;The cursor has moved
161                 BL      dbx_sendEvent           ;Send the user an event
162
163 90numWrite      LDMFD   R13!,{R0-R7,R14}        ;Unstack the registers
164                 BICS    PC,R14,#C_flag          ;Let someone else have it
165
166                 LTORG
167
168 ; --- numWrite_set ---
169 ;
170 ; On entry:     R0 == dialogue box handle
171 ;               R1 == icon number within dialogue
172 ;               R2 == value to set in the icon
173 ;
174 ; On exit:      R2 == value actually set
175 ;
176 ; Use:          Writes the specified numeric value into the given writable
177 ;               icon.  The icon must be a dbx control with numWrite type
178 ;               for this to work.
179
180                 EXPORT  numWrite_set
181 numWrite_set    ROUT
182
183                 STMFD   R13!,{R0,R1,R8-R10,R14} ;Save some registers
184                 MOV     R10,R0                  ;Keep the dialogue handle
185                 BL      dbx_findData            ;Look up all the dbx info
186                 BL      numWrite__set           ;Do the actual work
187                 LDMFD   R13!,{R0,R1,R8-R10,PC}^ ;Return to caller
188
189                 LTORG
190
191 ; --- numWrite__set ---
192 ;
193 ; On entry:     R1 == icon handle to set it in
194 ;               R2 == value to set
195 ;               R9 == pointer to minimum and maximum values
196 ;               R10 == dialogue box handle
197 ;
198 ; On exit:      R2 == actual value set
199 ;
200 ; Use:          Forces the given value between the limits for the icon
201 ;               and writes it into the specified icon.
202
203 numWrite__set   STMFD   R13!,{R0-R2,R14}        ;Save some registers
204
205                 ; --- Force the value in range ---
206
207                 LDMIA   R9,{R0,R1}              ;Load min and max values
208                 CMP     R2,R0                   ;Is it big enough?
209                 MOVLT   R2,R0                   ;No -- make it bigger then
210                 CMP     R2,R1                   ;Is it small enough?
211                 MOVGT   R2,R1                   ;No -- make it smaller then
212                 STR     R2,[R13,#8]             ;Return this modified value
213
214                 ; --- Translate it into a string ---
215
216                 MOV     R0,R2                   ;Get value in R0 now
217                 MOV     R1,R11                  ;Build string in scratchpad
218                 MOV     R2,#256                 ;Specify the scratchpad size
219                 SWI     OS_ConvertInteger4      ;Convert it to a string
220
221                 ; --- Write it into the icon ---
222
223                 MOV     R2,R0                   ;Point at my nice new string
224                 LDR     R1,[R13,#4]             ;Load the icon handle back
225                 MOV     R0,R10                  ;Get the dialogue handle
226                 BL      dbox_setField           ;And write it into the icon
227                 LDMFD   R13!,{R0-R2,PC}^        ;Return to caller
228
229                 LTORG
230
231 ; --- numWrite_read ---
232 ;
233 ; On entry:     R0 == dialogue box handle
234 ;               R1 == icon handle
235 ;
236 ; On exit:      CC if icon contains a valid integer, and
237 ;                 R2 == value shown in the icon
238 ;               else CS and
239 ;                 R2 == 0
240 ;
241 ; Use:          Reads the numeric value within the icon specifed.
242
243                 EXPORT  numWrite_read
244 numWrite_read   ROUT
245
246                 STMFD   R13!,{R14}              ;Save the link register
247                 BL      dbox_getField           ;Find the icon string
248                 BL      numWrite__read          ;Convert it to an integer
249                 LDMFD   R13!,{PC}               ;Return it and the flags
250
251                 LTORG
252
253 ; --- numWrite__read ---
254 ;
255 ; On entry:     R2 == pointer to a string
256 ;
257 ; On exit:      R2 == integer represented by string and CC or 0 and CS
258 ;
259 ; Use:          Converts a string showing a decimal integer to the value
260 ;               it represents.
261
262 numWrite__read  ROUT
263
264                 STMFD   R13!,{R0,R1,R14}
265
266                 ; --- Set up some initial values ---
267
268                 MOV     R0,R2                   ;Point to the string start
269                 MOV     R1,#0                   ;Not found any digits yet
270                 MOV     R2,#0                   ;A good accumulator
271
272                 ; --- Check for a leading sign ---
273
274                 LDRB    R14,[R0],#1             ;Load a byte from the string
275                 CMP     R14,#'-'                ;Is it a `-' sign?
276                 ORREQ   R1,R1,#1                ;Set the `negative' bit
277                 LDREQB  R14,[R0],#1             ;Yes -- load another byte
278
279                 ; --- Now read bytes from the string ---
280                 ;
281                 ; We stop as soon as we find a character which isn't a
282                 ; digit.
283
284 10              SUB     R14,R14,#'0'            ;Convert to an integer
285                 CMP     R14,#10                 ;Is it in range?
286                 BCS     %20numWrite__read       ;No -- that's it then
287                 TST     R1,#1                   ;Is the number negative?
288                 ADD     R2,R2,R2,LSL #2         ;Multiply by 5
289                 ADDEQ   R2,R14,R2,LSL #1        ;If +ve, double and add new
290                 RSBNE   R2,R14,R2,LSL #1        ;Otherwise, subtract it
291                 ORR     R1,R1,#2                ;Say we read something good
292                 LDRB    R14,[R0],#1             ;Load a new byte
293                 B       %10numWrite__read       ;Go round the loop again
294
295                 ; --- Return the value ---
296
297 20              TST     R1,#2                   ;Was the number valid?
298                 LDMFD   R13!,{R0,R1,R14}        ;Restore the registers
299                 ORREQS  PC,R14,#C_flag          ;No -- set C as error warning
300                 BICNES  PC,R14,#C_flag          ;Otherwise clear it
301
302                 LTORG
303
304 ; --- numWrite_bump ---
305 ;
306 ; On entry:     R0 == dialogue box handle
307 ;               R1 == icon handle
308 ;               R2 == increment to apply to it
309 ;
310 ; On exit:      R2 == updated value in the icon
311 ;
312 ; Use:          Adjusts the value in a writable icon by a given increment.
313
314                 EXPORT  numWrite_bump
315 numWrite_bump   ROUT
316
317                 STMFD   R13!,{R0,R1,R3,R14}     ;Save some registers
318                 MOV     R3,R2                   ;Look after the increment
319                 BL      numWrite_read           ;Read the current value
320                 ADDCC   R2,R2,R3                ;If valid, apply increment
321                 BL      numWrite_set            ;And write the value back
322                 LDMFD   R13!,{R0,R1,R3,PC}^     ;Return to caller
323
324                 LTORG
325
326 ;----- Constants ------------------------------------------------------------
327
328 numWrite_event  EQU     &80000004               ;R1 == icon number changed
329                                                 ;R2 == subreason code
330                                                 ;R3 == new value of icon
331
332 numWrite_change EQU     0                       ;Subreason -- number changed
333 numWrite_move   EQU     1                       ;Subreason -- cursor moved
334
335 ;----- That's all, folks ----------------------------------------------------
336
337                 END