Initial revision
[ssr] / StraySrc / Libraries / Steel / c / scroller
1 /*
2 * scroller.c
3 *
4 * Scrolling text in an icon
5 *
6 * © 1994-1998 Straylight
7 */
8
9 /*----- Licensing note ----------------------------------------------------*
10 *
11 * This file is part of Straylight's Steel library.
12 *
13 * Steel 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 * Steel 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 Steel. If not, write to the Free Software Foundation,
25 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 */
27
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31
32 #include "scroller.h"
33
34 #include "steel.h"
35 #include "bbc.h"
36 #include "msgs.h"
37 #include "werr.h"
38
39 typedef struct scroller__str
40 {
41 wimp_w w; /* Window handle of scroller */
42 wimp_i i; /* icon Handle */
43 char *string; /* Scrolling Message */
44 char *initText; /* Start Message */
45 int index; /* Index into actual string */
46 int chars; /* Printable string index */
47 int initIndent; /* X indent for initial message */
48 int speed; /* Speed of scroll */
49 int cspeed; /* Current speed of scroll */
50 int counter; /* Current value of delay */
51 wimp_box box; /* Icon bounding box */
52 int baseline; /* Y Position of message */
53 int len; /* Length of printable string */
54 int cfg; /* Current foreground colour */
55 int fg :4; /* Defualt foreground colour */
56 int bg :4; /* Defualt background colour */
57 int pixel :8; /* Current pixel offset */
58 BOOL started :1; /* Have we wrapped around? */
59 }
60 scroller__str;
61
62 #define max2(x,y) ((x)>(y) ? (x) : (y))
63 #define min2(x,y) ((x)<(y) ? (x) : (y))
64
65 /* Display the entire string - used for redraw events */
66
67 static void scroller__display(scroller s,char *p)
68 {
69 int col;
70 while (*p)
71 {
72 if (*p=='[')
73 {
74 switch (*++p)
75 {
76 case 'C':
77 sscanf(p+1,"%i",&col);
78 wimp_setcolour(col);
79 break;
80 case 'c':
81 wimp_setcolour(s->fg);
82 break;
83 }
84 while (*p++!=']') ;
85 }
86 else
87 bbc_vdu(*p++);
88 }
89 }
90
91 /* Calculate the length of the string, without control codes */
92
93 static int scroller__length(char *p)
94 {
95 int i=0;
96 while (*p)
97 {
98 if (*p=='[')
99 {
100 while (*p++!=']') ;
101 }
102 else
103 i++,p++;
104 }
105 return (i);
106 }
107
108 /* Redraw the icon */
109
110 void scroller_redraw(scroller s,wimp_redrawstr *r)
111 {
112 int ox,oy;
113 int dx=wimpt_dx(),dy=wimpt_dy();
114 ox=r->box.x0-r->scx;
115 oy=r->box.y1-r->scy;
116
117 /* Does icon bounding box intersect with graphics window */
118
119 if ( !( ox+s->box.x0 <= r->g.x1-dx &&
120 oy+s->box.y0 <= r->g.y1-dy &&
121 ox+s->box.x1-dx >= r->g.x0 &&
122 oy+s->box.y1-dy >= r->g.y0))
123 return;
124
125 /* Yes -- Set graphics window to insection */
126
127 bbc_gwindow(max2(ox+s->box.x0,r->g.x0),
128 max2(oy+s->box.y0,r->g.y0),
129 min2(ox+s->box.x1,r->g.x1)-dx,
130 min2(oy+s->box.y1,r->g.y1)-dy);
131
132 wimp_setcolour(s->bg | 0x80);
133 bbc_clg();
134 wimp_setcolour(s->fg);
135
136 if (s->started)
137 {
138 bbc_move(ox+s->box.x1-16*(s->chars+s->len)-s->pixel,oy+s->baseline);
139 scroller__display(s,s->string);
140 }
141 else
142 {
143 bbc_move(ox+s->box.x1-16*s->chars-s->pixel-s->initIndent,oy+s->baseline);
144 bbc_stringprint(s->initText);
145 }
146 bbc_move(ox+s->box.x1-16*s->chars-s->pixel,oy+s->baseline);
147 scroller__display(s,s->string);
148
149 bbc_gwindow(r->g.x0,
150 r->g.y0,
151 r->g.x1-dx,
152 r->g.y1-dy);
153 }
154
155 /* Called on idle events to do the scroll */
156
157 static void scroller__idles(void *handle)
158 {
159 scroller s=handle;
160 wimp_redrawstr r;
161 BOOL more;
162 int ox,oy;
163 if (s->counter)
164 {
165 s->counter--;
166 return;
167 }
168 s->pixel+=s->cspeed;
169 if (s->pixel>16)
170 {
171 s->pixel&=0x0f;
172 s->index++;
173 s->chars++;
174 if (!s->string[s->index])
175 {
176 s->index=0;
177 s->chars=0;
178 s->started=1;
179 }
180 if (s->string[s->index]=='[')
181 {
182 switch (s->string[++s->index])
183 {
184 case 'D':
185 sscanf(s->string+s->index+1,"%i",&s->counter);
186 while (s->string[s->index++]!=']') ;
187 s->pixel-=s->speed;
188 return;
189 case 'C':
190 sscanf(s->string+s->index+1,"%i",&s->cfg);
191 while (s->string[s->index++]!=']') ;
192 break;
193 case 'c':
194 while (s->string[s->index++]!=']') ;
195 s->cfg=s->fg;
196 break;
197 case 'S':
198 s->pixel-=s->cspeed;
199 sscanf(s->string+s->index+1,"%i",&s->cspeed);
200 while (s->string[s->index++]!=']') ;
201 s->pixel+=s->cspeed;
202 break;
203 case 's':
204 s->pixel-=s->cspeed;
205 s->cspeed=s->speed;
206 s->pixel+=s->cspeed;
207 while (s->string[s->index++]!=']') ;
208 break;
209 }
210 }
211 }
212 r.box=s->box;
213 r.box.x0+=s->cspeed;
214 wimp_blockcopy(s->w,&r.box,s->box.x0,s->box.y0);
215 r.box.x0=r.box.x1-s->cspeed;
216 r.w=s->w;
217 wimp_update_wind(&r,&more);
218 ox=r.box.x0-r.scx + s->box.x1-s->pixel;
219 oy=r.box.y1-r.scy + s->baseline;
220 while (more)
221 {
222 wimp_setcolour(s->bg);
223 bbc_rectanglefill(ox,oy-28,16,28);
224 wimp_setcolour(s->cfg);
225 bbc_move(ox,oy);
226 bbc_vdu(s->string[s->index]);
227 wimp_get_rectangle(&r,&more);
228 }
229 }
230
231 /* Create a new sroller */
232
233 scroller scroller_create(dbox d,
234 dbox_field f,
235 char *string,
236 char *initial,
237 int startDelay)
238 {
239 scroller s=mem_alloc(sizeof(scroller__str));
240 wimp_icon i;
241 if (!s)
242 {
243 werr(FALSE,msgs_lookup("scrlNEM:Not enough memory for scrolltext"));
244 return (FALSE);
245 }
246 s->w=dbox_syshandle(d);
247 s->i=f;
248 s->string=string;
249 s->index=s->chars=-1;
250 s->pixel=16;
251 s->counter=startDelay;
252 s->speed=s->cspeed=2;
253 s->started=0;
254 wimpt_noerr(wimp_get_icon_info(s->w,f,&i));
255 s->box=i.box;
256 s->len=scroller__length(string);
257 s->initText=initial;
258 s->initIndent=((i.box.x1-i.box.x0)/2+(strlen(s->initText)*8));
259 s->fg=s->cfg=(i.flags >> 24) & 0x0f;
260 s->bg=(i.flags >> 28) & 0x0f;
261 s->baseline=s->box.y1-(s->box.y1-s->box.y0-32)/2-4;
262 return (s);
263 }
264
265 void scroller_speed(scroller s,int speed)
266 {
267 s->speed=s->cspeed=speed;
268 }
269
270 void scroller_go(scroller s)
271 {
272 win_addIdleClaimer(scroller__idles,2,s);
273 }
274
275 void scroller_destroy(scroller s)
276 {
277 win_removeIdleClaimer(scroller__idles,s);
278 mem_free(s);
279 }