home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / FLTK-1.0.6 / src / Fl_Menu_add.cxx < prev    next >
Encoding:
C/C++ Source or Header  |  1999-07-12  |  7.1 KB  |  235 lines

  1. //
  2. // "$Id: Fl_Menu_add.cxx,v 1.9.2.4 1999/07/12 12:22:45 carl Exp $"
  3. //
  4. // Menu utilities for the Fast Light Tool Kit (FLTK).
  5. //
  6. // Copyright 1998-1999 by Bill Spitzak and others.
  7. //
  8. // This library is free software; you can redistribute it and/or
  9. // modify it under the terms of the GNU Library General Public
  10. // License as published by the Free Software Foundation; either
  11. // version 2 of the License, or (at your option) any later version.
  12. //
  13. // This library is distributed in the hope that it will be useful,
  14. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16. // Library General Public License for more details.
  17. //
  18. // You should have received a copy of the GNU Library General Public
  19. // License along with this library; if not, write to the Free Software
  20. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  21. // USA.
  22. //
  23. // Please report all bugs and problems to "fltk-bugs@easysw.com".
  24. //
  25.  
  26. // Methods to alter the menu in an Fl_Menu_ widget.
  27.  
  28. // These are for Forms emulation and for dynamically changing the
  29. // menus.  They are in this source file so they are not linked in if
  30. // not used, which is what will happen if the the program only uses
  31. // constant menu tables.
  32.  
  33. // Not at all guaranteed to be Forms compatable, especially with any
  34. // string with a % sign in it!
  35.  
  36. #include <FL/Fl_Menu_.H>
  37. #include <string.h>
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40.  
  41. // If the array is this, we will double-reallocate as necessary:
  42. static Fl_Menu_Item* local_array = 0;
  43. static int local_array_alloc = 0; // number allocated
  44. static int local_array_size = 0; // == size(local_array)
  45. extern Fl_Menu_* fl_menu_array_owner; // in Fl_Menu_.cxx
  46.  
  47. // For historical reasons there are matching methods that work on a
  48. // user-allocated array of Fl_Menu_Item.  These methods are quite
  49. // depreciated and should not be used.  These old methods use the
  50. // above pointers to detect if the array belongs to an Fl_Menu_
  51. // widget, and if so it reallocates as necessary.
  52.  
  53. // Insert a single Fl_Menu_Item into an array of size at offset n,
  54. // if this is local_array it will be reallocated if needed.
  55. static Fl_Menu_Item* insert(
  56.   Fl_Menu_Item* array, int size,
  57.   int n,
  58.   const char *text,
  59.   int flags
  60. ) {
  61.   if (array == local_array && size >= local_array_alloc) {
  62.     local_array_alloc = 2*size;
  63.     Fl_Menu_Item* newarray = new Fl_Menu_Item[local_array_alloc];
  64.     memmove(newarray, array, size*sizeof(Fl_Menu_Item));
  65.     delete[] local_array;
  66.     local_array = array = newarray;
  67.   }
  68.   // move all the later items:
  69.   memmove(array+n+1, array+n, sizeof(Fl_Menu_Item)*(size-n));
  70.   // create the new item:
  71.   Fl_Menu_Item* m = array+n;
  72.   m->text = text ? strdup(text) : 0;
  73.   m->shortcut_ = 0;
  74.   m->callback_ = 0;
  75.   m->user_data_ = 0;
  76.   m->flags = flags;
  77.   m->labeltype_ = m->labelfont_ = m->labelsize_ = m->labelcolor_ = 0;
  78.   return array;
  79. }
  80.  
  81. // Add an item.  The text is split at '/' characters to automatically
  82. // produce submenus (actually a totally unnecessary feature as you can
  83. // now add submenu titles directly by setting SUBMENU in the flags):
  84. int Fl_Menu_Item::add(
  85.   const char *text,
  86.   int shortcut,
  87.   Fl_Callback *cb,    
  88.   void *data,
  89.   int flags
  90. ) {
  91.   Fl_Menu_Item *array = this;
  92.   Fl_Menu_Item *m = this;
  93.   const char *p;
  94.   char *q;
  95.   char buf[1024];
  96.  
  97.   int size = array==local_array ? local_array_size : array->size();
  98.   int flags1 = 0;
  99.   char* item;
  100.   for (;;) {    /* do all the supermenus: */
  101.  
  102.     /* fill in the buf with name, changing \x to x: */
  103.     q = buf;
  104.     for (p=text; *p && *p != '/'; *q++ = *p++) if (*p=='\\') p++;
  105.     *q = 0;
  106.  
  107.     item = buf;
  108.     if (*item == '_') {item++; flags1 = FL_MENU_DIVIDER;}
  109.     if (*p != '/') break; /* not a menu title */
  110.     text = p+1;    /* point at item title */
  111.  
  112.     /* find a matching menu title: */
  113.     for (; m->text; m = m->next())
  114.       if (m->flags&FL_SUBMENU && !strcmp(item, m->text)) break;
  115.  
  116.     if (!m->text) { /* create a new menu */
  117.       int n = m-array;
  118.       array = insert(array, size, n, item, FL_SUBMENU|flags1);
  119.       size++;
  120.       array = insert(array, size, n+1, 0, 0);
  121.       size++;
  122.       m = array+n;
  123.     }
  124.     m++;    /* go into the submenu */
  125.     flags1 = 0;
  126.   }
  127.  
  128.   /* find a matching menu item: */
  129.   for (; m->text; m = m->next())
  130.     if (!strcmp(m->text,item)) break;
  131.  
  132.   if (!m->text) {    /* add a new menu item */
  133.     int n = m-array;
  134.     array = insert(array, size, n, item, flags|flags1);
  135.     size++;
  136.     if (flags & FL_SUBMENU) { // add submenu delimiter
  137.       array = insert(array, size, n+1, 0, 0);
  138.       size++;
  139.     }
  140.     m = array+n;
  141.   }
  142.  
  143.   /* fill it in */
  144.   m->shortcut_ = shortcut;
  145.   m->callback_ = cb;
  146.   m->user_data_ = data;
  147.   m->flags = flags|flags1;
  148.  
  149.   if (array == local_array) local_array_size = size;
  150.   return m-array;
  151. }
  152.  
  153. int Fl_Menu_::add(const char *t, int s, Fl_Callback *c,void *v,int f) {
  154.   // make this widget own the local array:
  155.   if (this != fl_menu_array_owner) {
  156.     if (fl_menu_array_owner) {
  157.       Fl_Menu_* o = fl_menu_array_owner;
  158.       // the previous owner get's its own correctly-sized array:
  159.       int value_offset = o->value_-local_array;
  160.       int n = local_array_size;
  161.       Fl_Menu_Item* newMenu = o->menu_ = new Fl_Menu_Item[n];
  162.       memcpy(newMenu, local_array, n*sizeof(Fl_Menu_Item));
  163.       if (o->value_) o->value_ = newMenu+value_offset;
  164.     }
  165.     if (menu_) {
  166.       // this already has a menu array, use it as the local one:
  167.       delete[] local_array;
  168.       if (!alloc) copy(menu_); // duplicate a user-provided static array
  169.       // add to the menu's current array:
  170.       local_array_alloc = local_array_size = size();
  171.       local_array = menu_;
  172.     } else {
  173.       // start with a blank array:
  174.       alloc = 2; // indicates that the strings can be freed
  175.       if (local_array) {
  176.     menu_ = local_array;
  177.       } else {
  178.     local_array_alloc = 15;
  179.     local_array = menu_ = new Fl_Menu_Item[local_array_alloc];
  180.       }
  181.       menu_[0].text = 0;
  182.       local_array_size = 1;
  183.     }
  184.     fl_menu_array_owner = this;
  185.   }
  186.   int r = menu_->add(t,s,c,v,f);
  187.   // if it rellocated array we must fix the pointer:
  188.   int value_offset = value_-menu_;
  189.   menu_ = local_array; // in case it reallocated it
  190.   if (value_) value_ = menu_+value_offset;
  191.   return r;
  192. }
  193.  
  194. // This is a Forms (and SGI GL library) compatable add function, it
  195. // adds many menu items, with '|' seperating the menu items, and tab
  196. // seperating the menu item names from an optional shortcut string.
  197. int Fl_Menu_::add(const char *str) {
  198.   char buf[128];
  199.   int r = 0;
  200.   while (*str) {
  201.     int shortcut = 0;
  202.     char *c;
  203.     for (c = buf; *str && *str != '|'; str++) {
  204.       if (*str == '\t') {*c++ = 0; shortcut = fl_old_shortcut(str);}
  205.       else *c++ = *str;
  206.     }
  207.     *c = 0;
  208.     r = add(buf, shortcut, 0, 0, 0);
  209.     if (*str) str++;
  210.   }
  211.   return r;
  212. }
  213.  
  214. void Fl_Menu_::replace(int i, const char *str) {
  215.   if (i<0 || i>=size()) return;
  216.   if (!alloc) copy(menu_);
  217.   if (alloc > 1) {
  218.     free((void *)menu_[i].text);
  219.     str = strdup(str);
  220.   }
  221.   menu_[i].text = str;
  222. }
  223.  
  224. void Fl_Menu_::remove(int i) {
  225.   int n = size();
  226.   if (i<0 || i>=n) return;
  227.   if (!alloc) copy(menu_);
  228.   if (alloc > 1) free((void *)menu_[i].text);
  229.   memmove(&menu_[i],&menu_[i+1],(n-i)*sizeof(Fl_Menu_Item));
  230. }
  231.  
  232. //
  233. // End of "$Id: Fl_Menu_add.cxx,v 1.9.2.4 1999/07/12 12:22:45 carl Exp $".
  234. //
  235.