4 ; Merge two DLL resources together (MDW)
6 ; © 1994-1998 Straylight
9 ;----- Licensing note -------------------------------------------------------
11 ; This file is part of Straylight's Dynamic Linking System (SDLS)
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)
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.
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.
27 ;----- Change history -------------------------------------------------------
31 ; 1.00 MDW Initial version written.
33 ; 1.01 MDW Added error handler to stop bombing out on errors.
35 ; 1.02 MDW Done copyright and version messages with setdate.
37 ; 1.03 MDW Made most SWIs generate errors, and added confirm
40 ; 1.04 MDW Updated dm_setField in line with Sapphire version.
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!
46 ; 1.06 MDW Used embedded templates instead of separate file.
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.
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.
60 ; 1.09 MDW Changed LDRs to ADRs when finding version and
61 ; copyright strings, now that the linker can handle it.
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.
68 ; 1.11 MDW Changed dm_error to base filler strings on `%0' not
69 ; `%1', and updated messages in line with this.
71 ;----- Standard header ------------------------------------------------------
78 ;----- External dependencies ------------------------------------------------
80 ; --- Embedded template handling ---
82 GET libs:embTemp.sh.embTemp
84 ; --- Linker symbols ---
86 IMPORT |Image$$RW$$Limit|
88 ; --- Linked resources ---
93 ; --- Generated strings ---
98 ;----- Macros ---------------------------------------------------------------
101 $label TWELVE $string
102 ASSERT :LEN:"$string"<=12
108 ;----- Icon numbers ---------------------------------------------------------
111 dm_INFO_PURPOSE EQU 5
113 dm_INFO_VERSION EQU 1
116 dm_MERGE_SOURCE EQU 3
119 ;----- Main code ------------------------------------------------------------
121 AREA |DLLMerge$$Code|,CODE,READONLY
134 returnPoint BL dm_poll
143 ; On exit: R12 and R13 set up, other registers corrupted
147 ; --- Set up application workspace ---
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
158 ; --- Initialise workspace contents ---
160 MOV R0,#0 ;No flags set yet
161 STR R0,dm_flags ;Store that away
163 MOVS PC,R14 ;Return to caller
167 ; --- dm_initWimp ---
170 ; On exit: Registers corrupted
174 STMFD R13!,{R14} ;Keep link register
176 ; --- Initialise WindowManager ---
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
183 ; --- Copy the menu over ---
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
198 ; --- Load required windows ---
200 MOV R1,#0 ;Not loaded any templates
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
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
211 ; --- Fill in the Info window fields ---
217 MOV R1,#dm_INFO_PURPOSE
218 ADRL R2,msg_infoPurpose
220 MOV R1,#dm_INFO_AUTHOR
223 MOV R1,#dm_INFO_VERSION
227 ; --- Open the merge window ---
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
237 LDMFD R13!,{PC}^ ;Return to caller
239 dm__name DCB "DLLMerge",0
241 dm_menuDef TWELVE "DLLMerge"
250 DCD msg_menuInfo,-1,1
255 DCD msg_menuQuit,-1,1
257 dm_menuSize EQU {PC}-dm_menuDef
261 ; --- dm_setHandlers ---
264 ; On exit: Registers corrupted
268 ; --- Find somewhere to go on an exception ---
270 STR R13,dm_exceptStack ;Save this stack pointer away
272 ; --- Set up the error handler ---
275 ADR R11,dm_handlers ;Point to handler buffer
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
284 ; --- Set up other handlers to quit the program ---
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
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
300 LDMFD R13!,{PC}^ ;Return to caller
304 ; --- dm_killHandlers ---
307 ; On exit: Registers preserved
311 STMFD R13!,{R0-R3,R11,R14} ;Save registers
313 ADR R11,dm_handlers ;Point to handlers buffer
317 SWI XOS_ChangeEnvironment
321 SWI XOS_ChangeEnvironment
325 SWI XOS_ChangeEnvironment
327 LDMFD R13!,{R0-R3,R11,PC}^ ;Return to caller
333 ; On entry: R0 == pointer to my workspace
334 ; On exit: Doesn't -- goes back to main loop at appropriate point
338 ; --- Reset stack and workspace pointers ---
340 MOV R12,R0 ;Point to my workspace
341 LDR R13,dm_exceptStack ;Restore my stack pointer
343 ; --- Is this a double exception? ---
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
349 ; --- Mark that we're in the error handler ---
351 ORR R0,R0,#dm_ERROR ;Say we're in the handler
352 STR R0,dm_flags ;Store this in the flags
354 ; --- Report the error and give a chance to quit ---
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
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
372 B exitPoint ;Commit hari-kiri then
374 ; --- We can continue ---
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
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
390 ; On exit: Doesn't -- branches to main loop
392 dm_exits LDR R13,dm_exceptStack ;Get my stack pointer
393 B exitPoint ;Close down the application
397 ; On entry: R0 == UpCall type
400 dm_upcalls CMP R0,#256 ;Is a new app starting?
401 MOVNES PC,R14 ;No -- return to caller
403 ; --- Hopefully this will never happen :-) ---
405 MOVS PC,R14 ;Return to caller and hope
410 ; On exit: Registers corrupted
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
424 ; On exit: Registers corrupted
428 STMFD R13!,{R14} ;Keep return address
430 ; --- Find out if we need continue ---
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
436 ; --- Get an event and dispatch it ---
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
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
450 ; --- Event dispatching table ---
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
469 B dm_message ;User_Message
470 B dm_message ;User_Message_Recorded
471 MOVS PC,R14 ;User_Message_Acknowledge
475 ;----- Event handlers -------------------------------------------------------
477 ; --- Null_Reason_Code ---
479 ; We copy the source to the destination
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
491 ; --- Update the DLL$Path variable ---
493 MOV R0,R2 ;Point to destination name
494 SWI Wimp_StartTask ;Run its !Run file
496 ; --- Put the text into the message field ---
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
503 ; --- Update the flags and quit ---
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
510 ; --- It failed. Report an error and start again ---
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
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
529 MOV R0,#0 ;Clear all the flags
530 STR R0,dm_flags ;Store them away
538 ; --- Redraw_Window_Request ---
540 ; We just bundle the redraw event off to Sculptrix and forget about it
544 SWI Wimp_RedrawWindow
545 00dm_redraw CMP R0,#0
547 SWI XSculptrix_RedrawWindow
548 SWI Wimp_GetRectangle
553 ; --- Open_Window_Request ---
555 ; Just open the window. Nothing could be easier ---
564 ; --- Close_Window_Request ---
566 ; We close down the application.
577 ; --- Mouse_Clicked ---
579 ; If it's the Info window, we start moving it about. If it's the Merge
580 ; window, we open a menu
584 LDR R0,[R1,#12] ;Get the window handle
585 LDR R2,dm_windhand ;Is it the Merge window?
587 BEQ %10dm_click ;If so, handle it there
588 LDR R2,dm_infohand ;It may be the Info window
590 BEQ %20dm_click ;If so, handle it
591 MOVS PC,R14 ;Not recognised -- ignore it
593 ; --- Handle a click on the Merge window ---
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
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
605 ; --- Handle a click on the Info window ---
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
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
623 ; --- Menu_Selection ---
625 ; If it's Info, open the Info box. If it's Quit, then quit.
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
636 ; --- Open the Info... window ---
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
656 ; --- User_Message and User_Message_Recorded ---
658 ; Handle Quit messages, and files dropped on the window
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
669 ; --- Someone dropped a file on my window ---
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
676 ; --- Check what to do with it ---
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
682 ; --- Got to do something now ---
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
689 ; --- Which filename do I fill in? ---
691 TST R10,#dm_DEST ;Have I got one filename?
692 BNE %20dm_message ;Yes -- fill in the other
694 ; --- Fill in the first filename ---
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
704 ; --- Now display a new message ---
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
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
714 ; --- Fill in the second filename ---
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
724 ; --- Now display a new message ---
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
732 ; --- Reply to the message in the block ---
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
746 ;----- Support routines -----------------------------------------------------
748 ; --- dm_setField ---
750 ; On entry: R0 == window handle
752 ; R2 == string to write
753 ; On exit: Everything preserved unless there was an error
757 STMFD R13!,{R0-R5,R14} ;Stash registers away
759 ; --- Find out about the icon ---
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
768 ; --- Make sure we can change the text ---
770 LDR R1,[R13,#24] ;Get the icon's flags
772 ; --- Now find how much we actually have to copy ---
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
785 ; --- Copy the text into the buffer ---
787 00dm_setField LDR R0,[R13,#28] ;Find the buffer address
788 MOV R3,#0 ;Count the length too
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
797 ; --- Handle ellipsis generation ---
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
807 ; --- Return to normality ---
809 15dm_setField LDRB R14,[R0],#1 ;Get one from the buffer
810 CMP R14,#' ' ;Same for the buffer char
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
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
821 ; --- We've copied the string -- now update the icon ---
823 TST R4,#2 ;Is the string different?
824 BEQ %20dm_setField ;No -- skip ahead
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
832 ; --- Now check for the caret ---
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
842 ; --- Push the caret back a little ---
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
848 ; --- Now put the caret in the right place ---
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
855 ; --- Return nicely ---
857 20dm_setField ADD R13,R13,#40 ;Reclaim that temporary space
858 LDMFD R13!,{R0-R5,PC}^ ;Return to caller
862 ; --- dm_checkFile ---
864 ; On entry: R1 == pointer to message block
865 ; On exit: R0 == 0 if it *wasn't* a DLL folder
869 STMFD R13!,{R1-R5,R14} ;Stack registers
871 ; --- Ensure it's a directory ---
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.
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
885 ; --- Now find the leafname ---
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
894 ; --- Compare this to what it should be ---
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
901 MOV R0,#1 ;It was a real !DLLs resource
902 LDMFD R13!,{R1-R5,PC}^ ;Return to caller
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
914 dm__dlls DCB "!DLLs",0
918 ; --- dm_loadTemplate ---
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
927 STMFD R13!,{R2-R5,R14} ;Stack registers
929 ; --- Set up indirected data pointer ---
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
935 ; --- Load template into buffer ---
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
943 ; --- Create the window and return ---
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
953 ; On entry: R0 == pointer to string
954 ; On exit: R0 == length of string
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
971 ; On entry: R0 == destination string
972 ; R1 == source string
973 ; On exit: R0 == pointer to terminator of destination
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
990 ; On entry: R0 == pointer to string A
991 ; R1 == pointer to string B
992 ; R2 == 0 => case insensitive, 1 => case sensitive
994 ; On exit: Flags as appropriate
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
1002 CMP R2,#0 ;Do we want to do case xlate?
1003 BNE %10dm_strcmp ;No -- miss it out then
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
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
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
1027 ; On entry: R0 == Pointer to error message skeleton
1032 ; On exit: R0 == Pointer to constructed error in dm_errorbuf
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
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
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
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
1065 ;----- Workspace layout -----------------------------------------------------
1080 dm_menuBk # dm_menuSize
1099 dm_wsize EQU dm_wend-dm_wstart
1101 ;----- That's all folks -----------------------------------------------------