root/scripts/tkgen.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. start_proc
  2. clear_globalflags
  3. generate_if
  4. generate_if_for_outfile
  5. end_proc
  6. find_menu_size
  7. dump_tk_script

   1 /* Generate tk script based upon config.in
   2  *
   3  * Version 1.0
   4  * Eric Youngdale
   5  * 10/95
   6  *
   7  * 1996 01 04 - Avery Pennarun - Aesthetic improvements
   8  *              <apenwarr@foxnet.net>
   9  *
  10  * 1996 01 24 - Avery Pennarun - Bugfixes and more aesthetics
  11  */
  12 #include <stdio.h>
  13 #include "tkparse.h"
  14 
  15 #ifndef TRUE
  16 #define TRUE (1)
  17 #endif
  18 
  19 #ifndef FALSE
  20 #define FALSE (0)
  21 #endif
  22 
  23 /*
  24  * This prevents the Prev/Next buttons from going through the entire sequence
  25  * of submenus.  I need to fix the window titles before it would really be
  26  * appropriate to enable this.
  27  */
  28 #define PREVLAST_LIMITED_RANGE
  29 
  30 /*
  31  * This is the total number of submenus that we have.
  32  */
  33 static int tot_menu_num =0;
  34 
  35 /*
  36  * Generate portion of wish script for the beginning of a submenu.
  37  * The guts get filled in with the various options.
  38  */
  39 static start_proc(char * label, int menu_num, int flag)
     /* [previous][next][first][last][top][bottom][index][help] */
  40 {
  41   if( flag )
  42     printf("menu_option menu%d %d \"%s\"\n", menu_num, menu_num, label);
  43   printf("proc menu%d {w title} {\n", menu_num);
  44   printf("\tcatch {destroy $w}\n");
  45   printf("\ttoplevel $w -class Dialog\n");
  46   printf("\tmessage $w.m -width 400 -aspect 300 -background grey -text \\\n");
  47   printf("\t\t\"%s\"  -relief raised -bg grey\n",label);
  48   printf("\tpack $w.m -pady 10 -side top -padx 10\n");
  49   printf("\twm title $w \"%s\" \n\n", label);
  50   
  51   printf("\tframe $w.topline -relief ridge -borderwidth 2 -height 2\n");
  52   printf("\tpack $w.topline -side top -fill x\n\n");
  53   
  54   printf("\tframe $w.config\n");
  55   printf("\tpack $w.config -fill y -expand on\n\n");
  56   
  57   printf("\tscrollbar $w.config.vscroll -command \"$w.config.canvas yview\"\n");
  58   printf("\tpack $w.config.vscroll -side right -fill y\n\n");
  59   
  60   printf("\tframe $w.botline -relief ridge -borderwidth 2 -height 2\n");
  61   printf("\tpack $w.botline -side top -fill x\n\n");
  62   
  63   printf("\tcanvas $w.config.canvas -height 1\\\n"
  64          "\t\t-relief flat -borderwidth 0 -yscrollcommand \"$w.config.vscroll set\" \\\n"
  65          "\t\t-width [expr [winfo screenwidth .] * 1 / 2] \n");
  66   printf("\tframe $w.config.f\n");
  67   printf("\tpack $w.config.canvas -side right -fill y\n");
  68   
  69   printf("\n\n");
  70 }
  71 
  72 /*
  73  * Each proc we create needs a global declaration for any global variables we
  74  * use.  To minimize the size of the file, we set a flag each time we output
  75  * a global declaration so we know whether we need to insert one for a
  76  * given function or not.
  77  */
  78 clear_globalflags(struct kconfig * cfg)
     /* [previous][next][first][last][top][bottom][index][help] */
  79 {
  80   for(; cfg != NULL; cfg = cfg->next)
  81   {
  82     cfg->flags &= ~GLOBAL_WRITTEN;
  83   }
  84 }
  85 
  86 /*
  87  * This function walks the chain of conditions that we got from cond.c,
  88  * and creates a wish conditional to enable/disable a given widget.
  89  */
  90 generate_if(struct kconfig * item,
     /* [previous][next][first][last][top][bottom][index][help] */
  91             struct condition * cond,
  92             int menu_num,
  93             int line_num)
  94 {
  95   int i;
  96   struct condition * ocond;
  97 
  98   ocond = cond;
  99 
 100   /*
 101    * First write any global declarations we need for this conditional.
 102    */
 103   while(cond != NULL )
 104     {
 105       switch(cond->op){
 106       case op_variable:
 107         printf("\tglobal %s\n", cond->variable.str);
 108         break;
 109       case op_kvariable:
 110         if(cond->variable.cfg->flags & GLOBAL_WRITTEN) break;
 111         cond->variable.cfg->flags |= GLOBAL_WRITTEN;
 112         printf("\tglobal %s\n", cond->variable.cfg->optionname);
 113         break;
 114       default:
 115         break;
 116       }
 117       cond = cond->next;
 118     }
 119   
 120   /*
 121    * Now write this option.
 122    */
 123   if(   (item->flags & GLOBAL_WRITTEN) == 0
 124      && (item->optionname != NULL) )
 125     {
 126       printf("\tglobal %s\n", item->optionname);
 127       item->flags |= GLOBAL_WRITTEN;
 128     }
 129   /*
 130    * Now generate the body of the conditional.
 131    */
 132   printf("\tif {");
 133   cond = ocond;
 134   while(cond != NULL )
 135     {
 136       switch(cond->op){
 137       case op_bang:
 138         printf(" ! ");
 139         break;
 140       case op_eq:
 141         printf(" == ");
 142         break;
 143       case op_neq:
 144         printf(" != ");
 145         break;
 146       case op_and:
 147       case op_and1:
 148         printf(" && ");
 149         break;
 150       case op_or:
 151         printf(" || ");
 152         break;
 153       case op_lparen:
 154         printf("(");
 155         break;
 156       case op_rparen:
 157         printf(")");
 158         break;
 159       case op_variable:
 160         printf("$%s", cond->variable.str);
 161         break;
 162       case op_kvariable:
 163         printf("$%s", cond->variable.cfg->optionname);
 164         break;
 165       case op_shellcmd:
 166         printf("[exec %s]", cond->variable.str);
 167         break;
 168       case op_constant:
 169         if( strcmp(cond->variable.str, "y") == 0 )
 170           printf("1");
 171         else if( strcmp(cond->variable.str, "n") == 0 )
 172           printf("0");
 173         else if( strcmp(cond->variable.str, "m") == 0 )
 174           printf("2");
 175         else
 176           printf("\"%s\"", cond->variable);
 177         break;
 178       }
 179       cond = cond->next;
 180     }
 181 
 182   /*
 183    * Now we generate what we do depending upon the value of the conditional.
 184    * Depending upon what the token type is, there are different things
 185    * we must do to enable/disable the given widget - this code needs to
 186    * be closely coordinated with the widget creation procedures in header.tk.
 187    */
 188   switch(item->tok)
 189     {
 190     case tok_define:
 191       printf("} then { set %s %s } \n",  item->optionname, item->value);
 192       break;
 193     case tok_menuoption:
 194       printf("} then { .f0.x%d configure -state normal } else { .f0.x%d configure -state disabled }\n",
 195              menu_num, menu_num);
 196       break;
 197     case tok_int:
 198       printf("} then { ");
 199       printf(".menu%d.config.f.x%d.x configure -state normal -fore black; ", menu_num, line_num);
 200       printf(".menu%d.config.f.x%d.l configure -state normal; ", menu_num, line_num);
 201       printf("} else { ");
 202       printf(".menu%d.config.f.x%d.x configure -state disabled -fore gray60;", menu_num, line_num );
 203       printf(".menu%d.config.f.x%d.l configure -state disabled;", menu_num, line_num );
 204       printf("}\n");
 205       break;
 206     case tok_bool:
 207 #ifdef BOOL_IS_BUTTON
 208       /*
 209        * If a bool is just a button, then use this definition.
 210        */
 211       printf("} then { .menu%d.config.f.x%d configure -state normal } else { .menu%d.config.f.x%d configure -state disabled }\n",
 212              menu_num, line_num,
 213              menu_num, line_num );
 214 #else
 215       /*
 216        * If a bool is a radiobutton, then use this instead.
 217        */
 218       printf("} then { ");
 219       printf(".menu%d.config.f.x%d.y configure -state normal;",menu_num, line_num);
 220       printf(".menu%d.config.f.x%d.n configure -state normal;",menu_num, line_num);
 221       printf(".menu%d.config.f.x%d.l configure -state normal;",menu_num, line_num);
 222       printf("set %s [expr $%s&15];", item->optionname, item->optionname);
 223       printf("} else { ");
 224       printf(".menu%d.config.f.x%d.y configure -state disabled;",menu_num, line_num);
 225       printf(".menu%d.config.f.x%d.n configure -state disabled;",menu_num, line_num);
 226       printf(".menu%d.config.f.x%d.l configure -state disabled;",menu_num, line_num);
 227       printf("set %s [expr $%s|16];", item->optionname, item->optionname);
 228       printf("}\n");
 229 #endif
 230       break;
 231     case tok_tristate:
 232     case tok_dep_tristate:
 233       printf("} then { ");
 234       if( item->tok == tok_dep_tristate )
 235         {
 236           printf("global %s;", item->depend.str);
 237           printf("if { $%s == 2 } then {", item->depend.str);
 238           printf(".menu%d.config.f.x%d.y configure -state disabled;",menu_num, line_num);
 239           printf("} else {");
 240           printf(".menu%d.config.f.x%d.y configure -state normal;",menu_num, line_num);
 241           printf("}; ");
 242         }
 243       else
 244         {
 245           printf(".menu%d.config.f.x%d.y configure -state normal;",menu_num, line_num);
 246         }
 247       
 248       printf(".menu%d.config.f.x%d.n configure -state normal;",menu_num, line_num);
 249       printf(".menu%d.config.f.x%d.m configure -state normal;",menu_num, line_num);
 250       printf(".menu%d.config.f.x%d.l configure -state normal;",menu_num, line_num);
 251       /*
 252        * Or in a bit to the variable - this causes all of the radiobuttons
 253        * to be deselected (i.e. not be red).
 254        */
 255       printf("set %s [expr $%s&15];", item->optionname, item->optionname);
 256       printf("} else { ");
 257       printf(".menu%d.config.f.x%d.y configure -state disabled;",menu_num, line_num);
 258       printf(".menu%d.config.f.x%d.n configure -state disabled;",menu_num, line_num);
 259       printf(".menu%d.config.f.x%d.m configure -state disabled;",menu_num, line_num);
 260       printf(".menu%d.config.f.x%d.l configure -state disabled;",menu_num, line_num);
 261       /*
 262        * Clear the disable bit - this causes the correct radiobutton
 263        * to appear selected (i.e. turn red).
 264        */
 265       printf("set %s [expr $%s|16];", item->optionname, item->optionname);
 266       printf("}\n");
 267       break;
 268     case tok_choose:
 269     case tok_choice:
 270       fprintf(stderr,"Fixme\n");
 271       exit(0);
 272     default:
 273       break;
 274     }
 275 }
 276 
 277 /*
 278  * Similar to generate_if, except we come here when generating an
 279  * output file.  Thus instead of enabling/disabling a widget, we
 280  * need to decide whether to write out a given configuration variable
 281  * to the output file.
 282  */
 283 generate_if_for_outfile(struct kconfig * item,
     /* [previous][next][first][last][top][bottom][index][help] */
 284             struct condition * cond)
 285 {
 286   struct condition * ocond;
 287 
 288   /*
 289    * First write any global declarations we need for this conditional.
 290    */
 291   ocond = cond;
 292   for(; cond != NULL; cond = cond->next )
 293     {
 294       switch(cond->op){
 295       case op_variable:
 296         printf("\tglobal %s\n", cond->variable.str);
 297         break;
 298       case op_kvariable:
 299         if(cond->variable.cfg->flags & GLOBAL_WRITTEN) break;
 300         cond->variable.cfg->flags |= GLOBAL_WRITTEN;
 301         printf("\tglobal %s\n", cond->variable.cfg->optionname);
 302         break;
 303       default:
 304         break;
 305       }
 306     }
 307 
 308   /*
 309    * Now generate the body of the conditional.
 310    */
 311   printf("\tif {");
 312   cond = ocond;
 313   while(cond != NULL )
 314     {
 315       switch(cond->op){
 316       case op_bang:
 317         printf(" ! ");
 318         break;
 319       case op_eq:
 320         printf(" == ");
 321         break;
 322       case op_neq:
 323         printf(" != ");
 324         break;
 325       case op_and:
 326       case op_and1:
 327         printf(" && ");
 328         break;
 329       case op_or:
 330         printf(" || ");
 331         break;
 332       case op_lparen:
 333         printf("(");
 334         break;
 335       case op_rparen:
 336         printf(")");
 337         break;
 338       case op_variable:
 339         printf("$%s", cond->variable.str);
 340         break;
 341       case op_shellcmd:
 342         printf("[exec %s]", cond->variable.str);
 343         break;
 344       case op_kvariable:
 345         printf("$%s", cond->variable.cfg->optionname);
 346         break;
 347       case op_constant:
 348         if( strcmp(cond->variable.str, "y") == 0 )
 349           printf("1");
 350         else if( strcmp(cond->variable.str, "n") == 0 )
 351           printf("0");
 352         else if( strcmp(cond->variable.str, "m") == 0 )
 353           printf("2");
 354         else
 355           printf("\"%s\"", cond->variable);
 356         break;
 357       }
 358       cond = cond->next;
 359     }
 360 
 361   /*
 362    * Now we generate what we do depending upon the value of the
 363    * conditional.  Depending upon what the token type is, there are
 364    * different things we must do write the value the given widget -
 365    * this code needs to be closely coordinated with the widget
 366    * creation procedures in header.tk.  
 367    */
 368   switch(item->tok)
 369     {
 370     case tok_define:
 371       printf("} then {write_variable $cfg $autocfg %s %s $notmod }\n", item->optionname, item->value);
 372       break;
 373     case tok_comment:
 374       printf("} then {write_comment $cfg $autocfg \"%s\"}\n", item->label);
 375       break;
 376     case tok_dep_tristate:
 377       printf("} then { write_variable $cfg $autocfg %s $%s $%s } \n", 
 378              item->optionname, item->optionname, item->depend.str);
 379       break;
 380     case tok_tristate:
 381     case tok_bool:
 382     case tok_int:
 383       printf("} then { write_variable $cfg $autocfg %s $%s $notmod }\n", 
 384              item->optionname, item->optionname);
 385       break;
 386     case tok_choose:
 387     case tok_choice:
 388       fprintf(stderr,"Fixme\n");
 389       exit(0);
 390     default:
 391       break;
 392     }
 393 }
 394 
 395 /*
 396  * Generates a fragment of wish script that closes out a submenu procedure.
 397  */
 398 static end_proc(int menu_num, int first, int last)
     /* [previous][next][first][last][top][bottom][index][help] */
 399 {
 400   struct kconfig * cfg;
 401 
 402   printf("\n\n\n");
 403   printf("\tset oldFocus [focus]\n");
 404   printf("\tframe $w.f\n");
 405 
 406   /*
 407    * Attach the "Prev", "Next" and "OK" buttons at the end of the window.
 408    */
 409   printf("\tbutton $w.f.prev -text \"Prev\" -activebackground green \\\n");
 410       printf("\t\t-width 15 -command \" destroy $w; focus $oldFocus; menu%d .menu%d \\\"$title\\\"\"\n", menu_num-1, menu_num-1);
 411 #ifdef PREVLAST_LIMITED_RANGE
 412   if(first == menu_num ) printf("\t$w.f.prev configure -state disabled\n");
 413 #else
 414   if( 1 == menu_num ) printf("\t$w.f.prev configure -state disabled\n");
 415 #endif
 416 
 417   printf("\tbutton $w.f.next -text \"Next\" -activebackground green \\\n");
 418   printf("\t\t-width 15 -command \" destroy $w; focus $oldFocus;  menu%d .menu%d \\\"$title\\\"\"\n", menu_num+1, menu_num+1);
 419 #ifdef PREVLAST_LIMITED_RANGE
 420   if(last == menu_num ) printf("\t$w.f.next configure -state disabled\n");
 421 #else
 422   if(last == tot_menu_num ) printf("\t$w.f.next configure -state disabled\n");
 423 #endif
 424 
 425   printf("\tbutton $w.f.back -text \"Main Menu\" -activebackground green \\\n");
 426   printf("\t\t-width 15 -command \"destroy $w; focus $oldFocus; update_mainmenu $w\"\n");
 427 
 428   printf("\tpack $w.f.back $w.f.next $w.f.prev -side left -expand on\n");
 429   printf("\tpack $w.f -pady 10 -side bottom -anchor w -fill x\n");
 430   printf("\tfocus $w\n");
 431   printf("\tupdate_menu%d $w.config.f\n", menu_num);
 432   printf("\tglobal winx; global winy\n");
 433   printf("\tset winx [expr [winfo x .]+30]; set winy [expr [winfo y .]+30]\n");
 434   printf("\twm geometry $w +$winx+$winy\n");
 435   printf("\twm resizable $w no yes\n\n");
 436   
 437   /*
 438    * Now that the whole window is in place, we need to wait for an "update"
 439    * so we can tell the canvas what its virtual size should be.
 440    *
 441    * Unfortunately, this causes some ugly screen-flashing because the whole
 442    * window is drawn, and then it is immediately resized.  It seems
 443    * unavoidable, though, since "frame" objects won't tell us their size
 444    * until after an update, and "canvas" objects can't automatically pack
 445    * around frames.  Sigh.
 446    */
 447   printf("\tupdate idletasks\n");
 448   printf("\t$w.config.canvas create window 0 0 -anchor nw -window $w.config.f\n\n");
 449   printf("\t$w.config.canvas configure \\\n"
 450          "\t\t-width [expr [winfo reqwidth $w.config.f] + 1]\\\n"
 451          "\t\t-scrollregion \"-1 -1 [expr [winfo reqwidth $w.config.f] + 1] \\\n"
 452          "\t\t\t [expr [winfo reqheight $w.config.f] + 1]\"\n\n");
 453          
 454   /*
 455    * If the whole canvas will fit in 3/4 of the screen height, do it;
 456    * otherwise, resize to around 1/2 the screen and let us scroll.
 457    */
 458   printf("\tset winy [expr [winfo reqh $w] - [winfo reqh $w.config.canvas]]\n");
 459   printf("\tset scry [expr [winfo screenh $w] / 2]\n");
 460   printf("\tset maxy [expr [winfo screenh $w] * 3 / 4]\n");
 461   printf("\tset canvtotal [expr [winfo reqh $w.config.f] + 2]\n");
 462   printf("\tif [expr $winy + $canvtotal < $maxy] {\n"
 463          "\t\t$w.config.canvas configure -height $canvtotal\n"
 464          "\t} else {\n"
 465          "\t\t$w.config.canvas configure -height [expr $scry - $winy]\n"
 466          "\t}\n");
 467   
 468   printf("}\n\n\n");
 469 
 470   /*
 471    * Now we generate the companion procedure for the menu we just
 472    * generated.  This procedure contains all of the code to
 473    * disable/enable widgets based upon the settings of the other
 474    * widgets, and will be called first when the window is mapped,
 475    * and each time one of the buttons in the window are clicked.
 476    */
 477   printf("proc update_menu%d {w}  {\n", menu_num);
 478 
 479   printf("\tupdate_define\n");
 480   clear_globalflags(config);
 481   for(cfg = config;cfg != NULL; cfg = cfg->next)
 482     {
 483       /*
 484        * Skip items not for this menu, or ones having no conditions.
 485        */
 486       if (cfg->menu_number != menu_num ) continue;
 487       if (cfg->tok != tok_define) continue;
 488       /*
 489        * Clear all of the booleans that are defined in this menu.
 490        */
 491       if(   (cfg->flags & GLOBAL_WRITTEN) == 0
 492          && (cfg->optionname != NULL) )
 493         {
 494           printf("\tglobal %s\n", cfg->optionname);
 495           cfg->flags |= GLOBAL_WRITTEN;
 496           printf("\tset %s 0\n", cfg->optionname);
 497         }
 498 
 499     }
 500   for(cfg = config;cfg != NULL; cfg = cfg->next)
 501     {
 502       /*
 503        * Skip items not for this menu, or ones having no conditions.
 504        */
 505       if (cfg->menu_number != menu_num ) continue;
 506       if (cfg->tok == tok_menuoption) continue;
 507       if (cfg->cond != NULL ) 
 508         generate_if(cfg, cfg->cond, menu_num, cfg->menu_line);
 509       else
 510         {
 511           /*
 512            * If this token has no conditionals, check to see whether
 513            * it is a tristate - if so, then generate the conditional
 514            * to enable/disable the "y" button based upon the setting
 515            * of the option it depends upon.
 516            */
 517           if(cfg->tok == tok_dep_tristate)
 518             {
 519               printf("\tglobal %s;", cfg->depend.str);
 520               printf("\tif {$%s == 2 } then { .menu%d.config.f.x%d.y configure -state disabled } else { .menu%d.config.f.x%d.y configure -state normal}\n",cfg->depend.str,
 521                      menu_num, cfg->menu_line,
 522                      menu_num, cfg->menu_line);
 523               
 524             }
 525         }
 526 
 527     }
 528 
 529 
 530   printf("}\n\n\n");
 531 }
 532 
 533 /*
 534  * This function goes through and counts up the number of items in
 535  * each submenu. If there are too many options, we need to split it
 536  * into submenus.  This function just calculates how many submenus,
 537  * and how many items go in each submenu.
 538  */
 539 static int find_menu_size(struct kconfig *cfg,
     /* [previous][next][first][last][top][bottom][index][help] */
 540                           int *menu_max, 
 541                           int *menu_maxlines)
 542 
 543 {
 544   struct kconfig * pnt;
 545   int tot;
 546   int div;
 547   
 548   /*
 549    * First count up the number of options in this menu.
 550    */
 551   tot = 0;
 552   for(pnt = cfg->next; pnt; pnt = pnt->next)
 553   {
 554     if( pnt->tok == tok_menuoption) break;
 555     switch (pnt->tok)
 556       {
 557       case tok_bool:
 558       case tok_tristate:
 559       case tok_dep_tristate:
 560       case tok_int:
 561       case tok_choose:
 562       case tok_sound:
 563         tot++;
 564         break;
 565       case tok_choice:
 566       default:
 567         break;
 568       }
 569   }
 570 
 571 #ifdef OLD_SPLIT_MENUS
 572   /*
 573    * Now figure out how many items go on each page.
 574    */
 575   div = 1;
 576   while(tot / div > 15) div++;
 577   *menu_max = cfg->menu_number + div - 1;
 578   *menu_maxlines = (tot + div -1) / div;
 579 #else
 580   *menu_max = cfg->menu_number;
 581   *menu_maxlines = tot;
 582 #endif
 583 }
 584 
 585 /*
 586  * This is the top level function for generating the tk script.
 587  */
 588 dump_tk_script(struct kconfig *scfg)
     /* [previous][next][first][last][top][bottom][index][help] */
 589 {
 590   int i;
 591   int menu_num =0;
 592   int menu_max =0;
 593   int menu_min =0;
 594   int menu_line = 0;
 595   int menu_maxlines = 0;
 596   struct kconfig * cfg;
 597   struct kconfig * cfg1 = NULL;
 598   char * menulabel;
 599 
 600   /*
 601    * Start by assigning menu numbers, and submenu numbers.
 602    */
 603   for(cfg = scfg;cfg != NULL; cfg = cfg->next)
 604     {
 605       switch (cfg->tok)
 606         {
 607         case tok_menuname:
 608           break;
 609         case tok_menuoption:
 610           /*
 611            * At the start of a new menu, calculate the number of items
 612            * we will put into each submenu so we know when to bump the
 613            * menu number. The submenus are really no different from a
 614            * normal menu, but the top level buttons only access the first
 615            * of the chain of menus, and the prev/next buttons are used
 616            * access the submenus.
 617            */
 618           cfg->menu_number = ++menu_num;
 619           find_menu_size(cfg, &menu_max, &menu_maxlines);
 620           cfg->submenu_start = menu_num;
 621           cfg->submenu_end = menu_max;
 622           menu_line = 0;
 623           break;
 624         case tok_bool:
 625         case tok_tristate:
 626         case tok_dep_tristate:
 627         case tok_int:
 628         case tok_choose:
 629         case tok_sound:
 630           /*
 631            * If we have overfilled the menu, then go to the next one.
 632            */
 633           if( menu_line == menu_maxlines )
 634             {
 635               menu_line = 0;
 636               menu_num++;
 637             }
 638           cfg->menu_number = menu_num;
 639           cfg->submenu_start = menu_min;
 640           cfg->submenu_end = menu_max;
 641           cfg->menu_line = menu_line++;
 642           break;
 643         case tok_define:
 644           cfg->menu_number = -1;
 645         case tok_choice:
 646         default:
 647           break;
 648         };
 649     }
 650 
 651   /*
 652    * Record this so we can set up the prev/next buttons correctly.
 653    */
 654   tot_menu_num = menu_num;
 655 
 656   /*
 657    * Now start generating the actual wish script that we will use.
 658    * We need to keep track of the menu numbers of the min/max menu
 659    * for a range of submenus so that we can correctly limit the
 660    * prev and next buttons so that they don't go over into some other
 661    * category.
 662    */
 663   for(cfg = scfg; cfg != NULL; cfg = cfg->next)
 664     {
 665       switch (cfg->tok)
 666         {
 667         case tok_menuname:
 668           printf("mainmenu_name \"%s\"\n", cfg->label);
 669           break;
 670         case tok_menuoption:
 671           /*
 672            * We are at the start of a new menu. If we had one that
 673            * we were working on before, close it out, and then generate
 674            * the script to start the new one.
 675            */
 676           if( cfg->menu_number > 1 )
 677             {
 678               end_proc(menu_num, menu_min, menu_max);
 679             }
 680           menulabel = cfg->label;
 681           start_proc(cfg->label, cfg->menu_number, TRUE);
 682           menu_num = cfg->menu_number;
 683           menu_max = cfg->submenu_end;
 684           menu_min = cfg->submenu_start;
 685           break;
 686         case tok_bool:
 687           /*
 688            * If we reached the point where we need to switch over
 689            * to the next submenu, then bump the menu number and generate
 690            * the code to close out the old menu and start the new one.
 691            */
 692           if( cfg->menu_number != menu_num )
 693             {
 694               end_proc(menu_num, menu_min, menu_max);
 695               start_proc(menulabel, cfg->menu_number, FALSE);
 696               menu_num = cfg->menu_number;
 697             }
 698           printf("\tbool $w.config.f %d %d \"%s\" %s\n",
 699                  cfg->menu_number,
 700                  cfg->menu_line,
 701                  cfg->label,
 702                  cfg->optionname);
 703           break;
 704 
 705         case tok_choice:
 706           printf("\t$w.config.f.x%d.x.menu add radiobutton -label \"%s\" -variable %s -value %d -command \"update_menu%d .menu%d.config.f\"\n",
 707                  cfg1->menu_line,
 708                  cfg->label,
 709                  cfg1->optionname,
 710                  cfg->choice_value,
 711                  cfg1->menu_number, cfg1->menu_number);
 712           break;
 713         case tok_choose:
 714           if( cfg->menu_number != menu_num )
 715             {
 716               end_proc(menu_num, menu_min, menu_max);
 717               start_proc(menulabel, cfg->menu_number, FALSE);
 718               menu_num = cfg->menu_number;
 719             }
 720 #if 0
 721           printf("\tmenubutton $w.config.f.line%d -text \"%s\" -menu $w.config.f.line%d.menu \\\n",
 722                  cfg->menu_line, cfg->label, cfg->menu_line);
 723           printf("\t    -relief raised -width 35\n");
 724           printf("\tpack $w.config.f.line%d -anchor w\n", cfg->menu_line);
 725           printf("\tmenu $w.config.f.line%d.menu\n", cfg->menu_line);
 726 #else
 727           printf("\tminimenu $w.config.f %d %d \"%s\" %s\n",
 728                 cfg->menu_number,
 729                 cfg->menu_line,
 730                 cfg->label,
 731                 cfg->optionname);
 732           printf("\tmenu $w.config.f.x%d.x.menu\n", cfg->menu_line);
 733 #endif
 734           cfg1 = cfg;
 735           break;
 736         case tok_tristate:
 737           if( cfg->menu_number != menu_num )
 738             {
 739               end_proc(menu_num, menu_min, menu_max);
 740               start_proc(menulabel, cfg->menu_number, FALSE);
 741               menu_num = cfg->menu_number;
 742             }
 743           printf("\ttristate $w.config.f %d %d \"%s\" %s\n",
 744                  cfg->menu_number,
 745                  cfg->menu_line,
 746                  cfg->label,
 747                  cfg->optionname);
 748           break;
 749         case tok_dep_tristate:
 750           if( cfg->menu_number != menu_num )
 751             {
 752               end_proc(menu_num, menu_min, menu_max);
 753               start_proc(menulabel, cfg->menu_number, FALSE);
 754               menu_num = cfg->menu_number;
 755             }
 756           printf("\tdep_tristate $w.config.f %d %d \"%s\" %s\n",
 757                  cfg->menu_number,
 758                  cfg->menu_line,
 759                  cfg->label,
 760                  cfg->optionname,
 761                  cfg->depend);
 762           break;
 763         case tok_int:
 764           if( cfg->menu_number != menu_num )
 765             {
 766               end_proc(menu_num, menu_min, menu_max);
 767               start_proc(menulabel, cfg->menu_number, FALSE);
 768               menu_num = cfg->menu_number;
 769             }
 770           printf("\tint $w.config.f %d %d \"%s\" %s\n",
 771                  cfg->menu_number,
 772                  cfg->menu_line,
 773                  cfg->label,
 774                  cfg->optionname);
 775           break;
 776         case tok_sound:
 777           if( cfg->menu_number != menu_num )
 778             {
 779               end_proc(menu_num, menu_min, menu_max);
 780               start_proc(menulabel, cfg->menu_number, FALSE);
 781               menu_num = cfg->menu_number;
 782             }
 783           printf("\tdo_sound $w.config.f %d %d\n",
 784                  cfg->menu_number,
 785                  cfg->menu_line);
 786           break;
 787         default:
 788           break;
 789         }
 790 
 791     }
 792 
 793   /*
 794    * Generate the code to close out the last menu.
 795    */
 796   end_proc(menu_num, menu_min, menu_max);
 797 
 798 #ifdef ERIC_DONT_DEF
 799   /*
 800    * Generate the code for configuring the sound driver.  Right now this
 801    * cannot be done from the X script, but we insert the menu anyways.
 802    */
 803   start_proc("Configure sound driver", ++menu_num, TRUE);
 804 #if 0
 805   printf("\tdo_make -C drivers/sound config\n");
 806   printf("\techo check_sound_config %d\n",menu_num);
 807 #endif
 808   printf("\tlabel $w.config.f.m0 -bitmap error\n");
 809   printf("\tmessage $w.config.f.m1 -width 400 -aspect 300 -text \"The sound drivers cannot as of yet be configured via the X-based interface\" -relief raised\n");
 810   printf("\tpack $w.config.f.m0 $w.config.f.m1 -side top -pady 10 -expand on\n");
 811   /*
 812    * Close out the last menu.
 813    */
 814   end_proc(menu_num, menu_num, menu_num);
 815 #endif
 816 
 817   /*
 818    * The top level menu also needs an update function.  When we exit a
 819    * submenu, we may need to disable one or more of the submenus on
 820    * the top level menu, and this procedure will ensure that things are
 821    * correct.
 822    */
 823   printf("proc update_mainmenu {w}  {\n");
 824   for(cfg = scfg; cfg != NULL; cfg = cfg->next)
 825     {
 826       switch (cfg->tok)
 827         {
 828         case tok_menuoption:
 829           if (cfg->cond != NULL ) 
 830             generate_if(cfg, cfg->cond, cfg->menu_number, cfg->menu_line);
 831           break;
 832         default:
 833           break;
 834         }
 835     }
 836 
 837   printf("}\n\n\n");
 838 
 839 #if 0
 840   /*
 841    * Generate some code to set the variables that are "defined".
 842    */
 843   for(cfg = config;cfg != NULL; cfg = cfg->next)
 844     {
 845       /*
 846        * Skip items not for this menu, or ones having no conditions.
 847        */
 848       if( cfg->tok != tok_define) continue;
 849       if (cfg->cond != NULL ) 
 850         generate_if(cfg, cfg->cond, menu_num, cfg->menu_line);
 851       else
 852         {
 853           printf("\twrite_define %s %s\n", cfg->optionname, cfg->value);
 854         }
 855 
 856     }
 857 #endif
 858 
 859   /*
 860    * Now generate code to load the default settings into the variables.
 861    * Note that the script in tail.tk will attempt to load .config,
 862    * which may override these settings, but that's OK.
 863    */
 864   for(cfg = scfg; cfg != NULL; cfg = cfg->next)
 865     {
 866       switch (cfg->tok)
 867         {
 868         case tok_int:
 869         case tok_bool:
 870         case tok_tristate:
 871         case tok_dep_tristate:
 872         case tok_choice:
 873           printf("set %s 0\n", cfg->optionname);
 874           break;
 875         case tok_choose:
 876           printf("set %s %d\n", cfg->optionname, cfg->choice_value);
 877         default:
 878           break;
 879         }
 880     }
 881 
 882   /*
 883    * Next generate a function that can be called from the main menu that will
 884    * write all of the variables out.  This also serves double duty - we can
 885    * save configuration to a file using this.
 886    */
 887   printf("proc writeconfig {file1 file2} {\n");
 888   printf("\tset cfg [open $file1 w]\n");
 889   printf("\tset autocfg [open $file2 w]\n");
 890   printf("\tset notmod 1\n");
 891   printf("\tset notset 0\n");
 892   clear_globalflags(config);
 893   printf("\tputs $cfg \"#\"\n");
 894   printf("\tputs $cfg \"# Automatically generated make config: don't edit\"\n");
 895   printf("\tputs $cfg \"#\"\n");
 896 
 897   printf("\tputs $autocfg \"/*\"\n");
 898   printf("\tputs $autocfg \" * Automatically generated C config: don't edit\"\n");
 899   printf("\tputs $autocfg \" */\"\n");
 900   for(cfg = scfg; cfg != NULL; cfg = cfg->next)
 901     {
 902       switch (cfg->tok)
 903         {
 904         case tok_int:
 905         case tok_bool:
 906         case tok_tristate:
 907         case tok_dep_tristate:
 908         case tok_define:
 909         case tok_choose:
 910           if(cfg->flags & GLOBAL_WRITTEN) break;
 911           cfg->flags |= GLOBAL_WRITTEN;
 912           printf("\tglobal %s\n", cfg->optionname);
 913 
 914         case tok_comment:
 915           if (cfg->cond != NULL ) 
 916             generate_if_for_outfile(cfg, cfg->cond);
 917           else
 918             {
 919               if(cfg->tok == tok_dep_tristate)
 920                 {
 921                   printf("\tif {$%s == 2 } then {\n"
 922                          "\t\twrite_variable $cfg $autocfg %s $notset $notmod\n"
 923                          "\t} else {\n"
 924                          "\t\twrite_variable $cfg $autocfg %s $%s %s\n"
 925                          "\t}\n",
 926                          cfg->depend.str,
 927                          cfg->optionname,
 928                          cfg->optionname,
 929                          cfg->optionname,
 930                          cfg->depend.str);
 931                 }
 932               else if(cfg->tok == tok_comment)
 933                 {
 934                   printf("\twrite_comment $cfg $autocfg \"%s\"\n", cfg->label);
 935                 }
 936 #if 0
 937               else if(cfg->tok == tok_define)
 938                 {
 939                   printf("\twrite_define %s %s\n", cfg->optionname,
 940                          cfg->value);
 941                 }
 942 #endif
 943               else if (cfg->tok == tok_choose )
 944                 {
 945                   for(cfg1 = cfg->next; 
 946                       cfg1 != NULL && cfg1->tok == tok_choice;
 947                       cfg1 = cfg1->next)
 948                     {
 949                       printf("\tif { $%s == %d } then { write_variable $cfg $autocfg %s 1 $notmod }\n",
 950                              cfg->optionname,
 951                              cfg1->choice_value,
 952                              cfg1->optionname);
 953                     }
 954                 }
 955               else
 956                 {
 957                   printf("\twrite_variable $cfg $autocfg %s $%s $notmod\n",
 958                          cfg->optionname,
 959                          cfg->optionname);
 960                          
 961                 }
 962             }
 963           break;
 964         default:
 965           break;
 966         }
 967     }
 968   printf("\tclose $cfg\n");
 969   printf("\tclose $autocfg\n");
 970   printf("}\n\n\n");
 971 
 972   /*
 973    * Finally write a simple function that updates the master choice
 974    * variable depending upon what values were loaded from a .config
 975    * file.  
 976    */
 977   printf("proc clear_choices { } {\n");
 978   for(cfg = scfg; cfg != NULL; cfg = cfg->next)
 979     {
 980       if( cfg->tok != tok_choose ) continue;
 981       for(cfg1 = cfg->next; 
 982           cfg1 != NULL && cfg1->tok == tok_choice;
 983           cfg1 = cfg1->next)
 984         {
 985           printf("\tglobal %s; set %s 0\n",  cfg1->optionname, cfg1->optionname);
 986         }
 987     }
 988   printf("}\n\n\n");
 989 
 990   printf("proc update_choices { } {\n");
 991   for(cfg = scfg; cfg != NULL; cfg = cfg->next)
 992     {
 993       if( cfg->tok != tok_choose ) continue;
 994       printf("\tglobal %s\n", cfg->optionname);
 995       for(cfg1 = cfg->next; 
 996           cfg1 != NULL && cfg1->tok == tok_choice;
 997           cfg1 = cfg1->next)
 998         {
 999           printf("\tglobal %s\n", cfg1->optionname);
1000           printf("\tif { $%s == 1 } then { set %s %d }\n",
1001                  cfg1->optionname,
1002                  cfg->optionname,
1003                  cfg1->choice_value);
1004         }
1005     }
1006   printf("}\n\n\n");
1007 
1008   printf("proc update_define { } {\n");
1009   clear_globalflags(config);
1010   for(cfg = scfg; cfg != NULL; cfg = cfg->next)
1011     {
1012       if( cfg->tok != tok_define ) continue;
1013       printf("\tglobal %s; set %s 0\n",  cfg->optionname,  cfg->optionname);
1014       cfg->flags |= GLOBAL_WRITTEN;
1015     }
1016   for(cfg = scfg; cfg != NULL; cfg = cfg->next)
1017     {
1018       if( cfg->tok != tok_define ) continue;
1019       if (cfg->cond != NULL ) 
1020         generate_if(cfg, cfg->cond, -1, 0);
1021       else
1022         {
1023           printf("\tset %s %s\n",
1024                  cfg->optionname, cfg->value);
1025         }
1026     }
1027   printf("}\n\n\n");
1028   /*
1029    * That's it.  We are done.  The output of this file will have header.tk
1030    * prepended and tail.tk appended to create an executable wish script.
1031    */
1032 }

/* [previous][next][first][last][top][bottom][index][help] */