Initial revision
[ssr] / StraySrc / Libraries / Sapphire / s / help
1 ;
2 ; help.s
3 ;
4 ; Sending and handling help messages (MDW)
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:idle
36 GET sapphire:msgs
37 GET sapphire:sapphire
38 GET sapphire:string
39
40 ;----- Main code ------------------------------------------------------------
41
42 AREA |Sapphire$$Code|,CODE,READONLY
43
44 ; --- help_init ---
45 ;
46 ; On entry: --
47 ;
48 ; On exit: --
49 ;
50 ; Use: Initialises the help system for use.
51
52 EXPORT help_init
53 help_init ROUT
54
55 STMFD R13!,{R0,R1,R12,R14} ;Save some registers
56
57 ; --- Make sure we're not going already ---
58
59 WSPACE help__wSpace ;Locate my workspace pointer
60 LDR R14,help__flags ;Get my flags word
61 TST R14,#hFlag__inited ;Am I initialised already?
62 LDMNEFD R13!,{R0,R1,R12,PC}^ ;Yes - return to caller
63 ORR R14,R14,#hFlag__inited ;I will be initialised soon
64 STR R14,help__flags ;Store the flags word back
65
66 ; --- Set up the workspace ---
67
68 MOV R14,#20 ;Start message size as 20
69 STR R14,help__message+0 ;Store this in the block
70 MOV R14,#0 ;No message to reply to
71 STR R14,help__msgTask ;Store in the your_ref field
72
73 ; --- Set up my prefilter ---
74
75 BL event_init ;Make sure event is awake
76 ADR R0,help__preFilter ;Point to the prefilter
77 MOV R1,R12 ;Pass along my workspace
78 BL event_preFilter ;Register it with event
79 ADR R0,help__postFilter ;Point to the postfilter
80 BL event_postFilter ;Register that with event too
81 LDMFD R13!,{R0,R1,R12,PC}^ ;Return to caller
82
83 LTORG
84
85 help__wSpace DCD 0
86
87 ; --- help__preFilter ---
88 ;
89 ; On entry: --
90 ;
91 ; On exit: --
92 ;
93 ; Use: Dispatches the currently waiting help reply, if there is
94 ; one. Also fakes hint requests and dispatches finished hints
95 ; to windows.
96
97 help__preFilter ROUT
98
99 STMFD R13!,{R14} ;Save a register
100
101 ; --- Check for hints first ---
102
103 LDR R14,help__flags ;Get my flags word
104 TST R14,#hFlag__hinted ;Do we have a waiting hint?
105 BNE %50help__preFilter ;Yes -- dispatch it to window
106 TST R14,#hFlag__hinting ;Do we need to make a hint?
107 BNE %60help__preFilter ;Yes -- build the block then
108
109 ; --- Otherwise, check for finished help messages ---
110
111 LDR R14,help__msgTask ;Get the your_ref for this
112 CMP R14,#0 ;Is this sensible?
113 LDMEQFD R13!,{PC}^ ;No -- return
114
115 STMFD R13!,{R0-R3} ;Save some more registers
116 LDR R14,help__message+0 ;Load the message length
117 ADD R14,R14,#4 ;Word align the size as reqd.
118 BIC R14,R14,#3 ;Yep, indeedy
119 STR R14,help__message+0 ;Store length back again
120
121 ADR R1,help__message ;Point to the message block
122 LDR R2,help__msgTask ;Load the task handle out
123 MOV R0,#0 ;No more messages waiting
124 STR R0,help__msgTask ;So zero the task handle
125 MOV R0,#17 ;Don't care if it bounces
126 SWI Wimp_SendMessage ;Send the message out
127 LDMFD R13!,{R0-R3,PC}^ ;Return to caller
128
129 ; --- Send a finished hint to the hint window ---
130
131 50 STMFD R13!,{R1} ;Save some registers away
132 BIC R14,R14,#hFlag__hinted :OR: hFlag__hinting
133 STR R14,help__flags ;Clear all the hint flags
134 LDR R14,help__window ;Get the hint destination
135 STR R14,[R1,#0] ;Store in the poll block
136 ADD R0,R1,#4 ;Point to next spare field
137 ADR R1,help__message+20 ;Point to hint string
138 BL str_cpy ;Copy it over
139 MOV R0,#-1 ;The magic hint reason code
140 LDMFD R13!,{R1,R14} ;Restore registers
141 ORRS PC,R14,#C_flag ;Return to caller
142
143 ; --- Try to get a new hint from the window ---
144
145 60 STMFD R13!,{R1-R5} ;Save a load of registers
146 ORR R14,R14,#hFlag__hinted ;Dispatch hint next time
147 STR R14,help__flags ;Save new flags word
148
149 ; --- Build a skeleton hint in case of no reply ---
150
151 MOV R0,#0 ;A null string
152 STR R0,help__message+20 ;Store over the string start
153
154 ; --- Build a help request in the poll block ---
155
156 MOV R0,#44 ;Size of help request message
157 MOV R2,#-1 ;A very bogus task handle
158 MOV R3,#-1 ;A similarly bogus my_ref
159 MOV R4,#0 ;This is not a reply
160 MOV R5,#&500 ;Help request message code
161 ORR R5,R5,#&002 ;Finish off message code
162 STMIA R1!,{R0,R2-R5} ;Build message header
163 STR R4,help__msgTask ;Zero destination task handle
164 SWI Wimp_GetPointerInfo ;Get the current pointer pos
165 MOV R0,#18 ;Make it look real!
166 LDMFD R13!,{R1-R5,R14} ;Restore registers
167 ORRS PC,R14,#C_flag ;Return to caller
168
169 LTORG
170
171 ; --- help__postFilter ---
172 ;
173 ; On entry: R0 == event reason code
174 ; R1 == pointer to event block
175 ;
176 ; On exit: --
177 ;
178 ; Use: Catches pointer-entering and pointer-leaving events and
179 ; sets up the idle claimer appropriately.
180
181 help__postFilter ROUT
182
183 ; --- Ensure that we want this event ---
184
185 CMP R0,#4 ;Pointer leaving?
186 MOVNES PC,R14 ;No -- return now
187
188 ; --- Pointer is leaving one of tasks windows ---
189
190 STMFD R13!,{R0-R3,R14} ;Stack some registers
191 LDR R14,help__flags ;Get my flags word
192 TST R14,#hFlag__hintable ;Is window hintable?
193 LDMEQFD R13!,{R0-R3,PC}^ ;No -- ignore this then
194 MOV R0,#5 ;Call it this frequently
195 ADR R1,help__idles ;Call this on idle events
196 MOV R2,#0 ;Our user handle
197 MOV R3,R12 ;Put our workspace in R12
198 BL idle_removeHandler ;Remove handler
199
200 ; --- Pointer has just left the window ---
201 ;
202 ; It looks really silly if the window we left still has a
203 ; hint in it, so we send it a dummy hint with a null string.
204
205 MOV R0,#0 ;A zero byte for the string
206 STR R0,help__message+20 ;Store over the string start
207 LDR R14,help__flags ;Get my flags word
208 ORR R14,R14,#hFlag__hinted ;There's a hint waiting
209 BIC R14,R14,#hFlag__hintable;Disable the hints system
210 STR R14,help__flags ;Store flags back again
211 LDMFD R13!,{R0-R3,PC}^ ;Return to caller
212
213 LTORG
214
215 ; --- help_sendHints ---
216 ;
217 ; On entry: --
218 ;
219 ; On exit: --
220 ;
221 ; Use: Should be called on a pointer-entering-window event. It
222 ; enables hint requests for the window beneath the pointer.
223
224 EXPORT help_sendHints
225 help_sendHints ROUT
226
227 STMFD R13!,{R0-R3,R12,R14} ;Save some registers
228 WSPACE help__wSpace ;Load my workspace address
229 LDR R14,help__flags ;Load my flags word
230 TST R14,#hFlag__hintable ;Are hints enabled?
231 LDMNEFD R13!,{R0-R3,R12,PC}^ ;Yes -- then return now
232 ORR R14,R14,#hFlag__hintable;Set the hints enabled flag
233 STR R14,help__flags ;And save the flags back
234
235 MOV R0,#5 ;Call it this frequently
236 ADR R1,help__idles ;Call this on idle events
237 MOV R2,#0 ;Our user handle
238 MOV R3,R12 ;Put our workspace in R12
239 BL idle_handler ;Add idle handler
240 MOV R0,#-3 ;Set up previous icon hnd
241 STR R0,help__icon ;...to a really weird value
242 LDMFD R13!,{R0-R3,R12,PC}^ ;And return to caller
243
244 LTORG
245
246 ; --- help__idles ---
247 ;
248 ; On entry: --
249 ;
250 ; On exit: --
251 ;
252 ; Use: Catches pointer movement between icons, and sets the hint
253 ; flags accordingly.
254
255 help__idles ROUT
256
257 STMFD R13!,{R0-R2,R14} ;Save some registers away
258 SUB R13,R13,#24 ;Make space for a pointer blk
259 MOV R1,R13 ;Point to it
260 SWI Wimp_GetPointerInfo ;Get the current ptr posn
261 ADD R14,R13,#12 ;Point to window/icon hnds
262 LDMIA R14,{R0,R2} ;Load them out of the block
263 ADD R13,R13,#24 ;Reclaim the stack I used
264
265 ; --- Find out if we need to get a new hint ---
266
267 LDR R1,help__icon ;Get the old icon I was on
268 CMP R1,R2 ;Do they match?
269 BEQ %90help__idles ;Yes -- nothing more to do
270
271 CMP R2,#0 ;Is ptr over the background?
272 MOVLT R2,#-3 ;Yes -- give it a silly value
273 STR R2,help__icon ;No -- store as new old icon
274 STR R0,help__window ;Save the hint window handle
275 LDR R14,help__flags ;Get my flags word
276 ORR R14,R14,#hFlag__hinting ;Get ready to send a hint rq
277 STR R14,help__flags ;Store the flags away again
278
279 90help__idles LDMFD R13!,{R0-R2,PC}^ ;Return to caller
280
281 LTORG
282
283 ; --- help_add ---
284 ;
285 ; On entry: R0 == pointer to message string to add
286 ;
287 ; On exit: --
288 ;
289 ; Use: Adds a line to the help message being built currently. Note
290 ; that overflows are trapped, and errors are generated if one
291 ; would occur.
292
293 EXPORT help_add
294 help_add ROUT
295
296 STMFD R13!,{R0-R4,R12,R14} ;Save some registers
297 WSPACE help__wSpace ;Find my workspace area
298 LDR R14,help__msgTask ;Get the destination task
299 CMP R14,#0 ;Is there one set up?
300 BNE %10help_add ;Yes -- add a subsequent line
301
302 ; --- We're starting a new help reply ---
303
304 BL event_last ;Get the last event out
305 MOV R2,#&500 ;The message code to match
306 ORR R2,R2,#&002 ;Can't load in one op
307 CMP R0,#17 ;Make sure it's a message
308 CMPNE R0,#18 ;Either one will do
309 LDREQ R14,[R1,#16] ;Get the message code
310 CMPEQ R14,R2 ;Does this match up?
311 LDMNEFD R13!,{R0-R4,R12,PC}^ ;If not, return right now
312
313 ; --- Set up the message block ---
314
315 ADD R4,R2,#1 ;The reply code is one larger
316 MOV R0,#20 ;Size of the message block
317 LDR R3,[R1,#8] ;Load his my_ref value
318 MOV R14,#0 ;Null terminate the string
319 STMIB R12,{R0-R4,R14} ;Build the message block
320 LDR R14,[R1,#4] ;Get the task handle out
321 STR R14,help__msgTask ;Store the handle away
322
323 ; --- Set up for main copy loop ---
324
325 LDR R0,[R13,#0] ;Get the string pointer back
326 MOV R1,R11 ;Find a spare buffer
327 BL msgs_build ;Build the message nicely
328 ADR R1,help__message+20 ;Current pointer for string
329 MOV R2,#20 ;Current length
330 B %20help_add ;Now skip to main code
331
332 ; --- Add in a line separator ---
333
334 10help_add MOV R1,R11 ;Find a spare buffer
335 BL msgs_build ;Build the message nicely
336
337 LDR R2,help__message+0 ;Get the current message size
338 ADR R1,help__message ;Point to the message start
339 ADD R1,R1,R2 ;Get current pointer
340 CMP R2,#253 ;Make sure it will fit
341 BGT %90 ;If it doesn't, make error
342
343 LDR R14,help__flags ;Load my flags word
344 TST R14,#hFlag__hinted ;Am I building a hint?
345 MOVEQ R14,#'|' ;No -- strings get GSTransed
346 MOVNE R14,#' ' ;Yes -- spaces not newlines
347 STRB R14,[R1],#1 ;Store the character
348 MOVEQ R14,#'M' ;`|M' is a return character
349 STRB R14,[R1],#1 ;Store the character
350 ADD R2,R2,#2 ;We've added two characters
351
352 ; --- Now copy the string over, trapping overflows ---
353
354 20help_add CMP R2,#256 ;Do we have room for another?
355 BGE %90 ;No -- moan bitterly
356 LDRB R14,[R0],#1 ;Get an input character
357 CMP R14,#' ' ;Is this a control character?
358 MOVLT R14,#0 ;Yes -- store a zero nicely
359 STRB R14,[R1],#1 ;Store it in my message
360 ADD R2,R2,#1 ;Bump the character count
361 BGE %20help_add ;Loop round for more
362
363 ; --- Set things up for next time ---
364
365 SUB R2,R2,#1 ;Overwrite the last null byte
366 STR R2,help__message+0 ;Store the message length
367 LDMFD R13!,{R0-R4,R12,PC}^ ;Return to caller
368
369 ; --- We overflowed -- complain ---
370
371 90help_add MOV R0,#0 ;Zero the task handle...
372 STR R0,help__msgTask ;...to stop it being sent
373 ADR R0,help__overflow ;Point to the message
374 BL msgs_error ;Translate it as normal
375 SWI OS_GenerateError ;And generate the error
376
377 help__overflow DCD 1
378 DCB "helpOFLOW",0
379
380 LTORG
381
382 ; --- help_reset ---
383 ;
384 ; On entry: --
385 ;
386 ; On exit: --
387 ;
388 ; Use: Resets the help system so that a hint request is sent to an
389 ; icon that the pointer is already over. The proposed use
390 ; is that the caller can change a help message for a given
391 ; icon as soon as it is clicked on.
392
393 EXPORT help_reset
394 help_reset ROUT
395
396 STMFD R13!,{R12,R14} ;Stack some registers
397 WSPACE help__wSpace ;Load my workspace address
398 MOV R14,#-3 ;Set up previous icon hnd
399 STR R14,help__icon ;...to a really weird value
400 LDMFD R13!,{R12,PC}^ ;Return to caller
401
402 LTORG
403
404 ;----- Workspace ------------------------------------------------------------
405
406 ^ 0,R12
407 help__wStart # 0
408
409 help__flags # 4 ;Various flags
410 help__message # 256 ;The actual message to send
411 help__msgTask # 4 ;Task to send message to
412 help__msgNext # 4 ;Pointer to message tail
413 help__window # 4 ;The window the ptr is over
414 help__icon # 4 ;The icon the ptr is over
415
416 help__wSize EQU {VAR}-help__wStart
417
418 hFlag__inited EQU (1<<0) ;Am I initialised?
419 hFlag__hintable EQU (1<<1) ;Current window wants hints
420 hFlag__hinting EQU (1<<2) ;We're gathering up a hint
421 hFlag__hinted EQU (1<<3) ;Is a hint waiting?
422
423 AREA |Sapphire$$LibData|,CODE,READONLY
424
425 DCD help__wSize
426 DCD help__wSpace
427 DCD 0
428 DCD help_init
429
430 ;----- That's all, folks ----------------------------------------------------
431
432 END