chiark / gitweb /
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