fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
  SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation)  

Fl_Menu_Type.cxx

Go to the documentation of this file.
00001 //
00002 // "$Id: Fl_Menu_Type.cxx 7903 2010-11-28 21:06:39Z matt $"
00003 //
00004 // Menu item code for the Fast Light Tool Kit (FLTK).
00005 //
00006 // Menu items are kludged by making a phony Fl_Box widget so the normal
00007 // widget panel can be used to control them.
00008 //
00009 // This file also contains code to make Fl_Menu_Button, Fl_Menu_Bar,
00010 // etc widgets.
00011 //
00012 // Copyright 1998-2010 by Bill Spitzak and others.
00013 //
00014 // This library is free software; you can redistribute it and/or
00015 // modify it under the terms of the GNU Library General Public
00016 // License as published by the Free Software Foundation; either
00017 // version 2 of the License, or (at your option) any later version.
00018 //
00019 // This library is distributed in the hope that it will be useful,
00020 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00021 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00022 // Library General Public License for more details.
00023 //
00024 // You should have received a copy of the GNU Library General Public
00025 // License along with this library; if not, write to the Free Software
00026 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00027 // USA.
00028 //
00029 // Please report all bugs and problems on the following page:
00030 //
00031 //     http://www.fltk.org/str.php
00032 //
00033 
00034 #include <FL/Fl.H>
00035 #include "Fl_Widget_Type.h"
00036 #include "alignment_panel.h"
00037 #include <FL/fl_message.H>
00038 #include <FL/Fl_Menu_.H>
00039 #include <FL/Fl_Button.H>
00040 #include <FL/Fl_Value_Input.H>
00041 #include <FL/Fl_Text_Display.H>
00042 #include "../src/flstring.h"
00043 #include <stdio.h>
00044 #include <stdlib.h>
00045 
00046 Fl_Menu_Item menu_item_type_menu[] = {
00047   {"Normal",0,0,(void*)0},
00048   {"Toggle",0,0,(void*)FL_MENU_BOX},
00049   {"Radio",0,0,(void*)FL_MENU_RADIO},
00050   {0}};
00051 
00052 extern int reading_file;
00053 extern int force_parent;
00054 extern int i18n_type;
00055 extern const char* i18n_include;
00056 extern const char* i18n_function;
00057 extern const char* i18n_file;
00058 extern const char* i18n_set;
00059 
00060 static char submenuflag;
00061 
00062 void Fl_Input_Choice_Type::build_menu() {
00063   Fl_Input_Choice* w = (Fl_Input_Choice*)o;
00064   // count how many Fl_Menu_Item structures needed:
00065   int n = 0;
00066   Fl_Type* q;
00067   for (q = next; q && q->level > level; q = q->next) {
00068     if (q->is_parent()) n++; // space for null at end of submenu
00069     n++;
00070   }
00071   if (!n) {
00072     if (menusize) delete[] (Fl_Menu_Item*)(w->menu());
00073     w->menu(0);
00074     menusize = 0;
00075   } else {
00076     n++; // space for null at end of menu
00077     if (menusize<n) {
00078       if (menusize) delete[] (Fl_Menu_Item*)(w->menu());
00079       menusize = n+10;
00080       w->menu(new Fl_Menu_Item[menusize]);
00081     }
00082     // fill them all in:
00083     Fl_Menu_Item* m = (Fl_Menu_Item*)(w->menu());
00084     int lvl = level+1;
00085     for (q = next; q && q->level > level; q = q->next) {
00086       Fl_Menu_Item_Type* i = (Fl_Menu_Item_Type*)q;
00087       if (i->o->image()) i->o->image()->label(m);
00088       else {
00089         m->label(i->o->label() ? i->o->label() : "(nolabel)");
00090         m->labeltype(i->o->labeltype());
00091       }
00092       m->shortcut(((Fl_Button*)(i->o))->shortcut());
00093       m->callback(0,(void*)i);
00094       m->flags = i->flags();
00095       m->labelfont(i->o->labelfont());
00096       m->labelsize(i->o->labelsize());
00097       m->labelcolor(i->o->labelcolor());
00098       if (q->is_parent()) {lvl++; m->flags |= FL_SUBMENU;}
00099       m++;
00100       int l1 =
00101         (q->next && q->next->is_menu_item()) ? q->next->level : level;
00102       while (lvl > l1) {m->label(0); m++; lvl--;}
00103       lvl = l1;
00104     }
00105   }
00106   o->redraw();
00107 }
00108 
00109 
00110 Fl_Type *Fl_Menu_Item_Type::make() {
00111   // Find the current menu item:
00112   Fl_Type* q = Fl_Type::current;
00113   Fl_Type* p = q;
00114   if (p) {
00115     if ( (force_parent && q->is_menu_item()) || !q->is_parent()) p = p->parent;
00116   }
00117   force_parent = 0;
00118   if (!p || !(p->is_menu_button() || (p->is_menu_item() && p->is_parent()))) {
00119     fl_message("Please select a menu to add to");
00120     return 0;
00121   }
00122   if (!o) {
00123     o = new Fl_Button(0,0,100,20); // create template widget
00124     o->labelsize(Fl_Widget_Type::default_size);
00125   }
00126 
00127   Fl_Menu_Item_Type* t = submenuflag ? new Fl_Submenu_Type() : new Fl_Menu_Item_Type();
00128   t->o = new Fl_Button(0,0,100,20);
00129   t->factory = this;
00130   t->add(p);
00131   if (!reading_file) t->label(submenuflag ? "submenu" : "item");
00132   return t;
00133 }
00134 
00135 Fl_Type *Fl_Submenu_Type::make() {
00136   submenuflag = 1;
00137   Fl_Type* t = Fl_Menu_Item_Type::make();
00138   submenuflag = 0;
00139   return t;
00140 }
00141 
00142 Fl_Menu_Item_Type Fl_Menu_Item_type;
00143 Fl_Submenu_Type Fl_Submenu_type;
00144 
00146 // Writing the C code:
00147 
00148 // test functions in Fl_Widget_Type.C:
00149 int is_name(const char *c);
00150 const char *array_name(Fl_Widget_Type *o);
00151 int isdeclare(const char *c);
00152 
00153 // Search backwards to find the parent menu button and return it's name.
00154 // Also put in i the index into the button's menu item array belonging
00155 // to this menu item.
00156 const char* Fl_Menu_Item_Type::menu_name(int& i) {
00157   i = 0;
00158   Fl_Type* t = prev;
00159   while (t && t->is_menu_item()) {
00160     // be sure to count the {0} that ends a submenu:
00161     if (t->level > t->next->level) i += (t->level - t->next->level);
00162     // detect empty submenu:
00163     else if (t->level == t->next->level && t->is_parent()) i++;
00164     t = t->prev;
00165     i++;
00166   }
00167   return unique_id(t, "menu", t->name(), t->label());
00168 }
00169 
00170 #include "Fluid_Image.h"
00171 
00172 void Fl_Menu_Item_Type::write_static() {
00173   if (callback() && is_name(callback()) && !user_defined(callback()))
00174     write_declare("extern void %s(Fl_Menu_*, %s);", callback(),
00175                   user_data_type() ? user_data_type() : "void*");
00176   for (int n=0; n < NUM_EXTRA_CODE; n++) {
00177     if (extra_code(n) && isdeclare(extra_code(n)))
00178       write_declare("%s", extra_code(n));
00179   }
00180   if (callback() && !is_name(callback())) {
00181     // see if 'o' or 'v' used, to prevent unused argument warnings:
00182     int use_o = 0;
00183     int use_v = 0;
00184     const char *d;
00185     for (d = callback(); *d;) {
00186       if (*d == 'o' && !is_id(d[1])) use_o = 1;
00187       if (*d == 'v' && !is_id(d[1])) use_v = 1;
00188       do d++; while (is_id(*d));
00189       while (*d && !is_id(*d)) d++;
00190     }
00191     const char* cn = callback_name();
00192     const char* k = class_name(1);
00193     if (k) {
00194       write_c("\nvoid %s::%s_i(Fl_Menu_*", k, cn);
00195     } else {
00196       write_c("\nstatic void %s(Fl_Menu_*", cn);
00197     }
00198     if (use_o) write_c(" o");
00199     const char* ut = user_data_type() ? user_data_type() : "void*";
00200     write_c(", %s", ut);
00201     if (use_v) write_c(" v");
00202     write_c(") {\n  %s", callback());
00203     if (*(d-1) != ';') {
00204       const char *p = strrchr(callback(), '\n');
00205       if (p) p ++;
00206       else p = callback();
00207       // Only add trailing semicolon if the last line is not a preprocessor
00208       // statement...
00209       if (*p != '#' && *p) write_c(";");
00210     }
00211     write_c("\n}\n");
00212     if (k) {
00213       write_c("void %s::%s(Fl_Menu_* o, %s v) {\n", k, cn, ut);
00214       write_c("  ((%s*)(o->", k);
00215       Fl_Type* t = parent; while (t->is_menu_item()) t = t->parent;
00216       for (t = t->parent; t && t->is_widget() && !is_class(); t = t->parent) write_c("parent()->");
00217       write_c("user_data()))->%s_i(o,v);\n}\n", cn);
00218     }
00219   }
00220   if (image) {
00221     if (image->written != write_number) {
00222       image->write_static();
00223       image->written = write_number;
00224     }
00225   }
00226   if (next && next->is_menu_item()) return;
00227   // okay, when we hit last item in the menu we have to write the
00228   // entire array out:
00229   const char* k = class_name(1);
00230   if (k) {
00231     int i; 
00232     if (i18n_type) write_c("\nunsigned char %s::%s_i18n_done = 0;", k, menu_name(i));
00233     write_c("\nFl_Menu_Item %s::%s[] = {\n", k, menu_name(i));
00234   } else {
00235     int i; 
00236     if (i18n_type) write_c("\nunsigned char %s_i18n_done = 0;", menu_name(i));
00237     write_c("\nFl_Menu_Item %s[] = {\n", menu_name(i));
00238   }
00239   Fl_Type* t = prev; while (t && t->is_menu_item()) t = t->prev;
00240   for (Fl_Type* q = t->next; q && q->is_menu_item(); q = q->next) {
00241     ((Fl_Menu_Item_Type*)q)->write_item();
00242     int thislevel = q->level; if (q->is_parent()) thislevel++;
00243     int nextlevel =
00244       (q->next && q->next->is_menu_item()) ? q->next->level : t->level+1;
00245     while (thislevel > nextlevel) {write_c(" {0,0,0,0,0,0,0,0,0},\n"); thislevel--;}
00246   }
00247   write_c(" {0,0,0,0,0,0,0,0,0}\n};\n");
00248 
00249   if (k) {
00250     // Write menu item variables...
00251     t = prev; while (t && t->is_menu_item()) t = t->prev;
00252     for (Fl_Type* q = t->next; q && q->is_menu_item(); q = q->next) {
00253       Fl_Menu_Item_Type *m = (Fl_Menu_Item_Type*)q;
00254       const char *c = array_name(m);
00255       if (c) {
00256         if (c==m->name()) {
00257           // assign a menu item address directly to a variable
00258           int i; 
00259           const char* n = ((Fl_Menu_Item_Type *)q)->menu_name(i);
00260           write_c("Fl_Menu_Item* %s::%s = %s::%s + %d;\n", k, c, k, n, i);
00261         } else {
00262           // if the name is an array, only define the array. 
00263           // The actual assignment is in write_code1()
00264           write_c("Fl_Menu_Item* %s::%s;\n", k, c);
00265         }
00266       }
00267     }
00268   }
00269 }
00270 
00271 int Fl_Menu_Item_Type::flags() {
00272   int i = o->type();
00273   if (((Fl_Button*)o)->value()) i |= FL_MENU_VALUE;
00274   if (!o->active()) i |= FL_MENU_INACTIVE;
00275   if (!o->visible()) i |= FL_MENU_INVISIBLE;
00276   if (is_parent()) {
00277     if (user_data() == NULL) i |= FL_SUBMENU;
00278     else i |= FL_SUBMENU_POINTER;
00279   }
00280   if (hotspot()) i |= FL_MENU_DIVIDER;
00281   return i;
00282 }
00283 
00284 void Fl_Menu_Item_Type::write_item() {
00285   static const char * const labeltypes[] = {
00286     "FL_NORMAL_LABEL",
00287     "FL_NO_LABEL",
00288     "FL_SHADOW_LABEL",
00289     "FL_ENGRAVED_LABEL",
00290     "FL_EMBOSSED_LABEL",
00291     "FL_MULTI_LABEL",
00292     "FL_ICON_LABEL",
00293     "FL_IMAGE_LABEL"
00294   };
00295 
00296   write_c(" {");
00297   if (image) write_c("0");
00298   else if (label()) write_cstring(label()); // we will call i18n when the widget is instantiated for the first time
00299   else write_c("\"\"");
00300   if (((Fl_Button*)o)->shortcut()) {
00301                 int s = ((Fl_Button*)o)->shortcut();
00302                 if (use_FL_COMMAND && (s & (FL_CTRL|FL_META))) {
00303                         write_c(", FL_COMMAND|0x%x, ", s & ~(FL_CTRL|FL_META));
00304                 } else {
00305                         write_c(", 0x%x, ", s);
00306                 }
00307   } else
00308     write_c(", 0, ");
00309   if (callback()) {
00310     const char* k = is_name(callback()) ? 0 : class_name(1);
00311     if (k) {
00312       write_c(" (Fl_Callback*)%s::%s,", k, callback_name());
00313     } else {
00314       write_c(" (Fl_Callback*)%s,", callback_name());
00315     }
00316   } else
00317     write_c(" 0,");
00318   if (user_data())
00319     write_c(" (void*)(%s),", user_data());
00320   else
00321     write_c(" 0,");
00322   write_c(" %d, %s, %d, %d, %d", flags(),
00323           labeltypes[o->labeltype()], o->labelfont(), o->labelsize(), o->labelcolor());
00324   write_c("},\n");
00325 }
00326 
00327 void Fl_Menu_Item_Type::write_code1() {
00328   int i; const char* mname = menu_name(i);
00329   if (!prev->is_menu_item()) {
00330     // for first menu item, declare the array
00331     if (class_name(1)) {
00332       if (i18n_type) write_h("  static unsigned char %s_i18n_done;\n", mname);
00333       write_h("  static Fl_Menu_Item %s[];\n", mname);
00334     } else {
00335       if (i18n_type) write_h("extern unsigned char %s_i18n_done;\n", mname);
00336       write_h("extern Fl_Menu_Item %s[];\n", mname);
00337     }
00338   }
00339 
00340   const char *c = array_name(this);
00341   if (c) {
00342     if (class_name(1)) {
00343       write_public(public_);
00344       write_h("  static Fl_Menu_Item *%s;\n", c);
00345     } else {
00346       if (c==name())
00347         write_h("#define %s (%s+%d)\n", c, mname, i);
00348       else
00349         write_h("extern Fl_Menu_Item *%s;\n", c);
00350     }
00351   }
00352 
00353   if (callback()) {
00354     if (!is_name(callback()) && class_name(1)) {
00355       const char* cn = callback_name();
00356       const char* ut = user_data_type() ? user_data_type() : "void*";
00357       write_public(0);
00358       write_h("  void %s_i(Fl_Menu_*, %s);\n", cn, ut);
00359       write_h("  static void %s(Fl_Menu_*, %s);\n", cn, ut);
00360     }
00361   }
00362 
00363   int init = 0;
00364   // if the name is an array variable, assign the value here
00365   if (name() && strchr(name(), '[')) {
00366     write_c("%s%s = &%s[%d];\n", indent(), name(), mname, i);
00367   }
00368   if (image) {
00369     if (!init) {
00370       init = 1;
00371       write_c("%s{ Fl_Menu_Item* o = &%s[%d];\n", indent(), mname, i);
00372     }
00373     image->write_code("o");
00374   }
00375   for (int n=0; n < NUM_EXTRA_CODE; n++)
00376     if (extra_code(n) && !isdeclare(extra_code(n))) {
00377       if (!init) {
00378         init = 1;
00379         write_c("%s{ Fl_Menu_Item* o = &%s[%d];\n", indent(), mname, i);
00380       }
00381       write_c("%s  %s\n", indent(), extra_code(n));
00382     }
00383   if (init) write_c("%s}\n",indent());
00384 }
00385 
00386 void Fl_Menu_Item_Type::write_code2() {}
00387 
00389 // This is the base class for widgets that contain a menu (ie
00390 // subclasses of Fl_Menu_.
00391 // This is a parent widget and menu items can be added as
00392 // children.  An actual array of Fl_Menu_Items is kept parallel
00393 // with the child objects and updated as they change.
00394 
00395 void Fl_Menu_Type::build_menu() {
00396   Fl_Menu_* w = (Fl_Menu_*)o;
00397   // count how many Fl_Menu_Item structures needed:
00398   int n = 0;
00399   Fl_Type* q;
00400   for (q = next; q && q->level > level; q = q->next) {
00401     if (q->is_parent()) n++; // space for null at end of submenu
00402     n++;
00403   }
00404   if (!n) {
00405     if (menusize) delete[] (Fl_Menu_Item*)(w->menu());
00406     w->menu(0);
00407     menusize = 0;
00408   } else {
00409     n++; // space for null at end of menu
00410     if (menusize<n) {
00411       if (menusize) delete[] (Fl_Menu_Item*)(w->menu());
00412       menusize = n+10;
00413       w->menu(new Fl_Menu_Item[menusize]);
00414     }
00415     // fill them all in:
00416     Fl_Menu_Item* m = (Fl_Menu_Item*)(w->menu());
00417     int lvl = level+1;
00418     for (q = next; q && q->level > level; q = q->next) {
00419       Fl_Menu_Item_Type* i = (Fl_Menu_Item_Type*)q;
00420       if (i->o->image()) i->o->image()->label(m);
00421       else {
00422         m->label(i->o->label() ? i->o->label() : "(nolabel)");
00423         m->labeltype(i->o->labeltype());
00424       }
00425       m->shortcut(((Fl_Button*)(i->o))->shortcut());
00426       m->callback(0,(void*)i);
00427       m->flags = i->flags();
00428       m->labelfont(i->o->labelfont());
00429       m->labelsize(i->o->labelsize());
00430       m->labelcolor(i->o->labelcolor());
00431       if (q->is_parent()) {lvl++; m->flags |= FL_SUBMENU;}
00432       m++;
00433       int l1 =
00434         (q->next && q->next->is_menu_item()) ? q->next->level : level;
00435       while (lvl > l1) {m->label(0); m++; lvl--;}
00436       lvl = l1;
00437     }
00438   }
00439   o->redraw();
00440 }
00441 
00442 Fl_Type* Fl_Menu_Type::click_test(int, int) {
00443   if (selected) return 0; // let user move the widget
00444   Fl_Menu_* w = (Fl_Menu_*)o;
00445   if (!menusize) return 0;
00446   const Fl_Menu_Item* save = w->mvalue();
00447   w->value((Fl_Menu_Item*)0);
00448   Fl::pushed(w);
00449   w->handle(FL_PUSH);
00450   const Fl_Menu_Item* m = w->mvalue();
00451   if (m) {
00452     // restore the settings of toggles & radio items:
00453     if (m->flags & (FL_MENU_RADIO | FL_MENU_TOGGLE)) build_menu();
00454     return (Fl_Type*)(m->user_data());
00455   }
00456   w->value(save);
00457   return this;
00458 }
00459 
00460 void Fl_Menu_Type::write_code2() {
00461   if (next && next->is_menu_item()) {
00462     if (i18n_type) {
00463       // take care of i18n now!
00464       Fl_Menu_Item_Type *mi = (Fl_Menu_Item_Type*)next;
00465       int i, nItem = 0, nLabel = 0;
00466       const char *mName = mi->menu_name(i);
00467       for (Fl_Type* q = next; q && q->is_menu_item(); q = q->next) {
00468         if (((Fl_Menu_Item_Type*)q)->label()) nLabel++;
00469         nItem++;
00470       }
00471       if (nLabel) {
00472         write_c("%sif (!%s_i18n_done) {\n", indent(), mName);
00473         write_c("%s  int i=0;\n", indent());
00474         write_c("%s  for ( ; i<%d; i++)\n", indent(), nItem);
00475         write_c("%s    if (%s[i].label())\n", indent(), mName);
00476         switch (i18n_type) {
00477           case 1:
00478             write_c("%s      %s[i].label(%s(%s[i].label()));\n",
00479                     indent(), mName, i18n_function, mName);
00480             break;
00481           case 2:
00482             write_c("%s      %s[i].label(catgets(%s,%s,i+%d,%s[i].label()));\n",
00483                     indent(), mName, i18n_file[0] ? i18n_file : "_catalog", 
00484                     i18n_set, mi->msgnum(), mName);
00485             break;
00486         }
00487         write_c("%s  %s_i18n_done = 1;\n", indent(), mName);
00488         write_c("%s}\n", indent());
00489       }
00490     }
00491     write_c("%s%s->menu(%s);\n", indent(), name() ? name() : "o",
00492             unique_id(this, "menu", name(), label()));
00493   }
00494   Fl_Widget_Type::write_code2();
00495 }
00496 
00497 void Fl_Menu_Type::copy_properties() {
00498   Fl_Widget_Type::copy_properties();
00499   Fl_Menu_ *s = (Fl_Menu_*)o, *d = (Fl_Menu_*)live_widget;
00500   d->menu(s->menu());
00501   d->down_box(s->down_box());
00502   d->textcolor(s->textcolor());
00503   d->textfont(s->textfont());
00504   d->textsize(s->textsize());
00505 }
00506 
00508 
00509 #include <FL/Fl_Menu_Button.H>
00510 Fl_Menu_Item button_type_menu[] = {
00511   {"normal",0,0,(void*)0},
00512   {"popup1",0,0,(void*)Fl_Menu_Button::POPUP1},
00513   {"popup2",0,0,(void*)Fl_Menu_Button::POPUP2},
00514   {"popup3",0,0,(void*)Fl_Menu_Button::POPUP3},
00515   {"popup12",0,0,(void*)Fl_Menu_Button::POPUP12},
00516   {"popup23",0,0,(void*)Fl_Menu_Button::POPUP23},
00517   {"popup13",0,0,(void*)Fl_Menu_Button::POPUP13},
00518   {"popup123",0,0,(void*)Fl_Menu_Button::POPUP123},
00519   {0}};
00520 
00521 Fl_Menu_Button_Type Fl_Menu_Button_type;
00522 
00524 
00525 Fl_Menu_Item dummymenu[] = {{"CHOICE"},{0}};
00526 
00527 Fl_Choice_Type Fl_Choice_type;
00528 
00529 Fl_Input_Choice_Type Fl_Input_Choice_type;
00530 
00531 void Fl_Input_Choice_Type::copy_properties() {
00532   Fl_Widget_Type::copy_properties();
00533   Fl_Input_Choice *s = (Fl_Input_Choice*)o, *d = (Fl_Input_Choice*)live_widget;
00534   d->menu(s->menu());
00535   d->down_box(s->down_box());
00536   d->textcolor(s->textcolor());
00537   d->textfont(s->textfont());
00538   d->textsize(s->textsize());
00539 }
00540 
00541 Fl_Type* Fl_Input_Choice_Type::click_test(int, int) {
00542   if (selected) return 0; // let user move the widget
00543   Fl_Menu_* w = ((Fl_Input_Choice*)o)->menubutton();
00544   if (!menusize) return 0;
00545   const Fl_Menu_Item* save = w->mvalue();
00546   w->value((Fl_Menu_Item*)0);
00547   Fl::pushed(w);
00548   w->handle(FL_PUSH);
00549   const Fl_Menu_Item* m = w->mvalue();
00550   if (m) {
00551     // restore the settings of toggles & radio items:
00552     if (m->flags & (FL_MENU_RADIO | FL_MENU_TOGGLE)) build_menu();
00553     return (Fl_Type*)(m->user_data());
00554   }
00555   w->value(save);
00556   return this;
00557 }
00558 
00560 
00561 Fl_Menu_Bar_Type Fl_Menu_Bar_type;
00562 
00564 // Shortcut entry item in panel:
00565 
00566 #include <FL/Fl_Output.H>
00567 #include "Shortcut_Button.h"
00568 #include <FL/fl_draw.H>
00569 
00570 void Shortcut_Button::draw() {
00571   if (value()) draw_box(FL_DOWN_BOX, (Fl_Color)9);
00572   else draw_box(FL_UP_BOX, FL_WHITE);
00573   fl_font(FL_HELVETICA,14); fl_color(FL_FOREGROUND_COLOR);
00574         if (use_FL_COMMAND && (svalue & (FL_CTRL|FL_META))) {
00575                 char buf[1024];
00576                 fl_snprintf(buf, 1023, "Command+%s", fl_shortcut_label(svalue&~(FL_CTRL|FL_META)));
00577                 fl_draw(buf,x()+6,y(),w(),h(),FL_ALIGN_LEFT);
00578         } else {
00579                 fl_draw(fl_shortcut_label(svalue),x()+6,y(),w(),h(),FL_ALIGN_LEFT);
00580         }
00581 }
00582 
00583 int Shortcut_Button::handle(int e) {
00584   when(0); type(FL_TOGGLE_BUTTON);
00585   if (e == FL_KEYBOARD) {
00586     if (!value()) return 0;
00587     int v = Fl::event_text()[0];
00588     if ( (v > 32 && v < 0x7f) || (v > 0xa0 && v <= 0xff) ) {
00589       if (isupper(v)) {
00590         v = tolower(v);
00591         v |= FL_SHIFT;
00592       }
00593       v = v | (Fl::event_state()&(FL_META|FL_ALT|FL_CTRL));
00594     } else {
00595       v = (Fl::event_state()&(FL_META|FL_ALT|FL_CTRL|FL_SHIFT)) | Fl::event_key();
00596       if (v == FL_BackSpace && svalue) v = 0;
00597     }
00598     if (v != svalue) {svalue = v; set_changed(); redraw(); do_callback(); }
00599     return 1;
00600   } else if (e == FL_UNFOCUS) {
00601     int c = changed(); value(0); if (c) set_changed();
00602     return 1;
00603   } else if (e == FL_FOCUS) {
00604     return value();
00605   } else {
00606     int r = Fl_Button::handle(e);
00607     if (e == FL_RELEASE && value() && Fl::focus() != this) take_focus();
00608     return r;
00609   }
00610 }
00611   
00612 void shortcut_in_cb(Shortcut_Button* i, void* v) {
00613   if (v == LOAD) {
00614     if (current_widget->is_button())
00615       i->svalue = ((Fl_Button*)(current_widget->o))->shortcut();
00616     else if (current_widget->is_input())
00617       i->svalue = ((Fl_Input_*)(current_widget->o))->shortcut();
00618     else if (current_widget->is_value_input())
00619       i->svalue = ((Fl_Value_Input*)(current_widget->o))->shortcut();
00620     else if (current_widget->is_text_display())
00621       i->svalue = ((Fl_Text_Display*)(current_widget->o))->shortcut();
00622     else {
00623       i->hide();
00624       return;
00625     }
00626     i->show();
00627     i->redraw();
00628   } else {
00629     int mod = 0;
00630     for (Fl_Type *o = Fl_Type::first; o; o = o->next)
00631       if (o->selected && o->is_button()) {
00632         Fl_Button* b = (Fl_Button*)(((Fl_Widget_Type*)o)->o);
00633         if (b->shortcut()!=i->svalue) mod = 1;
00634         b->shortcut(i->svalue);
00635         if (o->is_menu_item()) ((Fl_Widget_Type*)o)->redraw();
00636       } else if (o->selected && o->is_input()) {
00637         Fl_Input_* b = (Fl_Input_*)(((Fl_Widget_Type*)o)->o);
00638         if (b->shortcut()!=i->svalue) mod = 1;
00639         b->shortcut(i->svalue);
00640       } else if (o->selected && o->is_value_input()) {
00641         Fl_Value_Input* b = (Fl_Value_Input*)(((Fl_Widget_Type*)o)->o);
00642         if (b->shortcut()!=i->svalue) mod = 1;
00643         b->shortcut(i->svalue);
00644       } else if (o->selected && o->is_text_display()) {
00645         Fl_Text_Display* b = (Fl_Text_Display*)(((Fl_Widget_Type*)o)->o);
00646         if (b->shortcut()!=i->svalue) mod = 1;
00647         b->shortcut(i->svalue);
00648       }
00649     if (mod) set_modflag(1);
00650   }
00651 }
00652 
00653 //
00654 // End of "$Id: Fl_Menu_Type.cxx 7903 2010-11-28 21:06:39Z matt $".
00655 //