Initial revision
[ssr] / StraySrc / Libraries / Sapphire / tms / s / tmsCreate
1 ;
2 ; tmsCreate.s
3 ;
4 ; Creation, recreation and destruction of tearoff menus (TMA)
5 ;
6 ; © 1994 Straylight
7 ;
8
9 ;----- Standard Header ------------------------------------------------------
10
11 GET libs:header
12 GET libs:swis
13
14 GET libs:stream
15
16 ;----- External dependencies ------------------------------------------------
17
18 GET sapphire:alloc
19 GET sapphire:heap
20 GET sapphire:keyString
21 GET sapphire:msgs
22 GET sapphire:resspr
23 GET sapphire:sapphire
24 GET sapphire:string
25 GET sapphire:wimp
26 GET sapphire:win
27 GET sapphire:winUtils
28
29 GET sapphire:_tms.tmsGlobal
30 GET sapphire:_tms.tmsMain
31
32 ;----- Main code ------------------------------------------------------------
33
34 AREA |Sapphire$$Code|,CODE,READONLY
35
36 ; --- tms__bitSpec ---
37 ;
38 ; On entry: R5 == pointer to base pointer (R10 or R12) for this item
39 ; R9 == pointer to bit specification to work out
40 ;
41 ; On exit: R9 has had 4 added to it
42 ; C set or clear according to settedness of the bit
43 ;
44 ; Use: Tells you whether a bit specification points at a bit which
45 ; is set or clear by copying it to the carry flag
46
47 tms__bitSpec ROUT
48
49 STMFD R13!,{R0,R14} ;Save some registers
50 LDR R0,[R9],#4 ;Load the specification
51 MOV R14,R0,LSR #5 ;Get the offset value
52 LDR R14,[R5,R14] ;Load the flags word out
53 AND R0,R0,#31 ;Leave only bit spec bits
54 ADD R0,R0,#1 ;To make it nice for shifting
55 MOVS R14,R14,LSR R0 ;Copy bit to carry flag
56 LDMFD R13!,{R0,R14} ;Load registers again
57 ORRCSS PC,R14,#C_flag ;Set C if C set
58 BICCCS PC,R14,#C_flag ;Clear C if C clear
59
60 LTORG
61
62 ; --- tms__findBase ---
63 ;
64 ; On entry: R2,R3 == R10 and R12 values to pass to event handler
65 ; R8 == flags word from packed definition
66 ;
67 ; On exit: R5 == correct base register for this item
68
69 tms__findBase ROUT
70
71 TST R8,#mFlag_R12 ;Is the R12 flag on?
72 MOVNE R5,R3 ;Yes -- return R12 value
73 MOVEQ R5,R2 ;No -- return R10 value
74 MOVS PC,R14 ;Return to caller
75
76 LTORG
77
78 ; --- tms__checksum ---
79 ;
80 ; On entry: R2 == pointer to a name
81 ;
82 ; On exit: R0 == checksum value
83 ;
84 ; Use: Calculates a checksum value for the given name
85
86 tms__checksum ROUT
87
88 STMFD R13!,{R2,R14} ;Stack some registers
89 MVN R0,#0 ;Start with -1
90 00 LDRB R14,[R2],#1 ;Load a byte
91 CMP R14,#' ' ;Are we at the end?
92 EORCS R0,R14,R0,LSL #2 ;Add it on to the sum
93 BCS %00tms__checksum ;No -- keep going then
94 LDMFD R13!,{R2,PC}^ ;Return to caller
95
96 ; --- tms__createTitle ---
97 ;
98 ; On entry: R9 == pointer to packed title definition
99 ;
100 ; On exit: R9 == pointer to packed item description
101 ; R10 == pointer to header structure, filled in and glorious
102 ; R0, R4-R8 corrupted
103 ;
104 ; Use: Builds a menu header block
105
106 tms__createTitle ROUT
107
108 BIC R14,R14,#V_flag ;Assume nothing can harm us
109 STMFD R13!,{R14} ;Save link register
110
111 MOV R0,#hSize ;Get the size we want
112 BL heap_alloc ;Allocate a block for it
113 BLCS alloc_error ;If no memory, get error msg
114 LDMVSFD R13!,{PC} ;And return with V still set
115 MOV R10,R0 ;Keep this pointer safe
116 STR R10,tms__creating ;Store this pointer nicely
117 STR R9,[R10,#hDefinition] ;Store pack defn pointer
118 MOV R0,#0 ;Also want to zero item blk
119 STR R0,tms__lastItems ;No item blocks created yet
120 STR R0,[R10,#hItems] ;No items attached yet
121 STR R0,[R10,#hKeyWidth] ;No shortcuts found yet
122 STR R0,[R10,#hTextWidth] ;No items yet
123 STR R0,[R10,#hSprWidth] ;No sprites yet
124 STR R0,[R10,#hHandle] ;No window attached yet
125 STR R0,[R10,#hNextTorn] ;Not in torn list
126 STR R0,[R10,#hDbox] ;No dialogue box yet
127 STR R0,[R10,#hFromItem] ;We're not from an item
128
129 MOV R6,#0 ;No flags defined yet
130
131 LDR R8,[R9],#4 ;Load the flags word out
132 BL tms__findBase ;Get the correct base pointer
133 TST R8,#mFlag_indirect ;Is this item indirected?
134 BEQ %00tms__createTitle ;No -- jump on then
135 STMFD R13!,{R1} ;Save a register nicely
136 LDR R1,[R9],#4 ;Yes -- find offset nicely
137 LDR R0,[R9],#4 ;...and the buffer size
138 LDR R1,[R5,R1] ;...get the pointer out
139
140 BL heap_alloc ;Allocate some memory
141 BLCS alloc_error ;Get the error message
142 MOVCS R0,R10 ;...point to the block
143 BLCS heap_free ;...free the memory
144 LDMCSFD R13!,{R1,PC} ;...and return
145
146 STR R0,[R10,#hText] ;Store the text pointer
147 BL str_cpy ;Copy the string into buffer
148 MOV R0,R1 ;Put the string in R0
149 LDMFD R13!,{R1} ;And restore R1 saved above
150 ORR R6,R6,#hFlag__tIndir ;Title is indirected
151 BNE %10tms__createTitle ;Skip past this next bit
152
153 00 MOV R0,R9 ;Point to the message tag
154 BL msgs_lookup ;Translate the message
155 05 LDRB R14,[R9],#1 ;Get a message string byte
156 CMP R14,#' ' ;Is it a terminator?
157 BGE %05tms__createTitle ;No -- get another one
158 ADD R9,R9,#3 ;Add 3
159 BIC R9,R9,#3 ;And word align the pointer
160 STR R0,[R10,#hText] ;Store the text pointer
161
162 ; --- Store the string and get its length ---
163
164 10 BL wimp_strWidth ;Get the string's width
165 ADD R0,R0,#32
166 STR R0,[R10,#hTitleWidth] ;Store as title width
167
168 ; --- Now handle other bits of the flags ---
169
170 TST R8,#mFlag_tearoff ;Are we tearable?
171 ORRNE R6,R6,#hFlag__tearable ;Yes -- set the bit nicely
172 TST R8,#mFlag_global ;Is menu `global'?
173 ORRNE R6,R6,#hFlag__global ;Yes -- set the bit nicely
174 STR R6,[R10,#hFlags] ;Store the flags word
175
176 ; --- Now check for maximum height ---
177
178 TST R8,#mFlag_maxHeight ;Is there a maximum height?
179 LDRNE R0,[R9],#4 ;Yes -- read it out then
180 MOVEQ R0,#0 ;No -- zero is a silly value
181 STR R0,[R10,#hMaxHeight] ;Store in the right place
182
183 ; --- Perform any other business ---
184
185 ADD R0,R10,#hHandler ;Point to the handler bitty
186 STMIA R0,{R1-R3} ;Store the 'handlers' away
187
188 90 LDMFD R13!,{PC}^ ;Return to caller
189
190 LTORG
191
192 ; --- tms_create ---
193 ;
194 ; On entry: R0 == pointer to a menu block
195 ; R1 == pointer to event handler for the menu section
196 ; R2 == R10 value to pass to the event handler
197 ; R3 == R12 value to pass to the event handler
198 ;
199 ; On exit: R0 == tearoff handle for this menu
200 ; May return an error
201 ;
202 ; Use: Creates a new menu, or adds sections to an existing one.
203
204 EXPORT tms_create
205 tms_create ROUT
206
207 BIC R14,R14,#V_flag ;Hope there's no error
208 STMFD R13!,{R1-R10,R12,R14} ;Save some registers away
209 LDR R12,=tms__wSpace ;Find my workspace pointer
210 WSPACE [R12] ;And then my workspace
211 MOV R9,R0 ;Keep pointer to definition
212
213 ; --- Get the menu header we're working on ---
214
215 LDR R10,tms__creating ;Get the menu header pointer
216 CMP R10,#0 ;Is it actually defined?
217 BLEQ tms__createTitle ;No -- go away and create it
218 BVS %99tms_create ;It failed -- return an error
219
220 ; --- Update ---
221 ;
222 ; OK, the pointer to the first packed item is in R9, and
223 ; R10 contains a pointer to a menu header.
224
225 LDR R8,[R9],#4 ;Load the item flags word
226 TST R8,#mFlag_end ;Is there only a title?
227 MOVNE R0,R10 ;Yes -- return the handle
228 LDMNEFD R13!,{R1-R10,R12,PC}^ ;Return to caller nicely
229
230 ; --- Now we need to scan through to count the items ---
231
232 MOV R7,R9 ;Current ptr in packed defn
233 MOV R0,#iHdrSize ;Count the fixed-size header
234 MOV R4,#0 ;Number of items I've found
235
236 00tms_create TST R8,#mFlag_indirect ;Is this item indirected?
237 ADDNE R7,R7,#4 ;Yes -- skip the offset word
238 BNE %02tms_create ;And skip past the loop
239
240 ; --- Skip inline text string ---
241
242 01tms_create LDRB R14,[R7],#1 ;Get a message string byte
243 CMP R14,#' ' ;Is it a terminator?
244 BGE %01tms_create ;No -- get another one
245 ADD R7,R7,#3 ;Add 3
246 BIC R7,R7,#3 ;And word align the pointer
247
248 ; --- Now skip other optional blocks ---
249
250 02tms_create TST R8,#mFlag_shortcut ;Is ther a normal...
251 TSTEQ R8,#mFlag_iShortcut ;...or indirected shortcut?
252 ADDNE R7,R7,#4 ;Yes -- skip over it then
253 SKPITEM R8,R7 ;Skip past another item
254 ADD R0,R0,#iItemSize ;Add on size for another item
255 ADD R4,R4,#1 ;And bump my counter too
256 LDR R8,[R7],#4 ;Load the next flags word
257 TST R8,#mFlag_end ;Is this the end yet?
258 BEQ %00tms_create ;Yes -- continue with the fun
259
260 ; --- R0 now contains how much we want ---
261
262 BL heap_alloc ;Allocate the memory now
263 BLCS alloc_error ;If it failed, find an error
264 BVS %99tms_create ;And return it nicely
265
266 ; --- Mangle all the list stuff ---
267
268 MOV R7,R0 ;Keep the pointer safely
269 LDR R6,tms__lastItems ;Get the last item block
270 CMP R6,#0 ;Is there one defined?
271 STRNE R7,[R6,#iItems] ;Yes -- store in next field
272 STREQ R7,[R10,#hItems] ;No -- store as list head
273 STR R7,tms__lastItems ;This is the new last blk
274 MOV R0,#0 ;Want to terminate the list
275 STR R0,[R7,#iItems] ;Store it in the next field
276 STR R0,[R7,#iDbox] ;No dialogue box yet
277
278 ; --- Build the item block header ---
279
280 STR R4,[R7,#iNumber] ;Store item counter
281 SUB R0,R9,#4 ;Point to definition start
282 STR R0,[R7,#iDefinition] ;Store in the pointer field
283 ADD R0,R7,#iHandler ;Point to the handler words
284 STMIA R0,{R1-R3} ;Store handler information
285
286 ; --- Now we actually want to build the block ---
287
288 LDR R8,[R9,#-4] ;Load the initial flags again
289 ADD R7,R7,#iHdrSize ;Skip past header part
290
291 10tms_create MOV R0,#-1 ;Get a NULL word
292 STR R0,[R7,#iKeyCode] ;No shortcut yet
293 BL tms__findBase ;Find base workspace register
294 TST R8,#mFlag_indirect ;Is this item indirected?
295 LDRNE R0,[R9],#4 ;Yes -- find offset nicely
296 LDRNE R0,[R5,R0] ;And get the pointer out
297 BNE %12tms_create ;Skip past this next bit
298
299 MOV R0,R9 ;Point to the message tag
300 BL msgs_lookup ;Translate the message
301 11tms_create LDRB R14,[R9],#1 ;Get a message string byte
302 CMP R14,#' ' ;Is it a terminator?
303 BGE %11tms_create ;No -- get another one
304 ADD R9,R9,#3 ;Add 2 (we added one in LDRB)
305 BIC R9,R9,#3 ;And word align the pointer
306
307 ; --- Store the pointer and carry on ---
308
309 12tms_create STR R0,[R7,#iText] ;Store the text pointer
310 BL wimp_strWidth ;Find the item width
311 LDR R14,[R10,#hTextWidth] ;Load previous text width
312 CMP R0,R14 ;Is this bigger?
313 STRGT R0,[R10,#hTextWidth] ;Yes -- store it over
314
315 TST R8,#mFlag_shortcut ;Is there a menu short cut?
316 TSTEQ R8,#mFlag_iShortcut ;Or an indirected one?
317 BEQ %15tms_create ;No -- jump ahead
318 TST R8,#mFlag_shortcut ;Is there a menu short cut?
319 LDRNE R0,[R9],#4 ;Yes -- load out key code
320 LDREQ R0,[R9],#4 ;No -- Load offset of code
321 LDREQ R0,[R5,R0] ;...load out key code
322 STR R0,[R7,#iKeyCode] ;Store the key code
323 MOV R1,#1 ;Return short version
324 BL keyString ;Find correct string
325 BL wimp_strWidth ;Get the string width
326 ADD R0,R0,#16 ;Put a gap on each side
327 LDR R1,[R10,#hKeyWidth] ;Get longest one so far
328 CMP R0,R1 ;Is this on longer?
329 STRGT R0,[R10,#hKeyWidth] ;Yes -- store it then
330
331 ; --- Severe cleverness warning ---
332 ;
333 ; The TST instructions clear Z iff the appropriate bit is
334 ; on. tms__bitSpec sets C iff the appropriate bit read from
335 ; a bit spec is on. We can actually combine testing for
336 ; (C && !Z) with the HI condition code. This saves jumping
337 ; around a lot.
338
339 15tms_create MOV R6,#0 ;Current flags word
340
341 TST R8,#mFlag_shade ;Check shadedness bit
342 BLNE tms__bitSpec ;Handle the bit specification
343 ORRHI R6,R6,#iFlag__shaded ;If set, shade the item
344 BHI %13tms_create ;...and jump this next bit
345
346 TST R8,#mFlag_iShade ;Check shadedness bit
347 BLNE tms__bitSpec ;Handle the bit specification
348 ORRNE R6,R6,#iFlag__shaded ;Set shaded bit anyway
349 BICHI R6,R6,#iFlag__shaded ;Bit clear it again if set!
350
351 13tms_create TST R8,#mFlag_switch ;Check switchiness bit
352 BLNE tms__bitSpec ;Handle the bit specification
353 ORRHI R6,R6,#iFlag__ticked ;If set, tick it
354
355 TST R8,#mFlag_radio ;Check radioness bit
356 BEQ %14tms_create ;If not set, skip ahead
357 LDMIA R9!,{R0,R1} ;Load the information out
358 LDR R0,[R5,R0] ;Load the radio specifier
359 CMP R0,R1 ;Is this a match made in hvn?
360 ORREQ R6,R6,#iFlag__radio ;Yes -- attach the splodge
361
362 ; --- Deal with sprites ---
363
364 14tms_create TST R8,#mFlag_sprite ;Is there a sprite?
365 BEQ %20tms_create ;No -- jump ahead
366 STMFD R13!,{R2-R6} ;SpriteOp corrupts all these!
367 LDMIA R9!,{R0,R1} ;Load the information out
368 LDR R2,[R5,R0] ;Load the actual sprit addr
369 STR R2,[R7,#iSprName] ;Save the name value
370 BL tms__checksum ;Get the checksum
371 STR R0,[R7,#iSprCsum] ;And store it away
372 MOVS R0,R1 ;Get the sprite area
373 BLMI resspr_area ;Negative -- get app's one
374 MOV R1,R0 ;Put sprite area in R1 again
375 STR R1,[R7,#iSprArea] ;Save the sprite area
376 ORR R6,R6,#iFlag__sprite ;The item has a sprite
377 TST R8,#mFlag_halfSize ;Should we display at half sz
378 ORRNE R6,R6,#iFlag__halfSize ;Yes -- remember this
379 STR R6,[R13,#16] ;Save this for later
380
381 ; --- Find the width of the sprite ---
382
383 CMP R1,#1 ;Are we using WIMP area?
384 MOVNE R0,#256+40 ;No -- on user area name
385 SWINE OS_SpriteOp ;...get information
386 MOVEQ R0,#40 ;Yes -- info please
387 SWIEQ Wimp_SpriteOp ;Get it then
388 MOV R0,R6 ;Get the sprite's mode
389 MOV R1,#4 ;Get the XEig factor
390 SWI OS_ReadModeVariable ;Read the value
391 MOV R3,R3,LSL R2 ;Work out the width in OS
392 LDR R0,[R10,#hSprWidth] ;Load current sprite width
393 TST R8,#mFlag_halfSize ;Should we display at half sz
394 MOVNE R3,R3,LSR #1 ;Yes -- then divide by 2
395 ADD R3,R3,#16 ;Add on a little clearance
396 CMP R3,R0 ;Is this bigger than that?
397 STRGT R3,[R10,#hSprWidth] ;Yes -- then overwrite
398 LDMFD R13!,{R2-R6} ;Restore those registers
399
400 20tms_create TST R8,#mFlag_ruleOff ;Is there a ruleoff here
401 ORRNE R6,R6,#iFlag__dotted ;Yes -- add a dotted line
402 TST R8,#mFlag_subWarn+mFlag_subMenu ;Arrow wanted?
403 ORRNE R6,R6,#iFlag__arrow ;Yes -- add the arrow
404
405 SKIP mFlag_subMenu,8,R8,R9 ;Skip submenu bit nicely
406
407 TST R8,#mFlag_noWarn ;Do we warn on shaded items?
408 ORRNE R6,R6,#iFlag__noWarn ;No -- remember this
409
410 STR R6,[R7,#iFlags] ;Store the sussed out flags
411 MOV R6,#0 ;A NULL pointer
412 STR R6,[R7,#iSubMenu] ;No sub menu from here
413 ADD R7,R7,#iItemSize ;Point at the next item
414
415 ; --- Get the next flags word and loop ---
416
417 LDR R8,[R9],#4 ;Get the next flags word
418 TST R8,#mFlag_end ;Is this an end marker?
419 BEQ %10tms_create ;No -- do the next one
420
421 ; --- Return interesting things to caller ---
422
423 MOV R0,R10 ;Give caller my header block
424 LDMFD R13!,{R1-R10,R12,PC}^ ;Return to caller nicely
425
426 99tms_create ADD R2,R0,#4 ;Point to the message
427 MOVS R0,R10 ;Point to menu header
428 BLNE tms__destroy ;Destroy it if it exists
429 ADR R0,tms__noCreate ;Point to error skeleton
430 BL msgs_error ;Translate the error
431 LDMFD R13!,{R1-R10,R12,R14} ;Restore registers
432 ORRS PC,R14,#V_flag ;And return with the error
433
434 LTORG
435
436 tms__noCreate DCD 1
437 DCB "tmsCCTM:TMS cannot create menu: %s",0
438
439 ; --- tms__destroy ---
440 ;
441 ; On entry: R0 == handle of tearoff menu to destroy
442 ;
443 ; On exit: --
444 ;
445 ; Use: Zaps a tearoff menu entirely, leaving no survivors
446
447 EXPORT tms__destroy
448 tms__destroy ROUT
449
450 STMFD R13!,{R0-R4,R14} ;Stack some registers
451 MOV R4,R0 ;Preserve menu pointer
452
453 ; --- Delete the window, and remove its handler ---
454
455 ADD R1,R0,#hHandle ;Point to the handle
456 SWI Wimp_CloseWindow ;Close the window
457 SWI Wimp_DeleteWindow ;Then delete it
458 LDR R0,[R4,#hHandle] ;The window handle
459 LDR R1,=tms__eventHandler ;Point to the handler
460 MOV R2,R4 ;The handle passed
461 MOV R3,R12 ;Workspace passed in R3
462 BL win_removeEventHandler ;Remove the event handler
463 LDR R0,[R4,#hFlags] ;Load the header flags
464 TST R0,#hFlag__tIndir ;Is title indirected?
465 LDRNE R0,[R4,#hText] ;Yes -- load buffer pointer
466 BLNE heap_free ;And free it nicely
467 LDR R1,[R4,#hItems] ;Get the items pointer
468 MOV R0,R4 ;Point back to the block
469 BL heap_free ;Free the block
470
471 00tms__destroy MOVS R0,R1 ;Point R0 at the block
472 LDMEQFD R13!,{R0-R4,PC}^ ;Return PDQ
473 LDR R1,[R0,#iItems] ;Get the next items pointer
474 BL heap_free ;Free the block
475 B %00tms__destroy ;Keep destorying blocks
476
477 LTORG
478
479 ; --- tms__width ---
480 ;
481 ; On entry: R10 == pointer to the menu
482 ;
483 ; On exit: CS if the width has changed, CC otherwise
484 ;
485 ; Use: Calculates what the appropriate width fields of the given
486 ; menu should be.
487
488 EXPORT tms__width
489 tms__width ROUT
490
491 STMFD R13!,{R0-R8,R14} ;Stack some registers
492
493 MOV R4,#0 ;No sprite width
494 MOV R5,#0 ;No text width
495 MOV R6,#0 ;No shortcut width
496 LDR R7,[R10,#hTotWidth] ;Get the current width
497
498 LDR R2,[R10,#hItems] ;Point to the first items
499 05tms__width LDR R3,[R2,#iNumber] ;Load the number of items
500 ADD R8,R2,#iHdrSize ;Point to first item
501
502 ; --- Calculate string width ---
503
504 10tms__width LDR R0,[R8,#iText] ;Load the text pointer
505 BL wimp_strWidth ;Get the strings length
506 CMP R0,R5 ;Is it greater?
507 MOVGT R5,R0 ;Yes -- remember this then
508
509 ; --- Now the shortcut width ---
510
511 LDR R0,[R8,#iKeyCode] ;Load the key code
512 CMP R0,#-1 ;Is there one?
513 BEQ %12tms__width ;No -- jump ahead
514 MOV R1,#1 ;Return short version
515 BL keyString ;Find correct string
516 BL wimp_strWidth ;Get the string width
517 ADD R0,R0,#16 ;Put a gap on each side
518 CMP R0,R6 ;Is this on longer?
519 MOVGT R6,R0 ;Yes -- remember that fact
520
521 ; --- Finally the sprite width ---
522
523 12tms__width STMFD R13!,{R2-R6} ;Save some registers
524 LDR R14,[R8,#iFlags] ;Get the flags word
525 TST R14,#iFlag__sprite ;Is there a sprite here?
526 LDMEQFD R13!,{R2-R6} ;No -- restore registers
527 BEQ %15tms__width ;...jump ahead a little
528 LDR R1,[R8,#iSprArea] ;Get the sprite area
529 LDR R2,[R8,#iSprName] ;And the sprite name
530 CMP R1,#1 ;Are we using WIMP area?
531 MOVNE R0,#256+40 ;No -- on user area name
532 SWINE OS_SpriteOp ;...get information
533 MOVEQ R0,#40 ;Yes -- info please
534 SWIEQ Wimp_SpriteOp ;Get it then
535 MOV R0,R6 ;Get the sprite's mode
536 MOV R1,#4 ;Get the XEig factor
537 SWI OS_ReadModeVariable ;Read the value
538 MOV R3,R3,LSL R2 ;Work out the width in OS
539 TST R14,#iFlag__halfSize ;Should we display at half sz
540 MOVNE R3,R3,LSR #1 ;Yes -- then divide by 2
541 ADD R3,R3,#16 ;Add on a little clearance
542 MOV R14,R3 ;Remember this width
543 LDMFD R13!,{R2-R6} ;Restore those registers
544 CMP R14,R4 ;Is this bigger than that?
545 MOVGT R4,R14 ;Yes -- use this value then
546
547 ; --- Now do other items ---
548
549 15tms__width ADD R8,R8,#iItemSize ;Point to the next item
550 SUBS R3,R3,#1 ;Decrement item count
551 BGT %10tms__width ;More to go -- do them
552
553 LDR R2,[R2,#iItems] ;Load the next items
554 CMP R2,#0 ;Are there any more?
555 BNE %05tms__width ;Yes -- look at them then
556
557 STR R4,[R10,#hSprWidth] ;Store the sprite width
558 STR R5,[R10,#hTextWidth] ;Store the text width
559 STR R6,[R10,#hKeyWidth] ;And shortcut width too
560
561 ADD R4,R4,R5 ;Add them all together
562 ADD R4,R4,R6 ;...
563 ADD R4,R4,#64 ;Left and right + 16
564
565 LDR R0,[R10,#hText] ;Load the title pointer
566 BL wimp_strWidth ;Find the string width
567 ADD R0,R0,#32 ;Add on some clearance
568 STR R0,[R10,#hTitleWidth] ;Store the title width
569 CMP R0,R4 ;Is this longer than rest?
570 MOVGT R4,R0 ;Yes -- use this width
571
572 STR R4,[R10,#hTotWidth] ;Store new total width
573
574 CMP R4,R7 ;Has the width changed?
575 BEQ %95tms__width ;No -- return
576
577 ; --- Change the extent of the window ---
578
579 LDR R14,[R10,#hHandle] ;Get the window handle
580 STR R14,[R13,#-36]! ;Get me a block
581 MOV R1,R13 ;Point to the block
582 SWI Wimp_GetWindowState ;Get the window state
583
584 SUB R13,R13,#16 ;Get another block
585 MOV R2,#0 ;Minimum x extent
586 LDR R3,[R10,#hHeight] ;Get the window height
587 RSB R3,R3,#0 ;Minimun y extent
588 MOV R5,#0 ;Maximum y extent
589 STMIA R13,{R2-R5} ;Store these in the block
590 MOV R0,R14 ;Get the window handle in R0
591 MOV R1,R13 ;Point to the block
592 SWI Wimp_SetExtent ;Set the extent
593
594 ADD R13,R13,#16 ;Get the first block back
595 LDR R0,[R13,#4] ;Get visible x0
596 ADD R0,R0,R4 ;Calculate x1
597 STR R0,[R13,#12] ;Store the maximum x extent
598 MOV R1,R13 ;Point to the block
599 SWI Wimp_OpenWindow ;Open the window
600
601 ADD R13,R13,#36 ;Reclaim the stack
602
603 ; --- Force a complete redraw ---
604 ;
605 ; It's a shame, but there's nothing else for it.
606
607 LDR R0,[R10,#hHandle] ;Load the window handle
608 MOV R1,#0 ;Left hand side of window
609 LDR R2,[R10,#hHeight] ;Load the window height
610 RSB R2,R2,#0 ;Make it nicely negative
611 LDR R3,[R10,#hTotWidth] ;Load the window width
612 MOV R4,#0 ;And the top of the window
613 SWI Wimp_ForceRedraw ;Aarggh boo spit spit
614
615 90tms__width LDMFD R13!,{R0-R8,R14} ;Get registers back
616 ORRS PC,R14,#C_flag ;Return with carry set
617
618 95tms__width LDMFD R13!,{R0-R8,R14} ;Get registers back
619 BICS PC,R14,#C_flag ;Return with carry clear
620
621 LTORG
622
623 ; --- tms__check ---
624 ;
625 ; On entry: R0 == pointer to menu to check
626 ; R12 == pointer to global tms workspace
627 ;
628 ; On exit: --
629 ;
630 ; Use: Checks to see if the given menu needs to be changed, and
631 ; updates it as appropriate if it does.
632
633 tms__check ROUT
634
635 STMFD R13!,{R0-R10,R14} ;Stack lots of registers
636
637 STR R0,tms__recreating ;Store a pointer to this menu
638 LDR R9,[R0,#hDefinition] ;Point to packed header defn
639 MOV R7,R0 ;Put structure in R7
640 LDR R8,[R9],#4 ;Load the title flags word
641 LDR R2,[R7,#hR10] ;Load R10 value
642 LDR R3,[R7,#hR12] ;And R12 value
643 BL tms__findBase ;Put base in R5
644 TST R8,#mFlag_indirect ;Is the text indirected?
645 BEQ %02tms__check ;No -- just skip over string
646 LDR R0,[R9],#4 ;Yes -- find offset
647 LDR R1,[R9],#4 ;And buffer length
648 LDR R0,[R5,R0] ;And point to the string
649
650 ; --- Compare to find a difference ---
651
652 LDR R1,[R7,#hText] ;Point to current text string
653 BL str_cmp ;Compare the strings
654 LDRNE R2,[R7,#hHandle] ;Load the window handle
655 BLNE winUtils_setTitle ;And set the title
656 B %05tms__check ;Jump ahead
657
658 ; --- Skip over embedded title string ---
659
660 02tms__check LDRB R14,[R9],#1 ;Get a message string byte
661 CMP R14,#' ' ;Is it a terminator?
662 BGE %02tms__check ;No -- get another one
663 ADD R9,R9,#3 ;Add 3
664 BIC R9,R9,#3 ;And word align the pointer
665
666 ; --- Now check the items ---
667
668 05tms__check LDR R6,[R7,#hItems] ;Point to first items
669 06tms__check LDR R2,[R6,#iR10] ;Load R10 value
670 LDR R3,[R6,#iR12] ;And R12 value
671
672 LDR R9,[R6,#iDefinition] ;Point to packed items defn
673 ADD R7,R6,#iHdrSize ;Point to first item
674 LDR R8,[R9],#4 ;Load the flags word
675 07tms__check BL tms__findBase ;Get base in R5
676 LDR R10,[R7,#iFlags] ;Get the existing flags
677 BIC R10,R10,#&FF000000 ;Clear redraw flags
678 STR R10,[R7,#iFlags] ;Store them back
679
680 ; --- First, compare the text strings ---
681
682 TST R8,#mFlag_indirect ;Is text indirected?
683 BEQ %10tms__check ;No -- just skip over string
684 LDR R0,[R9],#4 ;Yes -- find offset
685 LDR R0,[R5,R0] ;And point to the string
686
687 ; --- Compare to find a difference ---
688
689 LDR R1,[R7,#iText] ;Point to current text string
690 BL str_cmp ;Compare the strings
691 ORRNE R10,R10,#iFlag__newText ;If different, remember it
692 STRNE R0,[R7,#iText] ;And store new text ptr
693 B %11tms__check ;And jump ahead if no change
694
695 ; --- Skip over embedded item string ---
696
697 10tms__check LDRB R14,[R9],#1 ;Get a message string byte
698 CMP R14,#' ' ;Is it a terminator?
699 BGE %10tms__check ;No -- get another one
700 ADD R9,R9,#3 ;Add 3
701 BIC R9,R9,#3 ;And word align the pointer
702
703 ; --- The shortcut may have changed ---
704
705 11tms__check TST R8,#mFlag_iShortcut ;Is there a indir. shortcut?
706 BEQ %12tms__check ;No -- skip ahead
707
708 LDR R0,[R9] ;Get the value
709 LDR R0,[R5,R0] ;Load out the key code
710 LDR R14,[R7,#iKeyCode] ;Load current key code
711 CMP R14,R0 ;Has it changed?
712 STRNE R0,[R7,#iKeyCode] ;Yes -- store this value
713 ORRNE R10,R10,#iFlag__newKey ;...queue for redrawing
714
715 ; --- Now collect the item flags ---
716
717 12tms__check TST R8,#mFlag_shortcut ;Is there a shortcut?
718 TSTEQ R8,#mFlag_iShortcut ;Of any kind?
719 ADDNE R9,R9,#4 ;Yes -- skip over it
720
721 MOV R4,#0 ;No flags set yet
722
723 TST R8,#mFlag_shade ;Check shadedness bit
724 BLNE tms__bitSpec ;Handle the bit specification
725 ORRHI R4,R4,#iFlag__shaded ;If set, shade the item
726 BHI %13tms__check ;...and jump this next bit
727
728 TST R8,#mFlag_iShade ;Check shadedness bit
729 BLNE tms__bitSpec ;Handle the bit specification
730 ORRNE R4,R4,#iFlag__shaded ;Set shaded bit anyway
731 BICHI R4,R4,#iFlag__shaded ;Bit clear it again if set!
732
733 13tms__check TST R8,#mFlag_switch ;Check switchiness bit
734 BLNE tms__bitSpec ;Handle the bit specification
735 ORRHI R4,R4,#iFlag__ticked ;If set, tick it
736
737 TST R8,#mFlag_radio ;Check radioness bit
738 BEQ %14tms__check ;If not set, skip ahead
739 LDMIA R9!,{R0,R1} ;Load the information out
740 LDR R0,[R5,R0] ;Load the radio specifier
741 CMP R0,R1 ;Is this a match made in hvn?
742 ORREQ R4,R4,#iFlag__radio ;Yes -- attach the splodge
743
744 ; --- Now check the sprite ---
745
746 14tms__check TST R8,#mFlag_sprite ;Is there a sprite here?
747 BEQ %15tms__check ;No skipitty jump aaawhooo
748 STMFD R13!,{R2} ;Don't corrupt R2
749 LDR R2,[R9],#4 ;Yes -- load out name ptr ptr
750 LDR R2,[R5,R2] ;And get name ptr
751 BL tms__checksum ;Get the checksum
752 LDR R1,[R7,#iSprCsum] ;Load the current checksum
753 CMP R0,R1 ;Has it changed?
754 STRNE R0,[R7,#iSprCsum] ;Yes -- store the new one
755 STRNE R2,[R7,#iSprName] ;...and the new name
756 ORRNE R10,R10,#iFlag__newSpr ;...and queue for redraw
757 ADD R9,R9,#4 ;Skip over sprite area
758 LDMFD R13!,{R2} ;Return to caller
759
760 15tms__check
761 SKIP mFlag_subMenu,8,R8,R9 ;Skip submenu bit nicely
762
763 ; --- Have the flags changed? ---
764
765 LDR R14,[R7,#iFlags] ;Get the current item flags
766 AND R0,R14,#7 ;Clear unwanted flags
767 CMP R0,R4 ;Have flags changed?
768
769 BIC R14,R14,#7 ;Clear relevant flags
770 ORR R14,R14,R4 ;Set new flags up
771 MOV R1,R14 ;And remember them
772
773 ; --- Update text part ---
774
775 EOR R14,R0,R4 ;Get flags which have changed
776
777 TST R14,#iFlag__shaded ;Has shaded state changed?
778 ORRNE R10,R10,#&FF000000 ;Yes -- redraw the whole item
779 TST R14,#iFlag__ticked+iFlag__radio ;Need to redraw left?
780 ORRNE R10,R10,#iFlag__newTick ;Yes -- then queue an update
781 BIC R10,R10,#7 ;Clear these flags
782 BIC R1,R1,#&FF000000 ;Clear old update flags
783 ORR R1,R1,R10 ;Add in update bits
784 STR R1,[R7,#iFlags] ;Store the new flags
785
786 ; --- Check following items ---
787
788 20tms__check ADD R7,R7,#iItemSize ;Point at the next item
789 LDR R8,[R9],#4 ;Load the next flags word
790 TST R8,#mFlag_end ;Have we reached the end?
791 BEQ %07tms__check ;No -- keep check these items
792
793 LDR R6,[R6,#iItems] ;Point to next group of items
794 CMP R6,#0 ;Are there any more?
795 BNE %06tms__check ;Yes -- check them then
796
797 ; --- Maybe change menu width ---
798
799 LDR R10,tms__recreating ;Get the menu ptr
800 BL tms__width ;Recalculate the menu width
801 BCS %90tms__check ;If it redrew it, skip on
802
803 ; --- Now redraw items we queued above ---
804
805 MOV R0,#0 ;Only redraw queued bits
806 BL tms__update ;And update the window
807 90tms__check LDMFD R13!,{R0-R10,PC}^ ;Return to caller
808
809 LTORG
810
811 ; --- tms_recreate ---
812 ;
813 ; On entry: --
814 ;
815 ; On exit: --
816 ;
817 ; Use: Recreates the existing menu structure, making changes where
818 ; appropriate.
819
820 EXPORT tms_recreate
821 tms_recreate ROUT
822
823 ; --- A note to the wise ---
824 ;
825 ; We go through the data for every open tearoff menu, and
826 ; make any changes that are necessary. These include:
827 ;
828 ; Making the menu wider or narrower, if necessary
829 ; Changing textual strings where they are now different
830 ; Adding or removing of ticks and blobs
831 ; Shading or unshading of items
832
833 STMFD R13!,{R0,R14} ;Stack some registers
834 LDR R12,=tms__wSpace ;Point to workspace pointer
835 WSPACE [R12] ;Load out workspace pointer
836
837 LDR R0,tms__current ;Load the current menu ptr
838 CMP R0,#0 ;Is there one open?
839 BEQ %10tms_recreate ;No -- look at torn ones
840 00tms_recreate BL tms__check ;Check the menu, make changes
841 LDR R0,[R0,#hSubMenu] ;Get submenu pointer
842 CMP R0,#0 ;Is there one?
843 BNE %00tms_recreate ;Yes -- check it then
844
845 ; --- Now check the torn off menus ---
846
847 10tms_recreate LDR R0,tms__tornoffs ;Get first torn off menu
848 CMP R0,#0 ;Have we finished yet?
849 BEQ %90tms_recreate ;Yes -- return then
850 15tms_recreate BL tms__check ;Check the menu, make changes
851 LDR R0,[R0,#hNextTorn] ;Get the next torn menu
852 CMP R0,#0 ;Have we finished yet?
853 BNE %15tms_recreate ;No -- keep going then
854
855 90tms_recreate LDMFD R13!,{R0,PC}^ ;Return to caller
856
857 LTORG
858
859 ;----- That's all, folks ----------------------------------------------------
860
861 END