chiark / gitweb /
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