Include a stripped-down version of FLTK in tree and add a USE_INCLUDED_FLTK option to build against it.


git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4603 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/common/fltk/src/Fl_Menu_add.cxx b/common/fltk/src/Fl_Menu_add.cxx
new file mode 100644
index 0000000..2ce2804
--- /dev/null
+++ b/common/fltk/src/Fl_Menu_add.cxx
@@ -0,0 +1,496 @@
+//
+// "$Id: Fl_Menu_add.cxx 8110 2010-12-23 08:02:52Z manolo $"
+//
+// Menu utilities for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2010 by Bill Spitzak and others.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+// USA.
+//
+// Please report all bugs and problems on the following page:
+//
+//     http://www.fltk.org/str.php
+//
+// Methods to alter the menu in an Fl_Menu_ widget.
+
+// 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 program only uses
+// constant menu tables.
+
+// Not at all guaranteed to be Forms compatible, especially with any
+// string with a % sign in it!
+
+#include <FL/Fl_Menu_.H>
+#include "flstring.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+// 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
+
+// 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 of size at offset n,
+// if this is local_array it will be reallocated if needed.
+static Fl_Menu_Item* array_insert(
+  Fl_Menu_Item* array,  // array to modify
+  int size,             // size of array
+  int n,                // index of new insert position
+  const char *text,     // text of new item (copy is made)
+  int flags             // flags for new item
+) {
+  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));
+    delete[] local_array;
+    local_array = array = newarray;
+  }
+  // move all the later items:
+  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;
+  m->shortcut_ = 0;
+  m->callback_ = 0;
+  m->user_data_ = 0;
+  m->flags = flags;
+  m->labeltype_ = m->labelsize_ = m->labelcolor_ = 0;
+  m->labelfont_ = FL_HELVETICA; 
+  return array;
+}
+
+
+
+// Comparison that does not care about deleted '&' signs:
+static int compare(const char* a, const char* b) {
+  for (;;) {
+    int n = *a-*b;
+    if (n) {
+      if (*a == '&') a++;
+      else if (*b == '&') b++;
+      else return n;
+    } else if (*a) {
+      a++; b++;
+    } else {
+      return 0;
+    }
+  }
+}
+
+
+
+/** Adds an item.  The text is split at '/' characters to automatically
+   produce submenus (actually a totally unnecessary feature as you can
+   now add submenu titles directly by setting SUBMENU in the flags):
+*/
+int Fl_Menu_Item::add(
+  const char *mytext,
+  int sc,
+  Fl_Callback *cb,	
+  void *data,
+  int myflags
+) {
+  return(insert(-1,mytext,sc,cb,data,myflags));		// -1: append
+}
+
+
+
+/** 
+ Inserts an item at position \p index.
+    
+ If \p index is -1, the item is added the same way as Fl_Menu_Item::add().
+
+ If 'mytext' contains any un-escaped front slashes (/), it's assumed 
+ a menu pathname is being specified, and the value of \p index 
+ will be ignored.
+
+ In all other aspects, the behavior of insert() is the same as add().
+ 
+ \param index insert new items here
+ \param mytext new label string, details see above
+ \param sc keyboard shortcut for new item
+ \param cb callback function for new item
+ \param data user data for new item
+ \param myflags menu flags as described in FL_Menu_Item
+ \returns the index into the menu() array, where the entry was added
+*/
+int Fl_Menu_Item::insert(
+  int index,
+  const char *mytext,
+  int sc,
+  Fl_Callback *cb,	
+  void *data,
+  int myflags
+) {
+  Fl_Menu_Item *array = this;
+  Fl_Menu_Item *m = this;
+  const char *p;
+  char *q;
+  char buf[1024];
+
+  int msize = array==local_array ? local_array_size : array->size();
+  int flags1 = 0;
+  const char* item;
+
+  // split at slashes to make submenus:
+  for (;;) {
+
+    // leading slash makes us assume it is a filename:
+    if (*mytext == '/') {item = mytext; break;}
+
+    // leading underscore causes divider line:
+    if (*mytext == '_') {mytext++; flags1 = FL_MENU_DIVIDER;}
+
+    // copy to buf, changing \x to x:
+    q = buf;
+    for (p=mytext; *p && *p != '/'; *q++ = *p++) if (*p=='\\' && p[1]) p++;
+    *q = 0;
+
+    item = buf;
+    if (*p != '/') break; /* not a menu title */
+    index = -1;           /* any submenu specified overrides insert position */
+    mytext = p+1;         /* point at item title */
+
+    /* find a matching menu title: */
+    for (; m->text; m = m->next())
+      if (m->flags&FL_SUBMENU && !compare(item, m->text)) break;
+
+    if (!m->text) { /* create a new menu */
+      int n = (index==-1) ? m-array : index;
+      array = array_insert(array, msize, n, item, FL_SUBMENU|flags1);
+      msize++;
+      array = array_insert(array, msize, n+1, 0, 0);
+      msize++;
+      m = array+n;
+    }
+    m++;	/* go into the submenu */
+    flags1 = 0;
+  }
+
+  /* find a matching menu item: */
+  for (; m->text; m = m->next())
+    if (!(m->flags&FL_SUBMENU) && !compare(m->text,item)) break;
+
+  if (!m->text) {	/* add a new menu item */
+    int n = (index==-1) ? m-array : index;
+    array = array_insert(array, msize, n, item, myflags|flags1);
+    msize++;
+    if (myflags & FL_SUBMENU) { // add submenu delimiter
+      array = array_insert(array, msize, n+1, 0, 0);
+      msize++;
+    }
+    m = array+n;
+  }
+
+  /* fill it in */
+  m->shortcut_ = sc;
+  m->callback_ = cb;
+  m->user_data_ = data;
+  m->flags = myflags|flags1;
+
+  if (array == local_array) local_array_size = msize;
+  return m-array;
+}
+
+
+
+/**
+  Adds a new menu item.
+  
+  \param[in] label    The text label for the menu item.
+  \param[in] shortcut Optional keyboard shortcut that can be an int or string; (FL_CTRL+'a') or "^a". Default 0 if none.
+  \param[in] callback Optional callback invoked when user clicks the item. Default 0 if none.
+  \param[in] userdata Optional user data passed as an argument to the callback. Default 0 if none.
+  \param[in] flags    Optional flags that control the type of menu item; see below. Default is 0 for none.
+  \returns            The index into the menu() array, where the entry was added.
+  
+  \par Description
+  If the menu array was directly set with menu(x), then copy() is done 
+  to make a private array.
+  \par 
+  Since this method can change the internal menu array, any menu item
+  pointers or indecies the application may have cached can become stale,
+  and should be recalculated/refreshed.
+  \par
+  A menu item's callback must not add() items to its parent menu during the callback.
+
+  <B>Detailed Description of Parameters</B>
+  \par label
+  The menu item's label. This option is required.
+  \par
+  The characters "&", "/", "\", and "_" are treated as special characters in the label string. 
+  The "&" character specifies that the following character is an accelerator and will be underlined.
+  The "\" character is used to escape the next character in the string. 
+  Labels starting with the "_" character cause a divider to be placed after that menu item.
+  \par 
+  A label of the form "File/Quit" will create the submenu "File"
+  with a menu item called "Quit". The "/" character is ignored if it appears
+  as the first character of the label string, e.g.  "/File/Quit".
+  \par 
+  The label string is copied to new memory and can be freed.
+  The other arguments (including the shortcut) are copied into the
+  menu item unchanged.
+  \par 
+  If an item exists already with that name then it is replaced with
+  this new one.  Otherwise this new one is added to the end of the
+  correct menu or submenu.  The return value is the offset into the array
+  that the new entry was placed at.
+  
+  \par shortcut
+  The keyboard shortcut for this menu item. 
+  \par 
+  This parameter is optional, and defaults to 0 to indicate no shortcut.
+  \par
+  The shortcut can either be a raw integer value (eg. FL_CTRL+'A')
+  or a string (eg. "^c" or "^97").
+  \par
+  Raw integer shortcuts can be a combination of keyboard chars (eg. 'A')
+  and optional keyboard modifiers (see Fl::event_state(), e.g. FL_SHIFT, etc).
+  In addition, FL_COMMAND can be used to denote FL_META under Mac OS X and
+  FL_CTRL under other platforms.
+  \par
+  String shortcuts can be specified in one of two ways:
+  \par
+  \verbatim
+   [#+^]<ascii_value>    e.g. "97", "^97", "+97", "#97"
+   [#+^]<ascii_char>     e.g. "a", "^a", "+a", "#a"
+  \endverbatim
+  \par
+  ..where \<ascii_value\> is a decimal value representing an
+  ascii character (eg. 97 is the ascii code for 'a'), and the optional
+  prefixes enhance the value that follows. Multiple prefixes must
+  appear in the order below.
+  \par
+  \verbatim
+   # - Alt
+   + - Shift
+   ^ - Control
+  \endverbatim
+  \par
+  Internally, the text shortcuts are converted to integer values using
+  fl_old_shortcut(const char*).
+
+  \par callback
+  The callback to invoke when this menu item is selected. 
+  \par 
+  This parameter is optional, and defaults to 0 for no callback.
+
+  \par userdata
+  The callback's 'user data' that is passed to the callback. 
+  \par 
+  This parameter is optional, and defaults to 0.
+
+  \par flags
+  These are bit flags to define what kind of menu item this is. 
+  \par
+  This parameter is optional, and defaults to 0 to define a 'regular' menu item.
+  \par 
+  These flags can be 'OR'ed together:
+  \code
+      FL_MENU_INACTIVE     // Deactivate menu item (gray out)
+      FL_MENU_TOGGLE       // Item is a checkbox toggle (shows checkbox for on/off state)
+      FL_MENU_VALUE        // The on/off state for checkbox/radio buttons (if set, state is 'on')
+      FL_MENU_RADIO        // Item is a radio button (one checkbox of many can be on)
+      FL_MENU_INVISIBLE    // Item will not show up (shortcut will work)
+      FL_SUBMENU_POINTER   // Indicates user_data() is a pointer to another menu array
+      FL_SUBMENU           // This item is a submenu to other items
+      FL_MENU_DIVIDER      // Creates divider line below this item. Also ends a group of radio buttons.
+  \endcode
+
+  \todo Raw integer shortcut needs examples. 
+        Dependent on responses to http://fltk.org/newsgroups.php?gfltk.development+v:10086 and results of STR#2344
+ */
+int Fl_Menu_::add(const char *label,int shortcut,Fl_Callback *callback,void *userdata,int flags) {
+  return(insert(-1,label,shortcut,callback,userdata,flags));	// -1: append
+}
+
+
+
+/**
+  Inserts a new menu item at the specified \p index position.
+
+  If \p index is -1, the menu item is appended; same behavior as add().
+
+  To properly insert a menu item, \p label must be the name of the item (eg. "Quit"),
+  and not a 'menu pathname' (eg. "File/Quit").  If a menu pathname is specified, 
+  the value of \p index is \em ignored, the new item's position defined by the pathname.
+  
+  For more details, see add(). Except for the \p index parameter, add()
+  has more detailed information on parameters and behavior, and is
+  functionally equivalent.
+
+  \param[in] index    The menu array's index position where the new item
+                      is inserted. If -1, behavior is the same as add().
+  \param[in] label    The text label for the menu item. If the label 
+                      is a menu pathname, \p index is ignored, and the pathname
+		      indicates the position of the new item.
+  \param[in] shortcut Optional keyboard shortcut. Can be an int (FL_CTRL+'a')
+                      or a string ("^a"). Default is 0.
+  \param[in] callback Optional callback invoked when user clicks the item.
+                      Default 0 if none.
+  \param[in] userdata Optional user data passed as an argument to the callback.
+                      Default 0 if none.
+  \param[in] flags    Optional flags that control the type of menu item; 
+                      see add() for more info. Default is 0 for none.
+  \returns            The index into the menu() array, where the entry was added.
+
+  \see                add()
+
+ */
+int Fl_Menu_::insert(
+  int index,
+  const char *label,
+  int shortcut,
+  Fl_Callback *callback,
+  void *userdata,
+  int flags
+) {
+  // 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];
+        memset(local_array, 0, sizeof(Fl_Menu_Item) * local_array_alloc);
+      }
+      memset(menu_, 0, sizeof(Fl_Menu_Item));
+      local_array_size = 1;
+    }
+    fl_menu_array_owner = this;
+  }
+  int r = menu_->insert(index,label,shortcut,callback,userdata,flags);
+  // 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) compatible add function, it
+  adds many menu items, with '|' separating the menu items, and tab
+  separating the menu item names from an optional shortcut string.
+
+  The passed string is split at any '|' characters and then
+  add(s,0,0,0,0) is done with each section. This is
+  often useful if you are just using the value, and is compatible
+  with Forms and other GL programs. The section strings use the
+  same special characters as described for the long version of add().
+
+  No items must be added to a menu during a callback to the same menu.
+ 
+  \param str string containing multiple menu labels as described above
+  \returns the index into the menu() array, where the entry was added
+*/
+int Fl_Menu_::add(const char *str) {
+  char buf[1024];
+  int r = 0;
+  while (*str) {
+    int sc = 0;
+    char *c;
+    for (c = buf; c < (buf + sizeof(buf) - 2) && *str && *str != '|'; str++) {
+      if (*str == '\t') {*c++ = 0; sc = fl_old_shortcut(str);}
+      else *c++ = *str;
+    }
+    *c = 0;
+    r = add(buf, sc, 0, 0, 0);
+    if (*str) str++;
+  }
+  return r;
+}
+
+
+
+/**
+  Changes the text of item \p i.  This is the only way to get
+  slash into an add()'ed menu item.  If the menu array was directly set
+  with menu(x) then copy() is done to make a private array.
+ 
+  \param i index into menu array
+  \param str new label for menu item at index i
+*/
+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);
+  }
+  menu_[i].text = str;
+}
+
+
+
+/**
+  Deletes item \p i from the menu.  If the menu array was directly
+  set with menu(x) then copy() is done to make a private array.
+  
+  No items must be removed from a menu during a callback to the same menu.
+ 
+  \param i index into menu array
+*/
+void Fl_Menu_::remove(int i) {
+  int n = size();
+  if (i<0 || i>=n) return;
+  if (!alloc) copy(menu_);
+  // find the next item, skipping submenus:
+  Fl_Menu_Item* item = menu_+i;
+  const Fl_Menu_Item* next_item = item->next();
+  // delete the text only if all items were created with add():
+  if (alloc > 1) {
+    for (Fl_Menu_Item* m = item; m < next_item; m++)
+      if (m->text) free((void*)(m->text));
+  }
+  // MRS: "n" is the menu size(), which includes the trailing NULL entry...
+  memmove(item, next_item, (menu_+n-next_item)*sizeof(Fl_Menu_Item));
+}
+
+//
+// End of "$Id: Fl_Menu_add.cxx 8110 2010-12-23 08:02:52Z manolo $".
+//