home *** CD-ROM | disk | FTP | other *** search
/ Archive Magazine 1995 / ARCHIVE95.iso / discs / shareware / share_40 / star / !Star / c / Star
Text File  |  1990-09-21  |  14KB  |  538 lines

  1. /* Star IconBar menu
  2.    Fri,21 Sep 1990
  3.    Copyright C.T.Stretch 1990
  4. */
  5.  
  6. #include "wimp.h"
  7. #include "wimpt.h"
  8. #include "win.h"
  9. #include "event.h"
  10. #include "res.h"
  11. #include "menu.h"
  12. #include "template.h"
  13. #include "dbox.h"
  14. #include "dboxquery.h"
  15. #include "werr.h"
  16. #include "xferrecv.h"
  17. #include "flex.h"
  18.  
  19. #include <string.h>
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <ctype.h>
  23.  
  24. #define MAXM 16
  25. #define FIRSTITEM 2
  26. #define MAXF 16
  27. #define CMAX 255
  28. #define EDNLEN 64
  29. #define DEFTYPE 0x123456
  30. #define TRANS 0
  31. #define NOBAR (1<<30)
  32. #define NOTRANS -1
  33. #define SKIP for(;*s&&s<e;s++)
  34.  
  35. typedef struct comstr
  36. { char *fp;
  37.   int co,mo,len,mn;
  38. } comstr;
  39.  
  40. typedef struct fstr
  41. { char fn[CMAX+1];
  42.   int type;
  43. } fstr;
  44.  
  45. static comstr cd[MAXM];
  46. static fstr files[MAXF];
  47. static int fno=0;
  48. static menu barmenu,starmenu,unmenu;
  49. static int nextitem,nextmn;
  50. static int ino;
  51. static char icbuf[12]="0";
  52. static char cbuf[CMAX+1],kbuf[CMAX+1];
  53. static char *bufp;
  54. static char *ce=cbuf+CMAX,*ke=kbuf+CMAX;
  55. static int frep=0;
  56. static char *openbr=0;
  57. static int edhand=0;
  58. static char edname[EDNLEN];
  59. static BOOL ok=TRUE;
  60. static int barend=-1;
  61. static int trans;
  62.  
  63. static void barmenuproc(void *,char *);
  64.  
  65. static void err(char *m)
  66. { ok=FALSE;
  67.   os_swi6(0x24,(int)"Star$Error",(int)m,strlen(m),0,0,0);
  68. }
  69.  
  70. static int flen(char *fn)
  71. { os_filestr fstr;
  72.   fstr.action=17;
  73.   fstr.name=fn;
  74.   if(os_file(&fstr)) return -1;
  75.   return fstr.start;
  76. }
  77.  
  78. static void setmf(menu m,int n,int f)
  79. { int p=(int)menu_syshandle(m)+sizeof(wimp_menuhdr);
  80.   wimp_menuitem *mi=(wimp_menuitem*)p;
  81.   mi[n-1].flags=f;
  82. }
  83.  
  84. static BOOL newmenus(void)
  85. { barmenu=menu_new("Star","Star");
  86.   starmenu=menu_new("Star",">Info,Load,Unload,>Error,Quit");
  87.   unmenu=menu_new("UnloadMenu","All,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16");
  88.   menu_submenu(starmenu,3,unmenu);
  89.   menu_submenu(barmenu,1,starmenu);
  90.   nextitem=FIRSTITEM;nextmn=FIRSTITEM;
  91.   setmf(unmenu,1,wimp_MLAST);
  92.   if(!event_attachmenu(win_ICONBAR,barmenu,barmenuproc,0)) return FALSE;
  93.   return TRUE;
  94. }
  95.  
  96. static char *additems(char *s,char *e,menu m,int *off)
  97. { int n;
  98.   menu sub=0;
  99.   for(;s<e;s++)
  100.   { switch(*s)
  101.     { case ':':menu_extend(m,++s);(*off)++;
  102.                SKIP;
  103.                break;
  104.       case '{':menu_extend(m,++s);
  105.                sub=menu_new(s,"");
  106.                SKIP;n=1;
  107.                s=additems(++s,e,sub,&n);
  108.                menu_submenu(m,(*off)++,sub);
  109.                break;
  110.       case '}':SKIP;return s;
  111.       case ';':case  0 :case ' ':case '*':case '>':case '+':
  112.       case '?':case '|':case '(':case ')':case '[':
  113.       case ']':case '<':case '#':case '!':
  114.                SKIP;break;
  115.        default:werr(0,"odd line |%s| %d",s,*s);SKIP;
  116.     }
  117.   }
  118.   return e;
  119. }
  120.  
  121. static void nullify(char *s,char *e)
  122. { for(;s<e;s++) if(*s==10||*s==13) *s=0;
  123. }
  124.  
  125. static void setmenu(comstr *cs)
  126. { char *c,*s;
  127.   int bar=nextitem;
  128.   cs->mn=nextmn++;
  129.   cs->mo=nextitem;
  130.   additems(cs->fp+cs->co,cs->fp+cs->len,barmenu,&nextitem);
  131.   c=(char*)&(((wimp_menuitem*)
  132.   ((int)(menu_syshandle(unmenu))+sizeof(wimp_menuhdr)))[cs->mn-1].data);
  133.   for(s=cs->fp+strlen(cs->fp);*s!='.';s--);strncpy(c,s+1,12);
  134.   setmf(unmenu,cs->mn-1,0);setmf(unmenu,cs->mn,wimp_MLAST);
  135.   if(nextitem>bar) setmf(barmenu,bar-1,wimp_MSEPARATE);
  136. }
  137.  
  138. static void addmenu(char *fn)
  139. { int n,len;
  140.   FILE *file;
  141.   comstr *cs;
  142.   for(n=0;n<MAXM;n++) if(!cd[n].mo)break;
  143.   if(n>=MAXM) return;
  144.   cs=cd+n;
  145.   cs->co=strlen(fn)+1;
  146.   len=flen(fn);
  147.   if(len<=0) return;
  148.   if(!flex_alloc((flex_ptr)&(cs->fp),cs->co+len+1)) return;
  149.   strcpy(cs->fp,fn);
  150.   file=fopen(fn,"rb");
  151.   fread(cs->fp+cs->co,1,len,file);
  152.   fclose(file);
  153.   cs->len=cs->co+len;
  154.   if(cs->fp[cs->len-1]!=10) cs->fp[cs->len++]=10;
  155.   nullify(cs->fp+cs->co,cs->fp+cs->len);
  156.   setmenu(cs);
  157. }
  158.  
  159. static char *skipsub(char *s,char *e)
  160. { for(;s<e;s++)
  161.   { switch(*s)
  162.     { case '{':SKIP;
  163.                s=skipsub(++s,e);
  164.                break;
  165.       case '}':SKIP;return s;
  166.        default:SKIP;
  167.     }
  168.   }
  169.   return e;
  170. }
  171.  
  172. static char *findentry(char *h,char *s,char *e)
  173. { int n=0;
  174.   for(;s<e&&ok;s++)
  175.   { switch(*s)
  176.     { case ':':n+=1;
  177.                SKIP;
  178.                if(n>=h[0]) return ++s;
  179.                break;
  180.       case '{':n+=1;
  181.                SKIP;
  182.                if(n>=h[0]) return findentry((*h)?h+1:h,++s,e);
  183.                s=skipsub(++s,e);
  184.                break;
  185.       case '}':return 0;
  186.        default:SKIP;
  187.     }
  188.   }
  189.   return 0;
  190. }
  191.  
  192.  
  193. static void add(char c)
  194. { if(bufp<ke) *bufp++=c;
  195.   else err("Line too long");
  196. }
  197.  
  198. static void adds(char *s)
  199. { if(bufp+strlen(s)<=ke)
  200.   { strcpy(bufp,s);
  201.     bufp+=strlen(s);
  202.   }
  203.   else err("Line too long");
  204. }
  205.  
  206. static void addf(int n,char *p)
  207. { char *f=files[n].fn;
  208.   char *e=f+strlen(f);
  209.   char *q,c;
  210.   for(;*p=='<'||*p=='>';p++)
  211.   { for(q=e-1;q>f;q--) if(*q=='.')break;
  212.     if(*p=='<') e=q; else f=q+1;
  213.   }
  214.   if(f>=e) { err("Bad file part");return;}
  215.   c=*e;*e=0;adds(f);*e=c;
  216. }
  217.  
  218. static void subst(char *s,char *t)
  219. { int n;
  220.   char *c,*p,tbuf[CMAX];
  221.   dbox d;
  222.   bufp=kbuf;
  223.   for(;*s&&ok;s++)
  224.   { if(*s=='%')
  225.     { for(p=++s;*s=='<'||*s=='>';s++);
  226.       switch(*s)
  227.       { case '!':for(n=0;n<fno;n++){ addf(n,p);add(' ');}
  228.                  break;
  229.         case '?':if(!openbr) err("? not in brackets");
  230.                  if(ok) addf(frep,p);
  231.                  break;
  232.         case '"':for(c=++s;*s;s++) if(*s=='"') break;
  233.                  if(*s!='"'){err("missing \"");break;}
  234.                  d=dbox_new("prompt");
  235.                  if(!d) {err("Cant open prompt box");break;};
  236.                  *s=0;dbox_setfield(d,2,c);*s='"';
  237.                  dbox_show(d);
  238.                  if(dbox_fillin(d)) { dbox_dispose(&d);err("Canceled");break;}
  239.                  dbox_getfield(d,1,tbuf,CMAX);adds(tbuf);
  240.                  dbox_dispose(&d);
  241.                  break;
  242.         case '%':add('%');break;
  243.         default:n=*s-'0';
  244.                 if(n>=0&&n<=9)
  245.                 { if(files[n].type>=0) addf(n,p);
  246.                   else err("Too few files");
  247.                 }
  248.                 else err("Odd % substitution");
  249.       }
  250.     }
  251.     else add(*s);
  252.   }
  253.   add(0);
  254.   if(ok)
  255.   { if(trans!=NOTRANS)
  256.     { os_swi3r(0x27,(int)kbuf,(int)t,(ce-t)|trans,0,0,&n);
  257.       if(n>ce-t) err("Line too long");
  258.     }
  259.     else
  260.     { if(strlen(kbuf)<ce-t) strcpy(t,kbuf);else err("Line too long");
  261.     }
  262.   }
  263. }
  264.  
  265. static char *nextopen(char *s,char *e)
  266. { for(;s<e&&*s!=')';s++) SKIP;
  267.   if(*s!=')') err("Missing close bracket");
  268.   return s;
  269. }
  270.  
  271. static char *dofile(char *s,char *e)
  272. { BOOL manyfile=(openbr!=0);
  273.   FILE *file=fopen("<Star$Scrap>.Temp","wb");
  274.   if(!file) {err("Cant open scrap file");return 0;}
  275.   for(;s<e&&ok;s++)
  276.   { trans=NOTRANS;
  277.     if(*s=='|'){trans=TRANS;s++;}
  278.     if(*s=='!'){trans=NOBAR;s++;}
  279.     switch(*s)
  280.     { case '*':subst(++s,cbuf);
  281.                if(ok) { fputs(cbuf,file);fputc(10,file);}
  282.                SKIP;break;
  283.       case '(':if(manyfile||openbr) err("Odd open bracket");
  284.                if(isdigit(s[1])) frep=*(++s)-'0';
  285.                else frep=0;
  286.                if(frep>=fno) s=nextopen(s,e);
  287.                openbr=++s;SKIP;
  288.                break;
  289.       case ')':if(manyfile||!openbr) err("Odd close bracket");
  290.                if(++frep<fno) s=openbr;else openbr=0;
  291.                SKIP;break;
  292.       case ']':fclose(file);
  293.                system("settype <Star$Scrap>.Temp FEB");
  294.                strcpy(cbuf,"Obey <Star$Scrap>.Temp ");
  295.                subst(++s,cbuf+strlen(cbuf));
  296.                if(ok) wimp_starttask(cbuf);
  297.                SKIP;return s;
  298.       case ':':case '{':case '}':s=e;break;;
  299.       case ';':case ' ':case 0:SKIP;break;
  300.       default:err("Strange line");
  301.     }
  302.   }
  303.   fclose(file);
  304.   return 0;
  305. }
  306.  
  307. static void edfile(char *s)
  308. { wimp_msgstr m;
  309.   subst(s,cbuf);
  310.   if(ok)
  311.   { if(edhand)
  312.     { m.hdr.size=256;
  313.       m.hdr.your_ref=0;
  314.       m.hdr.action=wimp_MDATALOAD;
  315.       m.data.dataload.w=(wimp_w)-1;
  316.       m.data.dataload.i=0;
  317.       m.data.dataload.x=0;
  318.       m.data.dataload.y=0;
  319.       m.data.dataload.size=0;
  320.       m.data.dataload.type=0xFFF;
  321.       strcpy(m.data.dataload.name,cbuf);
  322.       wimpt_noerr(wimp_sendmessage(wimp_ESENDWANTACK,&m,edhand));
  323.     }
  324.     else
  325.     { if(strlen(cbuf)<252)
  326.       { sprintf(kbuf,"run %s",cbuf);
  327.         wimp_starttask(kbuf);
  328.       }
  329.       else err("Line too long");
  330.     }
  331.   }
  332. }
  333.  
  334. static void key(char *s)
  335. { char *c;
  336.   int b,n=0;
  337.   subst(s,cbuf);
  338.   if(ok) for(c=cbuf;*c;c++){ b=*c; os_byte(138,&n,&b);}
  339. }
  340.  
  341.  
  342. static void typecheck(char *s,int n)
  343. { int t=files[n].type;
  344.   for(;*s;s++) if(strtol(s,&s,16)==t) return;
  345.   err("Bad file type");
  346. }
  347.  
  348. static void checktype(char *s)
  349. { int n;
  350.   switch(*s)
  351.   { case '?':typecheck(++s,frep);break;
  352.     case '!':for(n=0;n<fno;n++) typecheck(++s,n);break;
  353.     default:if(isdigit(*s)) typecheck(++s,*s-'0');else err("Bad # suffix");
  354.   }
  355. }
  356.  
  357. static void doit(char *s,char *e)
  358. { int m,n;
  359.   openbr=0;
  360.   for(;s<e&&ok;s++)
  361.   { trans=NOTRANS;
  362.     if(*s=='|'){trans=TRANS;s++;}
  363.     if(*s=='!'){trans=NOBAR;s++;}
  364.     switch(*s)
  365.     { case '*':subst(++s,cbuf);
  366.                if(ok) wimp_starttask(cbuf);
  367.                break;
  368.       case '>':edfile(++s);break;
  369.       case '<':n=s[1];m=n-'0';
  370.                if(!isdigit(n)) err("Bad default");
  371.                else if(files[m].type<0)
  372.                { subst(s+2,cbuf);
  373.                  if(ok)
  374.                  { strcpy(files[m].fn,cbuf);
  375.                    files[m].type=DEFTYPE;
  376.                  }
  377.                }
  378.                break;
  379.       case '+':key(++s);break;
  380.       case '#':checktype(++s);break;
  381.       case '?':subst(++s,cbuf);
  382.                if(ok&&dboxquery(cbuf)!=dboxquery_YES) err("Canceled");
  383.                break;
  384.       case '(':if(openbr) err("Odd open bracket\n");
  385.                if(isdigit(s[1])) frep=*(++s)-'0';
  386.                else frep=0;
  387.                if(frep>=fno) s=nextopen(s,e);
  388.                openbr=++s;break;
  389.       case ')':if(!openbr) err("Odd close bracket\n");
  390.                if(++frep<fno)s=openbr;else openbr=0;
  391.                break;
  392.       case '[':SKIP;s=dofile(s,e);
  393.                break;
  394.       case ':':case '{':case '}':s=e;break;;
  395.       case ';':case ' ':case 0:break;
  396.       default:err("Strange line");
  397.     }
  398.     SKIP;
  399.   }
  400. }
  401.  
  402. static void findcom(char *h)
  403. { int n,k=0;
  404.   char *s;
  405.   comstr *cs=0;
  406.   for(n=0;n<MAXM;n++) if(cd[n].mo&&cd[n].mo<=h[0])
  407.   if(cd[n].mo>k) { cs=cd+n;k=cs->mo;}
  408.   if(!k) { werr(0,"Can't find comstr %d",h[0]);return;}
  409.   h[0]-=k-1;
  410.   s=findentry(h,cs->fp+cs->co,cs->fp+cs->len);
  411.   if(!s){ werr(0,"not found");return;}
  412.   doit(s,cs->fp+cs->len);
  413. }
  414.  
  415. static BOOL barhand(wimp_eventstr *e,void *v)
  416. { char *fn;
  417.   int ftype;
  418.   v=v;
  419.   switch(e->e)
  420.   { case wimp_ESEND:case wimp_ESENDWANTACK:
  421.     switch(e->data.msg.hdr.action)
  422.     { case wimp_MDATALOAD:ftype=xferrecv_checkinsert(&fn);
  423.                           if(strlen(fn)>CMAX||fno>=MAXF) break;
  424.                           strcpy(files[fno].fn,fn);files[fno].type=ftype;
  425.                           sprintf(icbuf,"%d",++fno);
  426.                         wimpt_noerr(wimp_set_icon_state((wimp_w)-1,ino,0,0));
  427.                           break;
  428.       case wimp_MINITTASK:if(!strcmp(edname,e->data.msg.data.chars+8))
  429.                             edhand=e->data.msg.hdr.task;
  430.                           return TRUE;
  431.       case wimp_MCLOSETASK:if(e->data.msg.hdr.task==edhand) edhand=0;
  432.     }
  433.     break;
  434.   }
  435.   return FALSE;
  436. }
  437.  
  438. static void barclick(wimp_eventstr *e,void *h) { e=e;h=h;}
  439.  
  440. static void unload(int n)
  441. { int m;
  442.   event_attachmenu(win_ICONBAR,0,barmenuproc,0);
  443.   if(n==1)
  444.   { for(m=0;m<MAXM;m++) if(cd[m].mo)
  445.     { flex_free((flex_ptr)&(cd[m].fp));
  446.       cd[m].mo=0;
  447.     }
  448.   }
  449.   else
  450.   { for(m=0;m<MAXM;m++)if(cd[m].mo&&cd[m].mn==n)
  451.     { flex_free((flex_ptr)&(cd[m].fp));
  452.       cd[m].mo=0;
  453.     }
  454.   }
  455.   menu_dispose(&barmenu,TRUE);
  456.   newmenus();
  457.   for(m=0;m<MAXM;m++) if(cd[m].mo) setmenu(cd+m);
  458. }
  459.  
  460. static void starmenuproc(char *h)
  461. { dbox db;
  462.   int n;
  463.   switch (h[1])
  464.   { case 1:if(!h[2])break;
  465.            db=dbox_new("Info");
  466.            if(db)
  467.            { dbox_setfield(db,4,"0.0 "__DATE__);
  468.              dbox_show(db);dbox_fillin(db);
  469.              dbox_dispose(&db);
  470.            }
  471.            break;
  472.     case 2:for(n=0;n<fno;n++) if(files[n].type==0xFFF) addmenu(files[n].fn);
  473.            break;
  474.     case 3:unload(h[2]);break;
  475.     case 4:if(!h[2]) break;
  476.            db=dbox_new("error");
  477.            if(db)
  478.            { os_read_var_val("Star$Error",cbuf,CMAX);
  479.              dbox_setfield(db,0,cbuf);
  480.              dbox_show(db);dbox_fillin(db);
  481.              dbox_dispose(&db);
  482.            }
  483.            break;
  484.     case 5:exit(0);
  485.   }
  486. }
  487.  
  488. static void barmenuproc(void *wh,char *h)
  489. { int n;
  490.   wh=wh;
  491.   if(h[0]<FIRSTITEM) starmenuproc(h);
  492.   else findcom(h);
  493.   fno=0;strcpy(icbuf,ok?"0":"!?");
  494.   for(n=0;n<MAXF;n++) files[n].type=-1;
  495.   wimpt_noerr(wimp_set_icon_state((wimp_w)-1,ino,0,0));
  496.   ok=TRUE;
  497. }
  498.  
  499. static void mybaricon(void)
  500. { wimp_icreate cr[1];
  501.   cr->w=(wimp_w)barend;
  502.   cr->i.box.x0=0;cr->i.box.x1=68;
  503.   cr->i.box.y0=-16;cr->i.box.y1=84;
  504.   cr->i.flags=wimp_ISPRITE|wimp_INDIRECT|(wimp_IBTYPE*wimp_BCLICKDEBOUNCE);
  505.   cr->i.flags|=wimp_ITEXT|(wimp_IFORECOL*7)|wimp_IFILLED|wimp_IHCENTRE;
  506.   cr->i.flags|=wimp_IBACKCOL;
  507.   cr->i.data.indirecttext.buffer=icbuf;
  508.   cr->i.data.indirecttext.validstring="S!star";
  509.   cr->i.data.indirecttext.bufflen=12;
  510.   wimpt_noerr(wimp_create_icon(cr,&ino));
  511.   win_register_event_handler(win_ICONBAR,barclick,0);
  512.   win_activeinc();
  513. }
  514.  
  515. static BOOL init(void)
  516. { wimpt_init("Star");
  517.   res_init("Star");
  518.   template_init();
  519.   dbox_init();
  520.   flex_init();
  521.   mybaricon();
  522.   if(!newmenus())werr(0,"Failed");
  523.   win_register_event_handler(win_ICONBARLOAD,(win_event_handler)barhand,0);
  524.   win_add_unknown_event_processor(barhand,0);
  525.   os_read_var_val("Star$Ed",edname,EDNLEN);
  526.   if(!edname[0]) strcpy(edname,"Edit");
  527.   return TRUE;
  528. }
  529.  
  530. int main(int n,char **c)
  531. { int i=1;
  532.   if(n>1&&*(c[1])=='-') {i++;barend=-2;}
  533.   if(!init()) return 0;
  534.   for(;i<n;i++) addmenu(c[i]);
  535.   for(;;) event_process();
  536.   return 0;
  537. }
  538.