chiark / gitweb /
JPEG support and other fixes from Nick Clark
[ssr] / StraySrc / Libraries / Sapphire / s / menu
1 ;
2 ; menu.s
3 ;
4 ; RISC OS menu handling facilities (TMA)
5 ;
6 ; © 1994-1998 Straylight
7 ;
8
9 ;----- Licensing note -------------------------------------------------------
10 ;
11 ; This file is part of Straylight's Sapphire library.
12 ;
13 ; Sapphire is free software; you can redistribute it and/or modify
14 ; it under the terms of the GNU General Public License as published by
15 ; the Free Software Foundation; either version 2, or (at your option)
16 ; any later version.
17 ;
18 ; Sapphire is distributed in the hope that it will be useful,
19 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 ; GNU General Public License for more details.
22 ;
23 ; You should have received a copy of the GNU General Public License
24 ; along with Sapphire.  If not, write to the Free Software Foundation,
25 ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26
27 ;----- Standard header ------------------------------------------------------
28
29                 GET     libs:header
30                 GET     libs:swis
31
32 ;----- External dependencies ------------------------------------------------
33
34                 GET     sapphire:event
35                 GET     sapphire:libOpts
36                 GET     sapphire:sapphire
37                 GET     sapphire:string
38                 GET     sapphire:fastMove
39                 GET     sapphire:msgs
40                 GET     sapphire:help
41
42 ;----- Useful values --------------------------------------------------------
43
44 mFlag_tearoff   EQU     (1<<1)                  ;Menu has a tearoff bar
45 mFlag_makeMe    EQU     (1<<2)                  ;Recreate menu on adjust
46 mFlag_maxHeight EQU     (1<<3)                  ;Menu has a maximum height
47
48 mFlag_indirect  EQU     (1<<0)                  ;Item text is indirected
49 mFlag_shortcut  EQU     (1<<1)                  ;Item has a keyboard shortcut
50 mFlag_iShortcut EQU     (1<<2)                  ;Item has an indirected S/C
51 mFlag_shade     EQU     (1<<3)                  ;Item is shadable
52 mFlag_iShade    EQU     (1<<4)                  ;Item is inverse shadable
53 mFlag_switch    EQU     (1<<5)                  ;Item is a switch
54 mFlag_radio     EQU     (1<<6)                  ;Item is a radio item
55 mFlag_sprite    EQU     (1<<7)                  ;Menu item has a sprite
56 mFlag_halfSize  EQU     (1<<8)                  ;Sprite is halfsize
57 mFlag_subWarn   EQU     (1<<9)                  ;Warn client if submenu warn
58 mFlag_subMenu   EQU     (1<<10)                 ;Item has menu to be opened
59
60 mFlag_R12       EQU     (1<<16)                 ;Use R12 for runtime data
61 mFlag_noWarn    EQU     (1<<17)                 ;Don't warn on shaded items
62 mFlag_ruleOff   EQU     (1<<18)                 ;Put a ruleoff after item
63 mFlag_noTrans   EQU     (1<<19)                 ;Don't translate messages
64
65 mFlag_end       EQU     (1<<31)                 ;No more items
66
67 ; --- Event types ---
68
69 mEvent_select   EQU     0                       ;Normal menu selection
70                                                 ;  R1 == index of item
71 mEvent_arrow    EQU     1                       ;Sub menu warning
72                                                 ;  R1 == index of item
73 mEvent_deleted  EQU     2                       ;Menu has been deleted
74 mEvent_help     EQU     3                       ;Menu help requested
75                                                 ;  R1 == ndex of item
76                                                 ;  R2 == ptr to packed itmdef
77
78 ;----- Main code ------------------------------------------------------------
79
80                 AREA    |Sapphire$$Code|,CODE,READONLY
81
82 ; --- menu__createTitle ---
83 ;
84 ; On entry:     R0 == pointer to menu title definition
85 ;               R1 == event handler to use (not used here)
86 ;               R2 == R10 value to use
87 ;               R3 == R12 value to use
88 ;               R4 == pointer to menu stack area
89 ;               R5 == pointer into stack to build definition
90 ;               R9 == workspace pointer
91 ;
92 ; On exit:      R0 == points to first word after table
93 ;               R1-R4 == preserved
94 ;               R5 == next free word in stack after defintion
95 ;
96 ; Use:          This call creates the title part of a WIMP menu from
97 ;               a menu definition table (assuming that it has a menu
98 ;               title definition).
99
100 menu__createTitle ROUT
101
102                 STMFD   R13!,{R1-R4,R6-R8,R14}  ;Stack some registers
103
104                 STMDB   R4,{R0-R3}              ;Store information in stack
105                 LDR     R7,[R0],#4              ;Get flags
106                 MOV     R8,R2                   ;Use R10 for runtime data
107                 TST     R7,#mFlag_R12           ;Should we use R12?
108                 MOVNE   R8,R3                   ;Yes, set R8 = R3 then
109                 TST     R7,#mFlag_indirect      ;Is the title indirected
110                 LDRNE   R6,[R0],#4              ;Yes -- load the offset
111                 LDRNE   R6,[R6,R8]              ;...find new pointer
112                 BNE     %05                     ;...and jump the next bit
113
114                 MOV     R6,R0                   ;Get the text pointer
115 00              LDRB    R8,[R0],#1              ;Get a byte
116                 CMP     R8,#0                   ;Was it the last character?
117                 BNE     %00                     ;No -- keep looking
118                 ADD     R0,R0,#3                ;Word align
119                 BIC     R0,R0,#3                ;Oh yes indeedy
120
121 05              MOV     R2,R0                   ;Remember this pointer
122                 MOV     R0,R6                   ;Point to the message
123                 TST     R7,#mFlag_noTrans       ;Do we translate the string?
124                 BLEQ    msgs_lookup             ;Yes -- lookup the message
125                 MOV     R6,R0                   ;Remember new pointer
126                 BL      str_len                 ;Get the length of the text
127                 STRGT   R0,menu__maxLen         ;Yes -- store new length
128                 TST     R7,#mFlag_makeMe        ;Is the menu recreatable?
129                 LDMNEIA R2!,{R8}                ;Yes -- read it
130                 TST     R7,#mFlag_maxHeight     ;Is there a maximum height
131                 LDMNEIA R2!,{R8}                ;Yes -- read it
132
133                 ; --- Now enter data into stack ---
134
135                 BL      menu__checkOverflow     ;Make sure there's room
136                 MOV     R0,R5                   ;Copy to here...
137                 MOV     R1,R6                   ;...this string
138                 BL      str_cpy                 ;Do the copy
139                 ADD     R5,R5,#12               ;Point past 12 bytes
140                 MOV     R0,R2                   ;Get the pointer back
141                 LDR     R4,=&00070207           ;Colours
142                 MOV     R6,#40                  ;Don't know width yet
143                 MOV     R7,#44                  ;Item height
144                 MOV     R8,#0                   ;Gap between items
145                 STMIA   R5!,{R4,R6-R8}          ;Store information
146
147                 ; --- Return thankfully ---
148
149                 LDMFD   R13!,{R1-R4,R6-R8,PC}^
150
151                 LTORG
152
153 ; --- menu_create ---
154 ;
155 ; On entry:     R0 == pointer to menu definition table
156 ;               R1 == event handler to use
157 ;               R2 == R10 value for handler
158 ;               R3 == R12 value for handler
159 ;
160 ; On exit:      --
161 ;
162 ; Use:          Creates a menu from the given menu definition
163 ;               table. If this call is called more than once before
164 ;               a menu is opened then the menu definiton are concatenated
165 ;               into a large menu. Only the first menu title read is
166 ;               taken notice of. Notice therefore, that the call doesn't
167 ;               actually open a menu.
168
169                 EXPORT  menu_create
170 menu_create     ROUT
171
172                 STMFD   R13!,{R0-R12,R14}       ;Stack some registers
173                 WSPACE  menu__wSpace,R9         ;Find my workspace
174
175                 MOV     R12,#0                  ;Number of items so far
176
177                 ; --- Do we need to read the menu title? ---
178
179                 LDR     R4,menu__flags          ;Get the flags word
180                 TST     R4,#mFlag__creating     ;Is this the first menu
181                 BEQ     %00menu_create          ;Yes -- set up things
182
183                 ; --- We are already creating a menu ---
184
185                 LDR     R6,menu__begin          ;Get beginning of real menu
186                 TST     R4,#mFlag__tOnly        ;Has just the title been done
187                 SUBNE   R4,R6,#24               ;Yes -- block already there
188                 LDR     R5,menu__end            ;Get the end marker
189                 LDMNEIA R13,{R0-R3}             ;Reclaim useful values
190                 STMNEFD R13!,{R0}               ;Pointer to item definitions
191                 BNE     %05menu_create          ;Now read the items
192
193                 SUB     R1,R6,#4                ;Copy from here..
194                 ADD     R0,R1,#20               ;...to here
195                 SUB     R2,R5,R1                ;...this much
196                 BL      fastMove                ;Do the copy
197                 ADD     R5,R5,#20               ;Increment end pointer
198                 MOV     R4,R1                   ;Write header here
199                 ADD     R6,R6,#20               ;The new beginning
200                 STR     R6,menu__begin          ;Store new value
201                 LDMIA   R13,{R0-R3}             ;Reclaim useful values
202                 STMFD   R13!,{R0}               ;Pointer to item definitions
203                 B       %05menu_create          ;Go through the items
204
205                 ; --- We are creating a new menu ---
206
207 00menu_create   STR     R12,menu__maxLen        ;Max length so far
208                 TST     R4,#mFlag__wasSub       ;Was last event a submenu?
209                 LDREQ   R4,menu__stack          ;No -- Get the stack address
210                 LDRNE   R4,menu__prevMenu       ;Yes - start of previous menu
211                 LDRNE   R5,[R4]                 ;...get length of menu
212                 ADDNE   R4,R4,R5                ;Start new menu here
213                 STR     R4,menu__start          ;The menu start (incl. defn)
214
215                 ADD     R5,R4,#44               ;Where to start adding defns
216                 ADD     R4,R4,#20               ;Where to write the header
217                 MOV     R6,#0                   ;The last header marker
218                 STR     R6,[R5,#-4]             ;Store it nicely
219                 STR     R5,menu__begin          ;Store the begin pointer
220                 BL      menu__createTitle       ;Create the title
221                 STMFD   R13!,{R0}               ;Pointer to item definitions
222
223                 ; --- Now go through the menu items ---
224                 ;
225                 ; At this point, R4 points to the menu header to write to,
226                 ; R5 points into the stack at the position that the next
227                 ; items should be written to. R0 points to the next menu
228                 ; item.
229
230 05menu_create   LDR     R7,[R0],#4              ;Get flags
231                 TST     R7,#mFlag_end           ;Any more items?
232                 BNE     %40menu_create          ;Nope -- branch ahead
233                 MOV     R8,R2                   ;Use R10 for runtime data
234                 TST     R7,#mFlag_R12           ;Should we use R12?
235                 MOVNE   R8,R3                   ;Yes, set R8 = R3 then
236                 TST     R7,#mFlag_indirect      ;Is the text indirected
237                 LDRNE   R6,[R0],#4              ;Yes -- load the offset
238                 LDRNE   R6,[R6,R8]              ;...find new pointer
239                 BNE     %07menu_create          ;...and jump the next bit
240
241                 MOV     R6,R0                   ;Point to the string
242 06menu_create   LDRB    R1,[R0],#1              ;Get a byte
243                 CMP     R1,#0                   ;Was it the last character?
244                 BNE     %06menu_create          ;No -- keep looking
245                 ADD     R0,R0,#3                ;Word align
246                 BIC     R0,R0,#3                ;Oh yes indeedy
247
248                 ; --- So, we have an item ---
249
250 07menu_create   MOV     R2,R0                   ;Remember this pointer
251                 MOV     R0,R6                   ;Point to the message
252                 TST     R7,#mFlag_noTrans       ;Do we translate the string?
253                 BLEQ    msgs_lookup             ;Yes -- lookup the message
254                 MOV     R6,R0                   ;Remember new pointer
255                 BL      str_len                 ;Get the length of the text
256                 TST     R7,#mFlag_sprite        ;Is there a sprite too?
257                 ADDNE   R0,R0,#2                ;Yes -- add 42 to the length
258                 LDR     R1,menu__maxLen         ;Get maximum length so far
259                 CMP     R0,R1                   ;Is new text longer?
260                 STRGT   R0,menu__maxLen         ;Yes -- store new length
261                 MOV     R0,R2                   ;Get the offset back
262                 MOV     R1,#24                  ;The WIMP item flags so far
263                 LDR     R2,=&7000131            ;The icon flags so far
264
265                 TST     R7,#mFlag_shade         ;Is it shadable?
266                 BEQ     %10menu_create          ;No -- jump this code
267                 BL      %99                     ;Do a bit specification
268                 ORRCS   R2,R2,#(1<<22)          ;Set the 'shaded' bit
269
270 10menu_create   TST     R7,#mFlag_iShade        ;Is it inverse shadable?
271                 BEQ     %15menu_create          ;No -- jump this code
272                 BL      %99                     ;Do a bit specification
273                 ORRCC   R2,R2,#(1<<22)          ;Set the 'shaded' bit
274
275 15menu_create   TST     R7,#mFlag_switch        ;Is it a switch?
276                 BEQ     %20menu_create          ;No -- jump this code
277                 BL      %99                     ;Do a bit specification
278                 ORRCS   R1,R1,#1                ;Set the tick flag
279
280 20menu_create   TST     R7,#mFlag_radio         ;Is is a radio type?
281                 BEQ     %23menu_create          ;No -- try next type
282                 LDMIA   R0!,{R10,R14}           ;Get offset and selector
283                 ADD     R10,R10,R8              ;Get real offset
284                 LDR     R10,[R10]               ;Get the word there
285                 CMP     R10,R14                 ;It is the same as selector?
286                 ORREQ   R1,R1,#1                ;Yes -- set the tick flag
287
288 23menu_create   TST     R7,#mFlag_sprite        ;Does item contain a sprite?
289                 BEQ     %25menu_create          ;No -- try next type
290                 LDR     R10,[R0],#4             ;Get the sprite name pointer
291                 ORR     R2,R2,#2                ;Set the 'sprite' bit
292                 STR     R10,menu__sprite        ;Store the sprite pointer
293
294 25menu_create   TST     R7,#mFlag_halfSize      ;Make sprite half size?
295                 ORRNE   R2,R2,#(1<<11)          ;Yeap -- set the bit
296
297                 TST     R7,#mFlag_noWarn        ;Don't open subs if shaded?
298                 BICNE   R1,R1,#16               ;Clear relevant bit
299
300                 TST     R7,#mFlag_ruleOff       ;Put a rule off here?
301                 ORRNE   R1,R1,#2                ;Yes -- set the bit up
302
303                 ; --- Now store this information in the block ---
304
305                 BL      menu__checkOverflow     ;Make sure there's room
306                 MOV     R10,R2                  ;Put the icon flags in R10
307                 MOV     R2,#-1                  ;No submenu yet
308                 TST     R7,#mFlag_subMenu       ;Automatic sub menu?
309                 LDMNEIA R0!,{R2,R14}            ;Yes -- get menu pointer
310                 TST     R7,#mFlag_subWarn       ;Submenu warning required
311                 MOVNE   R2,#1                   ;Yeap -- put non -1 value in
312                 STMIA   R5!,{R1,R2,R10}         ;Splodge!
313                 TST     R10,#2                  ;Is the sprite bit set?
314                 MOVEQ   R10,#-1                 ;No -- no validation
315                 LDRNE   R10,menu__sprite        ;Yes -- point to sprite name
316                 MOV     R14,#255                ;Buffer length
317                 STMIA   R5!,{R6,R10,R14}        ;Icon data -- splodge!
318
319                 ; --- Now, keep searching for icons ---
320
321                 ADD     R12,R12,#1              ;Increment item count
322                 ADD     R1,R13,#8               ;Point to useful values
323                 LDMIA   R1,{R1-R3}              ;Load back useful values
324                 B       %05menu_create          ;Keep looking
325
326                 ; --- All the icons have been found, tidy up ---
327
328 40menu_create   LDR     R0,menu__flags          ;Get my flags word
329                 CMP     R12,#0                  ;Did we create any items?
330                 ORREQ   R0,R0,#mFlag__tOnly     ;Yes -- set the flag
331                 BICNE   R0,R0,#mFlag__tOnly     ;No -- clear the flag
332                 ORR     R0,R0,#mFlag__creating  ;We are creating a menu
333                 STR     R0,menu__flags          ;Store updated flags
334                 STR     R12,[R4],#4             ;Store number of items
335                 STR     R5,menu__end            ;The end pointer
336                 LDR     R6,menu__start          ;Get the start
337                 SUB     R7,R5,R6                ;Get the length
338                 STR     R7,[R6]                 ;Store in the header
339                 LDMFD   R13!,{R5}               ;First item pointer
340                 LDMFD   R13!,{R0-R3}            ;Load some stuff
341                 MOV     R14,R0                  ;Remember user R0
342                 MOV     R0,R5                   ;Pointer to first item defn
343                 STMIA   R4!,{R0-R3}             ;Store them in the header
344                 MOV     R0,R14                  ;Preserve R0
345
346                 ; --- And return to the client ---
347
348                 LDMFD   R13!,{R4-R12,PC}^       ;Return to client
349
350                 ; --- Do a bit specification ---
351
352 99              STMFD   R13!,{R14}              ;Save a register
353                 LDR     R10,[R0],#4             ;Get the next word
354                 ADD     R14,R8,R10,LSR#5        ;Get the offset
355                 LDR     R14,[R14]               ;And the byte there
356                 AND     R10,R10,#31             ;Clear bit we don't want
357                 ADD     R10,R10,#1              ;Correct for shifting
358                 MOVS    R14,R14,LSR R10         ;Shift that bit into carry
359                 LDMFD   R13!,{PC}               ;And return to caller
360
361                 LTORG
362
363 ; --- menu__checkOverflow ---
364 ;
365 ; On entry:     R5 == offset in menu stack for creating next item
366 ;
367 ; On exit:      --
368 ;
369 ; Use:          Checks to see if there's enough room in the menu stack for
370 ;               a new menu item or header.
371
372 menu__checkOverflow ROUT
373
374                 STMFD   R13!,{R14}              ;Save some registers
375                 LDR     R14,menu__stackEnd      ;Find the end of the stack
376                 SUB     R14,R14,#64             ;Allow a nice bit of space
377                 CMP     R14,R5                  ;Do we have enough space?
378                 LDMGEFD R13!,{PC}^              ;Yes -- return then
379
380                 LDR     R14,menu__flags         ;Get my flags word
381                 AND     R14,R14,#mFlag__inited  ;Reset all the flags
382                 STR     R14,menu__flags         ;Store updated flags
383                 MOV     R1,#-1                  ;An invalid menu pointer
384                 SWI     XWimp_CreateMenu        ;Close the current menu tree
385                 ADR     R0,menu__noMem          ;Point to error message
386                 BL      msgs_error              ;Translate the error message
387                 SWI     OS_GenerateError        ;And generate the error
388
389 menu__noMem     DCD     1
390                 DCB     "mSOVF",0
391
392                 LTORG
393
394 ; --- menu__recreate ---
395 ;
396 ; On entry:     R1 == pointer to list of menu hits
397 ;               R9 == pointer to workspace
398 ;
399 ; On exit:      --
400 ;
401 ; Use:          Called to recreate the menu definition after an adjust
402 ;               click was made on a menu.
403
404 menu__recreate  ROUT
405
406                 STMFD   R13!,{R0-R12,R14}       ;Stack some registers
407
408                 MOV     R10,R1                  ;We need this list
409                 LDR     R12,menu__stack         ;Point to first menu header
410 00              LDR     R0,[R10],#4             ;Load a menu hit (ignore 1st)
411                 CMP     R0,#-1                  ;Is this the end?
412                 BEQ     %90                     ;Yes -- finish
413
414                 LDR     R0,[R12,#4]             ;Get the title defn pointer
415                 LDR     R2,[R0],#4              ;Get the flags word
416                 MOV     R6,R0                   ;Point to the text
417                 TST     R2,#mFlag_R12           ;Do we use R12?
418                 LDREQ   R7,[R12,#12]            ;No -- use R10 value
419                 LDRNE   R7,[R12,#16]            ;Yes -- use R12 value
420
421                 TST     R2,#mFlag_indirect      ;Is the text indirected?
422                 LDRNE   R6,[R0]                 ;Yes -- get the offset
423                 LDRNE   R6,[R7,R6]              ;...load indirected pointer
424                 BL      menu__skipText          ;Skip past the text
425                 STMFD   R13!,{R10}              ;Save this R10 value
426                 TST     R2,#mFlag_makeMe        ;Is it a 'makeme' type
427                 BEQ     %01                     ;No -- skip this bit
428                 LDR     R5,[R10]                ;Get the next hit
429                 CMP     R5,#-1                  ;Are we at the last menu
430                 BNE     %01                     ;No -- ignore this function
431                 LDR     R5,[R0],#4              ;Get the 'make me' function
432
433                 ; --- Recreate the menu over the top of the old one ---
434
435                 MOV     R6,#0                   ;Set the new length
436                 STR     R6,[R12]                ;Store this length in field
437                 LDR     R6,menu__flags          ;Get my flags word
438                 ORR     R6,R6,#mFlag__wasSub    ;Fool menu_create
439                 STR     R6,menu__flags          ;Store the modified flags
440                 STR     R12,menu__prevMenu      ;Make this the previous menu
441                 MOV     R14,PC                  ;Set up the return address
442                 MOV     PC,R5                   ;Branch to the function
443                 ORR     R6,R6,#mFlag__recreating ;We're recreating
444                 STR     R6,menu__flags          ;Store the modified flags
445                 STR     R12,menu__start         ;Update this menu
446                 MOV     R2,R6                   ;Put the flags in R2
447                 BL      menu__open              ;Set the menu up properley
448                 BIC     R6,R6,#mFlag__creating  ;We're not really creating
449                 STR     R6,menu__flags          ;Store the modified flags
450                 B       %90                     ;Tidy up and return
451
452 01              MOV     R0,R6                   ;Point to the text
453                 TST     R2,#mFlag_noTrans       ;Do we translate the string?
454                 BLEQ    msgs_lookup             ;Yes -- lookup the message
455                 MOV     R6,R0                   ;Remember new pointer
456                 BL      str_len                 ;Get the length of the text
457                 STR     R0,menu__maxLen         ;Store max length
458
459                 ; --- Go through the items changing the flags ---
460                 ;
461                 ; We have to use three pointers, one to keep track of
462                 ; the real WIMP icon so that we can alter it, one
463                 ; to keep track of our position in the users block, and
464                 ; one to keep track of which header we are using!
465
466                 ; --- Find the first real item ---
467
468                 MOV     R0,R12                  ;Point to menu defn
469                 BL      menu__locateFirst       ;Locate the first item
470                 MOV     R3,R0                   ;Use R3 instead
471                 STMFD   R13!,{R3}               ;Stack this pointer
472                 SUB     R0,R3,#28               ;Point the the menu header
473                 MOV     R1,R6                   ;The text string
474                 BL      str_cpy                 ;Copy the title across
475                 MOV     R14,#7                  ;Might have trashed colour
476                 STRB    R14,[R3,#12-28]         ;So store colour back ;-)
477
478                 ; --- Set up the pointer to the first header ---
479
480                 ADD     R1,R12,#20              ;Point to first header
481 05              LDR     R8,[R1,#12]             ;Get the R10 value
482                 LDR     R10,[R1,#16]            ;Get the R12 value
483
484                 ; --- Finally locate the users definition ---
485
486                 LDR     R0,[R1,#4]              ;Get the pointer
487
488                 ; --- Now go through the list ---
489
490 06              LDR     R2,[R0],#4              ;Get the flags word
491                 TST     R2,#mFlag_end           ;No more items?
492                 BNE     %20                     ;No -- try for more
493                 LDR     R4,[R3,#0]              ;Load the item flags
494                 MOV     R7,R8                   ;Use R10 value
495                 TST     R2,#mFlag_R12           ;Do we use R12?
496                 MOVNE   R7,R10                  ;Yes -- set up R7
497                 MOV     R5,R0                   ;Pointer to the text
498                 TST     R2,#mFlag_indirect      ;Is the text indirected?
499                 LDRNE   R0,[R0]                 ;Yes -- get the offset
500                 LDRNE   R0,[R7,R0]              ;...load indirected pointer
501                 TST     R2,#mFlag_noTrans       ;Do we translate the string?
502                 BLEQ    msgs_lookup             ;Yes -- lookup the message
503                 STR     R0,[R3,#12]             ;Store the new text pointer
504                 BL      str_len                 ;Get the length
505                 TST     R2,#mFlag_sprite                ;Is there a sprite?
506                 ADDNE   R0,R0,#2                ;Yes -- allow for it
507                 LDR     R6,menu__maxLen         ;Get the current max length
508                 CMP     R0,R6                   ;Is new length longer?
509                 STRGT   R0,menu__maxLen         ;Yes, store this
510                 MOV     R0,R5                   ;Get current offset back
511                 BL      menu__skipText          ;Skip the text part
512 07              TST     R2,#mFlag_shade         ;Is it shadable?
513                 BEQ     %10                     ;No -- jump this code
514                 BL      %99                     ;Do a bit specification
515                 LDR     R5,[R3,#8]              ;Get the icon flags
516                 ORRCS   R5,R5,#(1<<22)          ;Set the 'shaded' bit
517                 BICCC   R5,R5,#(1<<22)          ;Or maybe clear it
518                 STR     R5,[R3,#8]              ;Put them back
519
520 10              TST     R2,#mFlag_iShade        ;Is it inverse shadable?
521                 BEQ     %11                     ;No -- jump this code
522                 BL      %99                     ;Do a bit specification
523                 LDR     R5,[R3,#8]              ;Get the icon flags
524                 ORRCC   R5,R5,#(1<<22)          ;Set the 'shaded' bit
525                 BICCS   R5,R5,#(1<<22)          ;Or maybe clear it
526                 STR     R5,[R3,#8]              ;Put them back
527
528 11              TST     R2,#mFlag_switch        ;Is it a switch
529                 BEQ     %12                     ;No -- jump this code
530                 BL      %99                     ;Do a bit specification
531                 ORRCS   R4,R4,#1                ;Set the tick flag
532                 BICCC   R4,R4,#1                ;Or maybe clear it
533
534 12              TST     R2,#mFlag_radio         ;Is is a radio type?
535                 BEQ     %13                     ;No -- jump this code
536                 LDMIA   R0!,{R5,R6}             ;Get offset and selector
537                 ADD     R5,R5,R7                ;Get real offset
538                 LDR     R5,[R5]                 ;Get the word there
539                 CMP     R5,R6                   ;It is the same as selector?
540                 ORREQ   R4,R4,#1                ;Yes -- set the tick flag
541                 BICNE   R4,R4,#1                ;No -- clear it
542
543 13              TST     R2,#mFlag_sprite        ;Is there a sprite?
544                 ADDNE   R0,R0,#4                ;Yes -- skip the pointer
545
546                 TST     R2,#mFlag_subMenu       ;Automatic submenu?
547                 ADDNE   R0,R0,#8                ;Yes -- skip those fields
548
549                 STR     R4,[R3,#0]              ;Store the item flags back
550                 ADD     R3,R3,#24               ;Point to next real icon
551                 B       %06                     ;Try another icon
552
553                 ; --- Try more items from next header ---
554
555 20              ADD     R1,R1,#20               ;Point to next header
556                 LDR     R0,[R1]                 ;Get the item count
557                 CMP     R0,#0                   ;Is there one?
558                 BNE     %05                     ;...and do it
559
560                 ; --- Now move onto next menu ---
561
562                 LDMFD   R13!,{R3}               ;Get the first item pointer
563                 LDR     R0,menu__maxLen         ;Get the menu with
564                 ADD     R0,R0,#1                ;Add a character width
565                 MOV     R0,R0,LSL#4             ;Multiply width by 16
566                 STR     R0,[R3,#-12]            ;Store in menu width field
567                 LDR     R0,[R12]                ;Get the length
568                 ADD     R12,R12,R0              ;Point to the next menu
569                 LDMFD   R13!,{R10}              ;Load menu hit pointer
570                 B       %00                     ;And keep looking
571
572                 ; --- We have apparently finished now ---
573
574 90              LDMFD   R13!,{R0-R12,PC}^       ;Return to caller
575
576                 ; --- Calculate a bit specification ---
577
578 99              LDR     R5,[R0],#4              ;Get the next word
579                 ADD     R6,R7,R5,LSR#5          ;Get the offset
580                 LDR     R6,[R6]                 ;And the byte there
581                 AND     R5,R5,#31               ;Clear bits we don't want
582                 ADD     R5,R5,#1                ;Correct for shifting
583                 MOVS    R6,R6,LSR R5            ;Shift that bit into carry
584                 MOV     PC,R14                  ;Return from subroutine
585
586                 LTORG
587
588 ; --- menu__locateFirst ---
589 ;
590 ; On entry:     R0 == pointer to my menu defn
591 ;
592 ; On exit:      R0 == pointer to first item in menu
593 ;               R1 == Number of items in menu
594 ;
595 ; Use:          Given a pointer to a menu definition (my type, not
596 ;               WIMP), it returns a pointer to the first item, and
597 ;               a count of the number of items in the menu.
598
599 menu__locateFirst
600                 ROUT
601
602                 STMFD   R13!,{R2-R6,R14}        ;Stack some registers
603
604                 MOV     R1,#0                   ;Item count
605                 ADD     R0,R0,#20               ;Point past length/re-create
606 00              LDMIA   R0!,{R2,R3,R4,R5,R6}    ;Load menu data
607                 CMP     R2,#0                   ;Is this the last item?
608                 ADDNE   R1,R1,R2                ;No -- increment item count
609                 BNE     %00                     ;Keep searching
610                 ADD     R0,R0,#12               ;Point to the first item
611                 LDMFD   R13!,{R2-R6,PC}^        ;Return to caller
612
613                 LTORG
614
615 ; --- menu__height ---
616 ;
617 ; On entry:     R1 == pointer to real menu block
618 ;
619 ; On exit:      R0 == height of menu
620 ;
621 ; Use:          Calculates the height of a WIMP menu, from its data structure
622
623 menu__height    ROUT
624
625                 STMFD   R13!,{R1-R2,R14}        ;Stack some registers
626
627                 MOV     R0,#0                   ;The height so far
628                 ADD     R1,R1,#28               ;Point to the first item
629 00              ADD     R0,R0,#44               ;Increment the height
630                 LDR     R2,[R1]                 ;Get the flags word
631                 TST     R2,#2                   ;Is there a dotted line?
632                 ADDNE   R0,R0,#24               ;Yes -- add 24 to height
633                 TST     R2,#&80                 ;Is this the last item?
634                 ADDEQ   R1,R1,#24               ;No -- point to next item
635                 BEQ     %00                     ;...and keep counting
636
637                 LDMFD   R13!,{R1-R2,PC}^        ;Return to caller
638
639                 LTORG
640
641 ; --- menu__open ---
642 ;
643 ; On entry:     R2 == modules flags word
644 ;               R9 == workspace pointer
645 ;
646 ; On exit:      --
647 ;
648 ; Use:          Opens the next menu in the right place
649
650 menu__open      ROUT
651
652                 STMFD   R13!,{R0-R4,R14}        ;Stack some registers
653
654                 LDR     R0,menu__start          ;Point to current menu
655                 BL      menu__locateFirst       ;Find the first item
656                 SUB     R1,R1,#1                ;0 index item count
657                 MOV     R1,R1,LSL#3             ;Multiple no. of items by 8
658                 RSB     R1,R1,R1,LSL#2          ;And the by 3
659                 ADD     R1,R0,R1                ;Point to last item
660                 LDR     R3,[R1]                 ;Load the flags word
661                 ORR     R3,R3,#&80              ;Set 'Last item' bit
662                 BIC     R3,R3,#2                ;No ruleoff here
663                 STR     R3,[R1]                 ;Store the flags back
664
665                 SUB     R1,R0,#28               ;Point to real menu structure
666                 LDR     R0,menu__maxLen         ;Get the longest text length
667                 MOV     R0,R0,LSL#4             ;Multiply by 16
668                 ADD     R0,R0,#16               ;Add one for luck
669                 STR     R0,[R1,#16]             ;Store the width
670                 MOV     R4,R2                   ;Remember flags word
671                 TST     R4,#mFlag__recreating   ;Are we recreating a menu
672                 LDMNEFD R13!,{R0-R4,PC}^        ;Yes -- Return
673                 ADR     R2,menu__coords         ;Point to coords block
674                 LDMIA   R2,{R2,R3}              ;Get the x and y coords
675
676                 ; --- Ensure Y position is correct on icon bar ---
677
678                 TST     R4,#mFlag__iBar         ;Was it on the icon bar?
679                 BLNE    menu__height            ;Calculate the menu height
680                 ADDNE   R3,R0,#96               ;This is the Y position
681
682                 TST     R4,#mFlag__wasSub       ;Is it a submenu?
683                 BEQ     %90                     ;No -- create a normal menu
684                 LDR     R0,menu__prevMenu       ;Get menu from which it came
685                 ADD     R0,R0,#20               ;Point to the first header
686 50menu__open    LDR     R14,[R0],#4             ;Get the number of items
687                 CMP     R14,#0                  ;Any more headers?
688                 ADDNE   R0,R0,#16               ;Yes -- point to next one
689                 BNE     %50menu__open           ;...and keep looking
690                 ADD     R0,R0,#28               ;Point to first item
691                 LDR     R14,menu__prevItem      ;Get the previous item hit
692                 MOV     R14,R14,LSL#3           ;Multiply item hit by 8
693                 RSB     R14,R14,R14,LSL#2       ;And then by 3
694                 ADD     R0,R0,R14               ;Point to the item
695                 STR     R1,[R0,#4]              ;Store pointer in menu field
696                 SWI     Wimp_CreateSubMenu      ;Create sub menu
697                 LDMFD   R13!,{R0-R4,PC}^        ;Return
698
699 90menu__open    SUB     R2,R2,#64               ;No -- correct X position
700                 SWI     Wimp_CreateMenu         ;...create the menu
701                 ORR     R4,R4,#mFlag__opened    ;Set the opened bit
702                 STR     R4,menu__flags          ;Store the modified flags
703                 LDMFD   R13!,{R0-R4,PC}^        ;Return
704
705                 LTORG
706
707 ; --- menu__skipText ---
708 ;
709 ; On entry:     R0 == pointer to text field
710 ;               R2 == item flags for this item
711 ;
712 ; On exit:      R0 == pointer to first data field after the text
713 ;
714 ; Use:          Skips text part of an icon definition
715
716 menu__skipText  ROUT
717
718                 STMFD   R13!,{R14}              ;Stack registers
719
720                 TST     R2,#mFlag_indirect      ;Is it indirected?
721                 ADDNE   R0,R0,#4                ;Yes -- just skip a word
722                 LDMNEFD R13!,{PC}^              ;And return
723
724 00              LDRB    R14,[R0],#1             ;Get a character
725                 CMP     R14,#0                  ;Is it a NULL
726                 BNE     %00                     ;No, keep looking
727                 ADD     R0,R0,#3                ;Word align R0
728                 BIC     R0,R0,#3                ;Complete aligning
729                 LDMFD   R13!,{PC}^              ;And return
730
731                 LTORG
732
733 ; --- menu__findItem ---
734 ;
735 ; On entry:     R0 == pointer to menu definition (my kind)
736 ;               R1 == Item number to locate
737 ;
738 ; On exit:      R0 == pointer to the item definition
739 ;               R1 == pointer to header entry for this item
740 ;               R2 == index for this item (to pass to handler)
741 ;
742 ; Use:          Locates the given item from a created menu definition,
743 ;               and also finds the header entry for it
744
745 menu__findItem  ROUT
746
747                 STMFD   R13!,{R3,R4,R14}        ;Stack some registers
748
749                 ADD     R0,R0,#20               ;Point to first header
750                 MOV     R2,#0                   ;Item so far
751 00              LDR     R3,[R0]                 ;Number of items header's for
752                 MOV     R4,R2                   ;Number so far
753                 ADD     R2,R2,R3                ;Increment my count
754                 CMP     R1,R2                   ;Is this the relevant header?
755                 ADDGE   R0,R0,#20               ;No -- point to next header
756                 BGE     %00                     ;...and keep looking
757
758                 ; --- We have located the relevant header ---
759
760                 SUBS    R3,R1,R4                ;Calculate item index
761                 STMFD   R13!,{R3}               ;Store it on the stack
762                 MOV     R1,R0                   ;Point to header for user
763                 LDR     R0,[R1,#4]              ;Find definition pointer
764 10              LDMEQFD R13!,{R2-R4,PC}^        ;Yes -- return to caller
765                 LDR     R2,[R0],#4              ;Load the flags
766                 BL      menu__skipText          ;Skip the text
767                 TST     R2,#mFlag_shade         ;Is there a shade field
768                 ADDNE   R0,R0,#4                ;Yes -- skip it
769                 TST     R2,#mFlag_iShade        ;Is there a ishade field
770                 ADDNE   R0,R0,#4                ;Yes -- skip it
771                 TST     R2,#mFlag_switch        ;Is there a switch field
772                 ADDNE   R0,R0,#4                ;Yes -- skip it
773                 TST     R2,#mFlag_radio         ;Are there radio fields
774                 ADDNE   R0,R0,#8                ;Yes -- skip them
775                 TST     R2,#mFlag_sprite        ;Is there a sprite pointer?
776                 ADDNE   R0,R0,#4                ;Yes -- skip it
777                 TST     R2,#mFlag_subMenu       ;Automatic submenu?
778                 ADDNE   R0,R0,#8                ;Yes -- skip fields
779                 SUBS    R3,R3,#1                ;Decrement the count
780                 B       %10                     ;Keep searching
781
782                 LTORG
783
784 ; --- menu__dispatch ---
785 ;
786 ; On entry:     R0 == event type to send
787 ;               R1 == pointer to menu hits
788 ;
789 ; On exit:      --
790 ;
791 ; Use:          Called to dispatch a menu hit event
792
793 menu__dispatch  ROUT
794
795                 STMFD   R13!,{R0-R3,R10,R12,R14}
796
797                 MOV     R3,R0                   ;Remember event to send
798                 LDR     R0,menu__stack          ;Point to first menu header
799 00              LDR     R2,[R1,#4]!             ;Load a menu hit (ignore 1st)
800                 CMP     R2,#-1                  ;Is this the end?
801                 BEQ     %10                     ;Yes -- branch ahead
802                 LDR     R2,[R0]                 ;Get the length
803                 ADD     R0,R0,R2                ;Point to the next menu
804                 B       %00                     ;And keep looking
805 10              LDR     R1,[R1,#-4]             ;Get the item number
806                 BL      menu__findItem          ;Point to item and header
807                 MOV     R14,R0                  ;Keep the item pointer
808                 ADD     R1,R1,#8                ;Point to the event handler
809                 MOV     R0,R3                   ;Get the event type
810                 LDMFD   R1,{R3,R10,R12}         ;Get the values
811                 MOV     R1,R2                   ;The indexed item number
812                 MOV     R2,R14                  ;Pass item address in R2
813                 CMP     R3,#0                   ;Sanity check
814                 MOV     R14,PC                  ;Set up return address
815                 MOVNE   PC,R3                   ;Jump to the event handler
816
817                 LDMFD   R13!,{R0-R3,R10,R12,PC}^ ;Return
818
819                 LTORG
820
821 ; --- menu__preFilter ---
822 ;
823 ; On entry:     R0 == event mask and flags
824 ;               R1 == pointer to block to use
825 ;               R2 == earliest time to return with NULL event
826 ;               R3 == pointer to poll word
827 ;
828 ; On exit:      --
829 ;
830 ; Use:          Call as an event pre-filter. Its purpose is to open
831 ;               a previously created menu in the right place.
832
833 menu__preFilter ROUT
834
835                 STMFD   R13!,{R0-R2,R9,R14}     ;Stack some registers
836                 MOV     R9,R12                  ;Get workspace pointer in R9
837
838                 LDR     R2,menu__flags          ;Get my flags word
839                 TST     R2,#mFlag__creating     ;Are we creating a menu?
840                 BEQ     %90menu__preFilter      ;No -- return then
841                 TST     R2,#mFlag__wasSub       ;Is this from a sub menu?
842                 BNE     %70menu__preFilter      ;Yes -- just open the menu
843
844                 ; --- Set up menu coordinates and things ---
845
846                 BL      event_last              ;Get the last event
847                 CMP     R0,#6                   ;Mouse click?
848                 BEQ     %50menu__preFilter      ;Yes -- deal with it
849
850                 ; --- Open over the mouse pointer then ---
851
852                 MOV     R14,R2                  ;Preserve flags word
853                 SUB     R13,R13,#20             ;Get a block for me
854                 MOV     R1,R13                  ;Point to the block
855                 SWI     Wimp_GetPointerInfo     ;Get pointer information
856                 LDMIA   R1,{R0,R1}              ;Get coords out of block
857                 ADR     R2,menu__coords         ;Point to coords block
858                 STMIA   R2,{R0,R1}              ;Store them in the block
859                 ADD     R13,R13,#20             ;Get stack back
860                 MOV     R2,R14                  ;Get flags back
861                 B       %70menu__preFilter      ;Open the menu
862
863                 ; --- Deal with button click ---
864
865 50              MOV     R14,R2                  ;Preserve flags word
866                 LDR     R0,[R1,#12]             ;Get the window handle
867                 CMP     R0,#-2                  ;Is it the icon bar
868                 BNE     %60menu__preFilter      ;No -- jump
869                 ORR     R14,R14,#mFlag__iBar    ;Set relevent bit
870                 STR     R14,menu__flags         ;Store the flags back
871 60              ADR     R2,menu__coords         ;Point to coords block
872                 LDMIA   R1,{R0,R1}              ;Get x and y coords
873                 STMIA   R2,{R0,R1}              ;Store them in the block
874                 MOV     R2,R14                  ;Get flags word back
875
876                 ; --- Open the menu,then ---
877
878 70              BL      menu__open              ;Yes -- open the menu
879 90              LDR     R2,menu__flags          ;Get new flags
880                 AND     R2,R2,#mFlag__inited+mFlag__opened
881                 STR     R2,menu__flags          ;Store the new flags
882                 LDMFD   R13!,{R0-R2,R9,PC}^     ;Return to caller
883
884                 LTORG
885
886 ; --- menu__postFilter ---
887 ;
888 ; On entry:     R0 == wimp event
889 ;               R1 == pointer to block
890 ;
891 ; On exit:      --
892 ;
893 ; Use:          Called as an event post filter to catch menu related events
894
895 menu__postFilter
896                 ROUT
897
898                 ; --- Are we at all interested? ---
899
900                 STMFD   R13!,{R9,R14}           ;Store R9 value
901                 MOV     R9,R12                  ;Get the workspace pointer
902                 LDR     R14,menu__flags         ;Get the menu flags
903                 TST     R14,#mFlag__opened      ;Do we have a menu open?
904                 LDMEQFD R13!,{R9,PC}^           ;No -- ignore it then
905
906                 CMP     R0,#9                   ;Menu click?
907                 BEQ     %20                     ;Yes -- deal with that
908                 CMP     R0,#17                  ;User_Message
909                 CMPNE   R0,#18                  ;User_Message_Recorded
910                 BNE     %90                     ;No -- tidy up a bit
911
912                 ; --- It was a message, are we interested? ---
913                 ;
914                 ; Note that we are allowed to corrupt R12
915
916                 STMFD   R13!,{R0-R2}            ;Stack some registers
917                 LDR     R0,=&400C0              ;Menu warning
918                 LDR     R12,[R1,#16]            ;Get the message type
919                 CMP     R0,R12                  ;Is it menu warning?
920                 BEQ     %05                     ;Yes -- deal with it
921                 LDR     R0,=&400C9              ;Menus deleted
922                 CMP     R0,R12                  ;Is that the message?
923                 BEQ     %03                     ;Yes -- deal with it
924                 LDR     R0,=&502                ;Help request
925                 CMP     R0,R12                  ;Is that the message?
926                 LDMNEFD R13!,{R0-R2}            ;No -- Get registers
927                 BNE     %90                     ;...and tidy up a bit
928
929                 ; --- There was a help request ---
930
931                 STMFD   R13!,{R3,R10,R12}       ;We need these
932                 SUB     R13,R13,#40             ;Get a buffer
933                 MOV     R0,#1                   ;Get state give window/icon
934                 ADD     R1,R1,#32               ;Point to window/icon handle
935                 LDMIA   R1,{R2,R3}              ;Get them
936                 LDR     R14,menu__twin          ;Get the dbmn address
937                 LDR     R14,[R14,#twin_trans]   ;Get the transient dbox
938                 CMP     R14,R2                  ;Are they the same
939                 BEQ     %02                     ;Yes -- forget it
940                 MOV     R1,R13                  ;Use this buffer
941                 SWI     XWimp_GetMenuState      ;Get the menu state
942                 BVS     %02                     ;If failed, return
943                 LDR     R0,[R1,#0]              ;First first menu index
944                 CMP     R0,#-1                  ;Is it on our menu?
945                 BEQ     %02                     ;No -- skip forward
946                 MOV     R0,#mEvent_help         ;Set the event type
947                 BL      menu__dispatch          ;Dispatch the event
948
949                 ; --- Return to caller ---
950
951 02              ADD     R13,R13,#40             ;Reclaim my stack
952                 LDMFD   R13!,{R3,R10,R12}       ;Get these values back
953                 LDMFD   R13!,{R0-R2}            ;Get registers
954                 B       %90                     ;...and tidy up a bit
955
956                 ; --- There was a menus deleted message ---
957
958 03              STMFD   R13!,{R10,R12}          ;We need these
959                 LDR     R0,menu__flags          ;Get the flags word
960                 BIC     R0,R0,#mFlag__opened    ;Well,it's closed now
961                 STR     R0,menu__flags          ;Store the flags back
962                 LDR     R0,menu__stack          ;Find the top level menu
963                 ADD     R0,R0,#8                ;Point to the handler
964                 LDMIA   R0,{R2,R10,R12}         ;Get handler and R10/R12
965                 MOV     R0,#mEvent_deleted      ;Set the event type
966                 CMP     R2,#0                   ;Sanity check
967                 MOV     R14,PC                  ;Set the return address
968                 MOVNE   PC,R2                   ;Call the handler
969 04              LDMFD   R13!,{R10,R12}          ;Get these values back
970                 LDMFD   R13!,{R0-R2}            ;Get registers
971                 B       %90                     ;...and tidy up a bit
972
973                 ; --- It was a submenu warning ---
974
975 05              LDR     R0,menu__flags          ;Get the flags
976                 ORR     R0,R0,#mFlag__wasSub    ;It was a menu warning
977                 STR     R0,menu__flags          ;Put the flags back
978                 ADR     R0,menu__coords         ;Point to my coords block
979                 ADD     R1,R1,#24               ;Point to the (x,y) to use
980                 LDMIA   R1!,{R2,R12}            ;Load x and y
981                 STMIA   R0,{R2,R12}             ;And store them usefully
982
983                 ; --- We now need to find the menu in question ---
984
985                 LDR     R0,menu__stack          ;Point to first menu header
986 05              LDR     R2,[R1,#4]!             ;Load a menu hit (ignore 1st)
987                 CMP     R2,#-1                  ;Is this the end?
988                 BEQ     %10                     ;Yes -- branch ahead
989                 LDR     R2,[R0]                 ;Get the length
990                 ADD     R0,R0,R2                ;Point to the next menu
991                 B       %05                     ;And keep looking
992 10              STR     R0,menu__prevMenu       ;Store this pointer
993                 LDR     R1,[R1,#-4]             ;Get the item number
994                 STR     R1,menu__prevItem       ;Store the item number
995
996                 ; --- Now we need to create the submenu if we need to ---
997
998                 BL      menu__findItem          ;Point to the item definition
999                 LDR     R2,[R0],#4              ;Get the flags word
1000                 TST     R2,#mFlag_subMenu       ;Automatic menu?
1001                 BNE     %15                     ;Yes -- deal with it
1002
1003                 ; --- Here we must just tell the user ---
1004                 ;
1005                 ; R0 == pointer to the menu item definition+4
1006                 ; R1 == pointer to the menu header for this item
1007                 ; R2 == item flags
1008
1009                 MOV     R0,#mEvent_arrow        ;Set the event type
1010                 LDR     R1,[R13,#4]             ;Get the message block
1011                 ADD     R1,R1,#32               ;Point to the menu hit list
1012                 BL      menu__dispatch          ;Dispatch the event
1013                 LDMFD   R13!,{R0-R2,R9,PC}^     ;Return to caller
1014
1015                 ; --- We must automatically open the menu ---
1016
1017 15              BL      menu__skipText          ;Skip the item text
1018                 TST     R2,#mFlag_switch        ;Is there a switch field
1019                 ADDNE   R0,R0,#4                ;Yes -- skip it
1020                 TST     R2,#mFlag_shade         ;Is there a shade field
1021                 ADDNE   R0,R0,#4                ;Yes -- skip it
1022                 TST     R2,#mFlag_iShade        ;Is there a ishade field
1023                 ADDNE   R0,R0,#4                ;Yes -- skip it
1024                 TST     R2,#mFlag_radio         ;Are there radio fields
1025                 ADDNE   R0,R0,#8                ;Yes -- skip them
1026                 TST     R2,#mFlag_sprite        ;Is there a sprite?
1027                 ADDNE   R0,R0,#4                ;Yes -- skip pointer
1028                 ADD     R1,R1,#12               ;Point to R10,R12 for item
1029                 LDMIA   R1,{R2,R3}              ;Use these values again
1030                 LDMIA   R0,{R0,R1}              ;Get menu pointer & handler
1031                 BL      menu_create             ;Create this menu
1032
1033                 LDMFD   R13!,{R0-R2,R9,PC}^     ;Return to caller
1034
1035                 ; --- Deal with menu selection ---
1036
1037 20              STMFD   R13!,{R0-R2}            ;Stack some registers
1038                 BIC     R14,R14,#mFlag__opened  ;Say the menu just closed
1039                 STR     R14,menu__flags         ;Save these flags back
1040
1041                 ; --- Set up the dbmn flag word ---
1042
1043                 LDR     R2,menu__twin           ;Locate dbmn area
1044                 LDR     R14,[R2,#twin_flags]    ;Get the flags word
1045                 ORR     R14,R14,#twinFlag_recrt ;We are going to recreate it
1046                 STR     R14,[R2,#twin_flags]    ;Store the flags back
1047
1048                 ; --- Dispatch the event ---
1049
1050                 MOV     R0,#mEvent_select       ;Set the event type
1051                 BL      menu__dispatch          ;Dispatch the event
1052
1053                 LDR     R14,[R2,#twin_flags]    ;Get the flags word back
1054                 TST     R14,#twinFlag_recrt     ;Do we still need to recreate
1055                 LDMEQFD R13!,{R0-R2}            ;No -- get registers back
1056                 BEQ     %90                     ;...and tidy up
1057
1058                 ; --- Recreate the menu if we need to ---
1059
1060                 SUB     R13,R13,#20             ;Get a block
1061                 MOV     R1,R13                  ;Point to it
1062                 SWI     Wimp_GetPointerInfo     ;Get pointer information
1063                 LDR     R1,[R1,#8]              ;Get the button state
1064                 TST     R1,#1                   ;Was Adjust clicked?
1065                 ADD     R13,R13,#20             ;Get the stack back
1066                 LDMEQFD R13!,{R0-R2}            ;No -- get registers back
1067                 BEQ     %90                     ;...and tidy up
1068                 LDMIB   R13,{R1}                ;Get the menu hit list back
1069                 BL      menu__recreate          ;Recreate the menu
1070                 LDR     R1,menu__stack          ;Get the stack pointer
1071                 ADD     R1,R1,#20               ;Point to the first header
1072 25              LDR     R0,[R1],#4              ;Get the number of items
1073                 CMP     R0,#0                   ;Any more headers?
1074                 ADDNE   R1,R1,#16               ;Yes -- point to next one
1075                 BNE     %25                     ;...and keep looking
1076                 SWI     Wimp_CreateMenu         ;Recreate the menu
1077                 LDR     R14,menu__flags         ;Load the menu flags again
1078                 ORR     R14,R14,#mFlag__opened  ;The menu is still open
1079                 STR     R14,menu__flags         ;Save the flags back
1080
1081                 LDMFD   R13!,{R0-R2}            ;Get registers back
1082                 B       %90                     ;And tidy up
1083
1084                 ; --- Tidy up on a non-submenu warning event ---
1085
1086 90              LDR     R12,menu__flags         ;Get the flags
1087                 BIC     R12,R12,#mFlag__wasSub  ;It was not a menu warning
1088                 STR     R12,menu__flags         ;Put the flags back
1089                 LDMFD   R13!,{R9,PC}^           ;Return to caller
1090
1091                 LTORG
1092
1093 ; --- menu_help ---
1094 ;
1095 ; On entry:     R0 == pointer to base message tag
1096 ;               R1 == index of menu item
1097 ;
1098 ; On exit:      --
1099 ;
1100 ; Use:          Adds a string to the help message found by adding the menu
1101 ;               item number to the base message tag.
1102
1103                 EXPORT  menu_help
1104 menu_help       ROUT
1105
1106                 CMP     R1,#0                   ;Is the menu item sane?
1107                 MOVLTS  PC,R14                  ;No -- don't trust Tim
1108                 STMFD   R13!,{R0-R2,R14}        ;Save some registers
1109                 MOV     R1,R0                   ;Point to base message tag
1110                 MOV     R0,R11                  ;Point to scratchpad
1111                 BL      str_cpy                 ;Add the string in there
1112                 MOV     R1,R0                   ;Point to terminating null
1113                 MOV     R2,#25                  ;Should be 25 bytes left over
1114                 LDR     R0,[R13,#4]             ;Get his item number
1115                 SWI     OS_ConvertInteger4      ;Tack it on the end
1116                 MOV     R0,R11                  ;Point to the message tag
1117                 BL      msgs_lookup             ;Translate it nicely
1118                 BL      help_add                ;Add it to the help string
1119                 LDMFD   R13!,{R0-R2,PC}^        ;Return to caller
1120
1121                 LTORG
1122
1123 ; --- menu_init ---
1124 ;
1125 ; On entry:     --
1126 ;
1127 ; On exit:      --
1128 ;
1129 ; Use:          Initialises the menu system.
1130
1131                 EXPORT  menu_init
1132 menu_init       ROUT
1133
1134                 STMFD   R13!,{R0-R3,R9,R14}     ;Stack some registers
1135                 WSPACE  menu__wSpace,R9         ;Locate my workspace
1136
1137                 ; --- Are we already initialised? ---
1138
1139                 LDR     R0,menu__flags          ;Get my flags
1140                 TST     R0,#mFlag__inited       ;Are we initialised?
1141                 LDMNEFD R13!,{R0-R3,R9,PC}^     ;Yes -- return
1142
1143                 ORR     R0,R0,#mFlag__inited    ;Set initialised flag
1144                 STR     R0,menu__flags          ;And store them back
1145
1146                 ; --- Ensure that event is initialised ---
1147
1148                 BL      event_init              ;Initialise it
1149
1150                 ; --- Set up my menu stack ---
1151
1152                 LDR     R0,menu__optName        ;Get the option block name
1153                 BL      libOpts_find            ;Try to find the block
1154                 LDRCS   R3,[R0,#0]              ;If found, load stack size
1155                 MOVCC   R3,#2048                ;Otherwise use default 2K
1156                 MOV     R0,#2                   ;Allocate memory
1157                 BL      sapphire_heapAddr       ;Find the heap address
1158                 SWI     OS_Heap                 ;Allocate the stack
1159                 STR     R2,menu__stack          ;Store this value
1160                 ADD     R3,R3,R2                ;The end of the menu stack
1161                 STR     R3,menu__stackEnd       ;The menu stack end
1162
1163                 ; --- Set up the filters ---
1164
1165                 ADR     R0,menu__preFilter      ;Point to the filter
1166                 MOV     R1,R9                   ;Use this workspace
1167                 BL      event_preFilter         ;Add the pre filter
1168
1169                 ADR     R0,menu__postFilter     ;Point to the filter
1170                 MOV     R1,R9                   ;Use this workspace
1171                 BL      event_postFilter        ;Add the post filter
1172
1173                 ; --- Locate the TWIN global area ---
1174
1175                 LDR     R0,menu__TWIN           ;Load the global area name
1176                 MOV     R1,#twin_size           ;Load the area's size
1177                 BL      sapphire_global         ;Find the area's address
1178                 STR     R0,menu__twin           ;Store the address away
1179
1180                 MOVCC   R1,#0                   ;Clear the global area
1181                 MOVCC   R2,#0
1182                 MOVCC   R14,#0
1183                 STMCCIA R0,{R1,R2,R14}          ;Store zeroes all over it
1184
1185                 ; --- And return peacefully ---
1186
1187                 LDMFD   R13!,{R0-R3,R9,PC}^     ;Return to caller
1188
1189 menu__optName   DCB     "MENU"
1190 menu__TWIN      DCB     "TWIN"
1191
1192                 LTORG
1193
1194 menu__wSpace    DCD     0
1195
1196 ;----- Global area layouts --------------------------------------------------
1197
1198 ; --- TWIN global area ---
1199 ;
1200 ; See transWin for more details
1201
1202                 ^       0
1203 twin_flags      #       4                       ;Various flags for things
1204 twin_trans      #       4                       ;Handle of transient window
1205 twin_tmsHook    #       4                       ;Hook for TMS
1206 twin_size       #       4
1207
1208 twinFlag_recrt  EQU     (1<<0)                  ;Do we want to recreate?
1209
1210 ;----- Workspace ------------------------------------------------------------
1211
1212                 ^       0,R9
1213 menu__wStart    #       0
1214
1215 menu__flags     #       4                       ;Flags word
1216
1217 mFlag__inited   EQU     (1<<0)                  ;We are initialised
1218 mFlag__creating EQU     (1<<1)                  ;We are creating a menu
1219 mFlag__wasSub   EQU     (1<<2)                  ;Last event was sub menu warn
1220 mFlag__tOnly    EQU     (1<<4)                  ;Only the title has been done
1221 mFlag__iBar     EQU     (1<<5)                  ;The click was on icon bar
1222 mFlag__recreating EQU   (1<<6)                  ;We are recreating a menu
1223 mFlag__opened   EQU     (1<<7)                  ;I have a menu opened
1224
1225 menu__stack     #       4                       ;Pointer to the menu stack
1226 menu__stackEnd  #       4                       ;The end of the menu stack
1227 menu__start     #       4                       ;Start of current menu defn
1228 menu__begin     #       4                       ;Pointer to real menu
1229 menu__end       #       4                       ;The end of the menu
1230
1231 menu__maxLen    #       4                       ;Maximum length of items
1232 menu__sprite    #       4                       ;Pointer to a sprite name
1233 menu__coords    #       8                       ;(x,y) coords to open menu at
1234 menu__prevMenu  #       4                       ;Menu from which warning came
1235 menu__prevItem  #       4                       ;Menu from which warning came
1236 menu__twin      #       4                       ;Pointer to DBMN global area
1237
1238 menu__wSize     EQU     {VAR}-menu__wStart
1239
1240                 AREA    |Sapphire$$LibData|,CODE,READONLY
1241
1242                 DCD     menu__wSize             ;Workspace size
1243                 DCD     menu__wSpace            ;Workspace pointer
1244                 DCD     0                       ;Scratchpad size
1245                 DCD     menu_init               ;Initialisation
1246
1247 ;----- That's all, folks ----------------------------------------------------
1248
1249                 END