Initial revision
[ssr] / StraySrc / SDLS / !DLLMerge / s / dllmerge
1 ;
2 ; dllmerge.s
3 ;
4 ; Merge two DLL resources together (MDW)
5 ;
6 ; © 1994-1998 Straylight
7 ;
8
9 ;----- Licensing note -------------------------------------------------------
10 ;
11 ; This file is part of Straylight's Dynamic Linking System (SDLS)
12 ;
13 ; SDLS 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 ; SDLS 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 SDLS. If not, write to the Free Software Foundation,
25 ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26
27 ;----- Change history -------------------------------------------------------
28 ;
29 ; Version By Change
30 ;
31 ; 1.00 MDW Initial version written.
32 ;
33 ; 1.01 MDW Added error handler to stop bombing out on errors.
34 ;
35 ; 1.02 MDW Done copyright and version messages with setdate.
36 ;
37 ; 1.03 MDW Made most SWIs generate errors, and added confirm
38 ; on error handler.
39 ;
40 ; 1.04 MDW Updated dm_setField in line with Sapphire version.
41 ;
42 ; 1.05 MDW Moved menu definition into code area, and copied it
43 ; out at run-time, for the sake of tidiness. Workspace
44 ; now *exactly* &0900 bytes!
45 ;
46 ; 1.06 MDW Used embedded templates instead of separate file.
47 ;
48 ; 1.07 MDW Fixed problem identifying !DLLs folder link dragged
49 ; from Kysmet -- it was returning &FC0 as the filetype,
50 ; instead of &1000/&2000 as expected. I now check
51 ; the type with OS_File instead of relying on the
52 ; type in the message.
53 ;
54 ; 1.08 MDW Reduced size of prompt in `merge' template and
55 ; indirected data buffer. Image now less than 4K.
56 ; Made some other space-saving modifications, although
57 ; I can't reduce the memory requirements to less than
58 ; 8K, which is a shame.
59 ;
60 ; 1.09 MDW Changed LDRs to ADRs when finding version and
61 ; copyright strings, now that the linker can handle it.
62 ;
63 ; 1.10 MDW Moved all messages into a separate file so it can
64 ; be easily changed for different countries should the
65 ; need arise. This is converted to an AOF file and
66 ; linked in during the build.
67 ;
68 ; 1.11 MDW Changed dm_error to base filler strings on `%0' not
69 ; `%1', and updated messages in line with this.
70
71 ;----- Standard header ------------------------------------------------------
72
73 GET libs:header
74 GET libs:swis
75
76 GET libs:stream
77
78 ;----- External dependencies ------------------------------------------------
79
80 ; --- Embedded template handling ---
81
82 GET libs:embTemp.sh.embTemp
83
84 ; --- Linker symbols ---
85
86 IMPORT |Image$$RW$$Limit|
87
88 ; --- Linked resources ---
89
90 GET sh.templates
91 GET sh.messages
92
93 ; --- Generated strings ---
94
95 IMPORT version
96 IMPORT cright
97
98 ;----- Macros ---------------------------------------------------------------
99
100 MACRO
101 $label TWELVE $string
102 ASSERT :LEN:"$string"<=12
103 ALIGN
104 $label DCB "$string"
105 % 12-:LEN:"$string"
106 MEND
107
108 ;----- Icon numbers ---------------------------------------------------------
109
110 dm_INFO_NAME EQU 7
111 dm_INFO_PURPOSE EQU 5
112 dm_INFO_AUTHOR EQU 3
113 dm_INFO_VERSION EQU 1
114
115 dm_MERGE_DEST EQU 2
116 dm_MERGE_SOURCE EQU 3
117 dm_MERGE_MSG EQU 5
118
119 ;----- Main code ------------------------------------------------------------
120
121 AREA |DLLMerge$$Code|,CODE,READONLY
122 ENTRY
123
124 ; --- main ---
125 ;
126 ; On entry: --
127 ; On exit: Doesn't
128
129 main ROUT
130
131 BL dm_init
132 BL dm_initWimp
133 BL dm_setHandlers
134 returnPoint BL dm_poll
135 exitPoint BL dm_die
136 SWI OS_Exit
137
138 LTORG
139
140 ; --- dm_init ---
141 ;
142 ; On entry: --
143 ; On exit: R12 and R13 set up, other registers corrupted
144
145 dm_init ROUT
146
147 ; --- Set up application workspace ---
148
149 ADRL R12,|Image$$RW$$Limit| ;Find limit of this program
150 SWI OS_GetEnv ;Find info about application
151 MOV R13,R1 ;Start stack at top of slot
152 SUB R0,R13,R12 ;Find how mich space I have
153 LDR R1,=dm_wsize ;How much do I need?
154 CMP R0,R1 ;Do I have enough?
155 ADRLTL R0,msg_errNoMem ;No -- point to the error...
156 SWILT OS_GenerateError ;... and die
157
158 ; --- Initialise workspace contents ---
159
160 MOV R0,#0 ;No flags set yet
161 STR R0,dm_flags ;Store that away
162
163 MOVS PC,R14 ;Return to caller
164
165 LTORG
166
167 ; --- dm_initWimp ---
168 ;
169 ; On entry: --
170 ; On exit: Registers corrupted
171
172 dm_initWimp ROUT
173
174 STMFD R13!,{R14} ;Keep link register
175
176 ; --- Initialise WindowManager ---
177
178 MOV R0,#200 ;WindowManager version
179 LDR R1,=&4B534154 ;Magic TASK number
180 ADR R2,dm__name ;Point to my name
181 SWI Wimp_Initialise ;Start up the WIMP
182
183 ; --- Copy the menu over ---
184
185 ADR R0,dm_menuBk ;Point to output block
186 ADR R1,dm_menuDef ;Point to the definition
187 MOV R2,#dm_menuSize ;Get the size too
188 00 SUBS R2,R2,#16 ;I'll do 16 at a time
189 LDMCSIA R1!,{R3-R6} ;Load some bytes
190 STMCSIA R0!,{R3-R6} ;Save them out
191 BCS %b00 ;If more to do, loop
192 ADD R2,R2,#16 ;We must have overshot
193 00 SUBS R2,R2,#4 ;Now do one word at a time
194 LDRCS R14,[R1],#4 ;Load the word
195 STRCS R14,[R0],#4 ;And store it out
196 BCS %b00 ;And loop back again
197
198 ; --- Load required windows ---
199
200 MOV R1,#0 ;Not loaded any templates
201
202 ADRL R0,tpl_progInfo ;Find the template
203 BL dm_loadTemplate ;Load a window
204 STR R0,dm_infohand ;Store that away nicely
205 STR R0,dm_menuBk+28+0*24+4 ;And store as Info... submenu
206
207 ADRL R0,tpl_merge ;Point to template name
208 BL dm_loadTemplate ;Load a window
209 STR R0,dm_windhand ;Store that away nicely
210
211 ; --- Fill in the Info window fields ---
212
213 LDR R0,dm_infohand
214 MOV R1,#dm_INFO_NAME
215 ADR R2,dm__name
216 BL dm_setField
217 MOV R1,#dm_INFO_PURPOSE
218 ADRL R2,msg_infoPurpose
219 BL dm_setField
220 MOV R1,#dm_INFO_AUTHOR
221 ADRL R2,cright
222 BL dm_setField
223 MOV R1,#dm_INFO_VERSION
224 ADRL R2,version
225 BL dm_setField
226
227 ; --- Open the merge window ---
228
229 ADR R1,dm_pollbk ;Point to a work block
230 LDR R0,dm_windhand ;Get the window's handle
231 STR R0,[R1,#0] ;Store in the block
232 SWI Wimp_GetWindowState ;Find the position of window
233 MOV R2,#-1 ;Move the window to front
234 STR R2,[R1,#28] ;Store in `behind' field
235 SWI Wimp_OpenWindow ;Open the window
236
237 LDMFD R13!,{PC}^ ;Return to caller
238
239 dm__name DCB "DLLMerge",0
240
241 dm_menuDef TWELVE "DLLMerge"
242 DCB 7,2,7,0
243 DCD 16*7+16
244 DCD 44
245 DCD 0
246
247 DCD &00000000
248 DCD 0
249 DCD &07000131
250 DCD msg_menuInfo,-1,1
251
252 DCD &00000080
253 DCD -1
254 DCD &07000131
255 DCD msg_menuQuit,-1,1
256
257 dm_menuSize EQU {PC}-dm_menuDef
258
259 LTORG
260
261 ; --- dm_setHandlers ---
262 ;
263 ; On entry: --
264 ; On exit: Registers corrupted
265
266 dm_setHandlers ROUT
267
268 ; --- Find somewhere to go on an exception ---
269
270 STR R13,dm_exceptStack ;Save this stack pointer away
271
272 ; --- Set up the error handler ---
273
274 STMFD R13!,{R14}
275 ADR R11,dm_handlers ;Point to handler buffer
276
277 MOV R0,#6 ;Set up error handler
278 ADR R1,dm_errors ;Point to the error handler
279 MOV R2,R12 ;Set up the workspace ptr
280 ADR R3,dm_stacklim ;Use stack base as error buff
281 SWI OS_ChangeEnvironment ;Set up the handler
282 STMIA R11!,{R1-R3} ;Save the old information
283
284 ; --- Set up other handlers to quit the program ---
285
286 MOV R0,#11 ;Set up exit handler
287 ADR R1,dm_exits ;Point to the handler
288 MOV R2,R12 ;Point to my workspace
289 MOV R3,#0 ;No buffer pointer
290 SWI OS_ChangeEnvironment ;Set up the handler
291 STMIA R11!,{R1-R3} ;Save the old information
292
293 MOV R0,#16 ;Set up UpCall handler
294 ADR R1,dm_upcalls ;Point to the handler
295 MOV R2,R12 ;Point to my workspace
296 MOV R3,#0 ;No buffer pointer
297 SWI OS_ChangeEnvironment ;Set up the handler
298 STMIA R11!,{R1-R3} ;Save the old information
299
300 LDMFD R13!,{PC}^ ;Return to caller
301
302 LTORG
303
304 ; --- dm_killHandlers ---
305 ;
306 ; On entry: --
307 ; On exit: Registers preserved
308
309 dm_killHandlers ROUT
310
311 STMFD R13!,{R0-R3,R11,R14} ;Save registers
312
313 ADR R11,dm_handlers ;Point to handlers buffer
314
315 MOV R0,#6
316 LDMIA R11!,{R1-R3}
317 SWI XOS_ChangeEnvironment
318
319 MOV R0,#11
320 LDMIA R11!,{R1-R3}
321 SWI XOS_ChangeEnvironment
322
323 MOV R0,#16
324 LDMIA R11!,{R1-R3}
325 SWI XOS_ChangeEnvironment
326
327 LDMFD R13!,{R0-R3,R11,PC}^ ;Return to caller
328
329 LTORG
330
331 ; --- dm_errors ---
332 ;
333 ; On entry: R0 == pointer to my workspace
334 ; On exit: Doesn't -- goes back to main loop at appropriate point
335
336 dm_errors ROUT
337
338 ; --- Reset stack and workspace pointers ---
339
340 MOV R12,R0 ;Point to my workspace
341 LDR R13,dm_exceptStack ;Restore my stack pointer
342
343 ; --- Is this a double exception? ---
344
345 LDR R0,dm_flags ;Get my flags
346 TST R0,#dm_ERROR ;Is this a repeated error?
347 BNE %00dm_errors ;Yes -- handle this specially
348
349 ; --- Mark that we're in the error handler ---
350
351 ORR R0,R0,#dm_ERROR ;Say we're in the handler
352 STR R0,dm_flags ;Store this in the flags
353
354 ; --- Report the error and give a chance to quit ---
355
356 ADRL R1,dm_stacklim+8 ;Point to main error message
357 ADRL R0,msg_errInternal ;Point to error skeleton
358 BL dm_error ;Construct a message
359 MOV R1,#&00000003 ;Provide OK and Cancel boxes
360 ADR R2,dm__name ;Point to my name
361 SWI Wimp_ReportError ;Report the error
362 CMP R1,#1 ;Was OK clicked?
363 BEQ %01dm_errors ;Yes -- return to main loop
364
365 ADRL R0,msg_errConfirm ;Point to the confirm message
366 MOV R1,#3 ;OK and Cancel buttons again
367 ADR R2,dm__name ;Point to my name
368 SWI Wimp_ReportError ;Display the question
369 CMP R1,#1 ;Was OK clicked?
370 BEQ %01dm_errors ;Yes -- return to main loop
371
372 B exitPoint ;Commit hari-kiri then
373
374 ; --- We can continue ---
375
376 01dm_errors LDR R0,dm_flags ;Get my flags
377 BIC R0,R0,#dm_ERROR ;There's no error any more
378 STR R0,dm_flags ;Store the flags away
379 B returnPoint ;Go back into the top level
380
381 00dm_errors BL dm_killHandlers ;Restore all the handlers
382 ADRL R0,dm_stacklim+4 ;Point to the error buffer
383 SWI OS_GenerateError ;Let the OS handle it all
384
385 LTORG
386
387 ; --- dm_exits ---
388 ;
389 ; On entry: --
390 ; On exit: Doesn't -- branches to main loop
391
392 dm_exits LDR R13,dm_exceptStack ;Get my stack pointer
393 B exitPoint ;Close down the application
394
395 ; --- dm_upcalls ---
396 ;
397 ; On entry: R0 == UpCall type
398 ; On exit: Varies
399
400 dm_upcalls CMP R0,#256 ;Is a new app starting?
401 MOVNES PC,R14 ;No -- return to caller
402
403 ; --- Hopefully this will never happen :-) ---
404
405 MOVS PC,R14 ;Return to caller and hope
406
407 ; --- dm_die ---
408 ;
409 ; On entry: --
410 ; On exit: Registers corrupted
411
412 dm_die ROUT
413
414 STMFD R13!,{R14}
415 BL dm_killHandlers ;Get rid of any handlers
416 SWI Wimp_CloseDown ;Stop being a Wimp task
417 LDMFD R13!,{PC}^ ;Return to caller
418
419 LTORG
420
421 ; --- dm_poll ---
422 ;
423 ; On entry: --
424 ; On exit: Registers corrupted
425
426 dm_poll ROUT
427
428 STMFD R13!,{R14} ;Keep return address
429
430 ; --- Find out if we need continue ---
431
432 00dm_poll LDR R0,dm_flags ;Get the flags word
433 TST R0,#dm_QUIT ;Check the quit bit
434 LDMNEFD R13!,{PC}^ ;Return if it failed
435
436 ; --- Get an event and dispatch it ---
437
438 AND R0,R0,#dm_SOURCE :OR: dm_DONE ;What's my status?
439 CMP R0,#dm_SOURCE ;If not complete...
440 MOVEQ R0,#0 ;... wait for an idle event
441 MOVNE R0,#1 ;Otherwise, ignore idles
442 ADR R1,dm_pollbk ;Point to the big block
443 SWI Wimp_Poll ;Get an event
444
445 CMP R0,#19 ;Check the event is sensible
446 MOV R14,PC ;Set up return address
447 ADDLS PC,PC,R0,LSL #2 ;If so, go to branch table
448 B %00dm_poll ;Silly event -- ignore it
449
450 ; --- Event dispatching table ---
451
452 B dm_null ;Null_Reason_Code
453 B dm_redraw ;Redraw_Window_Request
454 B dm_open ;Open_Window_Request
455 B dm_close ;Close_Window_Request
456 MOVS PC,R14 ;Pointer_Leaving_Window
457 MOVS PC,R14 ;Pointer_Entering_Window
458 B dm_click ;Mouse_Clicked
459 MOVS PC,R14 ;User_Drag_Box
460 MOVS PC,R14 ;Key_Pressed
461 B dm_menu ;Menu_Selection
462 MOVS PC,R14 ;10
463 MOVS PC,R14 ;11
464 MOVS PC,R14 ;12
465 MOVS PC,R14 ;13
466 MOVS PC,R14 ;14
467 MOVS PC,R14 ;15
468 MOVS PC,R14 ;16
469 B dm_message ;User_Message
470 B dm_message ;User_Message_Recorded
471 MOVS PC,R14 ;User_Message_Acknowledge
472
473 LTORG
474
475 ;----- Event handlers -------------------------------------------------------
476
477 ; --- Null_Reason_Code ---
478 ;
479 ; We copy the source to the destination
480
481 dm_null ROUT
482
483 STMFD R13!,{R14} ;Stack the link register
484 MOV R0,#26 ;We want to do a copy
485 ADR R1,dm_source ;Point to source app
486 ADR R2,dm_dest ;Point to destination app
487 LDR R3,=&00005003 ;Copy options
488 SWI XOS_FSControl ;Do the copy operation
489 BVS %00dm_null ;If it failed, display msg
490
491 ; --- Update the DLL$Path variable ---
492
493 MOV R0,R2 ;Point to destination name
494 SWI Wimp_StartTask ;Run its !Run file
495
496 ; --- Put the text into the message field ---
497
498 LDR R0,dm_windhand ;Get the window handle
499 MOV R1,#dm_MERGE_MSG ;Get the icon handle
500 ADRL R2,msg_stateDone ;Point to message
501 BL dm_setField ;Write the text in
502
503 ; --- Update the flags and quit ---
504
505 LDR R0,dm_flags ;Get the flags word
506 ORR R0,R0,#dm_DONE ;We've finished
507 STR R0,dm_flags ;Write the flags back
508 LDMFD R13!,{PC}^ ;Return to caller
509
510 ; --- It failed. Report an error and start again ---
511
512 00dm_null ADD R1,R0,#4 ;Point to the message
513 ADRL R0,msg_errCopy ;Point to the error skeleton
514 BL dm_error ;Fill it in
515 MOV R1,#1 ;Only have an OK box
516 ADR R2,dm__name ;Point to my name
517 SWI Wimp_ReportError ;Make an error
518
519 LDR R0,dm_windhand ;Get the window handle
520 MOV R1,#dm_MERGE_DEST ;Get the icon handle
521 ADR R2,dm__empty ;Point to message
522 BL dm_setField ;Write the text in
523 MOV R1,#dm_MERGE_SOURCE ;Get the icon handle
524 BL dm_setField ;Write the text in
525 MOV R1,#dm_MERGE_MSG ;Get the icon handle
526 ADRL R2,msg_stateErr ;Point to message
527 BL dm_setField ;Write the text in
528
529 MOV R0,#0 ;Clear all the flags
530 STR R0,dm_flags ;Store them away
531
532 LDMFD R13!,{PC}^
533
534 dm__empty DCB 0
535
536 LTORG
537
538 ; --- Redraw_Window_Request ---
539 ;
540 ; We just bundle the redraw event off to Sculptrix and forget about it
541
542 dm_redraw ROUT
543
544 SWI Wimp_RedrawWindow
545 00dm_redraw CMP R0,#0
546 MOVEQS PC,R14
547 SWI XSculptrix_RedrawWindow
548 SWI Wimp_GetRectangle
549 B %00dm_redraw
550
551 LTORG
552
553 ; --- Open_Window_Request ---
554 ;
555 ; Just open the window. Nothing could be easier ---
556
557 dm_open ROUT
558
559 SWI Wimp_OpenWindow
560 MOVS PC,R14
561
562 LTORG
563
564 ; --- Close_Window_Request ---
565 ;
566 ; We close down the application.
567
568 dm_close ROUT
569
570 LDR R0,dm_flags
571 ORR R0,R0,#dm_QUIT
572 STR R0,dm_flags
573 MOVS PC,R14
574
575 LTORG
576
577 ; --- Mouse_Clicked ---
578 ;
579 ; If it's the Info window, we start moving it about. If it's the Merge
580 ; window, we open a menu
581
582 dm_click ROUT
583
584 LDR R0,[R1,#12] ;Get the window handle
585 LDR R2,dm_windhand ;Is it the Merge window?
586 CMP R0,R2 ;Find out
587 BEQ %10dm_click ;If so, handle it there
588 LDR R2,dm_infohand ;It may be the Info window
589 CMP R0,R2 ;So check
590 BEQ %20dm_click ;If so, handle it
591 MOVS PC,R14 ;Not recognised -- ignore it
592
593 ; --- Handle a click on the Merge window ---
594
595 10dm_click LDR R0,[R1,#8] ;Get the button status
596 TST R0,#2 ;Check the menu button bit
597 MOVEQS PC,R14 ;If not, return
598
599 LDMIA R1,{R2,R3} ;Get coordinates from block
600 SUB R2,R2,#64 ;Displace the menu
601 ADR R1,dm_menuBk ;Point to the menu defn
602 SWI Wimp_CreateMenu ;Display the menu
603 MOVS PC,R14 ;Return to caller
604
605 ; --- Handle a click on the Info window ---
606
607 20dm_click LDR R0,[R1,#8] ;Get the button status
608 TST R0,#5 ;Check for Select or Adjust
609 MOVEQS PC,R14 ;If not, return
610
611 SUB R13,R13,#56 ;Make a drag info block
612 LDR R0,dm_infohand ;Get the Info window handle
613 STR R0,[R13,#0] ;Store the window handle
614 MOV R0,#1 ;Move the window
615 STR R0,[R13,#4] ;Store the drag type
616 MOV R1,R13 ;Point to the block
617 SWI Wimp_DragBox ;Start the window moving
618 ADD R13,R13,#56 ;Reclaim the stack space
619 MOVS PC,R14 ;Return to caller
620
621 LTORG
622
623 ; --- Menu_Selection ---
624 ;
625 ; If it's Info, open the Info box. If it's Quit, then quit.
626
627 dm_menu ROUT
628
629 LDR R0,[R1,#0] ;Get toplevel selection
630 CMP R0,#0 ;Is it `Info...'?
631 BEQ %10dm_menu ;Yes -- process it
632 CMP R0,#1 ;Is it `Quit'?
633 BEQ dm_close ;Yes -- quit the program
634 MOVS PC,R14 ;Return to caller
635
636 ; --- Open the Info... window ---
637
638 10dm_menu SUB R13,R13,#36 ;Get some workspace
639 MOV R1,R13 ;Point to this new block
640 SWI Wimp_GetPointerInfo ;Where is the mouse now?
641 LDMIA R1,{R2,R3} ;Get the mouse coordinates
642 LDR R0,dm_infohand ;Get the window handle
643 STR R0,[R1,#0] ;Store the window handle
644 SWI Wimp_GetWindowState ;Get the window's information
645 LDMIA R1,{R1,R4-R7} ;Get the window positions
646 SUB R4,R6,R4 ;Get the window width
647 SUB R5,R7,R5 ;And the window height
648 SUB R2,R2,R4,LSR #1 ;Centre window over X
649 ADD R3,R3,R5,LSR #1 ;Centre window over Y
650 ADD R13,R13,#36 ;Reclaim the stack space
651 SWI Wimp_CreateMenu ;Display the Info window
652 MOVS PC,R14 ;And return to caller
653
654 LTORG
655
656 ; --- User_Message and User_Message_Recorded ---
657 ;
658 ; Handle Quit messages, and files dropped on the window
659
660 dm_message ROUT
661
662 LDR R0,[R1,#16] ;Get message type
663 CMP R0,#0 ;Is it a Message_Quit?
664 BEQ dm_close ;This has the code for quit
665 CMP R0,#3 ;Is it a load message?
666 BEQ %10dm_message ;Yes -- deal with it
667 MOVS PC,R14 ;If not interested, return
668
669 ; --- Someone dropped a file on my window ---
670
671 10dm_message LDR R0,[R1,#20] ;Where was the file dropped?
672 LDR R11,dm_windhand ;Get my window handle
673 CMP R0,R11 ;Do they match?
674 MOVNES PC,R14 ;No -- ignore it
675
676 ; --- Check what to do with it ---
677
678 LDR R10,dm_flags ;Get my flags word
679 TST R10,#dm_SOURCE ;Have I finished?
680 MOVNES PC,R14 ;Yes -- not interested then
681
682 ; --- Got to do something now ---
683
684 STMFD R13!,{R14} ;Stack link register now
685 BL dm_checkFile ;Make sure it's a !DLLs
686 CMP R0,#0 ;Did it fail?
687 LDMEQFD R13!,{PC}^ ;Yes -- return to poll loop
688
689 ; --- Which filename do I fill in? ---
690
691 TST R10,#dm_DEST ;Have I got one filename?
692 BNE %20dm_message ;Yes -- fill in the other
693
694 ; --- Fill in the first filename ---
695
696 ADD R1,R1,#44 ;Point to filename
697 ADR R0,dm_dest ;That's the destination file
698 BL dm_strcpy ;Copy it across
699 MOV R2,R1 ;Point to name again
700 MOV R1,#dm_MERGE_DEST+(1<<31)
701 MOV R0,R11 ;And set up the window handle
702 BL dm_setField ;Fill that icon in
703
704 ; --- Now display a new message ---
705
706 ADRL R2,msg_stateSource ;Point to the new message
707 MOV R1,#dm_MERGE_MSG ;Put it in the message icon
708 BL dm_setField ;Fill that icon in
709
710 ORR R10,R10,#dm_DEST ;Remember we've got a name
711 STR R10,dm_flags ;Store the new flags away
712 B %30dm_message ;Reply to the message now
713
714 ; --- Fill in the second filename ---
715
716 20dm_message ADD R1,R1,#44 ;Point to filename
717 ADR R0,dm_source ;That's the source file
718 BL dm_strcpy ;Copy it across
719 MOV R2,R1 ;Point to name again
720 MOV R1,#dm_MERGE_SOURCE+(1<<31)
721 MOV R0,R11 ;And set up the window handle
722 BL dm_setField ;Fill that icon in
723
724 ; --- Now display a new message ---
725
726 ADRL R2,msg_stateGoing ;Point to the new message
727 MOV R1,#dm_MERGE_MSG ;Put it in the message icon
728 BL dm_setField ;Fill that icon in
729 ORR R10,R10,#dm_SOURCE ;Remember we've got a name
730 STR R10,dm_flags ;Store the new flags away
731
732 ; --- Reply to the message in the block ---
733
734 30dm_message ADR R1,dm_pollbk ;Point to the message
735 LDR R0,[R1,#8] ;Get his reference
736 STR R0,[R1,#12] ;Store as his reference
737 MOV R0,#4 ;This is an acknowledgement
738 STR R0,[R1,#16] ;Store as the message type
739 MOV R0,#17 ;Don't bother recording it
740 LDR R2,[R1,#4] ;Get his task handle
741 SWI Wimp_SendMessage ;Reply to his message now
742 LDMFD R13!,{PC}^ ;Return to the caller
743
744 LTORG
745
746 ;----- Support routines -----------------------------------------------------
747
748 ; --- dm_setField ---
749 ;
750 ; On entry: R0 == window handle
751 ; R1 == icon handle
752 ; R2 == string to write
753 ; On exit: Everything preserved unless there was an error
754
755 dm_setField ROUT
756
757 STMFD R13!,{R0-R5,R14} ;Stash registers away
758
759 ; --- Find out about the icon ---
760
761 AND R4,R1,#&FF000000 ;Get the flag bits out
762 BIC R1,R1,#&FF000000 ;Leave just the icon number
763 SUB R13,R13,#40 ;Make space for icon block
764 STMIA R13,{R0,R1} ;Store the info in it
765 MOV R1,R13 ;Point to the icon block
766 SWI Wimp_GetIconState ;Get the icon's information
767
768 ; --- Make sure we can change the text ---
769
770 LDR R1,[R13,#24] ;Get the icon's flags
771
772 ; --- Now find how much we actually have to copy ---
773
774 LDR R5,[R13,#36] ;Get the buffer length
775 SUB R5,R5,#1 ;Take terminator into account
776 MOV R0,R2 ;Point to the string to copy
777 BL dm_strlen ;Find out how long it is
778 SUBS R0,R0,R5 ;Find out the difference
779 BICLE R4,R4,#(1<<31) ;If it fits, don't add dots
780 BLE %00dm_setField ;And skip ahead
781 TST R1,#1<<9 ;Is it right aligned?
782 ADDNE R2,R2,R0 ;Yes, chop off front
783 ORRNE R4,R4,#1 ;And set a flag to remember
784
785 ; --- Copy the text into the buffer ---
786
787 00dm_setField LDR R0,[R13,#28] ;Find the buffer address
788 MOV R3,#0 ;Count the length too
789
790 10dm_setField CMP R5,R3 ;How much space left in buff?
791 MOVLE R1,#0 ;None -- pretend null char
792 LDRGTB R1,[R2],#1 ;Get a byte from the string
793 CMP R1,#' ' ;Is it a control char?
794 MOVLO R1,#0 ;Yes -- say it's a zero
795 BLO %15dm_setField ;And don't bother with dots
796
797 ; --- Handle ellipsis generation ---
798
799 TST R4,#(1<<31) ;Do we put the ellipsis in?
800 BEQ %15dm_setField ;No -- skip ahead then
801 TST R4,#1 ;Are we right-justified?
802 ADDNE R14,R3,#1 ;Yes -- just get the length
803 SUBEQ R14,R5,R3 ;Otherwise find what's left
804 CMP R14,#4 ;Are we within three?
805 MOVLO R1,#'.' ;Yes -- put in a dot then
806
807 ; --- Return to normality ---
808
809 15dm_setField LDRB R14,[R0],#1 ;Get one from the buffer
810 CMP R14,#' ' ;Same for the buffer char
811 MOVLO R14,#0
812
813 CMP R1,R14 ;Are they different
814 ORRNE R4,R4,#2 ;Yes -- remember this
815 STRNEB R1,[R0,#-1] ;And store the different char
816
817 CMP R1,#0 ;Is that end of the string?
818 ADDNE R3,R3,#1 ;No -- bump the length on
819 BNE %10dm_setField ;And go round for another
820
821 ; --- We've copied the string -- now update the icon ---
822
823 TST R4,#2 ;Is the string different?
824 BEQ %20dm_setField ;No -- skip ahead
825
826 MOV R1,#0
827 STR R1,[R13,#8] ;The EOR mask for setstate
828 STR R1,[R13,#12] ;The BIC mask for setstate
829 MOV R1,R13 ;Point to the block
830 SWI Wimp_SetIconState ;Flicker the icon nastily
831
832 ; --- Now check for the caret ---
833
834 SWI Wimp_GetCaretPosition ;Find out where the caret is
835 LDMIA R13,{R2,R4} ;Get the window and icon
836 ADD R0,R13,#40 ;Point past this block
837 LDMIA R0,{R0,R1} ;Get the old window and icon
838 CMP R0,R2 ;Do the window handles match?
839 CMPEQ R1,R4 ;And the icon handles?
840 BNE %20dm_setField ;No -- skip ahead
841
842 ; --- Push the caret back a little ---
843
844 LDR R5,[R13,#20] ;Get the caret index
845 CMP R5,R3 ;Is this bigger than new len?
846 MOVGT R5,R3 ;Yes -- trim the index
847
848 ; --- Now put the caret in the right place ---
849
850 MOV R2,#-1 ;Don't set the x coord
851 MOV R3,#-1 ;Don't set the y coord
852 MOV R4,#-1 ;Don't set the height
853 SWI Wimp_SetCaretPosition ;Put the caret in its place
854
855 ; --- Return nicely ---
856
857 20dm_setField ADD R13,R13,#40 ;Reclaim that temporary space
858 LDMFD R13!,{R0-R5,PC}^ ;Return to caller
859
860 LTORG
861
862 ; --- dm_checkFile ---
863 ;
864 ; On entry: R1 == pointer to message block
865 ; On exit: R0 == 0 if it *wasn't* a DLL folder
866
867 dm_checkFile ROUT
868
869 STMFD R13!,{R1-R5,R14} ;Stack registers
870
871 ; --- Ensure it's a directory ---
872 ;
873 ; Kysmet seems to ignore the fact that it might be an image
874 ; and returns &FC0 for links, instead of &1000/&2000 which
875 ; the Filer gives you. So we examine the file using OS_File
876 ; and check bit 1 of the object type from that.
877
878 ADD R1,R1,#44 ;Find the name
879 MOV R0,#17 ;Try to read information
880 SWI XOS_File ;Read the file information
881 MOVVS R0,#0 ;Say not there if it failed
882 TST R0,#2 ;Is it a directory?
883 BEQ %10dm_checkFile ;No -- then complain
884
885 ; --- Now find the leafname ---
886
887 MOV R0,R1 ;Keep pointer to name
888 01dm_checkFile LDRB R14,[R1],#1 ;Get a character
889 CMP R14,#'.' ;Is it a dot?
890 MOVEQ R0,R1 ;Yes -- this it the leafname
891 CMP R14,#' ' ;Is it the end?
892 BGE %01dm_checkFile ;No -- go round again
893
894 ; --- Compare this to what it should be ---
895
896 ADR R1,dm__dlls ;Point to the ideal one
897 MOV R2,#0 ;Not case-sensitive
898 BL dm_strcmp ;Is it a match?
899 BNE %10dm_checkFile ;No -- be unhappy
900
901 MOV R0,#1 ;It was a real !DLLs resource
902 LDMFD R13!,{R1-R5,PC}^ ;Return to caller
903
904 10dm_checkFile ADRL R0,msg_errNotDLL ;Point to error message
905 LDR R1,[R13,#0] ;Get the message pointer
906 ADD R1,R1,#44 ;Find the name string
907 BL dm_error ;Fill in the error
908 MOV R1,#1 ;Just an OK box please
909 ADRL R2,dm__name ;Point to my name
910 SWI Wimp_ReportError ;Report the error
911 MOV R0,#0 ;It wasn't a real one
912 LDMFD R13!,{R1-R5,PC}^ ;Return to caller
913
914 dm__dlls DCB "!DLLs",0
915
916 LTORG
917
918 ; --- dm_loadTemplate ---
919 ;
920 ; On entry: R0 == pointer to template
921 ; R1 == 0 on first call, or R1 from previous
922 ; On exit: R0 == window handle
923 ; R1 == a new magic number
924
925 dm_loadTemplate ROUT
926
927 STMFD R13!,{R2-R5,R14} ;Stack registers
928
929 ; --- Set up indirected data pointer ---
930
931 CMP R1,#0 ;Is this the first call?
932 ADREQL R2,dm_indspace ;Yes -- point to buff start
933 MOVNE R2,R1 ;Set up indirected data ptr
934
935 ; --- Load template into buffer ---
936
937 ADRL R3,dm_eindspace ;Point to buff end
938 ADR R1,dm_pollbk ;Point to poll block
939 MOV R4,#1 ;Use the Wimp sprite area
940 MOV R5,#1 ;I really mean that
941 BL embTemp_extract ;Extract the template
942
943 ; --- Create the window and return ---
944
945 SWI Wimp_CreateWindow ;Create the window
946 MOV R1,R2 ;Get magic number to return
947 LDMFD R13!,{R2-R5,PC}^ ;Return to caller
948
949 LTORG
950
951 ; --- dm_strlen ---
952 ;
953 ; On entry: R0 == pointer to string
954 ; On exit: R0 == length of string
955
956 dm_strlen ROUT
957
958 STMFD R13!,{R1,R14} ;Save some registers
959 MOV R1,#0 ;Start the counter nicely
960 00dm_strlen LDRB R14,[R0],#1 ;Load a byte from the string
961 ADD R1,R1,#1 ;Bump on the counter
962 CMP R14,#32 ;Is it the end?
963 BHS %00dm_strlen ;No -- go round again then
964 SUB R0,R1,#1 ;Return count of actual chars
965 LDMFD R13!,{R1,PC}^ ;Return to caller
966
967 LTORG
968
969 ; --- dm_strcpy ---
970 ;
971 ; On entry: R0 == destination string
972 ; R1 == source string
973 ; On exit: R0 == pointer to terminator of destination
974
975 dm_strcpy ROUT
976
977 STMFD R13!,{R1,R14} ;Keep return address safe
978 00dm_strcpy LDRB R14,[R1],#1 ;Get a byte from source
979 CMP R14,#' ' ;Is it a control character
980 MOVLT R14,#0 ;Yes -- translate to a 0
981 STRB R14,[R0],#1 ;Store in destination
982 BGE %00dm_strcpy ;No -- copy another byte
983 SUB R0,R0,#1 ;Point back at terminator
984 LDMFD R13!,{R1,PC}^ ;Return to caller
985
986 LTORG
987
988 ; --- dm_strcmp ---
989 ;
990 ; On entry: R0 == pointer to string A
991 ; R1 == pointer to string B
992 ; R2 == 0 => case insensitive, 1 => case sensitive
993 ;
994 ; On exit: Flags as appropriate
995
996 dm_strcmp ROUT
997
998 STMFD R13!,{R0,R1,R3,R4,R14}
999 00dm_strcmp LDRB R3,[R0],#1 ;Get a character from A
1000 LDRB R4,[R1],#1 ;And one from B
1001
1002 CMP R2,#0 ;Do we want to do case xlate?
1003 BNE %10dm_strcmp ;No -- miss it out then
1004
1005 SUB R14,R3,#'a' ;Subtract the bottom limit
1006 CMP R14,#26 ;Is it a lower case letter?
1007 BICLO R3,R3,#&20 ;Yes -- convert to upper
1008 SUB R14,R4,#'a' ;Subtract the bottom limit
1009 CMP R14,#26 ;Is it a lower case letter?
1010 BICLO R4,R4,#&20 ;Yes -- convert to upper
1011
1012 10dm_strcmp CMP R3,#&20 ;Is that the end of A?
1013 MOVLO R3,#0 ;Yes -- pretend it's null
1014 CMP R4,#&20 ;Is that the end of B?
1015 MOVLO R4,#0 ;Yes -- pretend it's null
1016
1017 CMP R3,R4 ;How do they match up?
1018 LDMNEFD R13!,{R0,R1,R3,R4,PC} ;If NE, return condition
1019 CMP R3,#0 ;Is this the end?
1020 BNE %00dm_strcmp ;No -- loop again
1021 LDMFD R13!,{R0,R1,R3,R4,PC} ;Return to caller
1022
1023 LTORG
1024
1025 ; --- dm_error ---
1026 ;
1027 ; On entry: R0 == Pointer to error message skeleton
1028 ; R1 == Filler 1
1029 ; R2 == Filler 2
1030 ; R3 == Filler 3
1031 ; R4 == Filler 4
1032 ; On exit: R0 == Pointer to constructed error in dm_errorbuf
1033
1034 EXPORT dm_error
1035 dm_error ROUT
1036
1037 STMFD R13!,{R1-R6,R14}
1038 ADR R5,dm_pollbk ;Point to error buffer
1039 LDR R14,[R0],#4 ;Read the error's number
1040 STR R14,[R5],#4 ;And store in the new buffer
1041
1042 00dm_error LDRB R14,[R0],#1 ;Get an input character
1043 CMP R14,#'%' ;Is it a '%' sign?
1044 BEQ %01dm_error ;Yes -- deal with it
1045 02dm_error STRB R14,[R5],#1 ;Not special, so store it
1046 CMP R14,#0 ;Is it the end of input?
1047 BNE %00dm_error ;No -- get another one
1048 ADR R0,dm_pollbk ;Point to error start
1049 LDMFD R13!,{R1-R6,PC}^ ;And return to caller
1050
1051 01dm_error LDRB R14,[R0],#1 ;Get the next character
1052 SUB R14,R14,#'0' ;Convert to binary (0..3)
1053 CMP R14,#4 ;Is it in range?
1054 BCS %02dm_error ;No -- just ignore the '%'
1055 LDR R6,[R13,R14,LSL #2] ;Load appropriate register
1056
1057 03dm_error LDRB R14,[R6],#1 ;Get an input byte
1058 CMP R14,#&20 ;Is it the end of the string?
1059 BLT %00dm_error ;Yes -- read main string
1060 STRB R14,[R5],#1 ;No -- store it in output
1061 B %03dm_error ;... and get another one
1062
1063 LTORG
1064
1065 ;----- Workspace layout -----------------------------------------------------
1066
1067 ^ 0,R12
1068
1069 dm_wstart # 0
1070
1071 dm_exceptStack # 4
1072
1073 dm_windhand # 4
1074 dm_infohand # 4
1075
1076 dm_flags # 4
1077
1078 dm_handlers # 36
1079
1080 dm_menuBk # dm_menuSize
1081
1082 dm_QUIT EQU 1<<0
1083 dm_DEST EQU 1<<1
1084 dm_SOURCE EQU 1<<2
1085 dm_DONE EQU 1<<3
1086 dm_ERROR EQU 1<<4
1087
1088 dm_pollbk # 256
1089 dm_dest # 256
1090 dm_source # 256
1091
1092 dm_indspace # 384
1093 dm_eindspace # 0
1094
1095 dm_stacklim # 288
1096
1097 dm_wend # 0
1098
1099 dm_wsize EQU dm_wend-dm_wstart
1100
1101 ;----- That's all folks -----------------------------------------------------
1102
1103 END