home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / programming / tcl / tclsrc / c / WimpMenu < prev    next >
Encoding:
Text File  |  1996-03-06  |  7.4 KB  |  319 lines

  1. /* Wimp commands for tcl */
  2. /* (c) C.T.Stretch */
  3. /* Sat,25 Jun 1994 */
  4.  
  5. #include "h.WInt"
  6. #include "h.osbyte"
  7.  
  8. #define MENUFLAGS wimp_ICON_TEXT|wimp_ICON_INDIRECTED|wimp_ICON_FILLED|\
  9.         (wimp_COLOUR_BLACK<<wimp_ICON_FG_COLOUR_SHIFT)
  10.  
  11. #define TCLMENU(x) ((tcl_menu*)((x)+1)-1)
  12.  
  13. #define TRACEFLAGS (TCL_TRACE_WRITES|TCL_GLOBAL_ONLY)
  14.  
  15. static tcl_menu *thismenu,*iconbar_menu;
  16. static int iconbar_y;
  17.  
  18.  
  19. /*
  20.  *  menu_free --
  21.  *
  22.  *      Release the memory used by a menu.
  23.  *      Remove all the variable traces.
  24.  *      Called recursively for submenus.
  25.  *
  26.  * Results:
  27.  *      None.
  28.  *
  29.  * Side effects:
  30.  *      None.
  31.  *
  32. */
  33.  
  34. extern void menu_free(tcl_menu *m)
  35. { wimp_menu_entry *wme;
  36.   char **p;
  37.   trace *s,*t;
  38.   int i;
  39.   if(m==menu_NONE) return;
  40.   wme=m->menu.entries;
  41.   p=m->action;
  42.   for(i=0;i<m->n;i++)
  43.   { ckfree(*p);
  44.     if(wme->sub_menu!=wimp_NO_SUB_MENU&&
  45.       !(wme->menu_flags&wimp_MENU_GIVE_WARNING))
  46.         menu_free(TCLMENU(wme->sub_menu));
  47.     wme++;p++;
  48.   }
  49.   for(t=m->traces;t;)
  50.   { s=t->next;
  51.     Tcl_UntraceVar2(w_Interp,t->var,t->tag,TRACEFLAGS,t->proc,t->cd);
  52.     ckfree(t->var);ckfree(t->tag);
  53.     ckfree(t);
  54.     t=s;
  55.   }
  56.   ckfree(m->action);
  57.   ckfree(m);
  58. }
  59.  
  60. /*
  61.  *  tick --
  62.  *
  63.  *      Called as a trace procedure if the variable holding the tick
  64.  *      status of a menu item is changed.
  65.  *
  66.  *
  67.  * Results:
  68.  *      None.
  69.  *
  70.  * Side effects:
  71.  *      Adjusts the tick bit in the menu.
  72.  *
  73. */
  74.  
  75. static char *tick(ClientData d,Tcl_Interp *interp,char *n1,char *n2,int flags)
  76. { char *v=Tcl_GetVar2(interp,n1,n2,flags&TCL_GLOBAL_ONLY);
  77.   bits *b=(bits*)d;
  78.   if(!strcmp(v,"0")) (*b)&=~wimp_MENU_TICKED;
  79.   else (*b)|=wimp_MENU_TICKED;
  80.   return 0;
  81. }
  82.  
  83. /*
  84.  *  grey --
  85.  *
  86.  *
  87.  *      Called as a trace procedure if the variable holding the grey
  88.  *      status of a menu item is changed.
  89.  *
  90.  * Results:
  91.  *      None.
  92.  *
  93.  * Side effects:
  94.  *      Adjusts the grey bit in the menu.
  95.  *
  96. */
  97.  
  98. static char *grey(ClientData d,Tcl_Interp *interp,char *n1,char *n2,int flags)
  99. { char *v=Tcl_GetVar2(interp,n1,n2,flags&TCL_GLOBAL_ONLY);
  100.   bits *b=(bits*)d;
  101.   if(!strcmp(v,"0")) (*b)&=~wimp_ICON_SHADED;
  102.   else (*b)|=wimp_ICON_SHADED;
  103.   return 0;
  104. }
  105.  
  106. /*
  107.  *  menu_open --
  108.  *
  109.  *      Opens a menu in response to a menu button click.
  110.  *
  111.  *
  112.  *
  113.  * Results:
  114.  *      None.
  115.  *
  116.  * Side effects:
  117.  *      None.
  118.  *
  119. */
  120.  
  121. void menu_open(void)
  122. { int y=block.pointer.pos.y;
  123.   if(block.pointer.w==wimp_ICON_BAR)
  124.   { y=iconbar_y;thismenu=iconbar_menu;
  125.     substr['w'-'a']="bar";
  126.   }
  127.   else
  128.   { y=block.pointer.pos.y;
  129.     thismenu=diagram_menu();
  130.     if(thismenu==menu_NONE) return;
  131.     if(!thismenu)
  132.     { thismenu=document_menu();
  133.       if(thismenu==menu_NONE) return;
  134.     }
  135.   }
  136.   if(thismenu) wimp_create_menu(&(thismenu->menu),block.pointer.pos.x-64,y);
  137. }
  138.  
  139. /*
  140.  *  menu_select --
  141.  *
  142.  *      Called after a menu selection. Runs the associated script.
  143.  *      Re-opens the menu if adjust was used.
  144.  *
  145.  *
  146.  * Results:
  147.  *      None.
  148.  *
  149.  * Side effects:
  150.  *      None.
  151.  *
  152. */
  153.  
  154. void menu_select(void)
  155. { int i;
  156.   tcl_menu *tm=thismenu;
  157.   wimp_menu *wm;
  158.   wimp_pointer wp;
  159.   if(block.selection.items[0]>=0) for(i=0;i<7;i++)
  160.   { int j=block.selection.items[i];
  161.     if(block.selection.items[i+1]<0)
  162.     { if(tm->action[j]) checkEval(tm->action[j],"menu action");
  163.       break;
  164.     }
  165.     if(j<0||j>=tm->n) break;
  166.     wm=tm->menu.entries[j].sub_menu;
  167.     tm=TCLMENU(wm);
  168.   }
  169.   wimp_get_pointer_info(&wp);
  170.   if(wp.buttons==wimp_CLICK_ADJUST)
  171.       wimp_create_menu(&(thismenu->menu),wp.pos.x,wp.pos.y);
  172. }
  173.  
  174. /*
  175.  *  menu_make --
  176.  *
  177.  *      Constructs a menu from a menu description
  178.  *      Called recursively for submenus.
  179.  *
  180.  *
  181.  * Results:
  182.  *      Returns a tcl_menu or 0 for a bad description.
  183.  *
  184.  * Side effects:
  185.  *      None.
  186.  *
  187. */
  188.  
  189. tcl_menu *menu_make(char *desc,char *tag)
  190. { int width=12,nitems,i;
  191.   char **items;
  192.   char *name;
  193.   wimp_menu *wm;
  194.   tcl_menu *tm;
  195.   char *tg;
  196.   if(Tcl_SplitList(w_Interp,desc,&nitems,&items))
  197.     return wrong0("Bad list ",desc);
  198.   nitems--;
  199.   if(nitems<1) return wrong0("Menu with no items ",desc);
  200.   tm=ckalloc(sizeof(tcl_menu)+(nitems-1)*sizeof(wimp_menu_entry));
  201.   tm->action=ckalloc(nitems*sizeof(char*));
  202.   tm->n=nitems;
  203.   tm->traces=0;
  204.   wm=&(tm->menu);
  205.   for(i=0;i<nitems;i++)
  206.   { int nparts,j;
  207.     char **parts;
  208.     wimp_menu_entry *wme;
  209.     if(Tcl_SplitList(w_Interp,items[i+1],&nparts,&parts))
  210.       return wrong0("Bad list ",items[i+1]);
  211.     if(nparts<1) return wrong0("Bad menu item ",desc);
  212.     wme=&(wm->entries[i]);
  213.     wme->menu_flags=0;
  214.     wme->sub_menu=wimp_NO_SUB_MENU;
  215.     wme->icon_flags=MENUFLAGS;
  216.     tm->action[i]=0;
  217.     name=scopy(parts[0]);
  218.     wme->data.indirected_text.text=name;
  219.     wme->data.indirected_text.validation=0;
  220.     wme->data.indirected_text.size=strlen(name);
  221.     tg=0;
  222.     for(j=1;j<nparts;j++)
  223.     { if(!strcmp(parts[j],"-tag"))
  224.       { tg=tag;
  225.         continue;
  226.       }
  227.       if(j==nparts-1) return wrong0("Odd menu component ",parts[j]);
  228.       if(!strcmp(parts[j],"-click"))
  229.       { tm->action[i]=scopy(parts[++j]);
  230.         continue;
  231.       }
  232.       if(!strcmp(parts[j],"-tick"))
  233.       { int n=strlen(parts[++j]);
  234.         char *s;
  235.         trace *t=ckcalloc(sizeof(trace));
  236.         if(tg) n+=2+strlen(tg);
  237.         tm->action[i]=ckalloc(2*n+15);
  238.         if(tg) sprintf(tm->action[i],"set %s(%s) [expr !$%s(%s)]",
  239.                  parts[j],tg,parts[j],tg);
  240.         else sprintf(tm->action[i],"set %s [expr !$%s]",parts[j],parts[j]);
  241.         s=Tcl_GetVar2(w_Interp,parts[j],tg,TCL_GLOBAL_ONLY);
  242.         if(s)
  243.         { if(strcmp(s,"0")!=0) wme->menu_flags|=wimp_MENU_TICKED;
  244.         }
  245.         else Tcl_SetVar2(w_Interp,parts[j],tg,"0",TCL_GLOBAL_ONLY);
  246.         t->next=tm->traces;
  247.         tm->traces=t;
  248.         t->var=scopy(parts[j]);
  249.         if(tg) t->tag=scopy(tg);
  250.         t->proc=tick;
  251.         t->cd=(ClientData)&(wme->menu_flags);
  252.         Tcl_TraceVar2(w_Interp,parts[j],tg,TRACEFLAGS,tick,t->cd);
  253.         continue;
  254.       }
  255.       if(!strcmp(parts[j],"-grey"))
  256.       { char *s;
  257.         trace *t=ckcalloc(sizeof(trace));
  258.         s=Tcl_GetVar2(w_Interp,parts[++j],tg,TCL_GLOBAL_ONLY);
  259.         if(s&&(strcmp(s,"0")!=0)) wme->icon_flags|=wimp_ICON_SHADED;
  260.         t->next=tm->traces;
  261.         tm->traces=t;
  262.         t->var=scopy(parts[j]);
  263.         if(tg) t->tag=scopy(tg);
  264.         t->proc=grey;
  265.         t->cd=(ClientData)&(wme->icon_flags);
  266.         Tcl_TraceVar2(w_Interp,parts[j],tg,TRACEFLAGS,grey,t->cd);
  267.         continue;
  268.       }
  269.       if(!strcmp(parts[j],"-sub"))
  270.       { tcl_menu *tsm=menu_make(parts[++j],tag);
  271.         if(!tsm) return 0;
  272.         wme->sub_menu=&(tsm->menu);
  273.         continue;
  274.       }
  275.       if(!strcmp(parts[j],"-dbox"))
  276.       { wimp_menu *wm=box_find(parts[++j]);
  277.         if(!wm) return wrong0("Unknown dbox ",parts[j]);
  278.         wme->sub_menu=wm;
  279.         wme->menu_flags|=wimp_MENU_GIVE_WARNING;
  280.         continue;
  281.       }
  282.       return wrong0("Odd menu component ",parts[j]);
  283.     }
  284.     ckfree(parts);
  285.   }
  286.   wm->entries[0].menu_flags|=wimp_MENU_TITLE_INDIRECTED;
  287.   wm->entries[nitems-1].menu_flags|=wimp_MENU_LAST;
  288.   wm->title_data.indirected_text.text=scopy(items[0]);
  289.   wm->title_fg=wimp_COLOUR_BLACK;
  290.   wm->title_bg=wimp_COLOUR_LIGHT_GREY;
  291.   wm->work_fg=wimp_COLOUR_BLACK;
  292.   wm->work_bg=wimp_COLOUR_WHITE;
  293.   wm->width=width*16;
  294.   wm->height=44;
  295.   wm->gap=0;
  296.   return tm;
  297. }
  298.  
  299. /*
  300.  *  menu_bar --
  301.  *
  302.  *      Finds the height to open the iconbar menu.
  303.  *
  304.  * Results:
  305.  *      None.
  306.  *
  307.  * Side effects:
  308.  *      Sets iconbar_y and iconbar_menu.
  309.  *
  310. */
  311.  
  312. void menu_bar(tcl_menu *wm)
  313. { wimp_menu_entry *wme=wm->menu.entries;
  314.   iconbar_y=140;
  315.   for(;!(wme->menu_flags&wimp_MENU_LAST);wme++) iconbar_y+=44;
  316.   iconbar_menu=wm;
  317. }
  318.  
  319.