/* * creator.c * * Tearoff menu generating routines * * © 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. */ #define _CORE #define _STDAPP #include #include #include "steel.h" #include "string.h" #include "xtearoff.h" /*--------------------------------------------------------------------------- The syntax of menu strings is a subset of the system used by the RISC_OSlib menu segment: menu_description ::= { } flags ::= '!' | '~' | '>' | ' ' | '@' sep ::= ',' item ::= [#] flags have meanings as follows: ' ' has no effect '~' shades the item '>' item has a menu dbox attached '!' item is ticked '@' item is 'radioed' ---------------------------------------------------------------------------*/ static BOOL tearoff__parse(tearoff t,char **p,tearoff__item *item,int *y) { char *ind; int len=0; int hash=0; BOOL done=FALSE; tearoff__item *itm; char *eptr; item->sub=(tearoff)-1; item->subMenuWarning = FALSE; item->selType = 0; item->shaded = FALSE; item->subMenu = FALSE; item->subShaded = FALSE; item->dotted = FALSE; item->text = NULL; item->keys = NULL; item->y=*y; while (!done) { switch (**p) { case '!': item->selType=1; (*p)++; break; case '@': item->selType=2; (*p)++; break; case ' ': (*p)++; break; case '>': item->subMenuWarning=TRUE; (*p)++; break; case '~': item->shaded=TRUE; (*p)++; break; default: done=TRUE; break; } } done=FALSE; for (eptr=*p;*eptr!=0 && *eptr!='|' && *eptr!=',';eptr++,len++) if (*eptr=='#') hash=len; if (ind=mem_alloc(len+1),!ind) { werr(FALSE,msgs_lookup("menuNEM:Not enough memory to construct menu.")); return (FALSE); } itm=(tearoff__item *)(t+1); item->text=ind; if (hash) item->keys=ind+hash+1; while (**p!=0 && **p!='|' && **p!=',') { *ind=**p; if (*ind=='#') *ind=0; ind++; (*p)++; } if (**p == '|') { item->dotted = TRUE; t->dotted += 24; t->redraw=TRUE; *y-=24; } *(ind++)=0; if (!**p) *p=0; else (*p)++; t->numberOfItems+=1; *y-=44; return (TRUE); } static int tearoff__itemCount(char *s) { int count=1; if (*s=='|') s++; while (*s) { switch (*s) { case '|': case ',': count++; break; } s++; } return (count); } tearoff tearoff_create(char *title,char *items,BOOL tearable, tearoff_selectProc proc, int max, void *handle) { int i,y; tearoff__item *itm; tearoff t; int ino=tearoff__itemCount(items); if (t=mem_alloc(sizeof(tearoff__str) + ino*sizeof(tearoff__item)),!t) { werr(FALSE,msgs_lookup("Not enough memory to construct menu.")); return (0); } t->menuTitle=malloc(strlen(title)+1); if (!t->menuTitle) { werr(FALSE,msgs_lookup("Not enough memory to construct menu.")); return (0); } strcpy(t->menuTitle,title); t->numberOfItems=0; t->maxHeight=max; t->selected=0; t->tearoff=tearable; t->tornoff=FALSE; t->warned=FALSE; t->folded=FALSE; t->open=FALSE; t->redraw=FALSE; t->scrollBar=FALSE; t->selectProc=proc; t->userHandle=handle; t->w=NULL; t->sub=NULL; t->prev=NULL; t->dotted=0; t->nextTornoff=NULL; itm=((tearoff__item *)(t+1))-1; y=-44; if (t->tearoff) y-=tearoff__HEIGHT; for (i=0;iindirected) mem_free(t->indirected); mem_free(t); return (0); } } if (items) werr(TRUE,msgs_lookup("(tearoff_create): Menu item overcount.")); if (ino!=t->numberOfItems) werr(TRUE,msgs_lookup("(tearoff_create): Menu item count mismatch.")); return (t); } void tearoff_attachSubMenu(tearoff to,int itm,tearoff sub) { tearoff__item *item; if (to->numberOfItems < itm) { werr(TRUE,"(tearoff_attachSubMenu): Item does not exist"); return; } item = (tearoff__item *)(to+1); item += (itm-1); item->sub = sub; item->subMenu = TRUE; } void tearoff_destroy(tearoff t) { tearoff__item *i; int c; if (!t) return; i=(tearoff__item *)(t+1); for (c=1;c<=t->numberOfItems;c++,i++) mem_free(i->text); mem_free(t->menuTitle); mem_free(t); } void tearoff_selectItem(tearoff t, int item, tearoff_selectType type) { tearoff__item *i; int more; wimp_redrawstr r; wimp_icon icon; BOOL riscos3=(wimpt_getVersion()>=300); i = (tearoff__item *)(t + 1); i += (item-1); if (i->selType == type) return; i->selType = type; if (t->open && !t->folded) { r.w=t->w; r.box.x0=0; r.box.x1=24; r.box.y0=i->y; r.box.y1=i->y+44; wimp_update_wind(&r,&more); while (more) { icon.box.y1=i->y+44; icon.box.y0=i->y; icon.box.x0=0; icon.box.x1=24; icon.flags=wimp_IVCENTRE | wimp_IHCENTRE | wimp_IFILLED | wimp_IBACKCOL * 0 | wimp_IFORECOL * 7; if (i->shaded) icon.flags |= wimp_INOSELECT; if (!riscos3 && i->selType == tearoff_TICKED) { icon.flags |= wimp_ITEXT; strcpy(icon.data.text, "\x80"); } if (riscos3 && i->selType == tearoff_TICKED) { icon.flags |= wimp_ISPRITE | wimp_INDIRECT; icon.data.indirectsprite.name = "\x80"; icon.data.indirectsprite.spritearea = (sprite_area *)1; icon.data.indirectsprite.nameisname = 4; } if (i->selType == tearoff_RADIOED) { icon.flags |= wimp_ITEXT; strcpy(icon.data.text, "\x8F"); } if (i->selType == tearoff_NONE) { icon.flags |= wimp_ITEXT; strcpy(icon.data.text, ""); } wimpt_noerr(wimp_ploticon(&icon)); wimp_get_rectangle(&r,&more); } } } void tearoff_shadeItem(tearoff t, int item, BOOL shaded) { tearoff__item *i; wimp_redrawstr r; int more; i = (tearoff__item *)(t + 1); i += (item-1); if (i->shaded == shaded) return; i->shaded = shaded; if (t->open && !t->folded) { if (t->selected==item) { /* Close menu structure here */ t->selected=0; } r.w=t->w; r.box.x0=0; r.box.x1=t->width; r.box.y0=i->y; r.box.y1=i->y+44; wimp_update_wind(&r,&more); while (more) { tearoff__doRedraw(t, &r); wimp_get_rectangle(&r,&more); } } } void tearoff_changeItemText(tearoff t,int item,char *text) { tearoff__item *i; char *ind,*eptr; int len=0,hash=0,oldWidth; i=(tearoff__item *)(t+1); i+=(item-1); mem_free(i->text); i->text=i->keys=NULL; for (eptr=text;*eptr!=0;eptr++,len++) if (*eptr=='#') hash=len; if (ind=mem_alloc(len+1),!ind) { werr(FALSE,msgs_lookup("menuNEM:Not enough memory to construct menu.")); return; } i->text=ind; if (hash) i->keys=ind+hash+1; while (*text) { *ind=*text; if (*ind=='#') *ind=0; ind++; text++; } *ind=0; if (t->open) { oldWidth=t->width; tearoff_calculateMenuWidth(t); if (oldWidth!=t->width) tearoff_rebuildMenu(t); else { if (t->selected) tearoff_highlightItem(t->selected,t,FALSE); t->selected=item; tearoff_highlightItem(item,t,FALSE); t->selected=0; } } } void tearoff_changeTitle(tearoff t,char *title) { int oldWidth; mem_free(t->menuTitle); t->menuTitle=NULL; t->menuTitle=mem_alloc(strlen(title)+1); if (!t->menuTitle) return; strcpy(t->menuTitle,title); if (t->open) { oldWidth=t->width; tearoff_calculateMenuWidth(t); if (t->width!=oldWidth) tearoff_rebuildMenu(t); else win_settitle(t->w,title); } } tearoff tearoff_extendMenu(tearoff t,char *items) { tearoff__item *itm; int ino=tearoff__itemCount(items),i,y; if (!ino) return t; if (t=mem_reAlloc(t, sizeof(tearoff__str) + (ino+t->numberOfItems)*sizeof(tearoff__item)),!t) { werr(FALSE,msgs_lookup("Not enough memory to construct menu.")); return NULL; } itm=((tearoff__item *)(t+1)); itm+=(t->numberOfItems-1); y=itm->y-44; if (itm->dotted) y-=24; for (i=0;ishaded; } tearoff_selectType tearoff_howSelected(tearoff t,int item) { tearoff__item *i; i=(tearoff__item *)(t+1); i+=(item-1); return i->selType; }