Initial revision
[ssr] / StraySrc / Libraries / Sapphire / s / dbox
1 ;
2 ; dbox.s
3 ;
4 ; Dialogue box handling (MDW)
5 ;
6 ; © 1994-1998 Straylight
7 ;
8
9 ;----- Licensing note -------------------------------------------------------
10 ;
11 ; This file is part of Straylight's Sapphire library.
12 ;
13 ; Sapphire is free software; you can redistribute it and/or modify
14 ; it under the terms of the GNU General Public License as published by
15 ; the Free Software Foundation; either version 2, or (at your option)
16 ; any later version.
17 ;
18 ; Sapphire is distributed in the hope that it will be useful,
19 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 ; GNU General Public License for more details.
22 ;
23 ; You should have received a copy of the GNU General Public License
24 ; along with Sapphire. If not, write to the Free Software Foundation,
25 ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26
27 ;----- Standard header ------------------------------------------------------
28
29 GET libs:header
30 GET libs:swis
31
32 ;----- External dependencies ------------------------------------------------
33
34 GET sapphire:akbd
35 GET sapphire:alloc
36 GET sapphire:event
37 GET sapphire:keyMap
38 GET sapphire:help
39 GET sapphire:hour
40 GET sapphire:msgs
41 GET sapphire:sapphire
42 GET sapphire:string
43 GET sapphire:subAlloc
44 GET sapphire:template
45 GET sapphire:transWin
46 GET sapphire:win
47 GET sapphire:winUtils
48
49 ;----- Creating and deleting dialogue boxes ---------------------------------
50
51 AREA |Sapphire$$Code|,CODE,READONLY
52
53 ; --- dbox_create ---
54 ;
55 ; On entry: R0 == pointer to dialogue template name
56 ;
57 ; On exit: R0 == dialogue box handle for the dialogue
58 ; May return an error
59 ;
60 ; Use: Creates a dialogue box from a template definition.
61
62 EXPORT dbox_create
63 dbox_create ROUT
64
65 STMFD R13!,{R1-R3,R14} ;Save some registers
66
67 ; --- Locate the template and copy it ---
68
69 MOV R3,R0 ;Keep name pointer safe
70 MOV R1,#0 ;No template created yet
71 BL template_find ;Find the actual definition
72 MOVVC R2,R0 ;Keep this pointer
73 MOVVS R2,#1 ;Otherwise assume shared rsc
74 MOV R0,R3 ;Point at the name again
75 BL template_copy ;And create the copy I use
76 MOVVC R1,R0 ;Look after the copy
77
78 ; --- Now create a dialogue box around it ---
79
80 BLVC dbox_fromDefn ;Create dbox from window def
81 STRVC R2,[R0,#dbox__template] ;Store the template pointer
82 LDMVCFD R13!,{R1-R3,R14} ;Unstack the registers
83 BICVCS PC,R14,#V_flag ;And return errorless
84
85 ; --- Tidy up aftet an error
86
87 MOV R2,R0 ;Look after this
88 MOVS R0,R1 ;Get the template pointer
89 BLNE template_free ;Maybe we free it
90 MOVNE R0,R2 ;If not, get error back
91 ADDEQ R2,R2,#4 ;Otherwise find error text
92 ADREQ R0,dbox__createErr ;Point to my skeleton error
93 BLEQ msgs_error ;Translate and substitute
94 LDMFD R13!,{R1-R3,R14} ;Restore registers
95 ORRS PC,R14,#V_flag ;Return the error
96
97 LTORG
98
99 ; --- dbox_fromEmbedded ---
100 ;
101 ; On entry: R0 == pointer to an embedded template
102 ;
103 ; On exit: R0 == dialogue box handle
104 ; May return an error
105 ;
106 ; Use: Creates a dialogue box from an embedded template definition.
107
108 EXPORT dbox_fromEmbedded
109 dbox_fromEmbedded ROUT
110
111 STMFD R13!,{R1,R2,R14} ;Save some registers
112 MOV R1,#0 ;Clear template pointer
113 BL template_embedded ;Copy the template
114 MOVVC R1,R0 ;Look after this
115 BLVC dbox_fromDefn ;Create the dialogue box
116 MOVVC R14,#1 ;Mark as a template
117 STRVC R14,[R0,#dbox__template] ;So it gets freed properly
118 LDMVCFD R13!,{R1,R2,R14} ;Restore registers
119 BICVCS PC,R14,#V_flag ;And return with no error
120
121 MOV R2,R0 ;Look after this
122 MOVS R0,R1 ;Get the template pointer
123 BLNE template_free ;Maybe we free it
124 MOVNE R0,R2 ;If not, get error back
125 ADDEQ R2,R2,#4 ;Otherwise find error text
126 ADREQ R0,dbox__createErr ;Point to my skeleton error
127 BLEQ msgs_error ;Translate and substitute
128 LDMFD R13!,{R1,R2,R14} ;Restore registers
129 ORRS PC,R14,#V_flag ;Return the error
130
131 LTORG
132
133 ; --- dbox_fromDefn ---
134 ;
135 ; On entry: R0 == pointer to a window definition
136 ;
137 ; On exit: R0 == dialogue box handle for the dialogue
138 ; May return an error
139 ;
140 ; Use: Creates a dialogue box from an immediate window definition,
141 ; rather than a template. There are several things you need
142 ; to be aware of when you use this call to create a dialogue
143 ; box:
144 ;
145 ; * The window definition is not copied, but used directly
146 ; for the duration the dialogue box exists. It must
147 ; not move for this duration. When the dialogue is
148 ; destroyed, you can release the memory for the definition,
149 ; although this is your responsibility.
150 ;
151 ; * The indirected data is not copied either, so you'll have
152 ; to copy it yourself if you want multiple dialogues from
153 ; the same window definition.
154 ;
155 ; * The window definition and the indirected data must both
156 ; be writable.
157
158 EXPORT dbox_fromDefn
159 dbox_fromDefn ROUT
160
161 STMFD R13!,{R1-R3,R10,R14} ;Save some registers away
162
163 ; --- Obtain a dbox block from the heap ---
164
165 MOV R3,R0 ;Look after the definition
166 MOV R0,#dbox__blockSize ;Find out how much I need
167 BL alloc ;Allocate the memory
168 BLCS alloc_error ;If it failed, find error msg
169 BCS %99dbox_fromDefn ;... and quit if no memory
170
171 ; --- Now start filling in the structure ---
172
173 STR R3,[R0,#dbox__defn] ;Store the copy pointer away
174 MOV R2,#0 ;Start zeroing things
175 STR R2,[R0,#dbox__proc] ;No event handler yet
176 STR R2,[R0,#dbox__flags] ;Dialogue box has no flags
177 STR R2,[R0,#dbx__defn] ;Dbox not nabbed by dbx yet
178 STR R2,[R0,#dbox__template] ;No template definition
179 MOV R2,#-1 ;No embedded title icon
180 STR R2,[R0,#dbox__title] ;So store it away
181 MOV R10,R0 ;Keep this pointer safe
182
183 ; --- Now we need to create a window ---
184
185 MOV R1,R3 ;Point to the window defn
186 SWI XWimp_CreateWindow ;Create the window
187 BVS %98dbox_fromDefn ;If it failed, tidy up
188 STR R0,[R10,#dbox__window] ;Store the window handle
189
190 ; --- Now register our event handler for it ---
191
192 ADR R1,dbox__events ;Point to my event handler
193 MOV R2,R10 ;Pass the dialogue box handle
194 WSPACE dbox__wSpace,R3 ;And my workspace pointer
195 BL win_eventHandler ;Register the event handler
196 BVS %97dbox_fromDefn ;If that failed, tidy up
197
198 ; --- Now return the dialogue box handle ---
199
200 MOV R0,R10 ;Return pointer to my block
201 LDMFD R13!,{R1-R3,R10,R14} ;Restore the registers
202 BICS PC,R14,#V_flag ;Return with no errors
203
204 ; --- Tidy up after unfortunate events ---
205
206 97dbox_fromDefn MOV R3,R0 ;Keep error pointer
207 ADD R1,R10,#dbox__window ;Point to the window handle
208 SWI Wimp_DeleteWindow ;Delete the duff window
209 MOV R0,R3 ;Restore error pointer
210
211 98dbox_fromDefn MOV R2,R0 ;Keep error pointer
212 MOV R0,R10 ;Point to the block
213 BL free ;Free it up -- it's useless
214 MOV R0,R2 ;Restore error pointer
215
216 99dbox_fromDefn ADD R2,R0,#4 ;Point to the error message
217 ADR R0,dbox__createErr ;Point to my skeleton error
218 BL msgs_error ;Translate and substitute
219 LDMFD R13!,{R1-R3,R10,R14} ;Restore registers
220 ORRS PC,R14,#V_flag ;Return the error
221
222 dbox__createErr DCD 1
223 DCB "dboxCRTERR",0
224
225 ; --- dbox_destroy ---
226 ;
227 ; On entry: R0 == dialogue box handle
228 ;
229 ; On exit: --
230 ;
231 ; Use: Destroys a dialogue box, freeing all the memory it took
232 ; up etc.
233
234 EXPORT dbox_destroy
235 dbox_destroy ROUT
236
237 STMFD R13!,{R0,R1,R10,R14} ;Save some registers
238 MOV R10,R0 ;Get the dialogue handle
239
240 ; --- Make sure the dialogue's been closed ---
241
242 BL dbox_close ;Close the dialogue box
243 MOV R0,#dbEvent_lifeCycle ;Send a lifecycle message
244 MOV R1,#dblc_destroy ;Dialogue will be destroyed
245 BL dbox__dispatch ;Send the message
246
247 ; --- Remove the event handler ---
248
249 LDR R0,[R10,#dbox__window] ;Find the window handle
250 BL win_windowDeleted ;Window doesn't need handling
251
252 ; --- Delete the window ---
253
254 ADD R1,R10,#dbox__window ;Point to the window handle
255 SWI Wimp_DeleteWindow ;Delete the window
256
257 ; --- Free the template copy ---
258
259 LDR R14,[R10,#dbox__template] ;Load the template address
260 CMP R14,#0 ;Is there one defined?
261 LDRNE R0,[R10,#dbox__defn] ;Point to the template copy
262 BLNE template_free ;Free it up now
263
264 ; --- Free the dialogue block ---
265
266 MOV R0,R10 ;Point to the dbox block
267 BL free ;Free its memory up
268
269 ; --- Return to caller ---
270
271 LDMFD R13!,{R0,R1,R10,PC}^ ;Return to caller
272
273 ;----- The event handler ---------------------------------------------------
274
275 ; --- dbox__events ---
276 ;
277 ; On entry: R0 == the event code that happened
278 ; R1 == pointer to the event data
279 ; R10 == dialogue box it happened to
280 ;
281 ; On exit: CS if we handled the event, CC otherwise
282 ;
283 ; Use: Handles various events for a dialogue box
284
285 dbox__events ROUT
286
287 ; --- Dispatch the event to the right place ---
288
289 STR R10,dbox__eventDbox ;Remember this handle
290 CMP R0,#9 ;Is it a sensible event?
291 BGE %00dbox__events ;No -- check for messages
292 ADD PC,PC,R0,LSL #2 ;Yes -- dispatch to handler
293
294 ; --- Event dispatch table ---
295
296 B dbox__hint ;Hint for the hint bar
297 MOVS PC,R14 ;Null event
298 B dbox__redraw ;Redraw window request
299 B dbox__open ;Open window request
300 B dbox__close ;Close window request
301 B dbox__enterLeave ;Pointer leaving window
302 B dbox__enterLeave ;Pointer entering window
303 B dbox__mouse ;Mouse clicked
304 MOVS PC,R14 ;Drag event
305 B dbox__keyPress ;Key pressed
306
307 ; --- Handle a message ---
308
309 00dbox__events CMP R0,#17 ;User message
310 CMPNE R0,#18 ;Rubber message (bouncy!)
311 MOVNES PC,R14 ;No -- return unhandled
312 B dbox__message ;Handle the message event
313
314 ; --- dbox__dispatch ---
315 ;
316 ; On entry: R0 == the (dbox-style) event code to dispatch
317 ; R1-R7 == any additional arguments that want passing along
318 ; R10 == the dialogue box to send the event to
319 ;
320 ; On exit: CS or CC from the event handler
321 ;
322 ; Use: Dispatches an event to the event handler associated with the
323 ; dialogue box, and returns its response.
324
325 dbox__dispatch ROUT
326
327 STMFD R13!,{R8-R10,R12,R14} ;Save lots of registers
328 MOV R9,R10 ;Pass dialogue handle in R9
329 ADDS R0,R0,#0 ;Clear the carry flag
330 LDMIB R10,{R8,R10,R12} ;Get the event handler stuff
331 TEQ R8,#0 ;Is there an event handler?
332 MOVNE R14,PC ;Set up return address
333 MOVNE PC,R8 ;Call the event handler
334 LDMFD R13!,{R8-R10,R12,R14} ;Restore the registers
335 ORRCSS PC,R14,#C_flag ;Return CS if it returned CS
336 BICCCS PC,R14,#C_flag ;Return CC if it returned CC
337
338 LTORG
339
340 ; --- dbox__checkIcon ---
341 ;
342 ; On entry: R1 == icon handle
343 ; R10 == dialogue box handle
344 ;
345 ; On exit: R1 == icon handle or -1 if it was shaded
346 ;
347 ; Use: Translates an icon handle to the window background if it
348 ; is shaded, for passing to event handlers.
349
350 dbox__checkIcon ROUT
351
352 STMFD R13!,{R0,R14} ;Save some registers
353 MOV R0,R1 ;Move icon handle along
354 BL dbox__icon ;Find the icon definition
355 LDR R14,[R0,#16] ;Load the icon flags
356 TST R14,#&00400000 ;Is the icon shaded?
357 MOVNE R1,#-1 ;Yes -- return background
358 STR R1,dbox__eventIcon ;Store in workspace
359 LDMFD R13!,{R0,PC}^ ;Return to caller
360
361 LTORG
362
363 ; --- dbox__hint ---
364 ;
365 ; On entry: R0 == -1
366 ; R1 == pointer to hint event block
367 ;
368 ; On exit: C set if handled
369 ;
370 ; Use: Sends a hint event to the dbox handler
371
372 dbox__hint ROUT
373
374 STMFD R13!,{R0-R2,R14} ;Save some registers
375 MOV R0,#dbEvent_hint ;The event code
376 ADD R2,R1,#4 ;Point to the string
377 BL dbox__dispatch ;Send it to the handler
378 LDMFD R13!,{R0-R2,PC} ;Return with its flags
379
380 LTORG
381
382 ; --- dbox__redraw ---
383 ;
384 ; On entry: R0 == 1
385 ; R1 == pointer to window handle
386 ;
387 ; On exit: C set
388 ;
389 ; Use: Redraws a window using Sculptrix
390
391 dbox__redraw ROUT
392
393 STMFD R13!,{R0,R2,R3,R14} ;Save some registers
394
395 ; --- Start the redraw operation ---
396
397 SWI Wimp_RedrawWindow ;Start the redraw
398 CMP R0,#0 ;Is it over already?
399 BEQ %10dbox__redraw ;Yes -- skip to the end
400
401 ; --- Set up Sculptrix's sprite area ---
402
403 LDR R0,[R10,#dbox__defn] ;Find the window definition
404 LDR R0,[R0,#64] ;Load the sprite area pointer
405 SWI XSculptrix_SetSpriteArea ;Set up the sprite area
406
407 ; --- Do any bits that need doing ---
408
409 00dbox__redraw LDR R2,[R1,#4] ;Get the window left position
410 ADD R0,R1,#16 ;Point to the top position
411 LDMIA R0,{R0,R3,R14} ;Load top, and scroll posns
412 SUB R2,R2,R3 ;Convert to find origin x
413 SUB R3,R0,R14 ;Convert to find origin y
414 MOV R0,#dbEvent_redraw ;Give user a redraw event
415 BL dbox__dispatch ;Send it to the handler
416 BCS %01dbox__redraw ;If it claimed it, skip ahead
417
418 LDR R0,[R10,#dbox__title] ;Get the embedded title icon
419 CMP R0,#-1 ;Has it been defined?
420 MOVNE R0,R10 ;Give it the dialogue box
421 BLNE dbox_renderTitle ;Yes -- render it nicely
422
423 SWI XSculptrix_RedrawWindow ;Get Sculptrix to do its bit
424
425 01dbox__redraw SWI Wimp_GetRectangle ;Get the next rectangle
426 CMP R0,#0 ;Is this the end yet?
427 BNE %00dbox__redraw ;No -- do the rest
428
429 ; --- That's it, then ---
430
431 10dbox__redraw LDMFD R13!,{R0,R2,R3,R14} ;Unstack all the registers
432 ORRS PC,R14,#C_flag ;Set carry and return
433
434 LTORG
435
436 ; --- dbox__open ---
437 ;
438 ; On entry: R0 == 2
439 ; R1 == pointer to window open block
440 ;
441 ; On exit: C set
442 ;
443 ; Use: This just opens the window. Later, it may do clever things
444 ; with panes.
445
446 dbox__open SWI Wimp_OpenWindow ;Open the window
447 ORRS PC,R14,#C_flag ;Set carry and return
448
449 ; --- dbox__close ---
450 ;
451 ; On entry: R0 == 3
452 ; R1 == pointer to the window handle
453 ;
454 ; On exit: C set
455 ;
456 ; Use: Passes a close event to the user dialogue box handler.
457
458 dbox__close STMFD R13!,{R0,R14} ;Save some registers
459 MOV R0,#dbEvent_close ;The close event code
460 BL dbox__dispatch ;Pass it to the handler
461 LDMFD R13!,{R0,R14} ;Unstack all the registers
462 ORRS PC,R14,#C_flag ;Set carry and return
463
464 ; --- dbox__mouse ---
465 ;
466 ; On entry: R0 == 6
467 ; R1 == pointer to mouse status block
468 ;
469 ; On exit: C set if we understood the event, C clear otherwise
470 ;
471 ; Use: Passes a click event to the dbox event handler.
472
473 dbox__mouse ROUT
474
475 STMFD R13!,{R0-R2,R9,R14} ;Save some registers
476 MOV R9,R1 ;Keep the event pointer
477 LDR R1,[R9,#8] ;Get the button status
478 TST R1,#&5 ;Is it Select or Adjust?
479 BNE %10dbox__mouse ;Yes -- handle it nicely
480 TST R1,#&50 ;Is it a drag event?
481 BNE %20dbox__mouse ;Yes -- handle it nicely
482 TST R1,#&2 ;Is it a menu click?
483 LDMEQFD R13!,{R0-R2,R9,PC}^ ;No -- we're clueless then
484
485 ; --- The user clicked Menu ---
486
487 LDR R1,[R9,#16] ;Get the icon handle out
488 MOV R0,#dbEvent_menu ;Give it a menu click
489 BL dbox__checkIcon ;Handle icon shadedness
490 BL dbox__dispatch ;Give it to the user
491 B %80dbox__mouse ;And return C set
492
493 ; --- The user clicked Select or Adjust ---
494
495 10dbox__mouse LDR R1,[R9,#16] ;Get the icon handle out
496 BL dbox__checkIcon ;Handle icon shadedness
497 MOV R0,R1 ;Return icon number as event
498 LDR R1,[R9,#8] ;Load the button state again
499 BL dbox__dispatch ;Dispatch the event out
500 BCS %80dbox__mouse ;If handled, skip this bit
501
502 MOV R1,R0 ;Get the icon handle in R1
503 MOV R0,R10 ;And dialogue handle in R0
504 BL dbox_radio ;Handle magic radio buttons
505
506 LDR R0,[R10,#dbox__flags] ;Get this dialogue's flags
507 TST R0,#dbFlag__drag ;Is the move on drag bit on?
508 BEQ %80dbox__mouse ;No -- skip this bit out
509
510 SUB R13,R13,#56 ;Make a drag info block
511 LDR R0,[R10,#dbox__window] ;Get the window handle
512 STR R0,[R13,#0] ;Store the window handle
513 MOV R0,#1 ;Move the window
514 STR R0,[R13,#4] ;Store the drag type
515 MOV R1,R13 ;Point to the block
516 SWI Wimp_DragBox ;Start the window moving
517 ADD R13,R13,#56 ;Reclaim the stack space
518 B %80dbox__mouse ;Skip ahead to claim event
519
520 ; --- The user dragged an icon ---
521
522 20dbox__mouse LDR R1,[R9,#16] ;Get the icon handle out
523 BL dbox__checkIcon ;Handle shadiness nicely
524 MOV R2,R1 ;Move handle to right place
525 LDR R1,[R9,#8] ;Load button status again
526 MOV R0,#dbEvent_drag ;Give handler a drag event
527 BL dbox__dispatch ;And pass it to the handler
528 B %80dbox__mouse ;And claim the event
529
530 ; --- Finish everything off nicely ---
531
532 80dbox__mouse LDMFD R13!,{R0-R2,R9,R14} ;Restore the registers
533 ORRS PC,R14,#C_flag ;Claim the event nicely
534
535 LTORG
536
537 ; --- dbox__enterLeave ---
538 ;
539 ; On entry: R0 == 4 for leaving, 5 for entering
540 ;
541 ; On exit: --
542 ;
543 ; Use: Informs dialogue handlers that pointer has entered or left
544 ; a window.
545
546 dbox__enterLeave ROUT
547
548 STMFD R13!,{R0,R14} ;Save some registers
549 ADD R0,R0,#dbEvent_leave-4 ;Convert to appropriate event
550 BL dbox__dispatch ;Send it to the handler
551 LDMFD R13!,{R0,PC}^ ;And return to caller
552
553 LTORG
554
555 ; --- dbox__keyPress ---
556 ;
557 ; On entry: R0 == 8
558 ; R1 == pointer to caret block
559 ;
560 ; On exit: C clear
561 ;
562 ; Use: Handles key events for a dialogue box
563
564 dbox__keyPress ROUT
565
566 STMFD R13!,{R0-R3,R14} ;Save some registers
567
568 ; --- Send the event to the user ---
569
570 LDR R2,[R1,#4] ;Get the icon handle
571 STR R2,dbox__eventIcon ;Store it in workspace
572 LDR R0,[R1,#24] ;Get the key code
573 BL akbd_translate ;Mangle for extended keyset
574 MOV R1,R0 ;Move into right register
575 MOV R0,#dbEvent_key ;Key event code
576 BL dbox__dispatch ;Send it to the user
577 BCS %50dbox__keyPress ;If processed, skip ahead
578
579 ; --- Now see if it's one of ours ---
580
581 CMP R1,#&100 ;Is it an extended code?
582 BGE %20dbox__keyPress ;Yes -- skip forward
583
584 CMP R1,#key_Return ;Is it a return?
585 MOVEQ R0,#dbEvent_OK ;Yes -- give out an OK event
586 BEQ %10dbox__keyPress ;Send it on its way
587 CMP R1,#key_Esc ;Or maybe an escape
588 MOVEQ R0,#dbEvent_cancel ;Yes -- give a Cancel event
589 BEQ %10dbox__keyPress ;Send it on its way
590
591 00 LDMFD R13!,{R0-R3,PC}^ ;Forget it -- don't know
592
593 ; --- Send a key event on ---
594
595 10 MOV R1,#4 ;Pretend Select was pressed
596 BL dbox__dispatch ;Send it to the client
597 B %50dbox__keyPress ;Now we've done the deed...
598
599 11 MOV R1,#1 ;Pretend Adjust was pressed
600 BL dbox__dispatch ;Send it to the client
601 B %50dbox__keyPress ;Now we've done the deed...
602
603 ; --- Handle an extended key ---
604
605 20 AND R2,R1,#&FF ;Leave the bottom byte
606
607 ; --- Straight cursor keys ---
608
609 MOV R0,#0
610
611 CMP R2,#key_kEnter-256
612 MOVEQ R0,#dbEvent_OK
613 BEQ %10dbox__keyPress
614
615 CMP R2,#key_sReturn-256
616 CMPNE R2,#key_skEnter-256
617 MOVEQ R0,#dbEvent_OK
618 BEQ %11dbox__keyPress
619
620 CMP R2,#key_sEsc-256
621 MOVEQ R0,#dbEvent_cancel
622 BEQ %11dbox__keyPress
623
624 CMP R2,#key_Up-256
625 CMPNE R2,#key_sTab-256
626 MOVEQ R1,#-1
627 BEQ %40dbox__keyPress
628
629 CMP R2,#key_Down-256
630 CMPNE R2,#key_Tab-256
631 MOVEQ R1,#+1
632 BEQ %40dbox__keyPress
633
634 ; --- Control cursor keys ---
635
636 MOV R0,#1
637
638 CMP R2,#key_cUp-256
639 MOVEQ R1,#+1
640 BEQ %40dbox__keyPress
641
642 ; --- Cursor up ---
643
644 CMP R2,#key_cDown-256
645 MOVEQ R1,#-1
646 BEQ %40dbox__keyPress
647
648 ; --- Nothing worth knowing about ---
649
650 B %00dbox__keyPress
651
652 ; --- Actually do a cursor move ---
653
654 40 BL dbox__moveCaret ;Do the cursor move
655
656 ; --- Return and claim the keypress ---
657
658 50 LDMFD R13!,{R0-R3,R14}
659 ORRS PC,R14,#C_flag
660
661 LTORG
662
663 ; --- dbox__message ---
664 ;
665 ; On entry: R0 == 17 or 18
666 ; R1 == pointer to message data
667 ;
668 ; On exit: C set if the event was handled, or clear otherwise
669 ;
670 ; Use: Handles messages sent to dialogue boxes.
671
672 dbox__message ROUT
673
674 STMFD R13!,{R0-R4,R9,R14} ;Save some registers
675 MOV R9,R1 ;Point to the event block
676 LDR R14,[R9,#16] ;Get the message type number
677 CMP R14,#1 ;Is it a save message?
678 CMPNE R14,#3 ;Or a load message?
679 BEQ %10dbox__message ;Yes -- handle them the same
680 MOV R0,#&500 ;&502 is a help request
681 ORR R0,R0,#&002 ;Build the full number
682 CMP R14,R0 ;Is it a help request?
683 LDMNEFD R13!,{R0-R4,R9,PC}^ ;No -- we don't understand
684
685 ; --- Handle help requests for the dbox ---
686
687 LDR R1,[R9,#36] ;Obtain the icon handle
688 BL dbox__checkIcon ;Handle icon shadiness
689 MOV R0,#dbEvent_help ;Pass a help request on
690 BL dbox__dispatch ;Send it to the client
691 B %80dbox__message ;Skip on and claim the event
692
693 ; --- Handle save and load events ---
694
695 10dbox__message CMP R14,#1 ;Is it a save message?
696 MOVEQ R0,#dbEvent_save ;Yes -- give a save event
697 MOVNE R0,#dbEvent_load ;No -- give a load event
698 LDR R1,[R9,#24] ;Get the icon handle
699 BL dbox__checkIcon ;Handle icon shadiness
700 LDR R2,[R9,#40] ;Get filetype in R2
701 ADD R3,R9,#44 ;Point to filename with R3
702 LDR R4,[R9,#36] ;Estimated size in R4
703 BL dbox__dispatch ;Send the message on
704 B %80dbox__message ;Skip on and claim the event
705
706 ; --- We did something, so claim event ---
707
708 80dbox__message LDMFD R13!,{R0-R4,R9,R14} ;Restore all the registers
709 ORRS PC,R14,#C_flag ;Return, claiming the event
710
711 LTORG
712
713 ;----- Locating icons -------------------------------------------------------
714
715 ; --- dbox__find ---
716 ;
717 ; On entry: R0 == icon number to start from or -1
718 ; R1 == AND mask for flags
719 ; R2 == flags word to match
720 ; R3 == direction to scan in (either +1 or -1 unless you're
721 ; very odd)
722 ; R10 == dialogue box handle
723 ;
724 ; On exit: R0 == icon number of found icon or -1
725 ; Other registers preserved
726 ;
727 ; Use: Locates an icon within a window with flags that match the
728 ; ones given. Note that icon definitions within the cached
729 ; window definition are scanned, not icons in their actual
730 ; current state.
731 ;
732 ; Searching from icon `-1' means to start from one end and
733 ; keep looking until you've gone through all of them.
734 ; Otherwise, the scan starts from the icon *after* the one
735 ; specified in R0 on entry.
736 ;
737 ; The return value is the number of the first icon that
738 ; matched the specification, or -1 if none of them matched.
739
740 dbox__find ROUT
741
742 STMFD R13!,{R4-R6,R14} ;Save some registers
743
744 ; --- Find the cached window defintion ---
745
746 LDR R4,[R10,#dbox__defn] ;Locate the definition
747
748 ; --- Work out a sensible scanning start position ---
749
750 CMP R0,#-1 ;Extremity requested?
751 ADDNE R0,R0,R3 ;No -- skip over start icon
752 BNE %00dbox__find ;And skip past this bit
753 CMP R3,#0 ;Is the increment positive?
754 MOVGT R0,#0 ;Yes -- start from 0
755 LDRLT R0,[R4,#84] ;No -- load the icon count
756 SUBLT R0,R0,#1 ;And bump down -- zero index
757
758 ; --- Now work out when to stop scanning ---
759
760 00dbox__find CMP R3,#0 ;What's the increment again?
761 BEQ %02dbox__find ;If it's silly, find nothing
762 LDRGT R5,[R4,#84] ;Positive -- stop at the
763 SUBGT R5,R5,#1 ;...number of icons -1
764
765 ; --- A few other pre-scan bits ---
766
767 AND R2,R2,R1 ;Make sure flags aren't silly
768 ADD R6,R4,#88 ;Point to icon number 0
769 ADD R6,R6,R0,LSL #5 ;Point to the right icon
770
771 ; --- The main scanning loop ---
772 ;
773 ; The comparison at the end is slightly tricky. It works
774 ; on the basis that if R3>0, the condition is that R0>R5,
775 ; and if R3<0, the condition is that R0<0. Each of these
776 ; double-barrelled conditions can be done in two ARM
777 ; instructions, and both together, complete with branches
778 ; can be done in 6.
779 ;
780 ; Rather oddly, we start with the termination condition.
781
782 01dbox__find CMP R3,#0 ;What's the increment like?
783 CMPLT R0,#0 ;Check not gone too low
784 BLT %02dbox__find ;Yes -- exit the loop
785 CMP R3,#0 ;Check increment again
786 CMPGT R0,R5 ;Check not gone too high
787 BGT %02dbox__find ;Yes -- exit the loop
788
789 ; --- Now see if we got a match ---
790
791 LDR R14,[R6,#16] ;Get icon flags for this one
792 AND R14,R14,R1 ;Apply the AND mask to them
793 CMP R14,R2 ;Is this a match?
794 LDMEQFD R13!,{R4-R6,PC}^ ;Yes -- return to caller
795
796 ; --- Set up for the next one ---
797
798 ADD R0,R0,R3 ;Move the icon number on
799 ADD R6,R6,R3,LSL #5 ;And bump icon pointer too
800 B %01dbox__find ;Jump back to the loop start
801
802 ; --- We failed to find it -- return -1 ---
803
804 02dbox__find MOV R0,#-1 ;Return funny failure value
805 LDMFD R13!,{R4-R6,PC}^ ;Return to caller
806
807 LTORG
808
809 ; --- dbox__icon ---
810 ;
811 ; On entry: R0 == icon number wanted
812 ; R10 == dialogue box block pointer
813 ;
814 ; On exit: R0 == pointer to numbered icon's definition
815 ;
816 ; Use: Locates an icon definition given its number
817
818 dbox__icon STMFD R13!,{R14} ;Save link register a bit
819 LDR R14,[R10,#dbox__defn] ;Find window definition
820 ADD R14,R14,#88 ;Point to the first icon
821 ADD R0,R14,R0,LSL #5 ;Add R0*32 to point to icon
822 LDMFD R13!,{PC}^ ;Return to caller nicely
823
824 ;----- Main initialisation --------------------------------------------------
825
826 ; --- dbox_init ---
827 ;
828 ; On entry: --
829 ;
830 ; On exit: --
831 ;
832 ; Use: Initialises the dbox system.
833
834 EXPORT dbox_init
835 dbox_init ROUT
836
837 STMFD R13!,{R12,R14} ;Save a load of registers
838 WSPACE dbox__wSpace ;Find my workspace
839
840 ; --- Make sure I'm not running yet ---
841
842 LDR R14,dbox__wFlags ;Get hold of my flags word
843 TST R14,#dbFlag__inited ;Am I running yet?
844 LDMNEFD R13!,{R12,PC}^ ;Yes -- return immediately
845
846 ; --- Set up the flags nicely ---
847
848 MOV R14,#dbFlag__inited ;I am initialised now
849 STR R14,dbox__wFlags ;Save my flags back again
850 MOV R14,#0 ;Zero some workspace bits
851 STR R14,dbox__clickList ;Nothing on the click list
852 BL win_init ;Make sure win's awake
853 BL transWin_init ;And also for transWin
854 LDMFD R13!,{R12,PC}^ ;Return to caller
855
856 LTORG
857
858 dbox__wSpace DCD 0
859
860 ;----- Opening and closing dialogue boxes -----------------------------------
861
862 ; --- dbox_open ---
863 ;
864 ; On entry: R0 == dialogue box handle
865 ; R1 == how to open the dialogue box
866 ; Other registers depend on R1, and are described at the end
867 ; of this header file
868 ;
869 ; On exit: --
870 ;
871 ; Use: Displays the dialogue box on the screen in the given manner.
872
873 EXPORT dbox_open
874 dbox_open ROUT
875
876 STMFD R13!,{R0-R6,R10,R12,R14}
877 WSPACE dbox__wSpace ;Locate my workspace
878 MOV R10,R0 ;Move the dbox handle away
879
880 ; --- Is this a submenu request? ---
881
882 ADDS R0,R0,#0 ;Clear the C flag
883 TST R1,#dbOpen_nonSub ;Do we ignore this?
884 BLEQ transWin_subWaiting ;No -- waiting for a submenu?
885 BCS %60dbox_open ;Yes -- open as a submenu
886
887 ; --- Now work out how to open it ---
888
889 LDR R6,[R10,#dbox__flags] ;Get the dialogue's flags
890 TST R1,#dbOpen_persist ;Is this a persistent dbox?
891 BICEQ R6,R6,#dbFlag__static ;No -- clear static flag
892 ORRNE R6,R6,#dbFlag__static ;Yes -- set static flag
893 MOV R4,R1 ;Look after open style
894
895 ; --- Read the dialogue's position ---
896
897 SUB R13,R13,#36 ;Enough for a window block
898 LDR R0,[R10,#dbox__window] ;Get the window handle
899 STR R0,[R13,#0] ;Store it in the block
900 MOV R1,R13 ;Point to the window handle
901 SWI Wimp_GetWindowState ;Read in the information
902
903 ; --- Move the dialogue box to the right position ---
904
905 BIC R0,R4,#dbOpen_persist + dbOpen_nonSub
906 BL winUtils_setPosition ;Position the window nicely
907 TST R6,#dbFlag__static ;Is it static?
908 BEQ %40dbox_open ;No -- skip ahead a bit
909
910 ; --- Open a persistent dialogue box ---
911
912 SWI Wimp_OpenWindow ;Open the window
913 ADD R13,R13,#36 ;Reclaim the stack space
914
915 ; --- If the window was already open, quit now ---
916
917 TST R6,#dbFlag__open ;Is the dialogue box open
918 BNE %80dbox_open ;Yes -- skip past this bit
919
920 ; --- Now find out if there's a caret to handle ---
921
922 MOV R0,#-1 ;Start searching from start
923 MOV R1,#&0000E000 ;Find all Writable icons
924 MOV R2,#&0000E000 ;Only check button type bits
925 MOV R3,#+1 ;Search forwards
926 BL dbox__find ;Find the icon
927 CMP R0,#-1 ;Is there a writable icon?
928 BICEQ R6,R6,#dbFlag__rCaret ;Don't have to restore caret
929 BEQ %10dbox_open ;No -- skip ahead
930
931 ; --- Read the old caret position ---
932
933 ADD R1,R10,#dbox__oldCaret ;Point to old caret block
934 SWI Wimp_GetCaretPosition ;Read the current position
935 LDR R0,[R10,#dbox__window] ;Get the dialogue window
936 MOV R1,#-1 ;In no particular icon
937 MOV R2,#&ff000000 ;Quite a long way away
938 ORR R2,R2,#&00ff0000
939 MOV R3,#0 ;Doesn't really matter
940 MOV R4,#&02000000 ;Hide caret, make it small
941 MOV R5,#-1 ;No index into icon, please
942 SWI Wimp_SetCaretPosition ;Set the caret's position
943 ORR R6,R6,#dbFlag__rCaret ;Remember to restore caret
944
945 ; --- That's it, so finish things off ---
946
947 10dbox_open B %80dbox_open ;Perform wrapping-up actions
948
949 ; --- Open as a transient menu ---
950
951 40dbox_open LDR R1,[R10,#dbox__window] ;Get the window handle ready
952 SWI Wimp_CreateMenu ;Create it as a menu :-/
953 BIC R6,R6,#dbFlag__rCaret ;Don't restore the caret
954 ADD R13,R13,#36 ;Reclaim the stack we used
955 MOV R0,R1 ;Get the window handle again
956 BL transWin_register ;This is transient window
957 B %80dbox_open ;Perform wrapping-up actions
958
959 ; --- Open in the correct submenu position ---
960
961 60dbox_open LDR R0,[R10,#dbox__window] ;Load the window handle
962 BL transWin_openSub ;And display as submenu
963 LDR R6,[R10,#dbox__flags] ;Read the dialogue box flags
964 BIC R6,R6,#dbFlag__static :OR: dbFlag__rCaret
965
966 ; --- Wrap everything up now ---
967
968 80dbox_open ORR R6,R6,#dbFlag__open ;The window is at last open
969 STR R6,[R10,#dbox__flags] ;Store the flags away now
970 MOV R0,#dbEvent_lifeCycle ;A lifecycle event
971 MOV R1,#dblc_open ;Box has opened
972 BL dbox__dispatch ;Send a message
973 LDMFD R13!,{R0-R6,R10,R12,PC}^
974
975 LTORG
976
977 ; --- dbox_close ---
978 ;
979 ; On entry: R0 == dialogue box handle
980 ;
981 ; On exit: --
982 ;
983 ; Use: Closes a dialogue box, by clearing the current menu if
984 ; necessary.
985
986 EXPORT dbox_close
987 dbox_close ROUT
988
989 STMFD R13!,{R0-R6,R10,R12,R14} ;Save some registers away
990 WSPACE dbox__wSpace ;Locate my workspace
991 MOV R10,R0 ;Move dbox handle away
992
993 ; --- First things first -- check it's open ---
994
995 LDR R6,[R10,#dbox__flags] ;Get the dialogue's flags
996 TST R6,#dbFlag__open ;Is the open flag on?
997 BEQ %80dbox_close ;No -- skip forward
998
999 ; --- Now restore the caret if needs be ---
1000 ;
1001 ; Try not to be overly upset if we can't put the caret back.
1002 ; After all, the window may have closed by now. An X SWI
1003 ; is called for, and we ignore V on exit.
1004
1005 TST R6,#dbFlag__rCaret ;Does caret need restoring?
1006 BEQ %00dbox_close ;No -- skip forwards
1007 ADD R0,R10,#dbox__oldCaret ;Point to old caret block
1008 LDMIA R0,{R0-R5} ;Load the old caret state
1009 SWI XWimp_SetCaretPosition ;And try to put it back
1010
1011 ; --- Now handle transientness properly ---
1012
1013 00dbox_close TST R6,#dbFlag__static ;Is this a static dialogue?
1014 LDREQ R0,[R10,#dbox__window] ;Yes -- find the window
1015 BLEQ transWin_close ;And close it
1016 ADDNE R1,R10,#dbox__window ;Point to the window handle
1017 SWINE Wimp_CloseWindow ;Close the window now
1018
1019 BIC R6,R6,#dbFlag__open :OR: dbFlag__rCaret
1020 STR R6,[R10,#dbox__flags] ;Store flags away again
1021
1022 ; --- Send a lifecycle warning ---
1023
1024 MOV R0,#dbEvent_lifeCycle ;Get the event code
1025 MOV R1,#dblc_close ;Box has closed
1026 BL dbox__dispatch ;Send the event
1027
1028 80dbox_close LDMFD R13!,{R0-R6,R10,R12,PC}^ ;Return to caller
1029
1030 LTORG
1031
1032 ; --- dbox_writePos ---
1033 ;
1034 ; On entry: R0 == dialogue box handle
1035 ;
1036 ; On exit: --
1037 ;
1038 ; Use: Saves the dialogue's current position so that it will be
1039 ; opened here the next time it is created. If the dialogue
1040 ; box was created from a template, the template is updated.
1041 ; Otherwise, the new state is written back to the definition
1042 ; supplied to dbox_fromDefn.
1043
1044 EXPORT dbox_writePos
1045 dbox_writePos ROUT
1046
1047 STMFD R13!,{R0-R5,R10,R14} ;Save a load of registers
1048 MOV R10,R0 ;Keep the dialogue handle
1049 SUB R13,R13,#36 ;Make space on the stack
1050 LDR R14,[R10,#dbox__window] ;Get the dialogue's window
1051 STR R14,[R13,#0] ;Save in the block
1052 MOV R1,R13 ;Point to the block
1053 SWI Wimp_GetWindowState ;Get the window's position
1054 LDMIB R13,{R0-R5} ;Load pos and scroll settings
1055 LDR R14,[R10,#dbox__template] ;Find the template address
1056 CMP R14,#0 ;Is it actually there?
1057 CMPNE R14,#1 ;Check for embedded templates
1058 LDREQ R14,[R10,#dbox__defn] ;No -- just use definition
1059 STMIA R14,{R0-R5} ;Yes -- save them for later
1060 ADD R13,R13,#36 ;Reclaim the used stack space
1061 LDMFD R13!,{R0-R5,R10,PC}^ ;Return to caller
1062
1063 LTORG
1064
1065 ;----- Caret handling functions ---------------------------------------------
1066
1067 ; --- dbox__viewIcon ---
1068 ;
1069 ; On entry: R0 == an icon number
1070 ; R10 == dialogue box handle
1071 ;
1072 ; On exit: --
1073 ;
1074 ; Use: Scrolls the given dialogue box so that the specified icon
1075 ; is visible. The icon is assumed to be in the same position
1076 ; as it was when it was created.
1077 ;
1078 ; This is translated fairly literally from the STEEL code
1079 ; in dbox__nextWritable.
1080
1081 dbox__viewIcon ROUT
1082
1083 STMFD R13!,{R0-R9,R14} ;Save a load of registers
1084
1085 ; --- Locate the icon definition ---
1086
1087 BL dbox__icon ;Find the icon position
1088 MOV R9,R0 ;Keep a pointer to it
1089
1090 ; --- Find the window position ---
1091
1092 SUB R13,R13,#36 ;Make space for a window def
1093 LDR R14,[R10,#dbox__window] ;Find the dbox's window hnd
1094 STR R14,[R13,#0] ;Store it in the block
1095 MOV R1,R13 ;Point to the block
1096 SWI Wimp_GetWindowState ;Find the window information
1097
1098 ; --- Now read the window scroll positions ---
1099
1100 LDMIB R13,{R0-R5} ;Load window visible coords
1101
1102 SUB R0,R2,R0 ;R0 == window width
1103 SUB R1,R3,R1 ;R1 == window height
1104 ADD R2,R4,R0 ;R2 == window right hand side
1105 SUB R3,R5,R1 ;R3 == window bottom edge
1106 ;R4 == window left hand side
1107 ;R5 == window top edge
1108
1109 LDMIA R9,{R6-R8,R14} ;Load icon coordinates nicely
1110
1111 SUB R6,R6,#24 ;Add a bit of extra around
1112 SUB R7,R7,#24
1113 ADD R8,R8,#24
1114 ADD R14,R14,#24
1115
1116 ; --- Bodge the scroll positions until icon is visible ---
1117 ;
1118 ; This section is fairly self-explanatory, and the comments
1119 ; are very dull.
1120
1121 CMP R7,R3
1122 ADDLT R5,R7,R1
1123 CMP R14,R5
1124 MOVGT R5,R14
1125 CMP R6,R4
1126 MOVLT R4,R6
1127 CMP R8,R2
1128 SUBGT R4,R8,R0
1129
1130 ; --- Now store the scroll offsets back and reopen ---
1131
1132 ADD R1,R13,#20 ;Point to scroll offsets
1133 STMIA R1,{R4,R5} ;Store them back in the block
1134 MOV R1,R13 ;Point to the block
1135 SWI Wimp_OpenWindow ;Now open the window nicely
1136
1137 ; --- Reclaim the stack and return ---
1138
1139 ADD R13,R13,#36
1140 LDMFD R13!,{R0-R9,PC}^ ;Return to caller
1141
1142 LTORG
1143
1144 ; --- dbox__moveCaret ---
1145 ;
1146 ; On entry: R0 == 0 to move relative to current input focus
1147 ; 1 to move absolute (for ctrl cursor keys)
1148 ; R1 == direction to move in (+1 or -1, if you've any sense)
1149 ; R10 == dialogue box handle
1150 ;
1151 ; On exit: --
1152 ;
1153 ; Use: Moves the caret between writable icons, responding to cursor
1154 ; key presses.
1155
1156 dbox__moveCaret ROUT
1157
1158 STMFD R13!,{R0-R5,R14} ;Save a few registers
1159
1160 ; --- Find out where the cursor is ---
1161
1162 SUB R13,R13,#24 ;Make way for a caret block
1163 MOV R1,R13 ;Point to it
1164 SWI Wimp_GetCaretPosition ;Find the caret nicely
1165
1166 ; --- Check this is the right window ---
1167
1168 LDMIA R13,{R0,R5} ;Get the input focus window
1169 LDR R14,[R10,#dbox__window] ;Get dialogue box window
1170 ADD R13,R13,#24 ;Reclaim that stack space
1171 CMP R0,R14 ;Do they match nicely?
1172 LDMNEFD R13!,{R0-R5,PC}^ ;No -- return to caller
1173
1174 ; --- Now set up a search for the icon ---
1175
1176 LDMIA R13,{R0,R3} ;Get the stacked start pos
1177 CMP R0,#0 ;Is it a zero?
1178 MOVNE R0,#-1 ;No -- start from one end
1179 MOVEQ R0,R5 ;Yes -- start from current
1180
1181 ; --- Load the icon flags to search for ---
1182
1183 MOV R2,#&0000E000 ;Find writable icons
1184 ORR R1,R2,#&00400000 ;Also check shaded bit
1185 BL dbox__find ;Find the icon nicely
1186 CMP R0,#-1 ;Did it find one?
1187 BLEQ dbox__find ;No -- search from one end
1188
1189 ; --- Now it's come up with the goods ---
1190
1191 CMP R0,#-1 ;Did it fail this time?
1192 CMPNE R0,R5 ;Or just come back again?
1193 LDMEQFD R13!,{R0-R5,PC}^ ;Yes -- nothing doing then
1194
1195 ; --- Scroll to make icon visible ---
1196
1197 BL dbox__viewIcon ;Scroll the window nicely
1198
1199 ; --- Set the caret position nicely ---
1200
1201 MOV R1,R0 ;Icon number to R1
1202 BL dbox__fieldLen ;Find the string length
1203 MOV R5,R0 ;This is icon text index
1204 MOV R4,#-1 ;Calculate things for me
1205 LDR R0,[R10,#dbox__window] ;Get the window handle
1206 SWI Wimp_SetCaretPosition ;Move the caret nicely now
1207
1208 LDMFD R13!,{R0-R5,PC}^ ;Return to caller at last
1209
1210 LTORG
1211
1212 ;----- Selecting and shading icons ------------------------------------------
1213
1214 ; --- dbox_select ---
1215 ;
1216 ; On entry: R0 == dialogue box handle
1217 ; R1 == icon number
1218 ; R2 == 0 to deselect the icon, 1 to select it, 2 to toggle
1219 ; its current selected state
1220 ;
1221 ; On exit: --
1222 ;
1223 ; Use: Selects or deselects the specified icon in the Acorn sense
1224 ; (i.e. by flipping its selected bit). The state is only
1225 ; changed if required, to reduce flicker.
1226
1227 EXPORT dbox_select
1228 dbox_select ROUT
1229
1230 STMFD R13!,{R0-R2,R14} ;Save some registers away
1231
1232 ; --- Find the old state ---
1233
1234 SUB R13,R13,#40 ;Make space for an icon block
1235 LDR R0,[R0,#dbox__window] ;Get the window handle
1236 STMIA R13,{R0,R1} ;Save the handles away
1237 MOV R1,R13 ;Point to the block
1238 SWI Wimp_GetIconState ;Find out about the icon
1239
1240 ; --- Find out the current selection state ---
1241
1242 LDR R14,[R13,#24] ;Load the flags word
1243 AND R14,R14,#&00200000 ;Clear all but the select bit
1244 CMP R2,#1 ;Are we to select the icon?
1245 MOVEQ R2,#&00200000 ;Yes -- set the select bit
1246 CMP R2,#2 ;Are we to toggle it?
1247 EOREQ R2,R14,#&00200000 ;Yes -- toggle it then
1248
1249 ; --- Make sure we need to do something ---
1250
1251 CMP R2,R14 ;Are the states the same?
1252 ADDEQ R13,R13,#40 ;Yes -- restore the stack
1253 LDMEQFD R13!,{R0-R2,PC}^ ;And return right now
1254
1255 ; --- Now change the icon state ---
1256
1257 ADD R0,R13,#8 ;Point to the flags masks
1258 MOV R14,#&00200000 ;Clear only the selected bit
1259 STMIA R0,{R2,R14} ;Save the masks in the block
1260 SWI Wimp_SetIconState ;Set the state nicely
1261
1262 ADD R13,R13,#40 ;Restore the stack nicely
1263 LDMFD R13!,{R0-R2,PC}^ ;Return to caller
1264
1265 LTORG
1266
1267 ; --- dbox_shade ---
1268 ;
1269 ; On entry: R0 == dialogue box handle
1270 ; R1 == icon number
1271 ; R2 == 0 to unshade the icon, 1 to shade it, 2 to toggle its
1272 ; current shaded state
1273 ;
1274 ; On exit: --
1275 ;
1276 ; Use: Makes the icon look dimmer, to indicate that it is not
1277 ; available. It uses its own shading algorithms, rather than
1278 ; the WindowManager's, so there are some things you must watch
1279 ; out for:
1280 ;
1281 ; * Don't use any other method of shading icons
1282 ;
1283 ; * Don't assume that a shaded icon isn't going to give you
1284 ; events. At the user level, this should have been tidied
1285 ; up, but at the Sapphire level, it's still a problem.
1286 ; There is a routine in winUtils which will tell you if an
1287 ; icon is shaded.
1288 ;
1289 ; This routine has been written so that it only flickers icons
1290 ; when they actually need it.
1291
1292 EXPORT dbox_shade
1293 dbox_shade ROUT
1294
1295 STMFD R13!,{R0-R6,R10,R14} ;Save a load of registers
1296
1297 ; --- Make sure we need to do something ---
1298
1299 MOV R10,R0 ;Look after the dbox handle
1300 MOV R0,R1 ;Get the original icon handle
1301 BL dbox__icon ;Find my cached icon defn
1302 MOV R4,R0 ;Look after this pointer
1303 LDR R6,[R4,#16] ;Load the icon's flags
1304 AND R5,R6,#&00400000 ;Leave only the selected bit
1305
1306 ; --- Work out what needs to be done ---
1307
1308 CMP R2,#1 ;Do we have to shade it?
1309 MOVEQ R2,#&00400000 ;Yes -- set the bit
1310 CMP R2,#2 ;Do we have to toggle it?
1311 EOREQ R2,R5,#&00400000 ;Yes -- get the toggled state
1312
1313 ; --- Now quit if there's nothing to do ---
1314
1315 CMP R2,R5 ;Are they the same now?
1316 LDMEQFD R13!,{R0-R6,R10,PC}^ ;Yes -- return right now
1317
1318 ; --- Find the old state from the icon ---
1319
1320 LDR R0,[R10,#dbox__window] ;Get the window handle
1321 SUB R13,R13,#40 ;Make way for an icon block
1322 STMIA R13,{R0,R1} ;Save window and icon handles
1323 MOV R1,R13 ;Point to the block
1324 SWI Wimp_GetIconState ;Get the icon information
1325 LDR R5,[R13,#24] ;Get the current icon flags
1326
1327 ; --- Now process the cached flags nicely ---
1328 ;
1329 ; We can just flip the bit now, because we know it must be
1330 ; different to its old state.
1331
1332 EOR R6,R6,#&00400000 ;Toggle the flag
1333 STR R6,[R4,#16] ;Store it back in the block
1334
1335 ; --- Now work out exactly what we have to do ---
1336
1337 TST R6,#&00400000 ;Are we meant to be shading?
1338 BEQ %50dbox_shade ;No -- unshade nicely
1339
1340 ; --- Lots of messing about with bitmasks ---
1341 ;
1342 ; We need to change the icon colours, the button type and
1343 ; the ESG number for text icons, and the shaded bit for
1344 ; sprite icons. If there's a sprite, or nothing at all, then
1345 ; we set the shaded bit. If there's text and a sprite, then
1346 ; we /don't/ do the text hacking if anti-aliased fonts are
1347 ; being used, since everything looks nasty.
1348
1349 MOV R0,#8 ;Read the font handle
1350 SWI XWimp_ReadSysInfo ;Read the handle then
1351 MOVVS R0,#0 ;Unknown -- not supported
1352
1353 AND R14,R5,#3 ;Get the contents bits
1354 TST R14,#2 ;Do we have a sprite?
1355 CMPNE R0,#0 ;And is there a font?
1356 TSTEQ R5,#&40 ;Or is the icon anti-aliased?
1357 BICNE R14,R14,#1 ;Yes -- clear text bit then
1358
1359 CMP R14,#1 ;Is it text only?
1360 ORRNE R5,R5,#&00400000 ;No -- set the shaded bit
1361 TST R14,#1 ;Does it contain text?
1362 BICNE R5,R5,#&0f100000 ;Clear foreg colour and ESG 5
1363 BICNE R5,R5,#&000ff000 ;Clear ESG and button type
1364 ORRNE R5,R5,#&02100000 ;Set foreg and ESG bit 5
1365 ORRNE R5,R5,#&000f0000 ;Set ESG to 31, leave btype
1366
1367 MOV R14,#-1 ;Clear all the flags bits
1368 ADD R0,R13,#8 ;Point to flags masks
1369 STMIA R0,{R5,R14} ;Store them in the block
1370 MOV R1,R13 ;Point to the block again
1371 SWI Wimp_SetIconState ;And `shade' the icon
1372
1373 ; --- Now make sure the caret's not in it ---
1374
1375 LDMIA R1,{R2,R3} ;Get the window and icon
1376 SWI Wimp_GetCaretPosition ;Find where the caret is
1377 LDMIA R1,{R4,R5} ;Get the focus window and icn
1378 CMP R2,R4 ;Check the windows match
1379 CMPEQ R3,R5 ;And check the icons match
1380 BNE %80dbox_shade ;If not, skip ahead a bit
1381
1382 ; --- Now kick the caret into cyberspace ---
1383
1384 LDMIA R1,{R0-R5} ;Load the caret registers
1385 MOV R1,#-1 ;Kick caret out of icon
1386 MOV R2,#&ff000000 ;Quite a long way away
1387 ORR R2,R2,#&00ff0000
1388 SWI Wimp_SetCaretPosition ;Set the new caret position
1389 B %80dbox_shade ;Tidy everything up
1390
1391 ; --- Now handle unshading -- this is easy :-/ ---
1392
1393 50dbox_shade BIC R6,R6,#&f000000f ;Clear some bits
1394 BIC R6,R6,#&00e00000 ;Clear some more bits
1395 BIC R6,R6,#&00000ff0 ;Clear yet more bits
1396
1397 BIC R5,R5,#&0f500000 ;Clear another load of bits
1398 BIC R5,R5,#&000ff000 ;And the last load of bits
1399
1400 ORR R5,R5,R6 ;Now merge them all together
1401 MOV R14,#-1 ;Update all of the flags
1402 ADD R0,R13,#8 ;Point to the flags masks
1403 STMIA R0,{R5,R14} ;Save the masks away
1404 SWI Wimp_SetIconState ;Now flicker the icon
1405
1406 ; --- Tidy everything up finally ---
1407
1408 80dbox_shade ADD R13,R13,#40 ;Restore the stack position
1409 LDR R0,[R10,#dbox__defn] ;Find the window definition
1410 LDR R0,[R0,#64] ;Load the sprite area pointer
1411 SWI XSculptrix_SetSpriteArea ;Set the sprite area up
1412 LDR R1,[R13,#4] ;Get the icon handle back
1413 LDR R0,[R10,#dbox__window] ;Get the window handle
1414 SWI XSculptrix_UpdateIcon ;And redraw the 3D border
1415 LDMFD R13!,{R0-R6,R10,PC}^ ;Return to caller
1416
1417 LTORG
1418
1419 ; --- dbox_selectMany ---
1420 ;
1421 ; On entry: R0 == dialogue box handle
1422 ; R1 == pointer to icon handle list, -1 terminated
1423 ; R2 == select action (0 == unselect, 1 == select, 2 == toggle)
1424 ;
1425 ; On exit: --
1426 ;
1427 ; Use: Changes the select state of a group of icons.
1428
1429 EXPORT dbox_selectMany
1430 dbox_selectMany ROUT
1431
1432 STMFD R13!,{R1,R3,R14} ;Save some registers
1433 MOV R3,R1 ;Remember this pointer
1434 00 LDR R1,[R3],#4 ;Load next icon handle
1435 CMP R1,#-1 ;Is it the end of the list?
1436 BLNE dbox_select ;No -- then do the select
1437 BNE %b00 ;And loop round again
1438 LDMFD R13!,{R1,R3,PC}^ ;And return to caller
1439
1440 LTORG
1441
1442 ; --- dbox_shadeMany ---
1443 ;
1444 ; On entry: R0 == dialogue box handle
1445 ; R1 == pointer to icon handle list, -1 terminated
1446 ; R2 == shade action (0 == unshade, 1 == shade, 2 == toggle)
1447 ;
1448 ; On exit: --
1449 ;
1450 ; Use: Changes the shade state of a group of icons.
1451
1452 EXPORT dbox_shadeMany
1453 dbox_shadeMany ROUT
1454
1455 STMFD R13!,{R1,R3,R14} ;Save some registers
1456 MOV R3,R1 ;Remember this pointer
1457 00 LDR R1,[R3],#4 ;Load next icon handle
1458 CMP R1,#-1 ;Is it the end of the list?
1459 BLNE dbox_shade ;No -- then do the select
1460 BNE %b00 ;And loop round again
1461 LDMFD R13!,{R1,R3,PC}^ ;And return to caller
1462
1463 LTORG
1464
1465 ; --- dbox_isSelected ---
1466 ;
1467 ; On entry: R0 == dialogue box handle
1468 ; R1 == icon number
1469 ;
1470 ; On exit: CS if the icon is selected, CC otherwise
1471 ;
1472 ; Use: Returns whether an icon is currently selected.
1473
1474 EXPORT dbox_isSelected
1475 dbox_isSelected ROUT
1476
1477 STMFD R13!,{R0,R1,R14} ;Save the registers away
1478 SUB R13,R13,#40 ;Make space for an icon block
1479 LDR R0,[R0,#dbox__window] ;Load the dialogue's window
1480 STMIA R13,{R0,R1} ;Store them in the block
1481 MOV R1,R13 ;Point to the block
1482 SWI Wimp_GetIconState ;Get the icon information
1483 LDR R14,[R13,#24] ;Load the icon flags
1484 ADD R13,R13,#40 ;Recover the stack space
1485 TST R14,#&00200000 ;Check the selected bit
1486 LDMFD R13!,{R0,R1,R14} ;Load the saved registers
1487 ORRNES PC,R14,#C_flag ;If flag set, return with CS
1488 BICEQS PC,R14,#C_flag ;Otherwise, clear carry
1489
1490 LTORG
1491
1492 ; --- dbox_radio ---
1493 ;
1494 ; On entry: R0 == dialogue box handle
1495 ; R1 == icon handle
1496 ;
1497 ; On exit: --
1498 ;
1499 ; Use: Checks to see if the icon is a radio button as defined by
1500 ; Sapphire, i.e. button type 3 (debounced) and non-zero ESG.
1501 ; If it is, it selects it, and deselects all other icons with
1502 ; this ESG.
1503
1504 EXPORT dbox_radio
1505 dbox_radio ROUT
1506
1507 STMFD R13!,{R0-R4,R9,R10,R14} ;Save some registers
1508 MOV R10,R0 ;Get the dialogue handle
1509 MOV R9,R1 ;Look after the icon number
1510
1511 ; --- Locate the icon and check it's a radio button ---
1512
1513 MOV R0,R1 ;Icon in R0 for dbox__icon
1514 BL dbox__icon ;Find the icon definition
1515 LDR R14,[R0,#16] ;Load the icon flags
1516 AND R4,R14,#&0000f000 ;Leave only the button type
1517 CMP R4,#&00003000 ;Make sure it's Debounced
1518 LDMNEFD R13!,{R0-R4,R9,R10,PC}^ ;No -- return right now
1519 ANDS R4,R14,#&001f0000 ;Leave only the ESG
1520 CMPNE R4,#&001f0000 ;Or 31 (i.e. it's shaded)
1521 LDMEQFD R13!,{R0-R4,R9,R10,PC}^ ;Yes -- return right now
1522
1523 ; --- The ESG is now in R4 -- process it ---
1524
1525 MOV R0,#-1 ;Start from the beginning
1526
1527 00dbox_radio MOV R1,#&001f0000 ;Mask out all but the ESG
1528 MOV R2,R4 ;Move ESG in to test it
1529 MOV R3,#+1 ;Search forwards nicely
1530 BL dbox__find ;Get the next matching icon
1531 CMP R0,#-1 ;None found?
1532 LDMEQFD R13!,{R0-R4,R9,R10,PC}^ ;Return to caller then
1533 MOV R1,R0 ;Icon number in R1 required
1534 MOV R0,R10 ;Dialogue box handle in R0
1535 CMP R1,R9 ;Is this the clicked icon?
1536 MOVEQ R2,#1 ;Yes -- select it
1537 MOVNE R2,#0 ;No -- deselect it
1538 BL dbox_select ;Change its selection state
1539 MOV R0,R1 ;Start search where we left
1540 B %00dbox_radio ;And loop round again
1541
1542 LTORG
1543
1544 ;----- Clicking and unclicking icons ----------------------------------------
1545
1546 ; --- dbox_slab ---
1547 ;
1548 ; On entry: R0 == dialogue box handle
1549 ; R1 == icon handle
1550 ;
1551 ; On exit: May return an error
1552 ;
1553 ; Use: Slabs an icon in properly, to give visual feedback when you
1554 ; click it.
1555
1556 EXPORT dbox_slab
1557 dbox_slab ROUT
1558
1559 STMFD R13!,{R0-R2,R12,R14} ;Save some registers away
1560 WSPACE dbox__wSpace ;Find my workspace pointer
1561
1562 ; --- Allocate a new block ---
1563
1564 MOV R0,#20 ;Make space for a new block
1565 BL sub_alloc ;Try to allocate the block
1566 BVS %90dbox_slab ;If it failed, skip forward
1567
1568 ; --- Link the block into the list ---
1569
1570 LDR R14,dbox__clickList ;Load the old list head
1571 STR R0,dbox__clickList ;Store this block as new head
1572 STR R14,[R0,#0] ;And store link to next one
1573
1574 ; --- Now actually slab the icon ---
1575
1576 ADD R2,R0,#4 ;Point to slab descriptor
1577 LDR R0,[R13,#0] ;Get the saved dbox handle
1578 LDR R0,[R0,#dbox__window] ;Get the window handle
1579 SWI XSculptrix_SlabIcon ;Slab the icon in nicely
1580 LDMFD R13!,{R0-R2,R12,PC}^ ;Return to caller
1581
1582 ; --- Tidy up after an error ---
1583
1584 90dbox_slab ADD R13,R13,#4 ;Skip past stacked R0
1585 LDMFD R13!,{R1,R2,R12,R14} ;Load the saved registers
1586 ORRS PC,R14,#V_flag ;Set V flag on exit
1587
1588 LTORG
1589
1590 ; --- dbox_unslab ---
1591 ;
1592 ; On entry: --
1593 ;
1594 ; On exit: CS if there are no more slabbed icons after this one, CC
1595 ; if there are more left.
1596 ;
1597 ; Use: Unslabs an icon slabbed with dbox_slab. Icons are unslabbed
1598 ; in reverse order to that in which they were slabbed. The
1599 ; carry flag is returned as an indication of whether there
1600 ; are any more icons left in the list -- you can unslab all
1601 ; icons in one go by doing:
1602 ;
1603 ; BL dbox_unslab
1604 ; SUBCC PC,PC,#12 ;Avoids a label!
1605 ;
1606 ; It is recommended that, if you are going to close a window,
1607 ; you unslab icons within it *after* you close, but before you
1608 ; actually destroy it, e.g.
1609 ;
1610 ; LDR R0,my_dbox
1611 ; BL dbox_close
1612 ; BL dbox_unslab
1613 ; BL dbox_destroy
1614
1615 EXPORT dbox_unslab
1616 dbox_unslab ROUT
1617
1618 STMFD R13!,{R0-R2,R12,R14} ;Save some registers away
1619 WSPACE dbox__wSpace ;Find my workspace pointer
1620 LDR R1,dbox__clickList ;Find the last slabbed icon
1621
1622 ; --- Get the descriptor to free ---
1623
1624 CMP R1,#0 ;Is there one at all?
1625 LDMEQFD R13!,{R0-R2,R12,R14} ;No -- restore the registers
1626 ORREQS PC,R14,#C_flag ;And return with C set
1627
1628 ; --- Unslab the icon and unlink the block ---
1629 ;
1630 ; Make sure the hourglass stays off all this time.
1631
1632 ADD R2,R1,#4 ;Point to the slab descriptor
1633 SUB R13,R13,#8 ;Make an hourglass status blk
1634 MOV R0,R13 ;Point to the block
1635 BL hour_suspend ;Save the old state a while
1636 SWI XSculptrix_UnslabIcon ;Unslab the icon nicely
1637 BL hour_resume ;Resume the hourglass now
1638 ADD R13,R13,#8 ;And restore the stack
1639 LDR R2,[R1,#0] ;Get the next field out
1640 STR R2,dbox__clickList ;Store it as the new head
1641
1642 ; --- Free the block now ---
1643
1644 MOV R0,R1 ;Point to the slab block
1645 MOV R1,#20 ;suballoc wants the size
1646 BL sub_free ;Free the block again
1647
1648 ; --- Now return the status to the user ---
1649
1650 CMP R2,#0 ;Was the next block null?
1651 LDMFD R13!,{R0-R2,R12,R14} ;Restore all the registers
1652 ORREQS PC,R14,#C_flag ;Yes -- return and set C
1653 BICNES PC,R14,#C_flag ;No -- return and clear C
1654
1655 LTORG
1656
1657 ;----- Messing with dialogue box fields -------------------------------------
1658
1659 ; --- dbox__fieldLen ---
1660 ;
1661 ; On entry: R1 == icon number
1662 ; R10 == dialogue box handle
1663 ;
1664 ; On exit: R0 == length of the text in the icon
1665 ;
1666 ; Use: Returns the length of the field in the given icon
1667
1668 dbox__fieldLen ROUT
1669
1670 STMFD R13!,{R1,R14} ;Save some registers
1671
1672 ; --- Find the icon definition ---
1673
1674 SUB R13,R13,#40 ;Make space for icon block
1675 LDR R0,[R10,#dbox__window] ;Get the window handle
1676 STMIA R13,{R0,R1} ;Store handles in block
1677 MOV R1,R13 ;Point at the block
1678 SWI Wimp_GetIconState ;Find the *current* icon info
1679
1680 ; --- Get the icon flags and find the data ---
1681
1682 LDR R0,[R13,#24] ;Load the flags word
1683 ANDS R0,R0,#1<<8 ;Check indir flag (clever)
1684 BEQ %10dbox__fieldLen ;Yes -- skip ahead a bit
1685
1686 ; --- Handle indirectedness ---
1687
1688 LDR R0,[R13,#28] ;Load the icon data pointer
1689 ADD R13,R13,#40 ;Reclaim the stack block
1690 LDMFD R13!,{R1,R14} ;Unstack the registers
1691 B str_len ;Find the string length
1692
1693 ; --- Handle nonindirectedness ---
1694 ;
1695 ; We know at this point that R0 is 0, because we used ANDS
1696 ; not TST above. This is a pointless optimisation.
1697
1698 10 ADD R1,R13,#28 ;Point to the data string
1699 11 LDRB R14,[R1],#1 ;Get a byte from the string
1700 CMP R14,#' ' ;Is it the end yet?
1701 BLT %12dbox__fieldLen ;Yes -- skip forward
1702 ADD R0,R0,#1 ;Bump on the counter
1703 CMP R0,#12 ;Is it maximum length yet?
1704 BLT %11dbox__fieldLen ;No -- skip back again
1705
1706 ; --- Return the calculated length ---
1707
1708 12 ADD R13,R13,#40 ;Reclaim the stack again
1709 LDMFD R13!,{R1,PC}^ ;Return to caller
1710
1711 LTORG
1712
1713 ; --- dbox_setField ---
1714 ;
1715 ; On entry: R0 == dialogue box handle
1716 ; R1 == icon number to write to (may be -1 for title)
1717 ; flags in top byte if not -1:
1718 ; dbFlag_dots (bit 31) == add `...' if text overflows
1719 ; R2 == pointer to string to use
1720 ;
1721 ; On exit: --
1722 ;
1723 ; Use: Writes the string specified into the indirection buffer
1724 ; for the given icon. If the icon is not indirected, an
1725 ; error is generated. If the indirected buffer is too small,
1726 ; the string is shortened by chopping off the beginning or
1727 ; the end, according to the setting of the icon's right
1728 ; justify flag.
1729 ;
1730 ; The icon is only flickered if the text has actually changed.
1731 ; The caret is moved correctly if it is within the icon to
1732 ; prevent it `falling off' the end and deleting the validation
1733 ; string, or being positioned incorrectly in centred icons if
1734 ; the length changes.
1735 ;
1736 ; Note that this routine requires a string to already be in
1737 ; the buffer, and doesn't perform any substitution or other
1738 ; transformations. This helps to prevent buffer full errors
1739 ; and similar problems.
1740
1741 EXPORT dbox_setField
1742 dbox_setField ROUT
1743
1744 STMFD R13!,{R0-R5,R14} ;Stash registers away
1745
1746 ; --- Handle the title bar nicely ---
1747
1748 CMP R1,#-1 ;Does he want the title?
1749 BEQ %30dbox_setField ;Yes -- jump ahead to do it
1750
1751 ; --- Find out about the icon ---
1752
1753 AND R4,R1,#&FF000000 ;Get the flag bits out
1754 BIC R1,R1,#&FF000000 ;Leave just the icon number
1755 LDR R0,[R0,#dbox__window] ;Get the dbox's window handle
1756 SUB R13,R13,#40 ;Make space for icon block
1757 STMIA R13,{R0,R1} ;Store the info in it
1758 MOV R1,R13 ;Point to the icon block
1759 SWI Wimp_GetIconState ;Get the icon's information
1760
1761 ; --- Make sure we can change the text ---
1762
1763 LDR R1,[R13,#24] ;Get the icon's flags
1764 TST R1,#&100 ;Check the indirected bit
1765 BEQ %80dbox_setField ;It's an error if it's clear
1766
1767 ; --- Now find how much we actually have to copy ---
1768
1769 LDR R5,[R13,#36] ;Get the buffer length
1770 SUB R5,R5,#1 ;Take terminator into account
1771 MOV R0,R2 ;Point to the string to copy
1772 BL str_len ;Find out how long it is
1773 SUBS R0,R0,R5 ;Find out the difference
1774 BICLE R4,R4,#(1<<31) ;If it fits, don't add dots
1775 BLE %00dbox_setField ;And skip ahead
1776 TST R1,#1<<9 ;Is it right aligned?
1777 ADDNE R2,R2,R0 ;Yes, chop off front
1778 ORRNE R4,R4,#1 ;And set a flag to remember
1779
1780 ; --- Copy the text into the buffer ---
1781
1782 00dbox_setField LDR R0,[R13,#28] ;Find the buffer address
1783 MOV R3,#0 ;Count the length too
1784
1785 10dbox_setField CMP R5,R3 ;How much space left in buff?
1786 MOVLE R1,#0 ;None -- pretend null char
1787 LDRGTB R1,[R2],#1 ;Get a byte from the string
1788 CMP R1,#' ' ;Is it a control char?
1789 MOVLO R1,#0 ;Yes -- say it's a zero
1790 BLO %15dbox_setField ;And don't bother with dots
1791
1792 ; --- Handle ellipsis generation ---
1793
1794 TST R4,#(1<<31) ;Do we put the ellipsis in?
1795 BEQ %15dbox_setField ;No -- skip ahead then
1796 TST R4,#1 ;Are we right-justified?
1797 ADDNE R14,R3,#1 ;Yes -- just get the length
1798 SUBEQ R14,R5,R3 ;Otherwise find what's left
1799 CMP R14,#4 ;Are we within three?
1800 MOVLO R1,#'.' ;Yes -- put in a dot then
1801
1802 ; --- Return to normality ---
1803
1804 15dbox_setField LDRB R14,[R0],#1 ;Get one from the buffer
1805 CMP R14,#' ' ;Same for the buffer char
1806 MOVLO R14,#0
1807
1808 CMP R1,R14 ;Are they different
1809 ORRNE R4,R4,#2 ;Yes -- remember this
1810 STRNEB R1,[R0,#-1] ;And store the different char
1811
1812 CMP R1,#0 ;Is that end of the string?
1813 ADDNE R3,R3,#1 ;No -- bump the length on
1814 BNE %10dbox_setField ;And go round for another
1815
1816 ; --- We've copied the string -- now update the icon ---
1817
1818 TST R4,#2 ;Is the string different?
1819 BEQ %20dbox_setField ;No -- skip ahead
1820
1821 MOV R1,#0
1822 STR R1,[R13,#8] ;The EOR mask for setstate
1823 STR R1,[R13,#12] ;The BIC mask for setstate
1824 MOV R1,R13 ;Point to the block
1825 SWI Wimp_SetIconState ;Flicker the icon nastily
1826
1827 ; --- Now check for the caret ---
1828
1829 SWI Wimp_GetCaretPosition ;Find out where the caret is
1830 LDMIA R13,{R2,R4} ;Get the window and icon
1831 ADD R0,R13,#40 ;Point past this block
1832 LDMIA R0,{R0,R1} ;Get the old dbox and icon
1833 LDR R0,[R0,#dbox__window] ;Get the window handle
1834 CMP R0,R2 ;Do the window handles match?
1835 CMPEQ R1,R4 ;And the icon handles?
1836 BNE %20dbox_setField ;No -- skip ahead
1837
1838 ; --- Push the caret back a little ---
1839
1840 LDR R5,[R13,#20] ;Get the caret index
1841 CMP R5,R3 ;Is this bigger than new len?
1842 MOVGT R5,R3 ;Yes -- trim the index
1843
1844 ; --- Now put the caret in the right place ---
1845
1846 MOV R2,#-1 ;Don't set the x coord
1847 MOV R3,#-1 ;Don't set the y coord
1848 MOV R4,#-1 ;Don't set the height
1849 SWI Wimp_SetCaretPosition ;Put the caret in its place
1850
1851 ; --- Return nicely ---
1852
1853 20dbox_setField ADD R13,R13,#40 ;Reclaim that temporary space
1854 LDMFD R13!,{R0-R5,PC}^ ;Return to caller
1855
1856 ; --- Caller wants to update the title bar ---
1857
1858 30dbox_setField LDR R14,[R0,#dbox__defn] ;Load the window definition
1859 LDR R5,[R14,#56] ;Load the title bar's flags
1860 TST R5,#&00000100 ;Check the indirected bit
1861 BEQ %80dbox_setField ;If clear, generate the error
1862
1863 LDR R1,[R14,#72] ;Load the buffer pointer
1864 LDR R2,[R0,#dbox__window] ;Load the window handle
1865 LDR R0,[R13,#8] ;Load the string pointer
1866 BL winUtils_setTitle ;And set the title string
1867 LDMFD R13!,{R0-R5,PC}^ ;Return to caller
1868
1869 ; --- Icon wasn't indirected ---
1870
1871 80dbox_setField ADR R0,dbox__nind ;Point to error
1872 BL msgs_error ;Translate the message
1873 SWI OS_GenerateError
1874
1875 dbox__nind DCD 1
1876 DCB "dboxNIND",0
1877
1878 LTORG
1879
1880 ; --- dbox_getField ---
1881 ;
1882 ; On entry: R0 == dialogue box handle
1883 ; R1 == icon number to interrogate
1884 ;
1885 ; On exit: R0, R1 preserved
1886 ; R2 == pointer to the icon text
1887 ;
1888 ; Use: Returns a pointer to the text associated with an icon.
1889 ; Note that if the icon is *not* indirected, the text will
1890 ; be copied into the scratchpad. Otherwise you get a pointer
1891 ; to the actual indirected data. You shouldn't write to the
1892 ; string returned at all -- dbox_setField is specially
1893 ; designed to do that sort of thing very well (i.e. not
1894 ; flickering the text unless it has to, truncating if it's too
1895 ; long, and handling the caret correctly). You *are* allowed
1896 ; to zero terminate the string if you want to, though.
1897 ;
1898 ; Despite all the PRM's assurances to the contrary, chances
1899 ; are the text will be terminated by some weird control char,
1900 ; so you'll have to handle this, and not just assume it's
1901 ; going to be null-terminated.
1902 ;
1903 ; Note: The indirected case is immensely quick -- just load a
1904 ; pointer. The non-indirected case has been optimised as much
1905 ; as possible.
1906
1907 EXPORT dbox_getField
1908 dbox_getField ROUT
1909
1910 STMFD R13!,{R0,R1,R10,R14} ;Save some registers
1911
1912 ; --- Find the icon defintion ---
1913
1914 MOV R10,R0 ;Keep dialogue box handle
1915 MOV R0,R1 ;Put icon handle in R0
1916 BL dbox__icon ;Find icon definition
1917
1918 ; --- Find out about indirectedness ---
1919
1920 LDR R14,[R0,#16] ;Load the icon flags word
1921 TST R14,#1<<8 ;Is the bit set?
1922 LDRNE R2,[R0,#20] ;Yes -- load the pointer
1923 LDMNEFD R13!,{R0,R1,R10,PC}^ ;And return
1924
1925 ; --- Copy the text to the scratchpad ---
1926
1927 ADD R0,R0,#20 ;Point to the text string
1928 LDMIA R0,{R0,R1,R14} ;Load the 12 bytes of text
1929 STMIA R11,{R0,R1,R14} ;Store them in scratchpad
1930 MOV R0,#0 ;Zero terminate nicely
1931 STRB R0,[R11,#12] ;In case string is too long
1932 MOV R2,R11 ;Point to string in scratch
1933 LDMFD R13!,{R0,R1,R10,PC}^ ;Return to caller
1934
1935 LTORG
1936
1937 ;---- Other utility functions -----------------------------------------------
1938
1939 ; --- dbox_eventHandler ---
1940 ;
1941 ; On entry: R0 == dialogue box handle
1942 ; R1 == pointer to handler routine
1943 ; R2 == value to pass to handler in R10
1944 ; R3 == value to pass to handler in R12
1945 ;
1946 ; On exit: R0 preserved
1947 ; R1 == pointer to old handler
1948 ; R2 == old R10 value
1949 ; R3 == old R12 value
1950 ;
1951 ; Use: Sets up an event handler for a dialogue box, and returns
1952 ; the previous one. If the pointer to handler is 0, there is
1953 ; no dialogue box event handler.
1954
1955 EXPORT dbox_eventHandler
1956 dbox_eventHandler
1957 ROUT
1958
1959 STMFD R13!,{R4-R6,R14} ;Save some registers
1960 LDR R14,[R0,#dbx__defn] ;Load the dbx pointer
1961 CMP R14,#0 ;Is there a dbx definition?
1962 ADDEQ R14,R0,#dbox__proc ;Point to the correct user...
1963 ADDNE R14,R0,#dbx__proc ;... handler
1964 LDMIA R14,{R4-R6} ;Load the old values out
1965 STMIA R14,{R1-R3} ;Store the new ones in
1966 MOV R1,R4 ;Move the old values to...
1967 MOV R2,R5 ;... the correct registers...
1968 MOV R3,R6 ;... for returning
1969 LDMFD R13!,{R4-R6,PC}^ ;Return to caller
1970
1971 LTORG
1972
1973 ; --- dbox_renderTitle ---
1974 ;
1975 ; On entry: R0 == dialogue box handle
1976 ; R1 == pointer to redraw block
1977 ;
1978 ; On exit: --
1979 ;
1980 ; Use: Renders a dialogue box's embedded title if there is one.
1981
1982 EXPORT dbox_renderTitle
1983 dbox_renderTitle
1984 ROUT
1985
1986 STMFD R13!,{R0-R3,R10,R14} ;Save a load of registers
1987
1988 MOV R10,R0 ;Move the handle into R10
1989 LDR R0,[R10,#dbox__title] ;Get the icon number out
1990 CMP R0,#-1 ;Check there really is one
1991 LDMEQFD R13!,{R0-R3,R10,PC}^ ;Return to caller if not
1992
1993 BL dbox__icon ;Find the icon pointer
1994 MOV R2,#0 ;Group box type 0, please
1995 LDR R3,[R10,#dbox__defn] ;Find the window definition
1996 LDR R3,[R3,#72] ;Get the actual data pointer
1997 SWI XSculptrix_PlotGroupBox ;Draw the group box
1998
1999 LDMFD R13!,{R0-R3,R10,PC}^ ;Return to caller now
2000
2001 LTORG
2002
2003 ; --- dbox_setEmbeddedTitle ---
2004 ;
2005 ; On entry: R0 == dialogue box handle
2006 ; R1 == icon which should contain the embedded title
2007 ;
2008 ; On exit: --
2009 ;
2010 ; Use: Declares a given dialogue box as requiring an embedded title
2011 ; (rather than the one the WindowManager put on).
2012
2013 EXPORT dbox_setEmbeddedTitle
2014 dbox_setEmbeddedTitle
2015 STR R1,[R0,#dbox__title] ;Store the icon number
2016 MOVS PC,R14
2017
2018 ; --- dbox_setClickDrag ---
2019 ;
2020 ; On entry: R0 == dialogue box handle
2021 ;
2022 ; On exit: --
2023 ;
2024 ; Use: Sets a given dialogue box so that the user can move it by
2025 ; dragging from any part of the window, not just the title
2026 ; bar.
2027
2028 EXPORT dbox_setClickDrag
2029 dbox_setClickDrag
2030 STMFD R13!,{R14} ;Save a register
2031 LDR R14,[R0,#dbox__flags] ;Load the flags word
2032 ORR R14,R14,#dbFlag__drag ;Set the click-drag flag
2033 STR R14,[R0,#dbox__flags] ;Save the flags back again
2034 LDMFD R13!,{PC}^ ;Return to caller
2035
2036 ; --- dbox_hasTitle ---
2037 ;
2038 ; On entry: R0 == dialogue box handle
2039 ;
2040 ; On exit: CS if the dialogue box has a title bar, CC if not
2041 ;
2042 ; Use: Informs the caller whether the dialogue box has a title bar.
2043 ; This is mainly useful for other library sections which
2044 ; conditionally add in embedded titles etc.
2045
2046 EXPORT dbox_hasTitle
2047 dbox_hasTitle ROUT
2048
2049 STMFD R13!,{R14} ;Save a register
2050 LDR R14,[R0,#dbox__defn] ;Load the window definition
2051 LDR R14,[R14,#28] ;Load the window flags
2052 TST R14,#1<<31 ;Using new gadget flags?
2053 BEQ %10dbox_hasTitle ;No -- skip to handle this
2054 TST R14,#1<<26 ;Test the title bar flag
2055 B %20dbox_hasTitle ;And skip the other test
2056
2057 10dbox_hasTitle TST R14,#1<<0 ;Test the old-fashioned bit
2058
2059 20dbox_hasTitle LDMFD R13!,{R14} ;Restore the register I saved
2060 ORRNES PC,R14,#C_flag ;If bit set, return carry
2061 BICEQS PC,R14,#C_flag ;Otherwise clear carry
2062
2063 LTORG
2064
2065 ; --- dbox_window ---
2066 ;
2067 ; On entry: R0 == dialogue box handle
2068 ;
2069 ; On exit: R0 == the dialogue box's window handle
2070 ;
2071 ; Use: Returns the Wimp window handle associated with a dialogue
2072 ; box. This may be useful if you want to perform lowlevel
2073 ; Wimp operation on it, or to subclass it using win.
2074
2075 EXPORT dbox_window
2076 dbox_window LDR R0,[R0,#dbox__window] ;Load the window handle
2077 MOVS PC,R14 ;Return to caller
2078
2079 ; --- dbox_help ---
2080 ;
2081 ; On entry: --
2082 ;
2083 ; On exit: --
2084 ;
2085 ; Use: Adds a help line to the current help message, read by
2086 ; scanning the icon to which the help was sent for an `H'
2087 ; validation string.
2088
2089 EXPORT dbox_help
2090 dbox_help ROUT
2091
2092 STMFD R13!,{R0-R4,R10,R12,R14} ;Save some registers
2093 WSPACE dbox__wSpace ;Find my workspace quickly
2094
2095 LDR R10,dbox__eventDbox ;Find the helpful dbox
2096 LDR R0,dbox__eventIcon ;Find the icon too
2097 CMP R0,#0 ;Is it a sensible number?
2098 BLT %99dbox_help ;No -- skip to the end
2099
2100 ; --- Locate the validation string ---
2101
2102 BL dbox__icon ;Find the icon definition
2103 MOV R1,#'H' ;Find `H' validation commands
2104 MOV R2,#0 ;Start from the beginning
2105 BL winUtils_findValid ;Find the validation string
2106 BCC %99dbox_help ;If not there, skip to end
2107
2108 ; --- Copy the message tag to scratchpad ---
2109
2110 MOV R0,R11 ;Point to scratchpad
2111 MOV R1,#0 ;We are not escaped yet
2112 ADD R2,R2,#1 ;Skip past `H' character
2113
2114 10dbox_help LDRB R14,[R2],#1 ;Get the next byte
2115
2116 CMP R14,#'\' ;Is it a backslash?
2117 CMPEQ R1,#0 ;Make sure it's not escaped
2118 MOVEQ R1,#1 ;Yes -- escape next char
2119 BEQ %10dbox_help ;And loop for next char
2120
2121 CMP R14,#' ' ;Is it a control character
2122 MOVLT R14,#0 ;Yes -- terminate string
2123 CMP R14,#';' ;Is it validation string end?
2124 CMPEQ R1,#0 ;Make sure it's not escaped
2125 MOVEQ R14,#0 ;Yes -- terminate string
2126 STRB R14,[R0],#1 ;Store character in buffer
2127 CMP R14,#0 ;Was that the end?
2128 BNE %10dbox_help ;No -- try for another one
2129
2130 ; --- Send the message to !Help ---
2131
2132 MOV R0,R11 ;Point to buffer start again
2133 BL msgs_lookup ;Lookup the message tag
2134 BL help_add ;Add it to the help message
2135
2136 99dbox_help LDMFD R13!,{R0-R4,R10,R12,PC}^ ;No -- return right now
2137
2138 LTORG
2139
2140 ;----- Useful constants -----------------------------------------------------
2141
2142 ; --- Ways of opening dialogue boxes ---
2143
2144 ^ 0
2145 dbOpen_current # 1 ;In its current position
2146 dbOpen_centre # 1 ;Centred on the screen
2147 dbOpen_pointer # 1 ;Centred over the pointer
2148 dbOpen_givenY # 1 ;At a given height on screen
2149 ; R2 == y coordinate to open
2150
2151 dbOpen_trans EQU &00 ;Make the dbox transient
2152 dbOpen_persist EQU &80 ;Make the dbox persistent
2153 dbOpen_nonSub EQU &40 ;Don't open as a submenu
2154
2155 ; --- Dialogue box event codes ---
2156
2157 dbEvent_close EQU -2 ;The user closed the dialogue
2158 ;C flag ignored on exit
2159
2160 dbEvent_help EQU -3 ;The user wants some help
2161 ;R1 == icon number
2162 ;C flag ignored on exit
2163
2164 dbEvent_OK EQU -4 ;The user clicked OK
2165 ;R1 == mouse button status
2166 ;C flag ignored on exit
2167
2168 dbEvent_cancel EQU -5 ;The user clicked Cancel
2169 ;R1 == mouse button status
2170 ;C flag ignored on exit
2171
2172 dbEvent_redraw EQU -6 ;Redraw a single rectangle
2173 ;R1 == pointer to redraw blk
2174 ;R2,R3 == coords of origin
2175 ;CS => don't do default draw
2176
2177 dbEvent_menu EQU -7 ;User clicked Menu button
2178 ;R1 == icon handle clicked
2179 ;C flag ignored on exit
2180
2181 dbEvent_drag EQU -8 ;User dragged an icon
2182 ;R1 == mouse button status
2183 ;R2 == icon handle dragged
2184 ;C flag ignored on exit
2185
2186 dbEvent_save EQU -9 ;User wants to import data
2187 ;R1 == icon handle dropped on
2188 ;R2 == filetype of data
2189 ;R3 == pointer to filename
2190 ;R4 == estimated file size
2191 ;C flag ignored on exit
2192
2193 dbEvent_load EQU -10 ;User wants to load data
2194 ;R1 == icon handle dropped on
2195 ;R2 == filetype of data
2196 ;R3 == pointer to filename
2197 ;R4 == estimated file size
2198 ;C flag ignored on exit
2199
2200 dbEvent_key EQU -11 ;User pressed a key
2201 ;R1 == key code received
2202 ;R2 == icon handle with caret
2203 ;CC => unknown keypress
2204 ;Key code has been translated
2205
2206 dbEvent_hint EQU -12 ;Received a hint message
2207 ;R2 == pointer to hint string
2208
2209 dbEvent_enter EQU -13 ;Pointer has entered window
2210
2211 dbEvent_leave EQU -14 ;Pointer has left window
2212
2213 dbEvent_lifeCycle EQU -15 ;Interesting points in cycle
2214 ;R1 == life cycle code
2215
2216 ; --- Life cycle codes ---
2217
2218 ^ 0
2219 dblc_create # 1 ;Creation (used by dbx)
2220 dblc_open # 1 ;Opening
2221 dblc_close # 1 ;Closing
2222 dblc_destroy # 1 ;Destruction
2223
2224 ; --- Other values ---
2225
2226 dbFlag_dots EQU (1<<31) ;Add dots if text overflows
2227 ; in dbox_setField
2228
2229 ;----- Dialogue box data structure ------------------------------------------
2230
2231 ^ 0
2232
2233 dbox__window # 4 ;The real window handle
2234 dbox__proc # 4 ;Pointer to event handler
2235 dbox__R10 # 4 ;Magic handle for event proc
2236 dbox__R12 # 4 ;Workspace for event proc
2237 dbox__oldCaret # 24 ;Caret position to restore
2238 dbox__defn # 4 ;Pointer to window template
2239 dbox__template # 4 ;Pointer to original template
2240 dbox__title # 4 ;Embedded title icon number
2241 dbox__flags # 4 ;Various interesting flags
2242
2243 dbx__proc # 4 ;Pointer to user event proc
2244 dbx__R10 # 4 ;Object pointer for user proc
2245 dbx__R12 # 4 ;Workspace for user proc
2246 dbx__defn # 4 ;Pointer to control def block
2247
2248 dbox__blockSize # 0 ;Size of the above block
2249
2250 dbFlag__open EQU (1<<0) ;Dialogue box is on-screen
2251 dbFlag__static EQU (1<<1) ;Dialogue box is static
2252 dbFlag__rCaret EQU (1<<2) ;We have to restore the caret
2253 dbFlag__drag EQU (1<<3) ;Clicking window starts move
2254
2255 ;----- Workspace ------------------------------------------------------------
2256
2257 ^ 0,R12
2258 dbox__wStart # 0
2259
2260 dbox__wFlags # 4 ;Various magic flags for me
2261 dbox__clickList # 4 ;List of button slabbings
2262 dbox__eventDbox # 4 ;Dbox last event happened to
2263 dbox__eventIcon # 4 ;Icon number from last event
2264
2265 dbFlag__inited EQU (1<<0) ;The dbox system is running
2266
2267 dbox__wSize EQU {VAR}-dbox__wStart
2268
2269 AREA |Sapphire$$LibData|,CODE,READONLY
2270
2271 DCD dbox__wSize
2272 DCD dbox__wSpace
2273 DCD 16
2274 DCD dbox_init
2275
2276 ;----- That's all, folks ----------------------------------------------------
2277
2278 END