; ; help.s ; ; Sending and handling help messages (MDW) ; ; © 1994-1998 Straylight ; ;----- Licensing note ------------------------------------------------------- ; ; This file is part of Straylight's Sapphire library. ; ; Sapphire is free software; you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation; either version 2, or (at your option) ; any later version. ; ; Sapphire is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with Sapphire. If not, write to the Free Software Foundation, ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;----- Standard header ------------------------------------------------------ GET libs:header GET libs:swis ;----- External dependencies ------------------------------------------------ GET sapphire:event GET sapphire:idle GET sapphire:msgs GET sapphire:sapphire GET sapphire:string ;----- Main code ------------------------------------------------------------ AREA |Sapphire$$Code|,CODE,READONLY ; --- help_init --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Initialises the help system for use. EXPORT help_init help_init ROUT STMFD R13!,{R0,R1,R12,R14} ;Save some registers ; --- Make sure we're not going already --- WSPACE help__wSpace ;Locate my workspace pointer LDR R14,help__flags ;Get my flags word TST R14,#hFlag__inited ;Am I initialised already? LDMNEFD R13!,{R0,R1,R12,PC}^ ;Yes - return to caller ORR R14,R14,#hFlag__inited ;I will be initialised soon STR R14,help__flags ;Store the flags word back ; --- Set up the workspace --- MOV R14,#20 ;Start message size as 20 STR R14,help__message+0 ;Store this in the block MOV R14,#0 ;No message to reply to STR R14,help__msgTask ;Store in the your_ref field ; --- Set up my prefilter --- BL event_init ;Make sure event is awake ADR R0,help__preFilter ;Point to the prefilter MOV R1,R12 ;Pass along my workspace BL event_preFilter ;Register it with event ADR R0,help__postFilter ;Point to the postfilter BL event_postFilter ;Register that with event too LDMFD R13!,{R0,R1,R12,PC}^ ;Return to caller LTORG help__wSpace DCD 0 ; --- help__preFilter --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Dispatches the currently waiting help reply, if there is ; one. Also fakes hint requests and dispatches finished hints ; to windows. help__preFilter ROUT STMFD R13!,{R14} ;Save a register ; --- Check for hints first --- LDR R14,help__flags ;Get my flags word TST R14,#hFlag__hinted ;Do we have a waiting hint? BNE %50help__preFilter ;Yes -- dispatch it to window TST R14,#hFlag__hinting ;Do we need to make a hint? BNE %60help__preFilter ;Yes -- build the block then ; --- Otherwise, check for finished help messages --- LDR R14,help__msgTask ;Get the your_ref for this CMP R14,#0 ;Is this sensible? LDMEQFD R13!,{PC}^ ;No -- return STMFD R13!,{R0-R3} ;Save some more registers LDR R14,help__message+0 ;Load the message length ADD R14,R14,#4 ;Word align the size as reqd. BIC R14,R14,#3 ;Yep, indeedy STR R14,help__message+0 ;Store length back again ADR R1,help__message ;Point to the message block LDR R2,help__msgTask ;Load the task handle out MOV R0,#0 ;No more messages waiting STR R0,help__msgTask ;So zero the task handle MOV R0,#17 ;Don't care if it bounces SWI Wimp_SendMessage ;Send the message out LDMFD R13!,{R0-R3,PC}^ ;Return to caller ; --- Send a finished hint to the hint window --- 50 STMFD R13!,{R1} ;Save some registers away BIC R14,R14,#hFlag__hinted :OR: hFlag__hinting STR R14,help__flags ;Clear all the hint flags LDR R14,help__window ;Get the hint destination STR R14,[R1,#0] ;Store in the poll block ADD R0,R1,#4 ;Point to next spare field ADR R1,help__message+20 ;Point to hint string BL str_cpy ;Copy it over MOV R0,#-1 ;The magic hint reason code LDMFD R13!,{R1,R14} ;Restore registers ORRS PC,R14,#C_flag ;Return to caller ; --- Try to get a new hint from the window --- 60 STMFD R13!,{R1-R5} ;Save a load of registers ORR R14,R14,#hFlag__hinted ;Dispatch hint next time STR R14,help__flags ;Save new flags word ; --- Build a skeleton hint in case of no reply --- MOV R0,#0 ;A null string STR R0,help__message+20 ;Store over the string start ; --- Build a help request in the poll block --- MOV R0,#44 ;Size of help request message MOV R2,#-1 ;A very bogus task handle MOV R3,#-1 ;A similarly bogus my_ref MOV R4,#0 ;This is not a reply MOV R5,#&500 ;Help request message code ORR R5,R5,#&002 ;Finish off message code STMIA R1!,{R0,R2-R5} ;Build message header STR R4,help__msgTask ;Zero destination task handle SWI Wimp_GetPointerInfo ;Get the current pointer pos MOV R0,#18 ;Make it look real! LDMFD R13!,{R1-R5,R14} ;Restore registers ORRS PC,R14,#C_flag ;Return to caller LTORG ; --- help__postFilter --- ; ; On entry: R0 == event reason code ; R1 == pointer to event block ; ; On exit: -- ; ; Use: Catches pointer-entering and pointer-leaving events and ; sets up the idle claimer appropriately. help__postFilter ROUT ; --- Ensure that we want this event --- CMP R0,#4 ;Pointer leaving? MOVNES PC,R14 ;No -- return now ; --- Pointer is leaving one of tasks windows --- STMFD R13!,{R0-R3,R14} ;Stack some registers LDR R14,help__flags ;Get my flags word TST R14,#hFlag__hintable ;Is window hintable? LDMEQFD R13!,{R0-R3,PC}^ ;No -- ignore this then MOV R0,#5 ;Call it this frequently ADR R1,help__idles ;Call this on idle events MOV R2,#0 ;Our user handle MOV R3,R12 ;Put our workspace in R12 BL idle_removeHandler ;Remove handler ; --- Pointer has just left the window --- ; ; It looks really silly if the window we left still has a ; hint in it, so we send it a dummy hint with a null string. MOV R0,#0 ;A zero byte for the string STR R0,help__message+20 ;Store over the string start LDR R14,help__flags ;Get my flags word ORR R14,R14,#hFlag__hinted ;There's a hint waiting BIC R14,R14,#hFlag__hintable;Disable the hints system STR R14,help__flags ;Store flags back again LDMFD R13!,{R0-R3,PC}^ ;Return to caller LTORG ; --- help_sendHints --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Should be called on a pointer-entering-window event. It ; enables hint requests for the window beneath the pointer. EXPORT help_sendHints help_sendHints ROUT STMFD R13!,{R0-R3,R12,R14} ;Save some registers WSPACE help__wSpace ;Load my workspace address LDR R14,help__flags ;Load my flags word TST R14,#hFlag__hintable ;Are hints enabled? LDMNEFD R13!,{R0-R3,R12,PC}^ ;Yes -- then return now ORR R14,R14,#hFlag__hintable;Set the hints enabled flag STR R14,help__flags ;And save the flags back MOV R0,#5 ;Call it this frequently ADR R1,help__idles ;Call this on idle events MOV R2,#0 ;Our user handle MOV R3,R12 ;Put our workspace in R12 BL idle_handler ;Add idle handler MOV R0,#-3 ;Set up previous icon hnd STR R0,help__icon ;...to a really weird value LDMFD R13!,{R0-R3,R12,PC}^ ;And return to caller LTORG ; --- help__idles --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Catches pointer movement between icons, and sets the hint ; flags accordingly. help__idles ROUT STMFD R13!,{R0-R2,R14} ;Save some registers away SUB R13,R13,#24 ;Make space for a pointer blk MOV R1,R13 ;Point to it SWI Wimp_GetPointerInfo ;Get the current ptr posn ADD R14,R13,#12 ;Point to window/icon hnds LDMIA R14,{R0,R2} ;Load them out of the block ADD R13,R13,#24 ;Reclaim the stack I used ; --- Find out if we need to get a new hint --- LDR R1,help__icon ;Get the old icon I was on CMP R1,R2 ;Do they match? BEQ %90help__idles ;Yes -- nothing more to do CMP R2,#0 ;Is ptr over the background? MOVLT R2,#-3 ;Yes -- give it a silly value STR R2,help__icon ;No -- store as new old icon STR R0,help__window ;Save the hint window handle LDR R14,help__flags ;Get my flags word ORR R14,R14,#hFlag__hinting ;Get ready to send a hint rq STR R14,help__flags ;Store the flags away again 90help__idles LDMFD R13!,{R0-R2,PC}^ ;Return to caller LTORG ; --- help_add --- ; ; On entry: R0 == pointer to message string to add ; ; On exit: -- ; ; Use: Adds a line to the help message being built currently. Note ; that overflows are trapped, and errors are generated if one ; would occur. EXPORT help_add help_add ROUT STMFD R13!,{R0-R4,R12,R14} ;Save some registers WSPACE help__wSpace ;Find my workspace area LDR R14,help__msgTask ;Get the destination task CMP R14,#0 ;Is there one set up? BNE %10help_add ;Yes -- add a subsequent line ; --- We're starting a new help reply --- BL event_last ;Get the last event out MOV R2,#&500 ;The message code to match ORR R2,R2,#&002 ;Can't load in one op CMP R0,#17 ;Make sure it's a message CMPNE R0,#18 ;Either one will do LDREQ R14,[R1,#16] ;Get the message code CMPEQ R14,R2 ;Does this match up? LDMNEFD R13!,{R0-R4,R12,PC}^ ;If not, return right now ; --- Set up the message block --- ADD R4,R2,#1 ;The reply code is one larger MOV R0,#20 ;Size of the message block LDR R3,[R1,#8] ;Load his my_ref value MOV R14,#0 ;Null terminate the string STMIB R12,{R0-R4,R14} ;Build the message block LDR R14,[R1,#4] ;Get the task handle out STR R14,help__msgTask ;Store the handle away ; --- Set up for main copy loop --- LDR R0,[R13,#0] ;Get the string pointer back MOV R1,R11 ;Find a spare buffer BL msgs_build ;Build the message nicely ADR R1,help__message+20 ;Current pointer for string MOV R2,#20 ;Current length B %20help_add ;Now skip to main code ; --- Add in a line separator --- 10help_add MOV R1,R11 ;Find a spare buffer BL msgs_build ;Build the message nicely LDR R2,help__message+0 ;Get the current message size ADR R1,help__message ;Point to the message start ADD R1,R1,R2 ;Get current pointer CMP R2,#253 ;Make sure it will fit BGT %90 ;If it doesn't, make error LDR R14,help__flags ;Load my flags word TST R14,#hFlag__hinted ;Am I building a hint? MOVEQ R14,#'|' ;No -- strings get GSTransed MOVNE R14,#' ' ;Yes -- spaces not newlines STRB R14,[R1],#1 ;Store the character MOVEQ R14,#'M' ;`|M' is a return character STRB R14,[R1],#1 ;Store the character ADD R2,R2,#2 ;We've added two characters ; --- Now copy the string over, trapping overflows --- 20help_add CMP R2,#256 ;Do we have room for another? BGE %90 ;No -- moan bitterly LDRB R14,[R0],#1 ;Get an input character CMP R14,#' ' ;Is this a control character? MOVLT R14,#0 ;Yes -- store a zero nicely STRB R14,[R1],#1 ;Store it in my message ADD R2,R2,#1 ;Bump the character count BGE %20help_add ;Loop round for more ; --- Set things up for next time --- SUB R2,R2,#1 ;Overwrite the last null byte STR R2,help__message+0 ;Store the message length LDMFD R13!,{R0-R4,R12,PC}^ ;Return to caller ; --- We overflowed -- complain --- 90help_add MOV R0,#0 ;Zero the task handle... STR R0,help__msgTask ;...to stop it being sent ADR R0,help__overflow ;Point to the message BL msgs_error ;Translate it as normal SWI OS_GenerateError ;And generate the error help__overflow DCD 1 DCB "helpOFLOW",0 LTORG ; --- help_reset --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Resets the help system so that a hint request is sent to an ; icon that the pointer is already over. The proposed use ; is that the caller can change a help message for a given ; icon as soon as it is clicked on. EXPORT help_reset help_reset ROUT STMFD R13!,{R12,R14} ;Stack some registers WSPACE help__wSpace ;Load my workspace address MOV R14,#-3 ;Set up previous icon hnd STR R14,help__icon ;...to a really weird value LDMFD R13!,{R12,PC}^ ;Return to caller LTORG ;----- Workspace ------------------------------------------------------------ ^ 0,R12 help__wStart # 0 help__flags # 4 ;Various flags help__message # 256 ;The actual message to send help__msgTask # 4 ;Task to send message to help__msgNext # 4 ;Pointer to message tail help__window # 4 ;The window the ptr is over help__icon # 4 ;The icon the ptr is over help__wSize EQU {VAR}-help__wStart hFlag__inited EQU (1<<0) ;Am I initialised? hFlag__hintable EQU (1<<1) ;Current window wants hints hFlag__hinting EQU (1<<2) ;We're gathering up a hint hFlag__hinted EQU (1<<3) ;Is a hint waiting? AREA |Sapphire$$LibData|,CODE,READONLY DCD help__wSize DCD help__wSpace DCD 0 DCD help_init ;----- That's all, folks ---------------------------------------------------- END