chiark / gitweb /
JPEG support and other fixes from Nick Clark
[ssr] / StraySrc / Libraries / Sapphire / s / template
1 ;
2 ; template.s
3 ;
4 ; Load window template resources (MDW)
5 ;
6 ; © 1994-1998 Straylight
7 ;
8
9 ;----- Licensing note -------------------------------------------------------
10 ;
11 ; This file is part of Straylight's Sapphire library.
12 ;
13 ; Sapphire is free software; you can redistribute it and/or modify
14 ; it under the terms of the GNU General Public License as published by
15 ; the Free Software Foundation; either version 2, or (at your option)
16 ; any later version.
17 ;
18 ; Sapphire is distributed in the hope that it will be useful,
19 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 ; GNU General Public License for more details.
22 ;
23 ; You should have received a copy of the GNU General Public License
24 ; along with Sapphire.  If not, write to the Free Software Foundation,
25 ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26
27 ;----- Standard header ------------------------------------------------------
28
29                 GET     libs:header
30                 GET     libs:swis
31
32 ;----- External dependencies ------------------------------------------------
33
34                 GET     sapphire:alloc
35                 GET     sapphire:fastMove
36                 GET     sapphire:except
37                 GET     sapphire:mem
38                 GET     sapphire:msgs
39                 GET     sapphire:res
40                 GET     sapphire:resources
41                 GET     sapphire:resspr
42                 GET     sapphire:sapphire
43                 GET     sapphire:string
44
45 ;----- Main code ------------------------------------------------------------
46
47                 AREA    |Sapphire$$Code|,CODE,READONLY
48
49 ; --- tpl__find ---
50 ;
51 ; On entry:     R0 == pointer to name to find
52 ;
53 ; On exit:      CS if template found in list, and
54 ;                 R0 == pointer to template block (internal format)
55 ;               else CC if in shared resource
56 ;                 R0 == pointer to embedded template definition
57 ;               May return an error
58 ;
59 ; Use:          Finds a named template in the list.
60
61 tpl__find       ROUT
62
63                 ORRS    R14,R14,#C_flag         ;Set C initially
64                 STMFD   R13!,{R1,R2,R12,R14}    ;Stack some registers
65                 WSPACE  template_wspace         ;Find my workspace
66                 LDR     R2,template_list        ;Find the list head
67
68                 ; --- Go through the list trying to find one ---
69
70 00              CMP     R2,#0                   ;Is this the list end?
71                 BEQ     %10tpl__find            ;Yes -- return the error
72                 ADD     R1,R2,#tlist_name       ;Find this template's name
73                 BL      str_icmp                ;Compare the names
74                 LDRNE   R2,[R2,#tlist_next]     ;If no match, get next one...
75                 BNE     %b00                    ;And go round again
76
77                 ; --- We found a match!!! ---
78
79                 MOV     R0,R2                   ;Point to the template
80                 LDMFD   R13!,{R1,R2,R12,R14}    ;Unstack some registers
81                 BICS    PC,R14,#V_flag          ;Return with no error
82
83                 ; --- No match -- try shared resource ---
84
85 10tpl__find     MOV     R1,R0                   ;Point to the template name
86                 MOV     R0,#rsType_template     ;Search for template resource
87                 BL      resources_find          ;Try to find the resource
88                 LDMCSFD R13!,{R1,R2,R12,R14}    ;If it worked, get registers
89                 BICCSS  PC,R14,#C_flag + V_flag ;And return with no error
90
91                 ; --- Couldn't find it then ---
92
93 20tpl__find     MOV     R2,R1                   ;Point to the template name
94                 ADR     R0,tpl__notfound        ;Point to error message
95                 BL      msgs_error              ;Translate the message
96                 LDMFD   R13!,{R1,R2,R12,R14}    ;Unstack some registers
97                 ORRS    PC,R14,#V_flag          ;Return with the error
98
99 tpl__notfound   DCD     1
100                 DCB     "tplTNF",0
101
102                 LTORG
103
104 ; --- template_find ---
105 ;
106 ; On entry:     R0 == pointer to name to match
107 ;
108 ; On exit:      R0 == pointer to window definition if found
109 ;               May return an error
110 ;
111 ; Use:          Locates a template in the list and gives you a pointer to
112 ;               the corresponding window defintion.  You may update the
113 ;               definition to store an updated window state if you really
114 ;               want to.
115 ;
116 ;               Note that this call will fail if you attempt to find a
117 ;               template which is held in the shared resources DLL.
118
119                 EXPORT  template_find
120 template_find   ROUT
121
122                 STMFD   R13!,{R1,R2,R14}        ;Save return address
123                 MOV     R2,R0                   ;Remember the name
124                 BL      tpl__find               ;Find the definition
125                 BVS     %10template_find        ;If failed, skip onwards
126                 BCC     %05template_find        ;If in resource DLL, skip
127                 ADD     R0,R0,#tlist_size       ;Point to window def
128                 LDMFD   R13!,{R1,R2,R14}        ;Return to caller
129                 BICS    PC,R14,#V_flag
130
131                 ; --- It's in the resources DLL ---
132
133 05template_find ADR     R0,tpl__notfound        ;Point to error message
134                 BL      msgs_error              ;Translate the message
135
136                 ; --- Couldn't find the template ---
137
138 10template_find LDMFD   R13!,{R1,R2,R14}        ;Restore registers
139                 ORRS    PC,R14,#V_flag          ;And return the error
140
141                 LTORG
142
143 ; --- template_copy ---
144 ;
145 ; On entry:     R0 == pointer to name to match
146 ;
147 ; On exit:      R0 == pointer to copy of a window definition
148 ;               May return an error
149 ;
150 ; Use:          Returns a copy of a window template (for the use of the
151 ;               dialogue box system mainly), including all indirected data
152 ;               set up properly and everything.  The copy is writable.  To
153 ;               get rid of the copy, call template_free.
154
155                 EXPORT  template_copy
156 template_copy   ROUT
157
158                 ; --- Find the copy first ---
159
160                 STMFD   R13!,{R1-R5,R14}        ;Save some registers
161                 BL      tpl__find               ;Find the definition
162                 BVS     %99template_copy        ;If it failed, tidy up
163                 BCC     %50template_copy        ;In resources -- handle it
164                 MOV     R5,R0                   ;Keep pointer to definition
165
166                 ; --- Now allocate the memory we need ---
167
168                 LDR     R0,[R5,#84+tlist_size]  ;Get the number of icons
169                 MOV     R0,R0,LSL #5            ;Multiply by 32 for size
170                 ADD     R0,R0,#88+tlist_size    ;Bump up by overhead
171                 MOV     R2,R0                   ;Keep the size safe
172                 BL      alloc                   ;Allocate the memory
173                 BCS     %98template_copy        ;If that failed, skip ahead
174                 MOV     R4,R0                   ;Keep that pointer safe
175
176                 ; --- Copy the window defintion over ---
177
178                 MOV     R1,R5                   ;Point to the definition
179                 MOV     R0,R4                   ;And my new block
180                 BL      fastMove                ;Copy that data across
181
182                 ; --- Now see if we need do anything else
183
184                 LDR     R0,[R5,#tlist_indsize]  ;Get indirected data size
185                 CMP     R0,#0                   ;Is there any?
186                 BEQ     %10template_copy        ;If not, skip past this bit
187
188                 ; --- Allocate the indirected space ---
189
190                 MOV     R2,R0                   ;Look after the size
191                 BL      alloc                   ;Allocate the new block
192                 BCS     %97template_copy        ;And tidy up if it failed
193
194                 ; --- Copy indirected data over ---
195
196                 LDR     R1,[R5,#tlist_indptr]   ;Find the old indirect block
197                 BL      fastMove                ;Copy it over very quickly
198                 STR     R0,[R4,#tlist_indptr]   ;Store the new block pointer
199
200                 ; --- Now fix up all the references ---
201
202                 SUB     R5,R0,R1                ;Get the relocation offset
203                 LDR     R0,[R4,#56+tlist_size]  ;Get the title bar flags
204                 ADD     R1,R4,#72+tlist_size    ;Point to the title data
205                 BL      tpl__fixData            ;Fix up that data
206
207                 LDR     R3,[R4,#84+tlist_size]  ;Get the number of icons
208                 ADD     R2,R4,#88+tlist_size    ;Point to the first icon
209 00template_copy SUBS    R3,R3,#1                ;Decrement the icon counter
210                 LDRGE   R0,[R2,#16]             ;Get the icon flags word
211                 ADDGE   R1,R2,#20               ;Point to the icon data
212                 BLGE    tpl__fixData            ;And fix up the icon data
213                 ADDGE   R2,R2,#32               ;Move onto the next icon
214                 BGE     %00template_copy        ;And move onto the next one
215
216                 ; --- All done -- return the pointer ---
217
218 10template_copy ADD     R0,R4,#tlist_size       ;Point to the actual defn
219                 LDMFD   R13!,{R1-R5,R14}        ;Unstack a load of registers
220                 BICS    PC,R14,#V_flag          ;Return to caller
221
222                 ; --- It's in the resources DLL ---
223
224 50template_copy LDMFD   R13!,{R1-R5,R14}        ;Restore these registers
225                 B       template_embedded       ;Extract embedded definition
226
227                 ; --- Error -- free the template block ---
228
229 97template_copy MOV     R0,R4                   ;Point to the template block
230                 BL      free                    ;Free up the block
231
232                 ; --- Return the error ---
233
234 98template_copy BL      alloc_error             ;Find the correct error mesg
235
236 99template_copy LDMFD   R13!,{R1-R5,R14}        ;Restore the registers
237                 ORRS    PC,R14,#V_flag          ;Return to caller
238
239                 LTORG
240
241 ; --- tpl__fixData ---
242 ;
243 ; On entry:     R0 == icon flags
244 ;               R1 == pointer to icon data to fix
245 ;               R5 == offset to bodge data by
246 ;
247 ; On exit:      Registers preserved
248 ;
249 ; Use:          Relocates indirected data by a given amount
250
251 tpl__fixData    ROUT
252
253                 TST     R0,#&00000100           ;Is it indirected?
254                 MOVEQS  PC,R14                  ;No -- return right now
255
256                 ; --- Fix up icon data ---
257
258                 STMFD   R13!,{R14}              ;Save the link register
259                 LDR     R14,[R1,#0]             ;Get the data pointer
260                 ADD     R14,R14,R5              ;Relocate it
261                 STR     R14,[R1,#0]             ;And store it back again
262
263                 ; --- Is there validation data too? ---
264
265                 TST     R0,#&00000001           ;Does it contain text data?
266                 LDRNE   R14,[R1,#4]             ;Yes -- get validation ptr
267                 CMPNE   R14,#-1                 ;If the pointer sensible?
268                 LDMEQFD R13!,{PC}^              ;No -- return
269
270                 ; --- Relocate validation string pointer ---
271
272                 ADD     R14,R14,R5              ;Relocate it
273                 STR     R14,[R1,#4]             ;Store it back in the block
274                 LDMFD   R13!,{PC}^              ;Return to caller
275
276                 LTORG
277
278 ; --- template_embedded ---
279 ;
280 ; On entry:     R0 == pointer to embedded template definition
281 ;
282 ; On exit:      R0 == pointer to copy (as for template_copy)
283 ;
284 ; Use:          Extracts an embedded template into a template block.
285 ;               Embedded templates can be generated using the templAOF
286 ;               program, and then linked into your application.
287
288                 EXPORT  template_embedded
289 template_embedded ROUT
290
291                 STMFD   R13!,{R1-R7,R14}        ;Save some registers
292
293                 ; --- First load the header out ---
294
295                 LDMIA   R0,{R3-R5}              ;Load the three pointers out
296                 ADD     R3,R3,R0                ;Relocate the window pointer
297                 ADD     R4,R4,R0                ;Relocate the ind base ptr
298                 ADD     R5,R5,R0                ;Relocate the ind limit ptr
299                 ADD     R6,R0,#12               ;And find the relocation tbl
300
301                 ; --- Allocate a block for the window definition ---
302
303                 LDR     R14,[R3,#84]            ;Load the number of icons
304                 MOV     R0,#88+tlist_size       ;Get the base memory req
305                 ADD     R0,R0,R14,LSL #5        ;Add space for the icons
306                 SUB     R2,R0,#tlist_size       ;Keep size without extras
307                 BL      alloc                   ;Try to allocate the space
308                 BLCS    alloc_error             ;If it failed, get error
309                 BCS     %99template_embedded    ;And skip onwards
310                 MOV     R7,R0                   ;Look after this pointer
311
312                 ; --- Copy the window data over ---
313
314                 ADD     R0,R7,#tlist_size       ;Point to window def area
315                 MOV     R1,R3                   ;Point to the original def
316                 BL      fastMove                ;Copy that over
317
318                 ; --- Now handle the data ---
319
320                 SUBS    R0,R5,R4                ;Find indirected data size
321                 STR     R0,[R7,#tlist_indsize]  ;Store the size away
322                 STREQ   R0,[R7,#tlist_indptr]   ;If none, store null ptr
323                 BEQ     %10template_embedded    ;And skip on to relocate
324
325                 BL      alloc                   ;Allocate the space
326                 BLCS    alloc_error             ;If it failed, get error
327                 BCS     %98template_embedded    ;And skip onwards
328                 STR     R0,[R7,#tlist_indptr]   ;Store the pointer
329
330                 ; --- Copy the data over ---
331
332                 MOV     R1,R4                   ;Point to original data
333                 SUB     R2,R5,R4                ;Find the data size
334                 BL      fastMove                ;Copy it over nicely
335
336                 ; --- Finally do the relocation ---
337
338 10              MOV     R5,R0                   ;Look after indirected addr
339                 BL      resspr_area             ;Find the sprite area
340                 MOV     R4,R0                   ;Look after that too
341                 ADD     R0,R7,#tlist_size       ;Find window definition
342
343 00              CMP     R6,R3                   ;Finished yet?
344                 BCS     %90template_embedded    ;Yes -- wrap things up
345                 LDR     R14,[R6],#4             ;Load next directive
346                 MOV     R2,R14,LSR #28          ;Get the directive type
347                 BIC     R14,R14,#&F0000000      ;And the offset
348                 ADD     PC,PC,R2,LSL #2         ;Dispatch to handler
349                 DCB     "MDW!"
350                 B       %15template_embedded
351                 B       %20template_embedded
352                 B       %b00
353
354 15              LDR     R2,[R0,R14]             ;Load the word
355                 ADD     R2,R2,R5                ;Relocate for indirectedness
356                 STR     R2,[R0,R14]             ;Store it back again
357                 B       %b00                    ;Loop
358
359 20              STR     R4,[R0,R14]             ;Store the sprite area
360                 B       %b00                    ;Loop
361
362                 ; --- Finished -- return ---
363
364 90              LDMFD   R13!,{R1-R7,R14}        ;Load lots of registers
365                 BICS    PC,R14,#V_flag          ;And return errorless
366
367                 ; --- Errors -- tidy up ---
368
369 98              MOV     R6,R0                   ;Look after error pointer
370                 MOV     R0,R7                   ;Get the template block
371                 BL      free                    ;Free it
372                 MOV     R0,R6                   ;Restore error pointer
373
374 99              LDMFD   R13!,{R1-R7,R14}        ;Load lots of registers
375                 ORRS    PC,R14,#V_flag          ;And return the error
376
377                 LTORG
378
379 ; --- template_free ---
380 ;
381 ; On entry:     R0 == pointer to block allocated with template_copy
382 ;
383 ; On exit:      --
384 ;
385 ; Use:          Frees a template copy created using template_copy.
386
387                 EXPORT  template_free
388 template_free   ROUT
389
390                 STMFD   R13!,{R0,R1,R14}        ;Save some registers
391                 SUB     R1,R0,#tlist_size       ;Find base of block
392                 LDR     R0,[R1,#tlist_indptr]   ;Get indirect data pointer
393                 CMP     R0,#0                   ;Is there any indirect data?
394                 BLNE    free                    ;Yes -- free the memory
395                 MOV     R0,R1                   ;Get the block pointer
396                 BL      free                    ;Free that too
397                 LDMFD   R13!,{R0,R1,PC}^        ;Return to caller
398
399                 LTORG
400
401 ; --- template_load ---
402 ;
403 ; On entry:     R0 == pointer to name of template file to load
404 ;
405 ; On exit:      May return an error
406 ;
407 ; Use:          Loads the specified template file, and adds its window
408 ;               definitions into the template list so they can be used when
409 ;               creating dialogue boxes or windows.
410 ;
411 ;               If the templates can't be loaded (e.g. there isn't enough
412 ;               memory) an error is generated (and can be caught using the
413 ;               standard Sapphire except mechanism).
414
415                 EXPORT  template_load
416 template_load   ROUT
417
418                 ; --- We need a lot of registers! ---
419
420                 STMFD   R13!,{R0-R12,R14}       ;Save the registers we want
421                 WSPACE  template_wspace         ;Find my workspace
422
423                 ; --- Find out how big the file is ---
424
425                 MOV     R1,R0                   ;Point to the filename
426                 MOV     R0,#17                  ;Info about file please
427                 SWI     XOS_File                ;Try to load the file
428                 BVS     %99template_load        ;If no luck, make the error
429
430                 ; --- Allocate a heap block for it ---
431
432                 MOV     R0,R4                   ;Get the template file size
433                 BL      alloc                   ;Allocate the block
434                 BLCS    alloc_error             ;If it failed, get error
435                 BCS     %99template_load        ;If no luck, make the error
436                 MOV     R8,R0                   ;Guard pointer with life :-)
437
438                 ; --- Load template file into buffer ---
439
440                 MOV     R0,#16                  ;Load a file into memory
441                 LDR     R1,[R13,#0]             ;Get the filename back
442                 MOV     R2,R8                   ;Point to my buffer
443                 MOV     R3,#0                   ;Load into my buffer
444                 SWI     XOS_File                ;Load the file now
445                 BVS     %98template_load        ;Bad news -- free block first
446
447                 ; --- Now we can parse the file up ---
448
449                 ADD     R10,R8,#16              ;Find the first index entry
450 00template_load LDR     R0,[R10,#0]             ;Is this an empty entry?
451                 CMP     R0,#0                   ;Just check quickly
452                 BEQ     %05template_load        ;Yes -- we've finished
453
454                 ADD     R9,R8,R0                ;Point to the actual entry
455
456                 LDR     R1,[R10,#8]             ;Get the entry type number
457                 SUB     R1,R1,#1                ;Convert it to zero-indexed
458                 CMP     R1,#(%11-%10)/4         ;Make sure it's recognised
459                 BCS     %02template_load        ;No -- don't to it then
460                 STMFD   R13!,{R8,R12}           ;Save workspace and base
461                 MOV     R12,R13                 ;Point to this pair
462                 MOV     R14,PC                  ;Set up return address
463                 ADD     PC,PC,R1,LSL #2         ;Branch table dispatch
464                 B       %01template_load        ;And link in the block
465
466 10template_load B       tpl__loadWind           ;Load a window definition
467 11template_load
468
469 01template_load LDMFD   R13!,{R8,R12}           ;Find workspace too
470                 BVS     %98template_load        ;It failed miserably
471
472                 ; --- Link the returned block into the list ---
473
474                 LDR     R1,template_list        ;Find the list head
475                 STR     R1,[R0,#tlist_next]     ;Make it this one's next ptr
476                 STR     R0,template_list        ;And make this the list head
477
478                 ; --- Move on to the next entry ---
479
480 02template_load ADD     R10,R10,#24             ;Move to the next entry
481                 B       %00template_load        ;And go back again
482
483                 ; --- We finished loading the file -- free buffer ---
484
485 05template_load MOV     R0,R8                   ;Point to the file buffer
486                 BL      free                    ;Free the memory now
487
488                 ; --- Now we can leave ---
489
490                 LDMFD   R13!,{R0-R12,R14}       ;Return to caller
491                 BICS    PC,R14,#V_flag
492
493                 ; --- Error encountered after block allocation ---
494
495 98template_load MOV     R9,R0                   ;Keep error pointer
496                 MOV     R0,R8                   ;Point to the file buffer
497                 BL      free                    ;Free the memory now
498                 MOV     R0,R9                   ;Restore error pointer
499
500                 ; --- Error encountered before block allocation ---
501
502 99template_load ADD     R2,R0,#4                ;Point to error message
503                 ADR     R0,tload__error         ;Point to error skeleton
504                 BL      msgs_error              ;Create the error message
505                 ADD     R13,R13,#4              ;Skip past stacked R0
506                 LDMFD   R13!,{R1-R12,R14}       ;Return to caller
507                 ORRS    PC,R14,#V_flag          ;With error indicator set
508
509 tload__error    DCD     1
510                 DCB     "tplTLE",0
511
512                 LTORG
513
514 template_wspace DCD     0
515
516 ; --- template_init ---
517 ;
518 ; On entry:     R0 == pointer to application name
519 ;
520 ; On exit:      --
521 ;
522 ; Use:          Initialises the template list and font array, and loads the
523 ;               `Templates' resource file.
524
525                 EXPORT  template_init
526 template_init   ROUT
527
528                 STMFD   R13!,{R0,R1,R12,R14}    ;Store some registers
529                 WSPACE  template_wspace         ;Find my workspace
530                 LDR     R14,template_list       ;Get the current list
531                 CMP     R14,#0                  ;Is it silly?
532                 LDMNEFD R13!,{R0,R1,R12,PC}^    ;No -- we're already running
533
534                 BL      alloc_init              ;Make sure we can find memory
535                 BL      resspr_init             ;This will initialise res too
536                 BL      except_init             ;For atexit to tidy up later
537
538                 ; --- Set up the workspace nicely ---
539
540                 MOV     R0,#0                   ;Store null pointers
541                 STR     R0,template_list        ;No templates yet
542                 STR     R0,template_fonts       ;No fonts found either
543
544                 ; --- Build the name in the scratchpad ---
545
546                 ADR     R0,tpl__templates       ;Point to the resource name
547                 MOV     R1,R11                  ;Point to scratchpad buffer
548                 ADDS    R0,R0,#0                ;Clear C and V flags
549                 BL      res_find                ;Find the resource file
550
551                 ; --- Load the file and return ---
552
553                 BLCS    template_load           ;Load the file if it's there
554                 SWIVS   OS_GenerateError        ;If it failed, make an error
555                 LDMFD   R13!,{R0,R1,R12,PC}^    ;Return to the caller
556
557 tpl__templates  DCB     "Templates",0
558
559                 LTORG
560
561 ; --- tpl__killFont ---
562 ;
563 ; On entry:     R12 == pointer to template workspace
564 ;
565 ; On exit:      --
566 ;
567 ; Use:          Loses loads of fonts when the application quits
568
569 tpl__killFont   ROUT
570
571                 STMFD   R13!,{R0-R2,R14}        ;Save some registers
572                 LDR     R1,template_fonts       ;Find the font array
573                 MOV     R0,#255                 ;Start at the top for this
574 00tpl__killFont LDRB    R2,[R1,R0]              ;Get the reference counter
575 01tpl__killFont SUBS    R2,R2,#1                ;Decrement the counter
576                 SWIGE   Font_LoseFont           ;Lose the font
577                 BGE     %01tpl__killFont        ;And go round again
578                 SUBS    R0,R0,#1                ;Decrement the handle
579                 BGE     %00tpl__killFont        ;And go round again
580                 LDMFD   R13!,{R0-R2,PC}^        ;And return to caller
581
582                 LTORG
583
584 ;----- Template loading routines --------------------------------------------
585 ;
586 ; For all routines:
587 ;
588 ; On entry:     R9 == pointer to entry in memory
589 ;               R10 == pointer to index entry for this object
590 ;               R12 == pointer to template base and workspace block
591 ;
592 ; On exit:      If successful:
593 ;                 R0 == pointer to template entry to add into the list
594 ;                 V flag clear
595 ;               If an error occurred:
596 ;                 R0 == pointer to standard error block
597 ;                 V flag set
598 ;               R1-R9 may be corrupted
599
600 ; --- tpl__loadWind ---
601 ;
602 ; Use:          Loads a window definition and converts it into a template
603 ;               list item
604
605 tpl__loadWind   ROUT
606
607                 STMFD   R13!,{R14}              ;Just stack the return addr
608
609                 ; --- Find out how many icons there are ---
610
611                 ADD     R0,R9,#84               ;Point to the right place
612                 AND     R1,R0,#3                ;Get the non-word-alignedness
613                 BIC     R0,R0,#3                ;And round down to word
614                 LDMIA   R0,{R2,R3}              ;Get the two words we want
615                 MOV     R1,R1,LSL #3            ;Turn bytes into bits
616                 MOV     R8,R2,LSR R1            ;Get the bottom few bytes
617                 RSB     R1,R1,#32               ;Get the shift the other way
618                 ORR     R8,R8,R3,LSL R1         ;And copy in the top bytes
619
620                 ; --- R8 now contains the number of icons ---
621
622                 ; --- Allocate a template block ---
623
624                 MOV     R3,R8,LSL #5            ;Multiply the number by 32
625                 ADD     R3,R3,#88+tlist_size    ;Add on window and list block
626                 MOV     R0,R3                   ;I want to allocate memory
627                 BL      alloc                   ;Allocate the space
628                 BLCS    alloc_error             ;If it failed, get error
629                 BCS     %99tpl__loadWind        ;If it failed, return error
630                 MOV     R7,R0                   ;Keep the pointer
631
632                 ; --- Copy the window definition into the block ---
633
634                 ADD     R0,R7,#tlist_size       ;Where to store definition
635                 SUB     R2,R3,#tlist_size       ;Size of block to copy
636                 MOV     R1,R9                   ;Point to the window def
637                 BL      fastMove                ;And shunt the bytes over
638
639                 ; --- We may as well copy the name over now too ---
640
641                 ADD     R1,R10,#12              ;Point to the template name
642                 ADD     R0,R7,#tlist_name       ;Point to my block section
643                 LDMIA   R1,{R2-R4}              ;Get the twelve bytes
644                 STMIA   R0,{R2-R4}              ;Store them in my block
645                 MOV     R1,#0                   ;And zero terminate
646                 STRB    R1,[R0,#12]             ;Stop the string off nicely
647
648                 ; --- Widge the sprite area ---
649
650                 BL      resspr_area             ;Load the sprite area ptr
651                 STR     R0,[R7,#64+tlist_size]  ;Store sprite area pointer
652
653                 ; --- Now count the amount of indirected data ---
654
655                 MOV     R6,#0                   ;Currently no indirected size
656
657                 LDR     R5,[R7,#56+tlist_size]  ;Get the title bar flags
658                 ADD     R4,R7,#72+tlist_size    ;Point to the title bar data
659                 BL      tpl__dataSize           ;Add in the space required
660
661                 MOV     R0,R8                   ;The number of icons I have
662                 ADD     R1,R7,#88+tlist_size    ;Point to the first icon
663 00tpl__loadWind SUBS    R0,R0,#1                ;Decrement the counter
664                 LDRGE   R5,[R1,#16]             ;Get the flags word here
665                 ADDGE   R4,R1,#20               ;Point to the icon data
666                 BLGE    tpl__dataSize           ;Add in the extra data
667                 ADDGE   R1,R1,#32               ;Point to the next icon defn
668                 BGE     %00tpl__loadWind        ;And go back for the rest
669
670                 ; --- We now have the data size in R6 ---
671
672                 STR     R6,[R7,#tlist_indsize]  ;Store the buffer size away
673                 CMP     R6,#0                   ;Is there any indirect space?
674                 STREQ   R6,[R7,#tlist_indptr]   ;No -- store a null pointer
675                 BEQ     %01tpl__loadWind        ;... and skip past allocation
676
677                 ; --- Allocate the buffer properly ---
678
679                 MOV     R0,R6                   ;Get the size of the block
680                 BL      alloc                   ;Allocate yet more memory
681                 BLCS    alloc_error             ;If failed, get error
682                 BCS     %98tpl__loadWind        ;If it failed, report error
683                 MOV     R6,R0                   ;Point to the new buffer
684                 STR     R6,[R7,#tlist_indptr]   ;Save indirected size away
685
686                 ; --- Now copy the indirected data across ---
687                 ;
688                 ; We also fix up the pointers at the same time, and set up
689                 ; any fonts that need loading.
690
691 01tpl__loadWind LDR     R5,[R7,#56+tlist_size]  ;Get the title bar flags
692                 ADD     R4,R7,#72+tlist_size    ;Point to the title bar data
693                 BL      tpl__copyData           ;Process the indirect data
694                 ADD     R5,R7,#56+tlist_size    ;Point to the flags now
695                 BL      tpl__findFont           ;And handle any fonts
696                 BVS     %97tpl__loadWind        ;Quit if something went wrong
697
698                 MOV     R0,R8                   ;The number of icons I have
699                 ADD     R1,R7,#88+tlist_size    ;Point to the first icon
700 02tpl__loadWind SUBS    R0,R0,#1                ;Decrement the counter
701                 BLT     %03tpl__loadWind        ;If no more, skip ahead
702                 LDR     R5,[R1,#16]             ;Get the flags word here
703                 ADD     R4,R1,#20               ;Point to the icon data
704                 BL      tpl__copyData           ;Copy over the indirect data
705                 ADD     R5,R1,#16               ;Point to the flags now
706                 BL      tpl__findFont           ;And handle any fonts
707                 BVS     %97tpl__loadWind        ;Quit if something went wrong
708                 ADD     R1,R1,#32               ;Point to the next icon defn
709                 B       %02tpl__loadWind        ;Now go back for the rest
710
711                 ; --- The excitement's over now, so that's it ---
712
713 03tpl__loadWind MOV     R0,R7                   ;Point at the template block
714                 LDMFD   R13!,{R14}              ;Get the link register out
715                 BICS    PC,R14,#V_flag          ;And return no errors
716
717                 ; --- Something screwed up -- deallocate both blocks ---
718
719 97tpl__loadWind MOV     R9,R0                   ;Save error pointer
720                 LDR     R0,[R7,#tlist_indptr]   ;Find the indirect block addr
721                 BL      free                    ;Free indirect data block
722                 MOV     R0,R9                   ;Restore error pointer
723
724                 ; --- Error occurred -- free the template block ---
725
726 98tpl__loadWind MOV     R9,R0                   ;Save error pointer
727                 MOV     R0,R7                   ;Point to template block
728                 BL      free                    ;Free the template block
729                 MOV     R0,R9                   ;Restore error pointer
730
731                 ; --- Error occurred -- return with V set ---
732
733 99tpl__loadWind LDMFD   R13!,{R14}              ;Get the link register
734                 ORRS    PC,R14,#V_flag          ;Set the error indicator
735
736                 LTORG
737
738 ;----- Support functions ----------------------------------------------------
739
740 ; --- tpl__dataSize ---
741 ;
742 ; On entry:     R4 == pointer to icon data
743 ;               R5 == icon flags word
744 ;               R6 == counter to increment
745 ;               R7 == pointer to window block
746 ;               R8 == number of icons in the window
747 ;               R9 == pointer to the window definition in the template file
748 ;               R10 == pointer to index for current window
749 ;               R12 == pointer to template base and workspace block
750 ;
751 ; On exit:      R6 incremented by an appropriate amount
752 ;               Everything else preserved (except R14, obviously!)
753 ;
754 ; Use:          Counts the amount of indirected space required for a given
755 ;               icon flags/data pair and adds it into a running total
756
757 tpl__dataSize   ROUT
758
759                 ; --- Make sure there's something to do ---
760
761                 TST     R5,#&00000100           ;Test indirected bit
762                 MOVEQS  PC,R14                  ;If not indirected, go away
763
764                 ; --- Locate and count the indirected data string ---
765
766                 STMFD   R13!,{R14}              ;Save some registers
767                 LDR     R14,[R4,#8]             ;Get the indirect buffer size
768                 ADD     R6,R6,R14               ;And add this onto the count
769
770                 ; --- Check if there's a validation string ---
771
772                 TST     R5,#&00000001           ;Is the `Is text' bit on?
773                 LDRNE   R14,[R4,#4]             ;Yes -- get validation ptr
774                 CMPNE   R14,#-1                 ;Is it a sensible pointer?
775                 LDMEQFD R13!,{PC}^              ;If not, we're done for now
776
777                 ; --- Count length of validation string ---
778
779                 STMFD   R13!,{R0}               ;Save another register
780                 ADD     R0,R14,R9               ;Point to string in memory
781                 BL      str_len                 ;Find its length
782                 ADD     R0,R0,#1                ;Account for the terminator
783                 ADD     R6,R6,R0                ;Add this to the counter
784                 LDMFD   R13!,{R0,PC}^           ;And return to the caller
785
786                 LTORG
787
788 ; --- tpl__copyData ---
789 ;
790 ; On entry:     R4 == pointer to icon data
791 ;               R5 == icon flags word
792 ;               R6 == pointer to free part of buffer
793 ;               R7 == pointer to window block
794 ;               R8 == number of icons in the window
795 ;               R9 == pointer to the window definition in the template file
796 ;               R10 == pointer to index for current window
797 ;               R12 == pointer to template base and workspace block
798 ;
799 ; On exit:      R6 incremented by an appropriate amount
800 ;               Everything else preserved (except R14, obviously!)
801 ;
802 ; Use:          Copies indirected data from an icon definition into the
803 ;               buffer given and fixes up pointers in the definition
804
805 tpl__copyData   ROUT
806
807                 ; --- Make sure there's something to do here ---
808
809                 TST     R5,#&00000100           ;Check the indirected bit
810                 MOVEQS  PC,R14                  ;If unset, return right now
811
812                 ; --- Handle basic indirected data ---
813
814                 STMFD   R13!,{R0,R1,R14}        ;Stack some registers
815                 LDR     R1,[R4,#0]              ;Get the indirected pointer
816                 STR     R6,[R4,#0]              ;Store the new pointer in
817                 ADD     R1,R9,R1                ;Offset by window address
818                 MOV     R0,R6                   ;Point to free bit of bufffer
819                 BL      str_cpy                 ;Copy (and null-terminate)
820                 LDR     R14,[R4,#8]             ;Get the indirect buffer size
821                 ADD     R6,R6,R14               ;Move buffer pointer on by it
822
823                 ; --- Check for validation string presence ---
824
825                 TST     R5,#&00000001           ;Is the `Is text' bit on?
826                 LDRNE   R14,[R4,#4]             ;Yes -- get validation ptr
827                 CMPNE   R14,#-1                 ;Is it a sensible pointer?
828                 LDMEQFD R13!,{R0,R1,PC}^        ;If not, we're done
829
830                 ; --- Handle the validation string ---
831
832                 STR     R6,[R4,#4]              ;Store the new pointer
833                 ADD     R1,R9,R14               ;Point to the validation str
834                 MOV     R0,R6                   ;Point to the bit of buffer
835                 BL      str_cpy                 ;And copy the string across
836                 ADD     R6,R0,#1                ;Point R6 past string term
837                 LDMFD   R13!,{R0,R1,PC}^        ;That's it from us, then
838
839                 LTORG
840
841 ; --- tpl__findFont ---
842 ;
843 ; On entry:     R5 == pointer to icon flags word
844 ;               R6 == pointer to free part of buffer
845 ;               R7 == pointer to window block
846 ;               R8 == number of icons in the window
847 ;               R9 == pointer to the window definition in the template file
848 ;               R10 == pointer to index for current window
849 ;               R12 == pointer to template base and workspace block
850 ;
851 ; On exit:      Everything preserved except R4 (and R14, obviously!)
852 ;
853 ; Use:          Fixes up an icon's anti-aliased font data.
854
855 tpl__findFont   ROUT
856
857                 LDR     R4,[R5]                 ;Get the icon flags word
858                 TST     R4,#&00000040           ;Is it antialiased?
859                 TSTNE   R4,#&00000001           ;Make sure it's text too
860                 BICEQS  PC,R14,#V_flag          ;If not, return no error
861
862                 ; --- Now to business -- ensure we have a font table ---
863
864                 STMFD   R13!,{R0-R3,R5,R12,R14} ;Save some registers
865                 LDMIA   R12,{R5,R12}            ;Load base and workspace
866                 LDR     R0,template_fonts       ;Find font array pointer
867                 CMP     R0,#0                   ;Is it null?
868                 BEQ     %00tpl__findFont        ;Yes -- allocate it
869
870                 ; --- Now locate the font table in the file ---
871
872 01tpl__findFont LDR     R3,[R5,#0]              ;Get the font table offset
873                 ADD     R3,R5,R3                ;Convert it to a pointer
874
875                 ; --- Find internal font handle and get table entry ---
876
877                 MOV     R0,R4,LSR #24           ;Leave only the font handle
878                 SUB     R0,R0,#1                ;Convert to 0-indexed
879                 STMFD   R13!,{R4,R5}            ;Need some more registers!!
880                 ADD     R4,R3,R0,LSL #4         ;R4 = R3 + R0 * 16
881                 ADD     R4,R4,R0,LSL #5         ;Now R4 = R3 + R0 * 48
882
883                 ; --- Now we must load the font width and height ---
884                 ;
885                 ; The problem is that they're not on word boundaries, so
886                 ; we must do clever-dick things with the barrel shifter.
887
888                 AND     R0,R3,#3                ;Get the bottom two bits
889                 BIC     R1,R3,#3                ;Word align the base address
890                 LDMIA   R1,{R2,R3,R14}          ;Get the width and height
891                 MOV     R0,R0,LSL #3            ;Convert bits to bytes
892                 RSB     R1,R0,#32               ;Get the other shift too
893                 MOV     R2,R2,LSR R0            ;Shift the bits down here
894                 ORR     R2,R2,R3,LSL R1         ;And add in the top bits
895                 MOV     R3,R3,LSR R0            ;Shift down bottom bits
896                 ORR     R3,R3,R14,LSL R1        ;And add in the top bits
897
898                 ; --- We are now in a position to find the font ---
899
900                 ADD     R1,R4,#8                ;Point to the font name
901                 MOV     R4,#0                   ;Default x scaling
902                 MOV     R5,#0                   ;Default y scaling
903                 SWI     Font_FindFont           ;Try very hard to find it
904                 LDMFD   R13!,{R4,R5}            ;Restore these registers
905                 ADDVS   R13,R13,#4              ;If it failed, skip R0,
906                 LDMVSFD R13!,{R1-R3,PC}         ;... and restore regs
907
908                 ; --- Now bump the item in the font array ---
909
910                 LDR     R1,template_fonts       ;Find the font array
911                 LDRB    R2,[R1,R0]              ;Get counter for the handle
912                 ADD     R2,R2,#1                ;Bump the counter a bit
913                 STRB    R2,[R1,R0]              ;And store it away again
914
915                 ; --- Bodge the icon flags word for the new handle ---
916
917                 BIC     R4,R4,#&FF000000        ;Clear out the old handle
918                 ORR     R4,R4,R0,LSL #24        ;Bring in the new...
919                 STR     R4,[R5]                 ;Store the new flags word
920                 LDMFD   R13!,{R0-R3,R5,R12,R14} ;Restore the registers
921                 BICS    PC,R14,#V_flag          ;And return with no error
922
923                 ; --- Create the font array if it's not there ---
924
925 00tpl__findFont MOV     R0,#256                 ;One byte for each font
926                 BL      alloc                   ;Allocate the memory
927                 BLCS    alloc_error             ;If failed, get error
928                 ADDCS   R13,R13,#4              ;If it failed, bump R13
929                 LDMCSFD R13!,{R1-R3,R5,R12,PC}  ;... and return with error
930                 STR     R0,template_fonts       ;Store the new pointer
931
932                 ; --- Clear the font array to 0s ---
933
934                 MOV     R1,#256                 ;The size of the array
935                 MOV     R2,#0                   ;Value to initialise with
936                 BL      mem_set                 ;Clear out the array
937
938                 ; --- Register our tidy-up routine ---
939
940                 ADR     R0,tpl__killFont        ;Point to tidy up function
941                 MOV     R1,R12                  ;Point to my workspace
942                 BL      except_atExit           ;Register it properly
943                 B       %01tpl__findFont        ;Return to the main proc
944
945                 LTORG
946
947 ;----- The list structure ---------------------------------------------------
948
949                 ^       0
950 tlist_start     #       0
951
952 tlist_next      #       4                       ;Pointer to the next one
953 tlist_name      #       16                      ;Name of this template
954 tlist_indptr    #       4                       ;Pointer to indirect data
955 tlist_indsize   #       4                       ;Size of indirect data
956 ; Window definition follows
957
958 tlist_size      #       0                       ;Size of that structure
959
960 ;----- Workspace ------------------------------------------------------------
961
962                 ^       0,R12
963 template_wstart #       0
964
965 template_list   #       4                       ;List head for templates
966 template_fonts  #       4                       ;Font array if we need one
967
968 template_wsize  EQU     {VAR}-template_wstart
969
970                 AREA    |Sapphire$$LibData|,CODE,READONLY
971
972                 DCD     template_wsize
973                 DCD     template_wspace
974                 DCD     256
975                 DCD     template_init
976
977 ;----- That's all, folks ----------------------------------------------------
978
979                 END