diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Fl_Menu_.cxx | 24 | ||||
| -rw-r--r-- | src/Fl_Menu_add.cxx | 108 |
2 files changed, 83 insertions, 49 deletions
diff --git a/src/Fl_Menu_.cxx b/src/Fl_Menu_.cxx index 875eef964..0a608e07e 100644 --- a/src/Fl_Menu_.cxx +++ b/src/Fl_Menu_.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Menu_.cxx,v 1.7.2.2 1999/04/08 19:13:02 carl Exp $" +// "$Id: Fl_Menu_.cxx,v 1.7.2.3 1999/04/19 07:01:23 bill Exp $" // // Common menu code for the Fast Light Tool Kit (FLTK). // @@ -113,16 +113,13 @@ void Fl_Menu_::menu(const Fl_Menu_Item* m) { } void Fl_Menu_::copy(const Fl_Menu_Item* m, void* user_data) { - int i, s = m->size(), n=s; - for (i=0; n; n>>=1, i++); - n = 1 << i; + int n = m->size(); Fl_Menu_Item* newMenu = new Fl_Menu_Item[n]; - memcpy(newMenu, m, s*sizeof(Fl_Menu_Item)); - memset(newMenu+s, 0, (n-s)*sizeof(Fl_Menu_Item)); + memcpy(newMenu, m, n*sizeof(Fl_Menu_Item)); menu(newMenu); - alloc = 1; // make destructor free it + alloc = 1; // make destructor free array, but not strings // for convienence, provide way to change all the user data pointers: - if (user_data) for (; s--;) { + if (user_data) for (; n--;) { if (newMenu->callback_) newMenu->user_data_ = user_data; newMenu++; } @@ -132,11 +129,18 @@ Fl_Menu_::~Fl_Menu_() { clear(); } +// Fl_Menu::add() uses this to indicate the owner of the dynamically- +// expanding array. We must not free this array: +Fl_Menu_* fl_menu_array_owner = 0; + void Fl_Menu_::clear() { if (alloc) { if (alloc>1) for (int i = size(); i--;) if (menu_[i].text) free((void*)menu_[i].text); - delete[] menu_; + if (this == fl_menu_array_owner) + fl_menu_array_owner = 0; + else + delete[] menu_; menu_ = 0; value_ = 0; alloc = 0; @@ -144,5 +148,5 @@ void Fl_Menu_::clear() { } // -// End of "$Id: Fl_Menu_.cxx,v 1.7.2.2 1999/04/08 19:13:02 carl Exp $". +// End of "$Id: Fl_Menu_.cxx,v 1.7.2.3 1999/04/19 07:01:23 bill Exp $". // diff --git a/src/Fl_Menu_add.cxx b/src/Fl_Menu_add.cxx index 98786bd2d..255625e39 100644 --- a/src/Fl_Menu_add.cxx +++ b/src/Fl_Menu_add.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Menu_add.cxx,v 1.9 1999/03/09 06:46:36 bill Exp $" +// "$Id: Fl_Menu_add.cxx,v 1.9.2.1 1999/04/19 07:01:23 bill Exp $" // // Menu utilities for the Fast Light Tool Kit (FLTK). // @@ -24,12 +24,11 @@ // // Methods to alter the menu in an Fl_Menu_ widget. -// This code is seperated so that it is not linked in if not used. -// These functions are for emulation of Forms and for dynamically -// changing the menus. They are in this source file so they are -// not linked in if not used, which is what will happen if the -// the program only uses constant menu tables. +// These are for Forms emulation and for dynamically changing the +// menus. They are in this source file so they are not linked in if +// not used, which is what will happen if the the program only uses +// constant menu tables. // Not at all guaranteed to be Forms compatable, especially with any // string with a % sign in it! @@ -38,34 +37,34 @@ #include <string.h> #include <stdlib.h> -// always allocate this much initially: -#define INITIAL_MENU_SIZE 15 +// If the array is this, we will double-reallocate as necessary: +static Fl_Menu_Item* local_array = 0; +static int local_array_alloc = 0; // number allocated +static int local_array_size = 0; // == size(local_array) +extern Fl_Menu_* fl_menu_array_owner; // in Fl_Menu_.cxx -// if this local pointer is set, array is reallocated and put here: -static Fl_Menu_Item** alloc; +// For historical reasons there are matching methods that work on a +// user-allocated array of Fl_Menu_Item. These methods are quite +// depreciated and should not be used. These old methods use the +// above pointers to detect if the array belongs to an Fl_Menu_ +// widget, and if so it reallocates as necessary. -// Insert a single Fl_Menu_Item into an array at offset n. If ::alloc -// is not zero, the array may be reallocated. This is done each time -// it's size passes through a power of 2. The new (or old) array is -// returned. -// Notice that size does not count the trailing null item, so one more -// item than you think must be copied. +// Insert a single Fl_Menu_Item into an array of size at offset n, +// if this is local_array it will be reallocated if needed. static Fl_Menu_Item* insert( Fl_Menu_Item* array, int size, int n, const char *text, - int flags) { - // If new size is a power of two, we reallocate to the next power - // of two: - if (alloc && size >= INITIAL_MENU_SIZE && !((size+1)&size)) { - Fl_Menu_Item* newarray = new Fl_Menu_Item[(size+1)*2]; - memcpy(newarray, array, (size+1)*sizeof(Fl_Menu_Item)); - memset(newarray+size+1, 0, (size+1)*sizeof(Fl_Menu_Item)); - delete[] array; - *alloc = array = newarray; + int flags +) { + if (array == local_array && size >= local_array_alloc) { + local_array_alloc = 2*size; + Fl_Menu_Item* newarray = new Fl_Menu_Item[local_array_alloc]; + memmove(newarray, array, size*sizeof(Fl_Menu_Item)); + local_array = array = newarray; } // move all the later items: - memmove(array+n+1, array+n, sizeof(Fl_Menu_Item)*(size-n+1)); + memmove(array+n+1, array+n, sizeof(Fl_Menu_Item)*(size-n)); // create the new item: Fl_Menu_Item* m = array+n; m->text = text ? strdup(text) : 0; @@ -85,15 +84,15 @@ int Fl_Menu_Item::add( int shortcut, Fl_Callback *cb, void *data, - int flags) -{ + int flags +) { Fl_Menu_Item *array = this; Fl_Menu_Item *m = this; const char *p; char *q; char buf[1024]; - int size = array->size(); + int size = array==local_array ? local_array_size : array->size(); int flags1 = 0; char* item; for (;;) { /* do all the supermenus: */ @@ -145,25 +144,54 @@ int Fl_Menu_Item::add( m->user_data_ = data; m->flags = flags|flags1; + if (array == local_array) local_array_size = size; return m-array; } int Fl_Menu_::add(const char *t, int s, Fl_Callback *c,void *v,int f) { - int n = value_ ? value_ - menu_ : 0; - if (!menu_) { - alloc = 2; // indicates that the strings can be freed - menu_ = new Fl_Menu_Item[INITIAL_MENU_SIZE+1]; - menu_[0].text = 0; + // make this widget own the local array: + if (this != fl_menu_array_owner) { + if (fl_menu_array_owner) { + Fl_Menu_* o = fl_menu_array_owner; + // the previous owner get's its own correctly-sized array: + int value_offset = o->value_-local_array; + int n = local_array_size; + Fl_Menu_Item* newMenu = o->menu_ = new Fl_Menu_Item[n]; + memcpy(newMenu, local_array, n*sizeof(Fl_Menu_Item)); + if (o->value_) o->value_ = newMenu+value_offset; + } + if (menu_) { + // this already has a menu array, use it as the local one: + delete[] local_array; + if (!alloc) copy(menu_); // duplicate a user-provided static array + // add to the menu's current array: + local_array_alloc = local_array_size = size(); + local_array = menu_; + } else { + // start with a blank array: + alloc = 2; // indicates that the strings can be freed + if (local_array) { + menu_ = local_array; + } else { + local_array_alloc = 15; + local_array = menu_ = new Fl_Menu_Item[local_array_alloc]; + } + menu_[0].text = 0; + local_array_size = 1; + } + fl_menu_array_owner = this; } - if (alloc) ::alloc = &menu_; int r = menu_->add(t,s,c,v,f); - ::alloc = 0; - if (value_) value_ = menu_+n; + // if it rellocated array we must fix the pointer: + int value_offset = value_-menu_; + menu_ = local_array; // in case it reallocated it + if (value_) value_ = menu_+value_offset; return r; } // This is a Forms (and SGI GL library) compatable add function, it -// adds strings of the form "name\tshortcut|name\tshortcut|..." +// adds many menu items, with '|' seperating the menu items, and tab +// seperating the menu item names from an optional shortcut string. int Fl_Menu_::add(const char *str) { char buf[128]; int r = 0; @@ -183,6 +211,7 @@ int Fl_Menu_::add(const char *str) { void Fl_Menu_::replace(int i, const char *str) { if (i<0 || i>=size()) return; + if (!alloc) copy(menu_); if (alloc > 1) { free((void *)menu_[i].text); str = strdup(str); @@ -193,10 +222,11 @@ void Fl_Menu_::replace(int i, const char *str) { void Fl_Menu_::remove(int i) { int n = size(); if (i<0 || i>=n) return; + if (!alloc) copy(menu_); if (alloc > 1) free((void *)menu_[i].text); memmove(&menu_[i],&menu_[i+1],(n-i)*sizeof(Fl_Menu_Item)); } // -// End of "$Id: Fl_Menu_add.cxx,v 1.9 1999/03/09 06:46:36 bill Exp $". +// End of "$Id: Fl_Menu_add.cxx,v 1.9.2.1 1999/04/19 07:01:23 bill Exp $". // |
