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