chiark / gitweb /
Create readable text `.bas' for each tokenized BASIC `,ffb' file.
[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 }