; ; tmsCreate.s ; ; Creation, recreation and destruction of tearoff menus (TMA) ; ; © 1994 Straylight ; ;----- Standard Header ------------------------------------------------------ GET libs:header GET libs:swis GET libs:stream ;----- External dependencies ------------------------------------------------ GET sapphire:alloc GET sapphire:heap GET sapphire:keyString GET sapphire:msgs GET sapphire:resspr GET sapphire:sapphire GET sapphire:string GET sapphire:wimp GET sapphire:win GET sapphire:winUtils GET sapphire:_tms.tmsGlobal GET sapphire:_tms.tmsMain ;----- Main code ------------------------------------------------------------ AREA |Sapphire$$Code|,CODE,READONLY ; --- tms__bitSpec --- ; ; On entry: R5 == pointer to base pointer (R10 or R12) for this item ; R9 == pointer to bit specification to work out ; ; On exit: R9 has had 4 added to it ; C set or clear according to settedness of the bit ; ; Use: Tells you whether a bit specification points at a bit which ; is set or clear by copying it to the carry flag tms__bitSpec ROUT STMFD R13!,{R0,R14} ;Save some registers LDR R0,[R9],#4 ;Load the specification MOV R14,R0,LSR #5 ;Get the offset value LDR R14,[R5,R14] ;Load the flags word out AND R0,R0,#31 ;Leave only bit spec bits ADD R0,R0,#1 ;To make it nice for shifting MOVS R14,R14,LSR R0 ;Copy bit to carry flag LDMFD R13!,{R0,R14} ;Load registers again ORRCSS PC,R14,#C_flag ;Set C if C set BICCCS PC,R14,#C_flag ;Clear C if C clear LTORG ; --- tms__findBase --- ; ; On entry: R2,R3 == R10 and R12 values to pass to event handler ; R8 == flags word from packed definition ; ; On exit: R5 == correct base register for this item tms__findBase ROUT TST R8,#mFlag_R12 ;Is the R12 flag on? MOVNE R5,R3 ;Yes -- return R12 value MOVEQ R5,R2 ;No -- return R10 value MOVS PC,R14 ;Return to caller LTORG ; --- tms__checksum --- ; ; On entry: R2 == pointer to a name ; ; On exit: R0 == checksum value ; ; Use: Calculates a checksum value for the given name tms__checksum ROUT STMFD R13!,{R2,R14} ;Stack some registers MVN R0,#0 ;Start with -1 00 LDRB R14,[R2],#1 ;Load a byte CMP R14,#' ' ;Are we at the end? EORCS R0,R14,R0,LSL #2 ;Add it on to the sum BCS %00tms__checksum ;No -- keep going then LDMFD R13!,{R2,PC}^ ;Return to caller ; --- tms__createTitle --- ; ; On entry: R9 == pointer to packed title definition ; ; On exit: R9 == pointer to packed item description ; R10 == pointer to header structure, filled in and glorious ; R0, R4-R8 corrupted ; ; Use: Builds a menu header block tms__createTitle ROUT BIC R14,R14,#V_flag ;Assume nothing can harm us STMFD R13!,{R14} ;Save link register MOV R0,#hSize ;Get the size we want BL heap_alloc ;Allocate a block for it BLCS alloc_error ;If no memory, get error msg LDMVSFD R13!,{PC} ;And return with V still set MOV R10,R0 ;Keep this pointer safe STR R10,tms__creating ;Store this pointer nicely STR R9,[R10,#hDefinition] ;Store pack defn pointer MOV R0,#0 ;Also want to zero item blk STR R0,tms__lastItems ;No item blocks created yet STR R0,[R10,#hItems] ;No items attached yet STR R0,[R10,#hKeyWidth] ;No shortcuts found yet STR R0,[R10,#hTextWidth] ;No items yet STR R0,[R10,#hSprWidth] ;No sprites yet STR R0,[R10,#hHandle] ;No window attached yet STR R0,[R10,#hNextTorn] ;Not in torn list STR R0,[R10,#hDbox] ;No dialogue box yet STR R0,[R10,#hFromItem] ;We're not from an item MOV R6,#0 ;No flags defined yet LDR R8,[R9],#4 ;Load the flags word out BL tms__findBase ;Get the correct base pointer TST R8,#mFlag_indirect ;Is this item indirected? BEQ %00tms__createTitle ;No -- jump on then STMFD R13!,{R1} ;Save a register nicely LDR R1,[R9],#4 ;Yes -- find offset nicely LDR R0,[R9],#4 ;...and the buffer size LDR R1,[R5,R1] ;...get the pointer out BL heap_alloc ;Allocate some memory BLCS alloc_error ;Get the error message MOVCS R0,R10 ;...point to the block BLCS heap_free ;...free the memory LDMCSFD R13!,{R1,PC} ;...and return STR R0,[R10,#hText] ;Store the text pointer BL str_cpy ;Copy the string into buffer MOV R0,R1 ;Put the string in R0 LDMFD R13!,{R1} ;And restore R1 saved above ORR R6,R6,#hFlag__tIndir ;Title is indirected BNE %10tms__createTitle ;Skip past this next bit 00 MOV R0,R9 ;Point to the message tag BL msgs_lookup ;Translate the message 05 LDRB R14,[R9],#1 ;Get a message string byte CMP R14,#' ' ;Is it a terminator? BGE %05tms__createTitle ;No -- get another one ADD R9,R9,#3 ;Add 3 BIC R9,R9,#3 ;And word align the pointer STR R0,[R10,#hText] ;Store the text pointer ; --- Store the string and get its length --- 10 BL wimp_strWidth ;Get the string's width ADD R0,R0,#32 STR R0,[R10,#hTitleWidth] ;Store as title width ; --- Now handle other bits of the flags --- TST R8,#mFlag_tearoff ;Are we tearable? ORRNE R6,R6,#hFlag__tearable ;Yes -- set the bit nicely TST R8,#mFlag_global ;Is menu `global'? ORRNE R6,R6,#hFlag__global ;Yes -- set the bit nicely STR R6,[R10,#hFlags] ;Store the flags word ; --- Now check for maximum height --- TST R8,#mFlag_maxHeight ;Is there a maximum height? LDRNE R0,[R9],#4 ;Yes -- read it out then MOVEQ R0,#0 ;No -- zero is a silly value STR R0,[R10,#hMaxHeight] ;Store in the right place ; --- Perform any other business --- ADD R0,R10,#hHandler ;Point to the handler bitty STMIA R0,{R1-R3} ;Store the 'handlers' away 90 LDMFD R13!,{PC}^ ;Return to caller LTORG ; --- tms_create --- ; ; On entry: R0 == pointer to a menu block ; R1 == pointer to event handler for the menu section ; R2 == R10 value to pass to the event handler ; R3 == R12 value to pass to the event handler ; ; On exit: R0 == tearoff handle for this menu ; May return an error ; ; Use: Creates a new menu, or adds sections to an existing one. EXPORT tms_create tms_create ROUT BIC R14,R14,#V_flag ;Hope there's no error STMFD R13!,{R1-R10,R12,R14} ;Save some registers away LDR R12,=tms__wSpace ;Find my workspace pointer WSPACE [R12] ;And then my workspace MOV R9,R0 ;Keep pointer to definition ; --- Get the menu header we're working on --- LDR R10,tms__creating ;Get the menu header pointer CMP R10,#0 ;Is it actually defined? BLEQ tms__createTitle ;No -- go away and create it BVS %99tms_create ;It failed -- return an error ; --- Update --- ; ; OK, the pointer to the first packed item is in R9, and ; R10 contains a pointer to a menu header. LDR R8,[R9],#4 ;Load the item flags word TST R8,#mFlag_end ;Is there only a title? MOVNE R0,R10 ;Yes -- return the handle LDMNEFD R13!,{R1-R10,R12,PC}^ ;Return to caller nicely ; --- Now we need to scan through to count the items --- MOV R7,R9 ;Current ptr in packed defn MOV R0,#iHdrSize ;Count the fixed-size header MOV R4,#0 ;Number of items I've found 00tms_create TST R8,#mFlag_indirect ;Is this item indirected? ADDNE R7,R7,#4 ;Yes -- skip the offset word BNE %02tms_create ;And skip past the loop ; --- Skip inline text string --- 01tms_create LDRB R14,[R7],#1 ;Get a message string byte CMP R14,#' ' ;Is it a terminator? BGE %01tms_create ;No -- get another one ADD R7,R7,#3 ;Add 3 BIC R7,R7,#3 ;And word align the pointer ; --- Now skip other optional blocks --- 02tms_create TST R8,#mFlag_shortcut ;Is ther a normal... TSTEQ R8,#mFlag_iShortcut ;...or indirected shortcut? ADDNE R7,R7,#4 ;Yes -- skip over it then SKPITEM R8,R7 ;Skip past another item ADD R0,R0,#iItemSize ;Add on size for another item ADD R4,R4,#1 ;And bump my counter too LDR R8,[R7],#4 ;Load the next flags word TST R8,#mFlag_end ;Is this the end yet? BEQ %00tms_create ;Yes -- continue with the fun ; --- R0 now contains how much we want --- BL heap_alloc ;Allocate the memory now BLCS alloc_error ;If it failed, find an error BVS %99tms_create ;And return it nicely ; --- Mangle all the list stuff --- MOV R7,R0 ;Keep the pointer safely LDR R6,tms__lastItems ;Get the last item block CMP R6,#0 ;Is there one defined? STRNE R7,[R6,#iItems] ;Yes -- store in next field STREQ R7,[R10,#hItems] ;No -- store as list head STR R7,tms__lastItems ;This is the new last blk MOV R0,#0 ;Want to terminate the list STR R0,[R7,#iItems] ;Store it in the next field STR R0,[R7,#iDbox] ;No dialogue box yet ; --- Build the item block header --- STR R4,[R7,#iNumber] ;Store item counter SUB R0,R9,#4 ;Point to definition start STR R0,[R7,#iDefinition] ;Store in the pointer field ADD R0,R7,#iHandler ;Point to the handler words STMIA R0,{R1-R3} ;Store handler information ; --- Now we actually want to build the block --- LDR R8,[R9,#-4] ;Load the initial flags again ADD R7,R7,#iHdrSize ;Skip past header part 10tms_create MOV R0,#-1 ;Get a NULL word STR R0,[R7,#iKeyCode] ;No shortcut yet BL tms__findBase ;Find base workspace register TST R8,#mFlag_indirect ;Is this item indirected? LDRNE R0,[R9],#4 ;Yes -- find offset nicely LDRNE R0,[R5,R0] ;And get the pointer out BNE %12tms_create ;Skip past this next bit MOV R0,R9 ;Point to the message tag BL msgs_lookup ;Translate the message 11tms_create LDRB R14,[R9],#1 ;Get a message string byte CMP R14,#' ' ;Is it a terminator? BGE %11tms_create ;No -- get another one ADD R9,R9,#3 ;Add 2 (we added one in LDRB) BIC R9,R9,#3 ;And word align the pointer ; --- Store the pointer and carry on --- 12tms_create STR R0,[R7,#iText] ;Store the text pointer BL wimp_strWidth ;Find the item width LDR R14,[R10,#hTextWidth] ;Load previous text width CMP R0,R14 ;Is this bigger? STRGT R0,[R10,#hTextWidth] ;Yes -- store it over TST R8,#mFlag_shortcut ;Is there a menu short cut? TSTEQ R8,#mFlag_iShortcut ;Or an indirected one? BEQ %15tms_create ;No -- jump ahead TST R8,#mFlag_shortcut ;Is there a menu short cut? LDRNE R0,[R9],#4 ;Yes -- load out key code LDREQ R0,[R9],#4 ;No -- Load offset of code LDREQ R0,[R5,R0] ;...load out key code STR R0,[R7,#iKeyCode] ;Store the key code MOV R1,#1 ;Return short version BL keyString ;Find correct string BL wimp_strWidth ;Get the string width ADD R0,R0,#16 ;Put a gap on each side LDR R1,[R10,#hKeyWidth] ;Get longest one so far CMP R0,R1 ;Is this on longer? STRGT R0,[R10,#hKeyWidth] ;Yes -- store it then ; --- Severe cleverness warning --- ; ; The TST instructions clear Z iff the appropriate bit is ; on. tms__bitSpec sets C iff the appropriate bit read from ; a bit spec is on. We can actually combine testing for ; (C && !Z) with the HI condition code. This saves jumping ; around a lot. 15tms_create MOV R6,#0 ;Current flags word TST R8,#mFlag_shade ;Check shadedness bit BLNE tms__bitSpec ;Handle the bit specification ORRHI R6,R6,#iFlag__shaded ;If set, shade the item BHI %13tms_create ;...and jump this next bit TST R8,#mFlag_iShade ;Check shadedness bit BLNE tms__bitSpec ;Handle the bit specification ORRNE R6,R6,#iFlag__shaded ;Set shaded bit anyway BICHI R6,R6,#iFlag__shaded ;Bit clear it again if set! 13tms_create TST R8,#mFlag_switch ;Check switchiness bit BLNE tms__bitSpec ;Handle the bit specification ORRHI R6,R6,#iFlag__ticked ;If set, tick it TST R8,#mFlag_radio ;Check radioness bit BEQ %14tms_create ;If not set, skip ahead LDMIA R9!,{R0,R1} ;Load the information out LDR R0,[R5,R0] ;Load the radio specifier CMP R0,R1 ;Is this a match made in hvn? ORREQ R6,R6,#iFlag__radio ;Yes -- attach the splodge ; --- Deal with sprites --- 14tms_create TST R8,#mFlag_sprite ;Is there a sprite? BEQ %20tms_create ;No -- jump ahead STMFD R13!,{R2-R6} ;SpriteOp corrupts all these! LDMIA R9!,{R0,R1} ;Load the information out LDR R2,[R5,R0] ;Load the actual sprit addr STR R2,[R7,#iSprName] ;Save the name value BL tms__checksum ;Get the checksum STR R0,[R7,#iSprCsum] ;And store it away MOVS R0,R1 ;Get the sprite area BLMI resspr_area ;Negative -- get app's one MOV R1,R0 ;Put sprite area in R1 again STR R1,[R7,#iSprArea] ;Save the sprite area ORR R6,R6,#iFlag__sprite ;The item has a sprite TST R8,#mFlag_halfSize ;Should we display at half sz ORRNE R6,R6,#iFlag__halfSize ;Yes -- remember this STR R6,[R13,#16] ;Save this for later ; --- Find the width of the sprite --- CMP R1,#1 ;Are we using WIMP area? MOVNE R0,#256+40 ;No -- on user area name SWINE OS_SpriteOp ;...get information MOVEQ R0,#40 ;Yes -- info please SWIEQ Wimp_SpriteOp ;Get it then MOV R0,R6 ;Get the sprite's mode MOV R1,#4 ;Get the XEig factor SWI OS_ReadModeVariable ;Read the value MOV R3,R3,LSL R2 ;Work out the width in OS LDR R0,[R10,#hSprWidth] ;Load current sprite width TST R8,#mFlag_halfSize ;Should we display at half sz MOVNE R3,R3,LSR #1 ;Yes -- then divide by 2 ADD R3,R3,#16 ;Add on a little clearance CMP R3,R0 ;Is this bigger than that? STRGT R3,[R10,#hSprWidth] ;Yes -- then overwrite LDMFD R13!,{R2-R6} ;Restore those registers 20tms_create TST R8,#mFlag_ruleOff ;Is there a ruleoff here ORRNE R6,R6,#iFlag__dotted ;Yes -- add a dotted line TST R8,#mFlag_subWarn+mFlag_subMenu ;Arrow wanted? ORRNE R6,R6,#iFlag__arrow ;Yes -- add the arrow SKIP mFlag_subMenu,8,R8,R9 ;Skip submenu bit nicely TST R8,#mFlag_noWarn ;Do we warn on shaded items? ORRNE R6,R6,#iFlag__noWarn ;No -- remember this STR R6,[R7,#iFlags] ;Store the sussed out flags MOV R6,#0 ;A NULL pointer STR R6,[R7,#iSubMenu] ;No sub menu from here ADD R7,R7,#iItemSize ;Point at the next item ; --- Get the next flags word and loop --- LDR R8,[R9],#4 ;Get the next flags word TST R8,#mFlag_end ;Is this an end marker? BEQ %10tms_create ;No -- do the next one ; --- Return interesting things to caller --- MOV R0,R10 ;Give caller my header block LDMFD R13!,{R1-R10,R12,PC}^ ;Return to caller nicely 99tms_create ADD R2,R0,#4 ;Point to the message MOVS R0,R10 ;Point to menu header BLNE tms__destroy ;Destroy it if it exists ADR R0,tms__noCreate ;Point to error skeleton BL msgs_error ;Translate the error LDMFD R13!,{R1-R10,R12,R14} ;Restore registers ORRS PC,R14,#V_flag ;And return with the error LTORG tms__noCreate DCD 1 DCB "tmsCCTM:TMS cannot create menu: %s",0 ; --- tms__destroy --- ; ; On entry: R0 == handle of tearoff menu to destroy ; ; On exit: -- ; ; Use: Zaps a tearoff menu entirely, leaving no survivors EXPORT tms__destroy tms__destroy ROUT STMFD R13!,{R0-R4,R14} ;Stack some registers MOV R4,R0 ;Preserve menu pointer ; --- Delete the window, and remove its handler --- ADD R1,R0,#hHandle ;Point to the handle SWI Wimp_CloseWindow ;Close the window SWI Wimp_DeleteWindow ;Then delete it LDR R0,[R4,#hHandle] ;The window handle LDR R1,=tms__eventHandler ;Point to the handler MOV R2,R4 ;The handle passed MOV R3,R12 ;Workspace passed in R3 BL win_removeEventHandler ;Remove the event handler LDR R0,[R4,#hFlags] ;Load the header flags TST R0,#hFlag__tIndir ;Is title indirected? LDRNE R0,[R4,#hText] ;Yes -- load buffer pointer BLNE heap_free ;And free it nicely LDR R1,[R4,#hItems] ;Get the items pointer MOV R0,R4 ;Point back to the block BL heap_free ;Free the block 00tms__destroy MOVS R0,R1 ;Point R0 at the block LDMEQFD R13!,{R0-R4,PC}^ ;Return PDQ LDR R1,[R0,#iItems] ;Get the next items pointer BL heap_free ;Free the block B %00tms__destroy ;Keep destorying blocks LTORG ; --- tms__width --- ; ; On entry: R10 == pointer to the menu ; ; On exit: CS if the width has changed, CC otherwise ; ; Use: Calculates what the appropriate width fields of the given ; menu should be. EXPORT tms__width tms__width ROUT STMFD R13!,{R0-R8,R14} ;Stack some registers MOV R4,#0 ;No sprite width MOV R5,#0 ;No text width MOV R6,#0 ;No shortcut width LDR R7,[R10,#hTotWidth] ;Get the current width LDR R2,[R10,#hItems] ;Point to the first items 05tms__width LDR R3,[R2,#iNumber] ;Load the number of items ADD R8,R2,#iHdrSize ;Point to first item ; --- Calculate string width --- 10tms__width LDR R0,[R8,#iText] ;Load the text pointer BL wimp_strWidth ;Get the strings length CMP R0,R5 ;Is it greater? MOVGT R5,R0 ;Yes -- remember this then ; --- Now the shortcut width --- LDR R0,[R8,#iKeyCode] ;Load the key code CMP R0,#-1 ;Is there one? BEQ %12tms__width ;No -- jump ahead MOV R1,#1 ;Return short version BL keyString ;Find correct string BL wimp_strWidth ;Get the string width ADD R0,R0,#16 ;Put a gap on each side CMP R0,R6 ;Is this on longer? MOVGT R6,R0 ;Yes -- remember that fact ; --- Finally the sprite width --- 12tms__width STMFD R13!,{R2-R6} ;Save some registers LDR R14,[R8,#iFlags] ;Get the flags word TST R14,#iFlag__sprite ;Is there a sprite here? LDMEQFD R13!,{R2-R6} ;No -- restore registers BEQ %15tms__width ;...jump ahead a little LDR R1,[R8,#iSprArea] ;Get the sprite area LDR R2,[R8,#iSprName] ;And the sprite name CMP R1,#1 ;Are we using WIMP area? MOVNE R0,#256+40 ;No -- on user area name SWINE OS_SpriteOp ;...get information MOVEQ R0,#40 ;Yes -- info please SWIEQ Wimp_SpriteOp ;Get it then MOV R0,R6 ;Get the sprite's mode MOV R1,#4 ;Get the XEig factor SWI OS_ReadModeVariable ;Read the value MOV R3,R3,LSL R2 ;Work out the width in OS TST R14,#iFlag__halfSize ;Should we display at half sz MOVNE R3,R3,LSR #1 ;Yes -- then divide by 2 ADD R3,R3,#16 ;Add on a little clearance MOV R14,R3 ;Remember this width LDMFD R13!,{R2-R6} ;Restore those registers CMP R14,R4 ;Is this bigger than that? MOVGT R4,R14 ;Yes -- use this value then ; --- Now do other items --- 15tms__width ADD R8,R8,#iItemSize ;Point to the next item SUBS R3,R3,#1 ;Decrement item count BGT %10tms__width ;More to go -- do them LDR R2,[R2,#iItems] ;Load the next items CMP R2,#0 ;Are there any more? BNE %05tms__width ;Yes -- look at them then STR R4,[R10,#hSprWidth] ;Store the sprite width STR R5,[R10,#hTextWidth] ;Store the text width STR R6,[R10,#hKeyWidth] ;And shortcut width too ADD R4,R4,R5 ;Add them all together ADD R4,R4,R6 ;... ADD R4,R4,#64 ;Left and right + 16 LDR R0,[R10,#hText] ;Load the title pointer BL wimp_strWidth ;Find the string width ADD R0,R0,#32 ;Add on some clearance STR R0,[R10,#hTitleWidth] ;Store the title width CMP R0,R4 ;Is this longer than rest? MOVGT R4,R0 ;Yes -- use this width STR R4,[R10,#hTotWidth] ;Store new total width CMP R4,R7 ;Has the width changed? BEQ %95tms__width ;No -- return ; --- Change the extent of the window --- LDR R14,[R10,#hHandle] ;Get the window handle STR R14,[R13,#-36]! ;Get me a block MOV R1,R13 ;Point to the block SWI Wimp_GetWindowState ;Get the window state SUB R13,R13,#16 ;Get another block MOV R2,#0 ;Minimum x extent LDR R3,[R10,#hHeight] ;Get the window height RSB R3,R3,#0 ;Minimun y extent MOV R5,#0 ;Maximum y extent STMIA R13,{R2-R5} ;Store these in the block MOV R0,R14 ;Get the window handle in R0 MOV R1,R13 ;Point to the block SWI Wimp_SetExtent ;Set the extent ADD R13,R13,#16 ;Get the first block back LDR R0,[R13,#4] ;Get visible x0 ADD R0,R0,R4 ;Calculate x1 STR R0,[R13,#12] ;Store the maximum x extent MOV R1,R13 ;Point to the block SWI Wimp_OpenWindow ;Open the window ADD R13,R13,#36 ;Reclaim the stack ; --- Force a complete redraw --- ; ; It's a shame, but there's nothing else for it. LDR R0,[R10,#hHandle] ;Load the window handle MOV R1,#0 ;Left hand side of window LDR R2,[R10,#hHeight] ;Load the window height RSB R2,R2,#0 ;Make it nicely negative LDR R3,[R10,#hTotWidth] ;Load the window width MOV R4,#0 ;And the top of the window SWI Wimp_ForceRedraw ;Aarggh boo spit spit 90tms__width LDMFD R13!,{R0-R8,R14} ;Get registers back ORRS PC,R14,#C_flag ;Return with carry set 95tms__width LDMFD R13!,{R0-R8,R14} ;Get registers back BICS PC,R14,#C_flag ;Return with carry clear LTORG ; --- tms__check --- ; ; On entry: R0 == pointer to menu to check ; R12 == pointer to global tms workspace ; ; On exit: -- ; ; Use: Checks to see if the given menu needs to be changed, and ; updates it as appropriate if it does. tms__check ROUT STMFD R13!,{R0-R10,R14} ;Stack lots of registers STR R0,tms__recreating ;Store a pointer to this menu LDR R9,[R0,#hDefinition] ;Point to packed header defn MOV R7,R0 ;Put structure in R7 LDR R8,[R9],#4 ;Load the title flags word LDR R2,[R7,#hR10] ;Load R10 value LDR R3,[R7,#hR12] ;And R12 value BL tms__findBase ;Put base in R5 TST R8,#mFlag_indirect ;Is the text indirected? BEQ %02tms__check ;No -- just skip over string LDR R0,[R9],#4 ;Yes -- find offset LDR R1,[R9],#4 ;And buffer length LDR R0,[R5,R0] ;And point to the string ; --- Compare to find a difference --- LDR R1,[R7,#hText] ;Point to current text string BL str_cmp ;Compare the strings LDRNE R2,[R7,#hHandle] ;Load the window handle BLNE winUtils_setTitle ;And set the title B %05tms__check ;Jump ahead ; --- Skip over embedded title string --- 02tms__check LDRB R14,[R9],#1 ;Get a message string byte CMP R14,#' ' ;Is it a terminator? BGE %02tms__check ;No -- get another one ADD R9,R9,#3 ;Add 3 BIC R9,R9,#3 ;And word align the pointer ; --- Now check the items --- 05tms__check LDR R6,[R7,#hItems] ;Point to first items 06tms__check LDR R2,[R6,#iR10] ;Load R10 value LDR R3,[R6,#iR12] ;And R12 value LDR R9,[R6,#iDefinition] ;Point to packed items defn ADD R7,R6,#iHdrSize ;Point to first item LDR R8,[R9],#4 ;Load the flags word 07tms__check BL tms__findBase ;Get base in R5 LDR R10,[R7,#iFlags] ;Get the existing flags BIC R10,R10,#&FF000000 ;Clear redraw flags STR R10,[R7,#iFlags] ;Store them back ; --- First, compare the text strings --- TST R8,#mFlag_indirect ;Is text indirected? BEQ %10tms__check ;No -- just skip over string LDR R0,[R9],#4 ;Yes -- find offset LDR R0,[R5,R0] ;And point to the string ; --- Compare to find a difference --- LDR R1,[R7,#iText] ;Point to current text string BL str_cmp ;Compare the strings ORRNE R10,R10,#iFlag__newText ;If different, remember it STRNE R0,[R7,#iText] ;And store new text ptr B %11tms__check ;And jump ahead if no change ; --- Skip over embedded item string --- 10tms__check LDRB R14,[R9],#1 ;Get a message string byte CMP R14,#' ' ;Is it a terminator? BGE %10tms__check ;No -- get another one ADD R9,R9,#3 ;Add 3 BIC R9,R9,#3 ;And word align the pointer ; --- The shortcut may have changed --- 11tms__check TST R8,#mFlag_iShortcut ;Is there a indir. shortcut? BEQ %12tms__check ;No -- skip ahead LDR R0,[R9] ;Get the value LDR R0,[R5,R0] ;Load out the key code LDR R14,[R7,#iKeyCode] ;Load current key code CMP R14,R0 ;Has it changed? STRNE R0,[R7,#iKeyCode] ;Yes -- store this value ORRNE R10,R10,#iFlag__newKey ;...queue for redrawing ; --- Now collect the item flags --- 12tms__check TST R8,#mFlag_shortcut ;Is there a shortcut? TSTEQ R8,#mFlag_iShortcut ;Of any kind? ADDNE R9,R9,#4 ;Yes -- skip over it MOV R4,#0 ;No flags set yet TST R8,#mFlag_shade ;Check shadedness bit BLNE tms__bitSpec ;Handle the bit specification ORRHI R4,R4,#iFlag__shaded ;If set, shade the item BHI %13tms__check ;...and jump this next bit TST R8,#mFlag_iShade ;Check shadedness bit BLNE tms__bitSpec ;Handle the bit specification ORRNE R4,R4,#iFlag__shaded ;Set shaded bit anyway BICHI R4,R4,#iFlag__shaded ;Bit clear it again if set! 13tms__check TST R8,#mFlag_switch ;Check switchiness bit BLNE tms__bitSpec ;Handle the bit specification ORRHI R4,R4,#iFlag__ticked ;If set, tick it TST R8,#mFlag_radio ;Check radioness bit BEQ %14tms__check ;If not set, skip ahead LDMIA R9!,{R0,R1} ;Load the information out LDR R0,[R5,R0] ;Load the radio specifier CMP R0,R1 ;Is this a match made in hvn? ORREQ R4,R4,#iFlag__radio ;Yes -- attach the splodge ; --- Now check the sprite --- 14tms__check TST R8,#mFlag_sprite ;Is there a sprite here? BEQ %15tms__check ;No skipitty jump aaawhooo STMFD R13!,{R2} ;Don't corrupt R2 LDR R2,[R9],#4 ;Yes -- load out name ptr ptr LDR R2,[R5,R2] ;And get name ptr BL tms__checksum ;Get the checksum LDR R1,[R7,#iSprCsum] ;Load the current checksum CMP R0,R1 ;Has it changed? STRNE R0,[R7,#iSprCsum] ;Yes -- store the new one STRNE R2,[R7,#iSprName] ;...and the new name ORRNE R10,R10,#iFlag__newSpr ;...and queue for redraw ADD R9,R9,#4 ;Skip over sprite area LDMFD R13!,{R2} ;Return to caller 15tms__check SKIP mFlag_subMenu,8,R8,R9 ;Skip submenu bit nicely ; --- Have the flags changed? --- LDR R14,[R7,#iFlags] ;Get the current item flags AND R0,R14,#7 ;Clear unwanted flags CMP R0,R4 ;Have flags changed? BIC R14,R14,#7 ;Clear relevant flags ORR R14,R14,R4 ;Set new flags up MOV R1,R14 ;And remember them ; --- Update text part --- EOR R14,R0,R4 ;Get flags which have changed TST R14,#iFlag__shaded ;Has shaded state changed? ORRNE R10,R10,#&FF000000 ;Yes -- redraw the whole item TST R14,#iFlag__ticked+iFlag__radio ;Need to redraw left? ORRNE R10,R10,#iFlag__newTick ;Yes -- then queue an update BIC R10,R10,#7 ;Clear these flags BIC R1,R1,#&FF000000 ;Clear old update flags ORR R1,R1,R10 ;Add in update bits STR R1,[R7,#iFlags] ;Store the new flags ; --- Check following items --- 20tms__check ADD R7,R7,#iItemSize ;Point at the next item LDR R8,[R9],#4 ;Load the next flags word TST R8,#mFlag_end ;Have we reached the end? BEQ %07tms__check ;No -- keep check these items LDR R6,[R6,#iItems] ;Point to next group of items CMP R6,#0 ;Are there any more? BNE %06tms__check ;Yes -- check them then ; --- Maybe change menu width --- LDR R10,tms__recreating ;Get the menu ptr BL tms__width ;Recalculate the menu width BCS %90tms__check ;If it redrew it, skip on ; --- Now redraw items we queued above --- MOV R0,#0 ;Only redraw queued bits BL tms__update ;And update the window 90tms__check LDMFD R13!,{R0-R10,PC}^ ;Return to caller LTORG ; --- tms_recreate --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Recreates the existing menu structure, making changes where ; appropriate. EXPORT tms_recreate tms_recreate ROUT ; --- A note to the wise --- ; ; We go through the data for every open tearoff menu, and ; make any changes that are necessary. These include: ; ; Making the menu wider or narrower, if necessary ; Changing textual strings where they are now different ; Adding or removing of ticks and blobs ; Shading or unshading of items STMFD R13!,{R0,R14} ;Stack some registers LDR R12,=tms__wSpace ;Point to workspace pointer WSPACE [R12] ;Load out workspace pointer LDR R0,tms__current ;Load the current menu ptr CMP R0,#0 ;Is there one open? BEQ %10tms_recreate ;No -- look at torn ones 00tms_recreate BL tms__check ;Check the menu, make changes LDR R0,[R0,#hSubMenu] ;Get submenu pointer CMP R0,#0 ;Is there one? BNE %00tms_recreate ;Yes -- check it then ; --- Now check the torn off menus --- 10tms_recreate LDR R0,tms__tornoffs ;Get first torn off menu CMP R0,#0 ;Have we finished yet? BEQ %90tms_recreate ;Yes -- return then 15tms_recreate BL tms__check ;Check the menu, make changes LDR R0,[R0,#hNextTorn] ;Get the next torn menu CMP R0,#0 ;Have we finished yet? BNE %15tms_recreate ;No -- keep going then 90tms_recreate LDMFD R13!,{R0,PC}^ ;Return to caller LTORG ;----- That's all, folks ---------------------------------------------------- END