chiark / gitweb /
Initial revision
[ssr] / StraySrc / Libraries / Sapphire / s / fontMenu
1 ;
2 ; fontMenu.s
3 ;
4 ; Fontmenu creation
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                 GET     libs:stream
33
34 ;----- External dependencies ------------------------------------------------
35
36                 GET     sapphire:alloc
37                 GET     sapphire:event
38                 GET     sapphire:flex
39                 GET     sapphire:menu
40                 GET     sapphire:menuDefs
41                 GET     sapphire:msgs
42                 GET     sapphire:sapphire
43                 GET     sapphire:string
44
45 ;----- Main code ------------------------------------------------------------
46
47                 AREA    |Sapphire$$Code|,CODE,READONLY
48
49 ; --- fm_create ---
50 ;
51 ; On entry:     R0 == current font name
52 ;               R1 == handler to call when selection made
53 ;               R2 == R10 value to call with
54 ;               R3 == R12 value to call with
55 ;               R4 == pointer to routine to call to create submenu
56 ;                     (ie. menu_create or tms_create)
57 ;
58 ; On exit:      CS if any fonts exist and
59 ;                 R0 == pointer to a menu definition
60 ;                 R1 == event handler to call
61 ;                 R2 == R10 value for event handler
62 ;                 R3 == R12 value for event handler
63 ;               else CC and
64 ;                 R0-R3 corrupted
65 ;               May return an error
66 ;
67 ; Use:          Creates a user menu definition suitable for passing directly
68 ;               to (menu|tms)_create. Note however, that the menu defintion
69 ;               does *not* include any title; this must be created first.
70 ;               If you require items such as the system font, then
71 ;               add these to the menu before creating the menu returned
72 ;               from this call.
73
74                 EXPORT  fm_create
75 fm_create       ROUT
76
77                 STMFD   R13!,{R0,R4-R10,R12,R14} ;Save some registers
78                 WSPACE  fm__wSpace
79
80                 ; --- Save the caller's handler ---
81
82                 ADR     R14,fm__userHandler     ;Point to the handler
83                 STMIA   R14,{R1-R4}             ;Store it away
84
85                 ; --- Ensure that we need to create it ---
86
87                 MOV     R0,R11                  ;Build path in scratchpad
88                 BL      fm__fontPath            ;Get the current fontpath
89                 BCC     %70fm_create            ;None found -- no fonts then
90
91                 LDR     R14,fm__flags           ;Load the flags word
92                 TST     R14,#fmFlag__changed    ;Have the fonts changed?
93                 BICNE   R14,R14,#fmFlag__changed ;Yes -- clear the flag
94                 STRNE   R14,fm__flags           ;...store the flags
95                 BNE     %00fm_create            ;...and recreate the menu
96
97                 LDR     R1,fm__block            ;Load our block address
98                 MOVS    R2,R1                   ;Is it defined yet?
99                 ADRNE   R1,fm__path             ;Point to saved font path
100                 BLNE    str_cmp                 ;Compare with current path
101                 MOVNE   R2,#0                   ;If not equal, clear pointer
102                 CMP     R2,#0                   ;So, do we recreate?
103                 BNE     %40fm_create            ;No -- return current menu
104
105                 MOV     R1,R11                  ;Point to font path string
106                 ADR     R0,fm__path             ;Point to font path buffer
107                 BL      str_cpy                 ;Take a copy of the path
108
109 00fm_create     LDR     R0,fm__block            ;Load address of menu block
110                 CMP     R0,#0                   ;Is it created currently?
111                 BLNE    free                    ;Yes -- free it then
112
113                 ; --- Set up a flex block ---
114                 ;
115                 ; We will read the font names into this block, to make it
116                 ; easier to actually build our menu, and reduce heap
117                 ; fragmentation.
118                 ;
119                 ; The format of the data in the block is as follows:
120                 ;
121                 ;        Size   Use
122                 ;     /   4     Number of variants (0 for regular only)
123                 ;     |   ?     Name of this family
124                 ;     \ [ ?     Name of this variant
125
126                 SUB     R13,R13,#12             ;Make a small anchor block
127                 MOV     R0,R13                  ;Point to the block
128                 MOV     R1,#1024                ;Start it off at 256 bytes
129                 BL      flex_alloc              ;Allocate the block
130                 BLCS    alloc_error             ;If it failed, get error
131                 BCS     %80fm_create            ;And return to caller
132
133                 MOV     R0,#0                   ;Start at the beginning
134                 STMIB   R13,{R0,R1}             ;Save them in the block
135
136                 MOV     R9,#4                   ;No length for main menu
137                 MOV     R10,#0                  ;Or for the submenus
138
139                 ; --- Start building font names now ---
140
141                 MOV     R2,#0                   ;Start from the beginning
142                 MOV     R1,R11                  ;Build string in ScratchPad
143                 MOV     R3,#256                 ;Size of scratchpad buffer
144                 SWI     Font_ListFonts          ;Read a font name
145                 CMP     R2,#-1                  ;Is that the very end?
146                 BEQ     %65fm_create            ;Yes -- abort now then
147                 MOV     R4,#0                   ;Found one family so far
148
149                 MOV     R6,#0                   ;Clear a flags word
150                 MOV     R1,R11                  ;Point to the font name
151                 BL      fm__parse               ;Break the name up
152                 ORRCC   R6,R6,#1                ;If `Regular', set a flag
153                 MOV     R3,R1                   ;Look after variant name
154                 MOV     R8,R0                   ;Look after the family name
155
156                 ; --- Set this family name up ---
157
158 10fm_create     MOV     R5,#0                   ;This is the first variant
159
160                 MOV     R0,R13                  ;Point to the anchor block
161                 MOV     R1,#4                   ;Make space for count word
162                 BL      fm__ensure              ;Allocate space for it
163                 BVS     %79fm_create            ;If we couldn't, abort
164                 ADD     R7,R0,#4                ;Point just past this word
165
166                 FSAVE   R7                      ;Save R7 on relocation stack
167                 MOV     R1,R8                   ;Get family name in R1
168                 MOV     R0,R13                  ;Point to the anchor block
169                 BL      fm__string              ;Write the family name out
170                 BVS     %79fm_create            ;If it failed, abort now
171                 ADD     R0,R0,#3+8              ;Word align returned length
172                 BIC     R0,R0,#3                ;Tumtetiddlytumtetum
173                 ADD     R9,R9,R0                ;Add on to main menu length
174                 ADD     R9,R9,#4                ;Remember space for radio
175                 ADD     R10,R10,R0              ;And add on submenu length
176
177                 ; --- Write this variant out ---
178
179 15fm_create     MOV     R0,R13                  ;Point to anchor block
180                 MOV     R1,R3                   ;Point to variant name
181                 BL      fm__string              ;Add this on the end
182                 BVS     %79fm_create            ;If it failed, abort now
183                 ADD     R0,R0,#3+12             ;Word align returned length
184                 BIC     R0,R0,#3                ;Omtiddlyompepom
185                 ADD     R10,R10,R0              ;Add this to submenu length
186                 ADD     R5,R5,#1                ;Increment variant counter
187
188                 ; --- Get the next font name ready ---
189
190                 MOV     R8,R6                   ;Remember current flags
191                 MOV     R1,R11                  ;Build string in ScratchPad
192                 MOV     R3,#256                 ;Size of scratchpad buffer
193                 SWI     Font_ListFonts          ;Read a font name
194                 CMP     R2,#-1                  ;Is that the very end?
195                 BEQ     %20fm_create            ;Yes -- we've finished then
196
197                 BL      fm__parse               ;Break up the font name
198                 ORRCC   R6,R6,#1                ;If `Regular', set a flag
199                 BICCS   R6,R6,#1                ;Otherwise clear it
200
201                 MOV     R3,R1                   ;Look after the variant name
202                 FLOAD   R1                      ;Restore family name address
203                 BL      str_cmp                 ;Do the strings match?
204                 FSAVE   R1                      ;Save the address back
205                 BEQ     %15fm_create            ;And loop round for more
206
207                 ; --- Finished a family ---
208
209 20fm_create
210                 FLOAD   R7                      ;Reload family name address
211                 CMP     R5,R8                   ;Is there only `Regular'?
212                 MOVEQ   R5,#0                   ;Yes -- claim no variants
213                 STR     R5,[R7,#-4]             ;Save it in the block
214                 MOV     R8,R0                   ;Look after the family name
215                 MOV     R0,R13                  ;Point to anchor block
216                 BL      fm__align               ;Word align output pointer
217                 ADD     R4,R4,#1                ;Increment family counter
218                 CMP     R2,#-1                  ;Are there more font names?
219                 BNE     %10fm_create            ;Yes -- put them in the block
220
221                 ; --- Allocate a big heap block ---
222
223                 ADD     R0,R9,R10               ;Add the menu sizes up
224                 ADD     R0,R0,R4,LSL #2         ;And an indexing block
225                 BL      alloc                   ;Allocate this block
226                 BLCS    alloc_error             ;If it failed, get error
227                 BCS     %79fm_create            ;And return to caller
228
229                 STR     R0,fm__block            ;Store this block address
230
231                 ; --- A note about register allocation ---
232                 ;
233                 ; Dear reader,
234                 ;   I have decided, it being Saturday and all, to allocate
235                 ; registers thusly:
236                 ;
237                 ;  R7 == pointer into submenu indexing table
238                 ;  R8 == pointer into the main menu structure
239                 ;  R9 == pointer into the submenu area
240                 ; R10 == pointer into our juicy big flex table
241                 ;
242                 ;               Yours sincerely
243                 ;
244                 ;                       Mark Wooding (Straylight Dev Lab)
245
246                 MOV     R7,R0                   ;Point to indexing table
247                 ADD     R8,R7,R4,LSL #2         ;Find the main menu area
248                 ADD     R9,R8,R9                ;And find the submenu area
249                 LDR     R10,[R13,#0]            ;Load base of flex block
250                 STR     R8,fm__menu             ;Store the menu address
251
252                 ; --- Now the fun begins ---
253
254 22fm_create     MOV     R0,#mFlag_radio         ;Get the flag ready
255                 ORR     R0,R0,#mFlag_R12        ;And make data R12-relative
256                 LDR     R6,[R10],#4             ;Load the number of variants
257                 CMP     R6,#0                   ;Do we want a submenu?
258                 ORRNE   R0,R0,#mFlag_subWarn    ;Yes -- set the flag then
259                 STR     R0,[R8],#4              ;Save it in the menu block
260
261                 MOVEQ   R14,#0                  ;No submenu -- get null ptr
262                 STREQ   R14,[R7],#4             ;And clear submenu address
263                 STRNE   R9,[R7],#4              ;Save this submenu address
264
265                 MOV     R0,R10                  ;Look after this address
266 23fm_create     LDRB    R14,[R10],#1            ;Load a family name byte
267                 CMP     R14,#0                  ;Is this the end yet?
268                 STRB    R14,[R8],#1             ;Save it in the menu block
269                 BNE     %23fm_create            ;And go round for the rest
270
271                 ADD     R8,R8,#3                ;Word align the output addr
272                 BIC     R8,R8,#3                ;Yingtongiddleipo
273
274                 MOV     R1,#4                   ;Offset 0 in radio block
275                 MOV     R2,R8                   ;Magic radio group tag
276                 STMIA   R8!,{R1,R2}             ;Save these in the block
277
278                 ; --- Now build the variants submenu ---
279
280                 CMP     R6,#0                   ;Do we want a submenu
281                 BEQ     %28fm_create            ;No -- *still skip past name*
282
283                 MOV     R14,#0                  ;Title flags
284                 STR     R14,[R9],#4             ;Save in submenu block
285 24fm_create     LDRB    R14,[R0],#1             ;Load a family name byte
286                 STRB    R14,[R9],#1             ;Save it in the menu block
287                 CMP     R14,#0                  ;Is this the end yet?
288                 BNE     %24fm_create            ;And go round for the rest
289
290                 ADD     R9,R9,#3                ;Word align the output addr
291                 BIC     R9,R9,#3                ;Obblyjobblywibbledidee
292
293                 ; --- Create an item for each variant ---
294
295 25fm_create     MOV     R0,#mFlag_radio         ;Get the flag ready
296                 ORR     R0,R0,#mFlag_R12        ;And make data R12-relative
297                 STR     R0,[R9],#4              ;Save in submenu block
298
299 26fm_create     LDRB    R14,[R10],#1            ;Load a variant name byte
300                 CMP     R14,#0                  ;Is this the end yet?
301                 STRB    R14,[R9],#1             ;Save it in the menu block
302                 BNE     %26fm_create            ;And go round for the rest
303
304                 ADD     R9,R9,#3                ;Word align the output addr
305                 BIC     R9,R9,#3                ;Obblyjobblywibbledidee
306
307                 MOV     R1,#8                   ;Offset 8 in radio block
308                 MOV     R2,R9                   ;Magic radio group tag
309                 STMIA   R9!,{R1,R2}             ;Save these in the block
310
311                 SUBS    R6,R6,#1                ;Decrement the counter
312                 BGT     %25fm_create            ;And do the rest of them
313
314                 MOV     R14,#mFlag_end          ;Terminate the menu
315                 STR     R14,[R9],#4             ;Save that at the end
316
317                 B       %30fm_create            ;Skip to end of family stuff
318
319                 ; --- No variants -- omit the submenu ---
320                 ;
321                 ; For odd reasons, we actually leave a `(Regular)' item
322                 ; in the flex block.  We need to skip over this here.
323
324 28fm_create     LDRB    R14,[R10],#1            ;Load a variant name byte
325                 CMP     R14,#0                  ;Is this the end yet?
326                 BNE     %28fm_create            ;And go round for the rest
327
328 30fm_create     ADD     R10,R10,#3              ;Word align flex block ptr
329                 BIC     R10,R10,#3              ;[Silly comment omitted]
330
331                 SUBS    R4,R4,#1                ;Done another family
332                 BGT     %22fm_create            ;And go round for the rest
333
334                 MOV     R14,#mFlag_end          ;Terminate the menu
335                 STR     R14,[R8],#4             ;Save that at the end
336
337                 ; --- Destroy the flex block ---
338
339                 MOV     R0,R13                  ;Point to the flex anchor
340                 BL      flex_free               ;Free the block
341                 ADD     R13,R13,#12             ;Restore stack pointer
342
343                 ; --- Now return the menu and things ---
344
345 40fm_create     LDR     R0,[R13],#4             ;Load the name to tick
346                 BL      fm_tickFont             ;Tick that font
347                 LDR     R0,fm__menu             ;Find the menu address
348                 ADR     R1,fm__handler1         ;I don't have a handler :-(
349                 MOV     R2,#0                   ;No R10 value either :~-(
350                 MOV     R3,R12                  ;And pass workspace in R12
351                 LDMFD   R13!,{R4-R10,R12,R14}   ;Restore registers
352                 ORR     R14,R14,#C_flag         ;Set C to say we did it
353                 BICS    PC,R14,#V_flag          ;And return errorless
354
355                 ; --- Couldn't find any fonts (oops) ---
356
357 65fm_create     ADD     R13,R13,#12             ;Restore stack pointer
358 70fm_create     LDMFD   R13!,{R0,R4-R10,R12,R14} ;Restore registers
359                 BICS    PC,R14,#V_flag+C_flag   ;And return CC
360
361                 ; --- Tidy up after catastrophes ---
362
363 79fm_create     MOV     R10,R0                  ;Look after the error
364                 MOV     R0,R13                  ;Point to the flex anchor
365                 BL      flex_free               ;Free the flex block
366                 MOV     R0,R10                  ;Restore the error pointer
367
368 80fm_create     ADD     R13,R13,#12+4           ;Restore the stack nicely
369                 LDMFD   R13!,{R4-R10,R12,R14}   ;Restore registers
370                 ORRS    PC,R14,#V_flag          ;And return the error
371
372                 LTORG
373
374 ; --- fm__handler1 ---
375 ;
376 ; On entry:     R0 == menu event
377 ;               R1 == menu item
378 ;               R12 == pointer to private workspace
379 ;
380 ; On exit:      --
381 ;
382 ; Use:          Handles events on the first level menu.
383
384 fm__handler1    ROUT
385
386                 CMP     R0,#mEvent_select       ;Is it a menu selection
387                 CMPNE   R0,#mEvent_subMenu      ;Or a submenu event?
388                 MOVNES  PC,R14                  ;Nope -- return
389
390                 STMFD   R13!,{R1-R4,R14}        ;Stack registers
391                 CMP     R0,#mEvent_select       ;A selection?
392                 BEQ     %50fm__handler1         ;Yes -- jump ahead
393
394                 ; --- Handle submenu events ---
395
396                 LDR     R0,fm__block            ;Point to useful table
397                 LDR     R0,[R0,R1,LSL #2]       ;Load submenu address
398                 MOV     R2,R1                   ;Pass item number in R10
399                 ADR     R1,fm__handler2         ;And point to second handler
400                 MOV     R3,R12                  ;And workspace in R12
401                 LDR     R4,fm__creator          ;Load address of creator
402                 MOV     R14,PC                  ;Set up return address
403                 MOV     PC,R4                   ;Call the creator
404                 B       %90fm__handler1         ;Return to caller
405
406                 ; --- User selected an item ---
407
408 50fm__handler1  MOV     R3,R1                   ;Remember index value
409                 BL      fm__familyName          ;Get family name pointer
410                 MOV     R1,R0                   ;Put it in R1
411                 ADR     R0,fm__name             ;Write the name here
412                 BL      str_cpy                 ;Copy over family name
413                 MOV     R2,R0                   ;Put terminator ptr in R2
414                 LDR     R0,fm__block            ;Load table pointer
415                 LDR     R0,[R0,R3,LSL #2]       ;Load submenu pointer
416                 CMP     R0,#0                   ;Is there a submenu?
417                 BEQ     %60fm__handler1         ;No -- jump ahead
418                 MOV     R1,#0                   ;Just choose first index
419                 BL      fm__variantName         ;Find the first variant name
420                 CMP     R0,#0                   ;Is there one?
421                 BEQ     %60fm__handler1         ;No -- return now then
422                 MOV     R1,R0                   ;Put it in R1
423                 MOV     R0,R2                   ;Copy it to here
424                 MOV     R14,#'.'                ;We want a '.' first
425                 STRB    R14,[R0],#1             ;Store in the string
426                 BL      str_cpy                 ;Copy over the string
427
428 60fm__handler1  MOV     R0,#fmEvent_select      ;The event type
429                 ADR     R1,fm__name             ;Point to the name
430                 BL      fm__dispatch            ;Dispatch the event
431
432 90fm__handler1  LDMFD   R13!,{R1-R4,PC}^        ;Load back registers
433
434                 LTORG
435
436 ; --- fm__handler2 ---
437 ;
438 ; On entry:     R0 == menu event
439 ;               R1 == menu item
440 ;               R10 == menu item submenu came from
441 ;               R12 == pointer to workspace
442 ;
443 ; On exit:      --
444 ;
445 ; Use:          Handles events for a second level submenu
446
447 fm__handler2    ROUT
448
449                 CMP     R0,#mEvent_select       ;Is it a menu selection
450                 MOVNES  PC,R14                  ;Nope -- return
451
452                 STMFD   R13!,{R1-R3,R14}        ;Stack registers
453
454                 MOV     R3,R1                   ;Remember index value
455                 MOV     R1,R10                  ;Get previous index
456                 BL      fm__familyName          ;Get family name pointer
457                 MOV     R1,R0                   ;Put it in R1
458                 ADR     R0,fm__name             ;Write the name here
459                 BL      str_cpy                 ;Copy over family name
460                 MOV     R2,R0                   ;Put terminator ptr in R2
461                 LDR     R0,fm__block            ;Load table pointer
462                 LDR     R0,[R0,R10,LSL #2]      ;Load submenu pointer
463                 MOV     R1,R3                   ;Put index in R1
464                 BL      fm__variantName         ;Find the variant name
465                 CMP     R0,#0                   ;Is there a name?
466                 BEQ     %10fm__handler2         ;No -- retur now then
467                 MOV     R1,R0                   ;Put it in R1
468                 MOV     R0,R2                   ;Copy it to here
469                 MOV     R14,#'.'                ;We want a '.' first
470                 STRB    R14,[R0],#1             ;Store in the string
471                 BL      str_cpy                 ;Copy over the string
472
473 10fm__handler2  MOV     R0,#fmEvent_select      ;The event type
474                 ADR     R1,fm__name             ;Point to the name
475                 BL      fm__dispatch            ;Dispatch the event
476
477                 LDMFD   R13!,{R1-R3,PC}^        ;Load back registers
478
479                 LTORG
480
481 ; --- fm__dispatch ---
482 ;
483 ; On entry:     R0-R9 == event data
484 ;               R12 == workspace pointer
485 ;
486 ; On exit:      --
487 ;
488 ; Use:          Sends an event to the users font menu handler.
489
490 fm__dispatch    ROUT
491
492                 STMFD   R13!,{R9,R10,R12,R14}   ;Stack registers
493                 ADR     R14,fm__userHandler     ;Point to the handler
494                 LDMIA   R14,{R9,R10,R12}        ;Load registers
495                 CMP     R9,#0                   ;Sanity check
496                 MOV     R14,PC                  ;Sey up return address
497                 MOVNE   PC,R9                   ;Call the handler
498                 LDMFD   R13!,{R9,R10,R12,PC}^   ;Return to caller
499
500                 LTORG
501
502 ; --- fm_tickFont ---
503 ;
504 ; On entry:     R0 == name to tick
505 ;
506 ; On exit:      --
507 ;
508 ; Use:          Ticks the font with tht given name in the fontmenu. If
509 ;               no font exists then the existing ticks are removed
510
511                 EXPORT  fm_tickFont
512 fm_tickFont     ROUT
513
514                 CMP     R0,#0                   ;Is R0 NULL?
515                 MOVEQS  PC,R14                  ;Yes -- return now
516                 STMFD   R13!,{R0-R4,R14}        ;Stack some registers
517                 WSPACE  fm__wSpace              ;Locate my workspace
518                 MOV     R1,R0                   ;Put the name in R1
519                 MOV     R0,R11                  ;Point to the scratchpad
520                 BL      str_cpy                 ;Copy the string over
521                 MOV     R1,R11                  ;Put the pointer in R1
522                 BL      fm__parse               ;Parse up the string
523                 MOVCS   R4,#1                   ;Not regular
524                 MOVCC   R4,#0                   ;Yes it is sir
525                 MOV     R3,R1                   ;Put variant name in R3
526
527                 ; --- Clear the existing ticks ---
528
529                 MOV     R14,#0                  ;Get a NULL word
530                 STR     R14,fm__ticks           ;Clear first tick
531                 STR     R14,fm__ticks+4         ;And second tick
532
533                 ; --- Search for the font name ---
534
535                 LDR     R1,fm__menu             ;Point to the menu definition
536                 MOV     R2,#0                   ;Index so far
537 00fm_tickFont   LDR     R14,[R1],#4             ;Load the flags word
538                 TST     R14,#mFlag_end          ;Have we reached the end?
539                 BNE     %90fm_tickFont          ;Yes -- return
540                 BL      str_icmp                ;Does this name match
541                 BEQ     %50fm_tickFont          ;Yes -- jump ahead
542 10fm_tickFont   LDRB    R14,[R1],#1             ;Load a character
543                 CMP     R14,#0                  ;Is it a terminator?
544                 BNE     %10fm_tickFont          ;No -- keep on looking
545                 ADD     R1,R1,#3+8              ;Word align, skip over data
546                 BIC     R1,R1,#3
547                 ADD     R2,R2,#1                ;Increment the index
548                 B       %00fm_tickFont          ;Keep on looking
549
550                 ; --- We have found a match ---
551                 ;
552                 ; First we must get the tick word thing
553
554 50fm_tickFont   LDRB    R14,[R1],#1             ;Load a character
555                 CMP     R14,#0                  ;Is it a terminator?
556                 BNE     %50fm_tickFont          ;No -- keep on looking
557                 ADD     R1,R1,#3+4              ;Word align, pount to thing
558                 BIC     R1,R1,#3
559                 LDR     R14,[R1]                ;Load the data word thing
560                 STR     R14,fm__ticks           ;Store as first level tick
561
562                 ; --- Now search the submenu ---
563
564                 LDR     R1,fm__block            ;Point to table
565                 LDR     R1,[R1,R2,LSL #2]       ;Load submenu pointer
566                 CMP     R1,#0                   ;Is there one?
567                 BEQ     %90fm_tickFont          ;Nope -- return
568
569                 MOV     R0,R3                   ;Put variant name in R0
570
571                 ; --- Skip over title data ---
572
573                 ADD     R1,R1,#4                ;Skip over flags word
574 52fm_tickFont   LDRB    R14,[R1],#1             ;Load a byte
575                 CMP     R14,#0                  ;Have we reach the end?
576                 BNE     %52fm_tickFont          ;No -- keep looking
577                 ADD     R1,R1,#3                ;Word align
578                 BIC     R1,R1,#3
579
580                 ; --- Select 'Regular' if appropriate ---
581
582                 CMP     R4,#0                   ;Did user select 'Regular'?
583                 ADDEQ   R1,R1,#4                ;Yes -- skip over glags
584                 BEQ     %58fm_tickFont          ;...and tick this one then
585
586                 ; --- Now search for the family name ---
587
588 54fm_tickFont   LDR     R14,[R1],#4             ;Load the flags word
589                 TST     R14,#mFlag_end          ;Have we reached the end?
590                 BNE     %90fm_tickFont          ;Yes -- return
591                 BL      str_icmp                ;Does this name match
592                 BEQ     %58fm_tickFont          ;Yes -- jump ahead
593 56fm_tickFont   LDRB    R14,[R1],#1             ;Load a character
594                 CMP     R14,#0                  ;Is it a terminator?
595                 BNE     %56fm_tickFont          ;No -- keep on looking
596                 ADD     R1,R1,#3+8              ;Word align, skip over data
597                 BIC     R1,R1,#3
598                 B       %54fm_tickFont          ;Keep on looking
599
600                 ; --- We have found a match ---
601
602 58fm_tickFont   LDRB    R14,[R1],#1             ;Load a character
603                 CMP     R14,#0                  ;Is it a terminator?
604                 BNE     %58fm_tickFont          ;No -- keep on looking
605                 ADD     R1,R1,#3+4              ;Word align, pount to thing
606                 BIC     R1,R1,#3
607                 LDR     R14,[R1]                ;Load the data word thing
608                 STR     R14,fm__ticks+4         ;Store as first level tick
609
610                 ; --- Return to caller ---
611
612 90fm_tickFont   LDMFD   R13!,{R0-R4,PC}^        ;Return to caller
613
614                 LTORG
615
616 ; --- fm__familyName ---
617 ;
618 ; On entry:     R1 == index of name
619 ;               R12 == workspace pointer
620 ;
621 ; On exit:      R0 == poiner to family name
622 ;
623 ; Use:          Points to the family name for the given menu index
624
625 fm__familyName  ROUT
626
627                 STMFD   R13!,{R1,R14}           ;Stack registers
628                 LDR     R0,fm__menu             ;Point to the menu block
629
630                 ADD     R0,R0,#4                ;Skip over flags word
631                 CMP     R1,#0                   ;Is this index 0?
632                 BEQ     %90fm__familyName       ;Yes -- return happy then
633 00              LDRB    R14,[R0],#1             ;Load a byte
634                 CMP     R14,#0                  ;Is it the end?
635                 BNE     %00fm__familyName       ;No -- keep looking
636                 ADD     R0,R0,#3+8+4            ;Word align and point to next
637                 BIC     R0,R0,#3
638                 SUBS    R1,R1,#1                ;Decrement the count
639                 BNE     %00fm__familyName       ;And keep on looking
640
641 90              LDMFD   R13!,{R1,PC}^           ;Return to caller
642
643                 LTORG
644
645 ; --- fm__variantName ---
646 ;
647 ; On entry:     R0 == pointer to submenu
648 ;               R1 == index of name
649 ;               R12 == workspace pointer
650 ;
651 ; On exit:      R0 == poiner to family name, or 0 for regular
652 ;
653 ; Use:          Points to the family name for the given menu index
654
655 fm__variantName ROUT
656
657                 STMFD   R13!,{R1,R14}           ;Stack registers
658
659                 ADD     R0,R0,#4                ;Skip over flags word
660
661 00              LDRB    R14,[R0],#1             ;Load a byte
662                 CMP     R14,#0                  ;Is it the end?
663                 BNE     %00fm__variantName      ;No -- keep looking
664                 ADD     R0,R0,#3+4              ;Word align and point to fst
665                 BIC     R0,R0,#3
666
667                 CMP     R1,#0                   ;Is this index 0?
668                 BEQ     %90fm__variantName      ;Yes -- return happy then
669 10              LDRB    R14,[R0],#1             ;Load a byte
670                 CMP     R14,#0                  ;Is it the end?
671                 BNE     %10fm__variantName      ;No -- keep looking
672                 ADD     R0,R0,#3+8+4            ;Word align and point to next
673                 BIC     R0,R0,#3
674                 SUBS    R1,R1,#1                ;Decrement the count
675                 BNE     %10fm__variantName      ;And keep on looking
676
677 90              MOV     R1,R0                   ;Put string in R1
678                 ADR     R0,fm__regular          ;Point to regular name
679                 BL      msgs_lookup             ;Translate it
680                 BL      str_cmp                 ;Is this a match?
681                 MOVNE   R0,R1                   ;No -- return name then
682                 MOVEQ   R0,#0                   ;Yes -- return 0 then
683                 LDMFD   R13!,{R1,PC}^           ;Return to caller
684
685                 LTORG
686
687 ; --- fm__parse ---
688 ;
689 ; On entry:     R1 == pointer to font name
690 ;
691 ; On exit:      R0 == pointer to font family name (R1 on entry)
692 ;               R1 == pointer to font variant name
693 ;               CS if variant spcified explicitly, CC if `Regular'
694 ;
695 ; Use:          Parses a font name into a family and variant.
696
697 fm__parse       ROUT
698
699                 STMFD   R13!,{R2,R3,R14}        ;Save some registers
700                 MOV     R2,R1                   ;Look after start pointer
701
702 00fm__parse     LDRB    R14,[R1],#1             ;Load next byte from name
703                 CMP     R14,#'.'                ;Is this a dot?
704                 BEQ     %10fm__parse            ;Yes -- found the variant
705                 CMP     R14,#32                 ;Is this the end?
706                 BCS     %00fm__parse            ;No -- keep looking then
707
708                 ; --- Reached end of name -- must be (Regular) ---
709
710                 MOV     R14,#0                  ;Zero terminate for luck
711                 STRB    R14,[R1,#-1]            ;Save it over the terminator
712                 ADR     R0,fm__regular          ;Find the regular message
713                 BL      msgs_lookup             ;Translate it nicely
714                 MOV     R3,R1                   ;Point to variant buffer
715 05fm__parse     LDRB    R14,[R0],#1             ;Load a byte from `Regular'
716                 CMP     R14,#32                 ;Is this a control char?
717                 MOVCC   R14,#0                  ;Yes -- zero terminate then
718                 STRB    R14,[R3],#1             ;Store in destination
719                 BCS     %05fm__parse            ;And loop round for the rest
720
721                 MOV     R0,R2                   ;Point to family name again
722                 LDMFD   R13!,{R2,R3,R14}        ;Unstack registers
723                 BICS    PC,R14,#C_flag          ;And return to caller
724
725                 ; --- Found a variant ---
726
727 10fm__parse     MOV     R14,#0                  ;Zero terminate for luck
728                 STRB    R14,[R1,#-1]            ;Save it over the terminator
729                 MOV     R0,R2                   ;Point to family name again
730                 LDMFD   R13!,{R2,R3,R14}        ;Unstack registers
731                 ORRS    PC,R14,#C_flag          ;And return to caller
732
733 fm__regular     DCB     "fmREG:(Regular)",0
734
735                 LTORG
736
737 ; --- fm__ensure ---
738 ;
739 ; On entry:     R0 == address of anchor and size info
740 ;               R1 == free space required
741 ;
742 ; On exit:      R0 == address of first free byte in area
743 ;               May return an error
744 ;
745 ; Use:          Ensures that there is the requested quantity of memory free
746 ;               in the given block.
747
748 fm__ensure      ROUT
749
750                 STMFD   R13!,{R1,R2,R14}        ;Save some registers
751                 LDMIB   R0,{R2,R14}             ;Load used and size words
752                 ADD     R1,R1,R2                ;Find new total size
753                 STR     R1,[R0,#4]              ;Save this back
754                 ADD     R1,R1,#255              ;Align up to next 256
755                 BIC     R1,R1,#255              ;For niceness's sake
756                 CMP     R1,R14                  ;Do we already have enough?
757                 BHI     %50fm__ensure           ;No -- allocate some more
758 10fm__ensure    STR     R1,[R0,#8]              ;Save new total size
759                 LDR     R0,[R0,#0]              ;Load address of block
760                 ADD     R0,R0,R2                ;Point to first free byte
761                 LDMFD   R13!,{R1,R2,R14}        ;And return to caller
762                 BICS    PC,R14,#V_flag
763
764 50fm__ensure    BL      flex_extend             ;No -- then extend the block
765                 BCC     %10fm__ensure           ;If OK, rejoin the main thing
766                 BL      alloc_error             ;Find an error message
767                 LDMFD   R13!,{R1,R2,R14}        ;Restore registers
768                 ORRS    PC,R14,#V_flag          ;And return the error
769
770                 LTORG
771
772 ; --- fm__string ---
773 ;
774 ; On entry:     R0 == pointer to anchor and size info
775 ;               R1 == pointer to null terminated string
776 ;
777 ; On exit:      R0 == length of the string+1
778 ;               May return an error
779 ;
780 ; Use:          Writes a string on the end of the given block.
781
782 fm__string      ROUT
783
784                 STMFD   R13!,{R0-R3,R14}        ;Save some registers
785                 MOV     R2,R0                   ;Look after the anchor ptr
786                 MOV     R3,R1                   ;Keep the string address
787                 MOV     R0,R1                   ;Point to the string
788                 BL      str_len                 ;Find the length of it
789                 ADD     R1,R0,#1                ;Allow space for terminator
790                 STR     R1,[R13,#0]             ;Save this as return value
791                 MOV     R0,R2                   ;Point to the anchor
792                 BL      fm__ensure              ;Make sure there's enough
793                 MOVVC   R1,R3                   ;Point to string to write
794                 BLVC    str_cpy                 ;Copy the string over
795                 STRVS   R0,[R13,#0]             ;If it failed, return error
796                 LDMFD   R13!,{R0-R3,PC}         ;And return to caller
797
798                 LTORG
799
800 ; --- fm__align ---
801 ;
802 ; On entry:     R0 == pointer to anchor and size info
803 ;
804 ; On exit:      --
805 ;
806 ; Use:          Word aligns the block output address.
807
808 fm__align       ROUT
809
810                 STMFD   R13!,{R14}              ;Save a register
811                 LDR     R14,[R0,#4]             ;Load the current used offset
812                 ADD     R14,R14,#3              ;Round up to word boundary
813                 BIC     R14,R14,#3              ;And do the round op
814                 STR     R14,[R0,#4]             ;Save the offset back again
815                 LDMFD   R13!,{PC}^              ;And return to caller
816
817                 LTORG
818
819 ; --- fm__fontPath ---
820 ;
821 ; On entry:     R0 == pointer to buffer
822 ;
823 ; On exit:      CS if there is a font path
824 ;               CC otherwise
825 ;
826 ; Use:          Reads the environmental variable font$path and copies
827 ;               it into the buffer given. The buffer must be at least 256
828 ;               bytes long.
829
830 fm__fontPath    ROUT
831
832                 STMFD   R13!,{R0-R4,R14}
833                 MOV     R1,R0                   ;But buffer ptr in R1
834                 ADR     R0,fm__varName          ;Point to the name
835                 MOV     R2,#256                 ;Length of buffer
836                 MOV     R3,#0                   ;First (and last) call
837                 MOV     R4,#0                   ;Don't expand the string
838                 SWI     XOS_ReadVarVal          ;Read the variable
839                 MOV     R14,#0                  ;We need a NULL byte
840                 STRVCB  R14,[R1,R2]             ;Store the terminator
841                 LDMFD   R13!,{R0-R4,R14}        ;Load registers
842                 ORRVCS  PC,R14,#C_flag          ;Return C set if exists
843                 BICVSS  PC,R14,#C_flag          ;Or clear otherwise
844
845 fm__varName     DCB     "Font$Path",0
846
847                 LTORG
848
849 fm__wSpace      DCD     0
850
851 ; --- fm__postFilter ---
852 ;
853 ; On entry:     R0 == wimp event
854 ;               R1 == wimp poll block pointer
855 ;
856 ; On exit:      --
857 ;
858 ; Use:          Looks out for font changed events.
859
860 fm__postFilter  ROUT
861
862                 CMP     R0,#17                  ;Is it a message?
863                 CMPNE   R0,#18
864                 MOVNES  PC,R14                  ;Nope -- return
865                 STMFD   R13!,{R0,R14}           ;Stack registers
866                 LDR     R0,[R1,#16]             ;Load the message type
867                 LDR     R14,=&4A2C0             ;Fonts changed message number
868                 CMP     R14,R0                  ;Is that the message?
869                 LDMNEFD R13!,{R0,PC}^           ;No -- return now
870                 LDR     R14,fm__flags           ;Load flags word
871                 ORR     R14,R14,#fmFlag__changed
872                 STR     R14,fm__flags           ;Store back flags
873                 LDMFD   R13!,{R0,PC}^           ;Return to caller
874
875                 LTORG
876
877 ; --- fm_init ---
878 ;
879 ; On entry:     --
880 ;
881 ; On exit:      --
882 ;
883 ; Use:          Initialises the font menu system.
884
885                 EXPORT  fm_init
886 fm_init         ROUT
887
888                 STMFD   R13!,{R0,R1,R12,R14}    ;Stack some registers
889                 WSPACE  fm__wSpace
890                 MOV     R14,#0
891                 STR     R14,fm__flags           ;No flags set yet
892
893                 ; --- Set up the post filter ---
894
895                 BL      event_init              ;Ensure event is ready
896                 ADR     R0,fm__postFilter       ;Point to the handler
897                 MOV     R1,R12                  ;R12 value to pass
898                 BL      event_postFilter        ;Add in the post filter
899                 SWIVS   OS_GenerateError        ;Generate the error
900                 LDMFD   R13!,{R0,R1,R12,PC}^    ;Return to caller
901
902                 LTORG
903
904 ;----- Events ---------------------------------------------------------------
905
906                 ^       0
907 fmEvent_select  #       1                       ;User selected a font
908                                                 ;R1 == pointer to name
909
910 ;----- Workspace ------------------------------------------------------------
911
912                 ^       0,R12
913
914 fm__wStart      #       0
915
916 fm__block       #       4                       ;Address of our heap block
917 fm__ticks       #       8                       ;Tick blocks
918 fm__menu        #       4                       ;Pointer to existing menu
919 fm__name        #       40                      ;Static buffer to return name
920 fm__userHandler #       4                       ;User handler function
921 fm__R10         #       4                       ;R10 value to call with
922 fm__R12         #       4                       ;R12 value to call with
923 fm__creator     #       4                       ;Menu creation routine
924 fm__flags       #       4                       ;Useful flags word
925 fm__path        #       256                     ;Current font path
926
927 fm__wSize       EQU     {VAR}-fm__wStart
928
929 fmFlag__changed EQU     (1<<0)                  ;The fonts have changed
930
931                 AREA    |Sapphire$$LibData|,CODE,READONLY
932
933                 DCD     fm__wSize
934                 DCD     fm__wSpace
935                 DCD     256
936                 DCD     fm_init
937
938 ;----- That's all, folks ----------------------------------------------------
939
940                 END