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   /*
 436    *    We have a cunning plan....
 437    */
 438   if(access("/usr/lib/tk4.0",0)==0)
 439           printf("\twm resizable $w no yes\n\n");
 440   
 441   /*
 442    * Now that the whole window is in place, we need to wait for an "update"
 443    * so we can tell the canvas what its virtual size should be.
 444    *
 445    * Unfortunately, this causes some ugly screen-flashing because the whole
 446    * window is drawn, and then it is immediately resized.  It seems
 447    * unavoidable, though, since "frame" objects won't tell us their size
 448    * until after an update, and "canvas" objects can't automatically pack
 449    * around frames.  Sigh.
 450    */
 451   printf("\tupdate idletasks\n");
 452   printf("\t$w.config.canvas create window 0 0 -anchor nw -window $w.config.f\n\n");
 453   printf("\t$w.config.canvas configure \\\n"
 454          "\t\t-width [expr [winfo reqwidth $w.config.f] + 1]\\\n"
 455          "\t\t-scrollregion \"-1 -1 [expr [winfo reqwidth $w.config.f] + 1] \\\n"
 456          "\t\t\t [expr [winfo reqheight $w.config.f] + 1]\"\n\n");
 457          
 458   /*
 459    * If the whole canvas will fit in 3/4 of the screen height, do it;
 460    * otherwise, resize to around 1/2 the screen and let us scroll.
 461    */
 462   printf("\tset winy [expr [winfo reqh $w] - [winfo reqh $w.config.canvas]]\n");
 463   printf("\tset scry [expr [winfo screenh $w] / 2]\n");
 464   printf("\tset maxy [expr [winfo screenh $w] * 3 / 4]\n");
 465   printf("\tset canvtotal [expr [winfo reqh $w.config.f] + 2]\n");
 466   printf("\tif [expr $winy + $canvtotal < $maxy] {\n"
 467          "\t\t$w.config.canvas configure -height $canvtotal\n"
 468          "\t} else {\n"
 469          "\t\t$w.config.canvas configure -height [expr $scry - $winy]\n"
 470          "\t}\n");
 471   
 472   printf("}\n\n\n");
 473 
 474   /*
 475    * Now we generate the companion procedure for the menu we just
 476    * generated.  This procedure contains all of the code to
 477    * disable/enable widgets based upon the settings of the other
 478    * widgets, and will be called first when the window is mapped,
 479    * and each time one of the buttons in the window are clicked.
 480    */
 481   printf("proc update_menu%d {w}  {\n", menu_num);
 482 
 483   printf("\tupdate_define\n");
 484   clear_globalflags(config);
 485   for(cfg = config;cfg != NULL; cfg = cfg->next)
 486     {
 487       /*
 488        * Skip items not for this menu, or ones having no conditions.
 489        */
 490       if (cfg->menu_number != menu_num ) continue;
 491       if (cfg->tok != tok_define) continue;
 492       /*
 493        * Clear all of the booleans that are defined in this menu.
 494        */
 495       if(   (cfg->flags & GLOBAL_WRITTEN) == 0
 496          && (cfg->optionname != NULL) )
 497         {
 498           printf("\tglobal %s\n", cfg->optionname);
 499           cfg->flags |= GLOBAL_WRITTEN;
 500           printf("\tset %s 0\n", cfg->optionname);
 501         }
 502 
 503     }
 504   for(cfg = config;cfg != NULL; cfg = cfg->next)
 505     {
 506       /*
 507        * Skip items not for this menu, or ones having no conditions.
 508        */
 509       if (cfg->menu_number != menu_num ) continue;
 510       if (cfg->tok == tok_menuoption) continue;
 511       if (cfg->cond != NULL ) 
 512         generate_if(cfg, cfg->cond, menu_num, cfg->menu_line);
 513       else
 514         {
 515           /*
 516            * If this token has no conditionals, check to see whether
 517            * it is a tristate - if so, then generate the conditional
 518            * to enable/disable the "y" button based upon the setting
 519            * of the option it depends upon.
 520            */
 521           if(cfg->tok == tok_dep_tristate)
 522             {
 523               printf("\tglobal %s;", cfg->depend.str);
 524               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,
 525                      menu_num, cfg->menu_line,
 526                      menu_num, cfg->menu_line);
 527               
 528             }
 529         }
 530 
 531     }
 532 
 533 
 534   printf("}\n\n\n");
 535 }
 536 
 537 /*
 538  * This function goes through and counts up the number of items in
 539  * each submenu. If there are too many options, we need to split it
 540  * into submenus.  This function just calculates how many submenus,
 541  * and how many items go in each submenu.
 542  */
 543 static int find_menu_size(struct kconfig *cfg,
     /* [previous][next][first][last][top][bottom][index][help] */
 544                           int *menu_max, 
 545                           int *menu_maxlines)
 546 
 547 {
 548   struct kconfig * pnt;
 549   int tot;
 550   int div;
 551   
 552   /*
 553    * First count up the number of options in this menu.
 554    */
 555   tot = 0;
 556   for(pnt = cfg->next; pnt; pnt = pnt->next)
 557   {
 558     if( pnt->tok == tok_menuoption) break;
 559     switch (pnt->tok)
 560       {
 561       case tok_bool:
 562       case tok_tristate:
 563       case tok_dep_tristate:
 564       case tok_int:
 565       case tok_choose:
 566       case tok_sound:
 567         tot++;
 568         break;
 569       case tok_choice:
 570       default:
 571         break;
 572       }
 573   }
 574 
 575 #ifdef OLD_SPLIT_MENUS
 576   /*
 577    * Now figure out how many items go on each page.
 578    */
 579   div = 1;
 580   while(tot / div > 15) div++;
 581   *menu_max = cfg->menu_number + div - 1;
 582   *menu_maxlines = (tot + div -1) / div;
 583 #else
 584   *menu_max = cfg->menu_number;
 585   *menu_maxlines = tot;
 586 #endif
 587 }
 588 
 589 /*
 590  * This is the top level function for generating the tk script.
 591  */
 592 dump_tk_script(struct kconfig *scfg)
     /* [previous][next][first][last][top][bottom][index][help] */
 593 {
 594   int i;
 595   int menu_num =0;
 596   int menu_max =0;
 597   int menu_min =0;
 598   int menu_line = 0;
 599   int menu_maxlines = 0;
 600   struct kconfig * cfg;
 601   struct kconfig * cfg1 = NULL;
 602   char * menulabel;
 603 
 604   /*
 605    * Start by assigning menu numbers, and submenu numbers.
 606    */
 607   for(cfg = scfg;cfg != NULL; cfg = cfg->next)
 608     {
 609       switch (cfg->tok)
 610         {
 611         case tok_menuname:
 612           break;
 613         case tok_menuoption:
 614           /*
 615            * At the start of a new menu, calculate the number of items
 616            * we will put into each submenu so we know when to bump the
 617            * menu number. The submenus are really no different from a
 618            * normal menu, but the top level buttons only access the first
 619            * of the chain of menus, and the prev/next buttons are used
 620            * access the submenus.
 621            */
 622           cfg->menu_number = ++menu_num;
 623           find_menu_size(cfg, &menu_max, &menu_maxlines);
 624           cfg->submenu_start = menu_num;
 625           cfg->submenu_end = menu_max;
 626           menu_line = 0;
 627           break;
 628         case tok_bool:
 629         case tok_tristate:
 630         case tok_dep_tristate:
 631         case tok_int:
 632         case tok_choose:
 633         case tok_sound:
 634           /*
 635            * If we have overfilled the menu, then go to the next one.
 636            */
 637           if( menu_line == menu_maxlines )
 638             {
 639               menu_line = 0;
 640               menu_num++;
 641             }
 642           cfg->menu_number = menu_num;
 643           cfg->submenu_start = menu_min;
 644           cfg->submenu_end = menu_max;
 645           cfg->menu_line = menu_line++;
 646           break;
 647         case tok_define:
 648           cfg->menu_number = -1;
 649         case tok_choice:
 650         default:
 651           break;
 652         };
 653     }
 654 
 655   /*
 656    * Record this so we can set up the prev/next buttons correctly.
 657    */
 658   tot_menu_num = menu_num;
 659 
 660   /*
 661    * Now start generating the actual wish script that we will use.
 662    * We need to keep track of the menu numbers of the min/max menu
 663    * for a range of submenus so that we can correctly limit the
 664    * prev and next buttons so that they don't go over into some other
 665    * category.
 666    */
 667   for(cfg = scfg; cfg != NULL; cfg = cfg->next)
 668     {
 669       switch (cfg->tok)
 670         {
 671         case tok_menuname:
 672           printf("mainmenu_name \"%s\"\n", cfg->label);
 673           break;
 674         case tok_menuoption:
 675           /*
 676            * We are at the start of a new menu. If we had one that
 677            * we were working on before, close it out, and then generate
 678            * the script to start the new one.
 679            */
 680           if( cfg->menu_number > 1 )
 681             {
 682               end_proc(menu_num, menu_min, menu_max);
 683             }
 684           menulabel = cfg->label;
 685           start_proc(cfg->label, cfg->menu_number, TRUE);
 686           menu_num = cfg->menu_number;
 687           menu_max = cfg->submenu_end;
 688           menu_min = cfg->submenu_start;
 689           break;
 690         case tok_bool:
 691           /*
 692            * If we reached the point where we need to switch over
 693            * to the next submenu, then bump the menu number and generate
 694            * the code to close out the old menu and start the new one.
 695            */
 696           if( cfg->menu_number != menu_num )
 697             {
 698               end_proc(menu_num, menu_min, menu_max);
 699               start_proc(menulabel, cfg->menu_number, FALSE);
 700               menu_num = cfg->menu_number;
 701             }
 702           printf("\tbool $w.config.f %d %d \"%s\" %s\n",
 703                  cfg->menu_number,
 704                  cfg->menu_line,
 705                  cfg->label,
 706                  cfg->optionname);
 707           break;
 708 
 709         case tok_choice:
 710           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",
 711                  cfg1->menu_line,
 712                  cfg->label,
 713                  cfg1->optionname,
 714                  cfg->choice_value,
 715                  cfg1->menu_number, cfg1->menu_number);
 716           break;
 717         case tok_choose:
 718           if( cfg->menu_number != menu_num )
 719             {
 720               end_proc(menu_num, menu_min, menu_max);
 721               start_proc(menulabel, cfg->menu_number, FALSE);
 722               menu_num = cfg->menu_number;
 723             }
 724 #if 0
 725           printf("\tmenubutton $w.config.f.line%d -text \"%s\" -menu $w.config.f.line%d.menu \\\n",
 726                  cfg->menu_line, cfg->label, cfg->menu_line);
 727           printf("\t    -relief raised -width 35\n");
 728           printf("\tpack $w.config.f.line%d -anchor w\n", cfg->menu_line);
 729           printf("\tmenu $w.config.f.line%d.menu\n", cfg->menu_line);
 730 #else
 731           printf("\tminimenu $w.config.f %d %d \"%s\" %s\n",
 732                 cfg->menu_number,
 733                 cfg->menu_line,
 734                 cfg->label,
 735                 cfg->optionname);
 736           printf("\tmenu $w.config.f.x%d.x.menu\n", cfg->menu_line);
 737 #endif
 738           cfg1 = cfg;
 739           break;
 740         case tok_tristate:
 741           if( cfg->menu_number != menu_num )
 742             {
 743               end_proc(menu_num, menu_min, menu_max);
 744               start_proc(menulabel, cfg->menu_number, FALSE);
 745               menu_num = cfg->menu_number;
 746             }
 747           printf("\ttristate $w.config.f %d %d \"%s\" %s\n",
 748                  cfg->menu_number,
 749                  cfg->menu_line,
 750                  cfg->label,
 751                  cfg->optionname);
 752           break;
 753         case tok_dep_tristate:
 754           if( cfg->menu_number != menu_num )
 755             {
 756               end_proc(menu_num, menu_min, menu_max);
 757               start_proc(menulabel, cfg->menu_number, FALSE);
 758               menu_num = cfg->menu_number;
 759             }
 760           printf("\tdep_tristate $w.config.f %d %d \"%s\" %s\n",
 761                  cfg->menu_number,
 762                  cfg->menu_line,
 763                  cfg->label,
 764                  cfg->optionname,
 765                  cfg->depend);
 766           break;
 767         case tok_int:
 768           if( cfg->menu_number != menu_num )
 769             {
 770               end_proc(menu_num, menu_min, menu_max);
 771               start_proc(menulabel, cfg->menu_number, FALSE);
 772               menu_num = cfg->menu_number;
 773             }
 774           printf("\tint $w.config.f %d %d \"%s\" %s\n",
 775                  cfg->menu_number,
 776                  cfg->menu_line,
 777                  cfg->label,
 778                  cfg->optionname);
 779           break;
 780         case tok_sound:
 781           if( cfg->menu_number != menu_num )
 782             {
 783               end_proc(menu_num, menu_min, menu_max);
 784               start_proc(menulabel, cfg->menu_number, FALSE);
 785               menu_num = cfg->menu_number;
 786             }
 787           printf("\tdo_sound $w.config.f %d %d\n",
 788                  cfg->menu_number,
 789                  cfg->menu_line);
 790           break;
 791         default:
 792           break;
 793         }
 794 
 795     }
 796 
 797   /*
 798    * Generate the code to close out the last menu.
 799    */
 800   end_proc(menu_num, menu_min, menu_max);
 801 
 802 #ifdef ERIC_DONT_DEF
 803   /*
 804    * Generate the code for configuring the sound driver.  Right now this
 805    * cannot be done from the X script, but we insert the menu anyways.
 806    */
 807   start_proc("Configure sound driver", ++menu_num, TRUE);
 808 #if 0
 809   printf("\tdo_make -C drivers/sound config\n");
 810   printf("\techo check_sound_config %d\n",menu_num);
 811 #endif
 812   printf("\tlabel $w.config.f.m0 -bitmap error\n");
 813   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");
 814   printf("\tpack $w.config.f.m0 $w.config.f.m1 -side top -pady 10 -expand on\n");
 815   /*
 816    * Close out the last menu.
 817    */
 818   end_proc(menu_num, menu_num, menu_num);
 819 #endif
 820 
 821   /*
 822    * The top level menu also needs an update function.  When we exit a
 823    * submenu, we may need to disable one or more of the submenus on
 824    * the top level menu, and this procedure will ensure that things are
 825    * correct.
 826    */
 827   printf("proc update_mainmenu {w}  {\n");
 828   for(cfg = scfg; cfg != NULL; cfg = cfg->next)
 829     {
 830       switch (cfg->tok)
 831         {
 832         case tok_menuoption:
 833           if (cfg->cond != NULL ) 
 834             generate_if(cfg, cfg->cond, cfg->menu_number, cfg->menu_line);
 835           break;
 836         default:
 837           break;
 838         }
 839     }
 840 
 841   printf("}\n\n\n");
 842 
 843 #if 0
 844   /*
 845    * Generate some code to set the variables that are "defined".
 846    */
 847   for(cfg = config;cfg != NULL; cfg = cfg->next)
 848     {
 849       /*
 850        * Skip items not for this menu, or ones having no conditions.
 851        */
 852       if( cfg->tok != tok_define) continue;
 853       if (cfg->cond != NULL ) 
 854         generate_if(cfg, cfg->cond, menu_num, cfg->menu_line);
 855       else
 856         {
 857           printf("\twrite_define %s %s\n", cfg->optionname, cfg->value);
 858         }
 859 
 860     }
 861 #endif
 862 
 863   /*
 864    * Now generate code to load the default settings into the variables.
 865    * Note that the script in tail.tk will attempt to load .config,
 866    * which may override these settings, but that's OK.
 867    */
 868   for(cfg = scfg; cfg != NULL; cfg = cfg->next)
 869     {
 870       switch (cfg->tok)
 871         {
 872         case tok_int:
 873         case tok_bool:
 874         case tok_tristate:
 875         case tok_dep_tristate:
 876         case tok_choice:
 877           printf("set %s 0\n", cfg->optionname);
 878           break;
 879         case tok_choose:
 880           printf("set %s %d\n", cfg->optionname, cfg->choice_value);
 881         default:
 882           break;
 883         }
 884     }
 885 
 886   /*
 887    * Next generate a function that can be called from the main menu that will
 888    * write all of the variables out.  This also serves double duty - we can
 889    * save configuration to a file using this.
 890    */
 891   printf("proc writeconfig {file1 file2} {\n");
 892   printf("\tset cfg [open $file1 w]\n");
 893   printf("\tset autocfg [open $file2 w]\n");
 894   printf("\tset notmod 1\n");
 895   printf("\tset notset 0\n");
 896   clear_globalflags(config);
 897   printf("\tputs $cfg \"#\"\n");
 898   printf("\tputs $cfg \"# Automatically generated make config: don't edit\"\n");
 899   printf("\tputs $cfg \"#\"\n");
 900 
 901   printf("\tputs $autocfg \"/*\"\n");
 902   printf("\tputs $autocfg \" * Automatically generated C config: don't edit\"\n");
 903   printf("\tputs $autocfg \" */\"\n");
 904   for(cfg = scfg; cfg != NULL; cfg = cfg->next)
 905     {
 906       switch (cfg->tok)
 907         {
 908         case tok_int:
 909         case tok_bool:
 910         case tok_tristate:
 911         case tok_dep_tristate:
 912         case tok_define:
 913         case tok_choose:
 914           if(cfg->flags & GLOBAL_WRITTEN) break;
 915           cfg->flags |= GLOBAL_WRITTEN;
 916           printf("\tglobal %s\n", cfg->optionname);
 917 
 918         case tok_comment:
 919           if (cfg->cond != NULL ) 
 920             generate_if_for_outfile(cfg, cfg->cond);
 921           else
 922             {
 923               if(cfg->tok == tok_dep_tristate)
 924                 {
 925                   printf("\tif {$%s == 2 } then {\n"
 926                          "\t\twrite_variable $cfg $autocfg %s $notset $notmod\n"
 927                          "\t} else {\n"
 928                          "\t\twrite_variable $cfg $autocfg %s $%s %s\n"
 929                          "\t}\n",
 930                          cfg->depend.str,
 931                          cfg->optionname,
 932                          cfg->optionname,
 933                          cfg->optionname,
 934                          cfg->depend.str);
 935                 }
 936               else if(cfg->tok == tok_comment)
 937                 {
 938                   printf("\twrite_comment $cfg $autocfg \"%s\"\n", cfg->label);
 939                 }
 940 #if 0
 941               else if(cfg->tok == tok_define)
 942                 {
 943                   printf("\twrite_define %s %s\n", cfg->optionname,
 944                          cfg->value);
 945                 }
 946 #endif
 947               else if (cfg->tok == tok_choose )
 948                 {
 949                   for(cfg1 = cfg->next; 
 950                       cfg1 != NULL && cfg1->tok == tok_choice;
 951                       cfg1 = cfg1->next)
 952                     {
 953                       printf("\tif { $%s == %d } then { write_variable $cfg $autocfg %s 1 $notmod }\n",
 954                              cfg->optionname,
 955                              cfg1->choice_value,
 956                              cfg1->optionname);
 957                     }
 958                 }
 959               else
 960                 {
 961                   printf("\twrite_variable $cfg $autocfg %s $%s $notmod\n",
 962                          cfg->optionname,
 963                          cfg->optionname);
 964                          
 965                 }
 966             }
 967           break;
 968         default:
 969           break;
 970         }
 971     }
 972   printf("\tclose $cfg\n");
 973   printf("\tclose $autocfg\n");
 974   printf("}\n\n\n");
 975 
 976   /*
 977    * Finally write a simple function that updates the master choice
 978    * variable depending upon what values were loaded from a .config
 979    * file.  
 980    */
 981   printf("proc clear_choices { } {\n");
 982   for(cfg = scfg; cfg != NULL; cfg = cfg->next)
 983     {
 984       if( cfg->tok != tok_choose ) continue;
 985       for(cfg1 = cfg->next; 
 986           cfg1 != NULL && cfg1->tok == tok_choice;
 987           cfg1 = cfg1->next)
 988         {
 989           printf("\tglobal %s; set %s 0\n",  cfg1->optionname, cfg1->optionname);
 990         }
 991     }
 992   printf("}\n\n\n");
 993 
 994   printf("proc update_choices { } {\n");
 995   for(cfg = scfg; cfg != NULL; cfg = cfg->next)
 996     {
 997       if( cfg->tok != tok_choose ) continue;
 998       printf("\tglobal %s\n", cfg->optionname);
 999       for(cfg1 = cfg->next; 
1000           cfg1 != NULL && cfg1->tok == tok_choice;
1001           cfg1 = cfg1->next)
1002         {
1003           printf("\tglobal %s\n", cfg1->optionname);
1004           printf("\tif { $%s == 1 } then { set %s %d }\n",
1005                  cfg1->optionname,
1006                  cfg->optionname,
1007                  cfg1->choice_value);
1008         }
1009     }
1010   printf("}\n\n\n");
1011 
1012   printf("proc update_define { } {\n");
1013   clear_globalflags(config);
1014   for(cfg = scfg; cfg != NULL; cfg = cfg->next)
1015     {
1016       if( cfg->tok != tok_define ) continue;
1017       printf("\tglobal %s; set %s 0\n",  cfg->optionname,  cfg->optionname);
1018       cfg->flags |= GLOBAL_WRITTEN;
1019     }
1020   for(cfg = scfg; cfg != NULL; cfg = cfg->next)
1021     {
1022       if( cfg->tok != tok_define ) continue;
1023       if (cfg->cond != NULL ) 
1024         generate_if(cfg, cfg->cond, -1, 0);
1025       else
1026         {
1027           printf("\tset %s %s\n",
1028                  cfg->optionname, cfg->value);
1029         }
1030     }
1031   printf("}\n\n\n");
1032   /*
1033    * That's it.  We are done.  The output of this file will have header.tk
1034    * prepended and tail.tk appended to create an executable wish script.
1035    */
1036 }

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