/* * scroller.c * * Scrolling text in an icon * * © 1994-1998 Straylight */ /*----- Licensing note ----------------------------------------------------* * * This file is part of Straylight's Steel library. * * Steel 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. * * Steel 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 Steel. If not, write to the Free Software Foundation, * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "scroller.h" #include "steel.h" #include "bbc.h" #include "msgs.h" #include "werr.h" typedef struct scroller__str { wimp_w w; /* Window handle of scroller */ wimp_i i; /* icon Handle */ char *string; /* Scrolling Message */ char *initText; /* Start Message */ int index; /* Index into actual string */ int chars; /* Printable string index */ int initIndent; /* X indent for initial message */ int speed; /* Speed of scroll */ int cspeed; /* Current speed of scroll */ int counter; /* Current value of delay */ wimp_box box; /* Icon bounding box */ int baseline; /* Y Position of message */ int len; /* Length of printable string */ int cfg; /* Current foreground colour */ int fg :4; /* Defualt foreground colour */ int bg :4; /* Defualt background colour */ int pixel :8; /* Current pixel offset */ BOOL started :1; /* Have we wrapped around? */ } scroller__str; #define max2(x,y) ((x)>(y) ? (x) : (y)) #define min2(x,y) ((x)<(y) ? (x) : (y)) /* Display the entire string - used for redraw events */ static void scroller__display(scroller s,char *p) { int col; while (*p) { if (*p=='[') { switch (*++p) { case 'C': sscanf(p+1,"%i",&col); wimp_setcolour(col); break; case 'c': wimp_setcolour(s->fg); break; } while (*p++!=']') ; } else bbc_vdu(*p++); } } /* Calculate the length of the string, without control codes */ static int scroller__length(char *p) { int i=0; while (*p) { if (*p=='[') { while (*p++!=']') ; } else i++,p++; } return (i); } /* Redraw the icon */ void scroller_redraw(scroller s,wimp_redrawstr *r) { int ox,oy; int dx=wimpt_dx(),dy=wimpt_dy(); ox=r->box.x0-r->scx; oy=r->box.y1-r->scy; /* Does icon bounding box intersect with graphics window */ if ( !( ox+s->box.x0 <= r->g.x1-dx && oy+s->box.y0 <= r->g.y1-dy && ox+s->box.x1-dx >= r->g.x0 && oy+s->box.y1-dy >= r->g.y0)) return; /* Yes -- Set graphics window to insection */ bbc_gwindow(max2(ox+s->box.x0,r->g.x0), max2(oy+s->box.y0,r->g.y0), min2(ox+s->box.x1,r->g.x1)-dx, min2(oy+s->box.y1,r->g.y1)-dy); wimp_setcolour(s->bg | 0x80); bbc_clg(); wimp_setcolour(s->fg); if (s->started) { bbc_move(ox+s->box.x1-16*(s->chars+s->len)-s->pixel,oy+s->baseline); scroller__display(s,s->string); } else { bbc_move(ox+s->box.x1-16*s->chars-s->pixel-s->initIndent,oy+s->baseline); bbc_stringprint(s->initText); } bbc_move(ox+s->box.x1-16*s->chars-s->pixel,oy+s->baseline); scroller__display(s,s->string); bbc_gwindow(r->g.x0, r->g.y0, r->g.x1-dx, r->g.y1-dy); } /* Called on idle events to do the scroll */ static void scroller__idles(void *handle) { scroller s=handle; wimp_redrawstr r; BOOL more; int ox,oy; if (s->counter) { s->counter--; return; } s->pixel+=s->cspeed; if (s->pixel>16) { s->pixel&=0x0f; s->index++; s->chars++; if (!s->string[s->index]) { s->index=0; s->chars=0; s->started=1; } if (s->string[s->index]=='[') { switch (s->string[++s->index]) { case 'D': sscanf(s->string+s->index+1,"%i",&s->counter); while (s->string[s->index++]!=']') ; s->pixel-=s->speed; return; case 'C': sscanf(s->string+s->index+1,"%i",&s->cfg); while (s->string[s->index++]!=']') ; break; case 'c': while (s->string[s->index++]!=']') ; s->cfg=s->fg; break; case 'S': s->pixel-=s->cspeed; sscanf(s->string+s->index+1,"%i",&s->cspeed); while (s->string[s->index++]!=']') ; s->pixel+=s->cspeed; break; case 's': s->pixel-=s->cspeed; s->cspeed=s->speed; s->pixel+=s->cspeed; while (s->string[s->index++]!=']') ; break; } } } r.box=s->box; r.box.x0+=s->cspeed; wimp_blockcopy(s->w,&r.box,s->box.x0,s->box.y0); r.box.x0=r.box.x1-s->cspeed; r.w=s->w; wimp_update_wind(&r,&more); ox=r.box.x0-r.scx + s->box.x1-s->pixel; oy=r.box.y1-r.scy + s->baseline; while (more) { wimp_setcolour(s->bg); bbc_rectanglefill(ox,oy-28,16,28); wimp_setcolour(s->cfg); bbc_move(ox,oy); bbc_vdu(s->string[s->index]); wimp_get_rectangle(&r,&more); } } /* Create a new sroller */ scroller scroller_create(dbox d, dbox_field f, char *string, char *initial, int startDelay) { scroller s=mem_alloc(sizeof(scroller__str)); wimp_icon i; if (!s) { werr(FALSE,msgs_lookup("scrlNEM:Not enough memory for scrolltext")); return (FALSE); } s->w=dbox_syshandle(d); s->i=f; s->string=string; s->index=s->chars=-1; s->pixel=16; s->counter=startDelay; s->speed=s->cspeed=2; s->started=0; wimpt_noerr(wimp_get_icon_info(s->w,f,&i)); s->box=i.box; s->len=scroller__length(string); s->initText=initial; s->initIndent=((i.box.x1-i.box.x0)/2+(strlen(s->initText)*8)); s->fg=s->cfg=(i.flags >> 24) & 0x0f; s->bg=(i.flags >> 28) & 0x0f; s->baseline=s->box.y1-(s->box.y1-s->box.y0-32)/2-4; return (s); } void scroller_speed(scroller s,int speed) { s->speed=s->cspeed=speed; } void scroller_go(scroller s) { win_addIdleClaimer(scroller__idles,2,s); } void scroller_destroy(scroller s) { win_removeIdleClaimer(scroller__idles,s); mem_free(s); }