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/FL/Fl_Table.H b/common/fltk/FL/Fl_Table.H
new file mode 100644
index 0000000..55c06fd
--- /dev/null
+++ b/common/fltk/FL/Fl_Table.H
@@ -0,0 +1,1081 @@
+//
+// "$Id: Fl_Table.H 8301 2011-01-22 22:40:11Z AlbrechtS $"
+//
+// Fl_Table -- A table widget
+//
+// Copyright 2002 by Greg Ercolano.
+// Copyright (c) 2004 O'ksi'D
+//
+// 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 to "erco at seriss dot com".
+//
+// TODO:
+//    o Auto scroll during dragged selection
+//    o Keyboard navigation (up/down/left/right arrow)
+//
+
+#ifndef _FL_TABLE_H
+#define _FL_TABLE_H
+
+#include <sys/types.h>
+#include <string.h>		// memcpy
+#ifdef WIN32
+#include <malloc.h>		// WINDOWS: malloc/realloc
+#else /*WIN32*/
+#include <stdlib.h>		// UNIX: malloc/realloc
+#endif /*WIN32*/
+
+#include <FL/Fl.H>
+#include <FL/Fl_Group.H>
+#include <FL/Fl_Scroll.H>
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Scrollbar.H>
+
+/**
+ A table of widgets or other content.
+ 
+ This is the base class for table widgets.
+ 
+ To be useful it must be subclassed and several virtual functions defined.
+ Normally applications use widgets derived from this widget, and do not use this 
+ widget directly; this widget is usually too low level to be used directly by 
+ applications.
+ 
+ This widget does \em not handle the data in the table. The draw_cell()
+ method must be overridden by a subclass to manage drawing the contents of 
+ the cells.
+ 
+ This widget can be used in several ways:
+ 
+ - As a custom widget; see examples/table-simple.cxx and test/table.cxx.
+   Very optimal for even extremely large tables.
+ - As a table made up of a single FLTK widget instanced all over the table,
+   simulating a numeric spreadsheet. See examples/table-spreadsheet.cxx and
+   examples/table-spreadsheet-with-keyboard-nav.cxx. Optimal for large tables.
+ - As a regular container of FLTK widgets, one widget per cell.
+   See examples/table-as-container.cxx. \em Not recommended for large tables.
+ 
+ \image html table-simple.png
+ \image latex table-simple.png "table-simple example" width=6cm
+
+ \image html table-as-container.png
+ \image latex table-as-container.png "table-as-container example" width=6cm
+ 
+ When acting as part of a custom widget, events on the cells and/or headings
+ generate callbacks when they are clicked by the user. You control when events 
+ are generated based on the setting for Fl_Table::when().
+ 
+ When acting as a container for FLTK widgets, the FLTK widgets maintain 
+ themselves. Although the draw_cell() method must be overridden, its contents 
+ can be very simple. See the draw_cell() code in examples/table-simple.cxx.
+ 
+ The following variables are available to classes deriving from Fl_Table:
+ 
+ \image html table-dimensions.png
+ \image latex table-dimensions.png "Fl_Table Dimensions" width=6cm
+ 
+ <table border=0>
+ <tr><td>x()/y()/w()/h()</td>
+ <td>Fl_Table widget's outer dimension. The outer edge of the border of the 
+ Fl_Table. (Red in the diagram above)</td></tr>
+ 
+ <tr><td>wix/wiy/wiw/wih</td>
+ <td>Fl_Table widget's inner dimension. The inner edge of the border of the 
+ Fl_Table. eg. if the Fl_Table's box() is FL_NO_BOX, these values are the same 
+ as x()/y()/w()/h(). (Yellow in the diagram above)</td></tr>
+ 
+ <tr><td>tox/toy/tow/toh</td>
+ <td>The table's outer dimension. The outer edge of the border around the cells,
+ but inside the row/col headings and scrollbars. (Green in the diagram above)
+ </td></tr>
+ 
+ <tr><td>tix/tiy/tiw/tih</td>
+ <td>The table's inner dimension. The inner edge of the border around the cells,
+ but inside the row/col headings and scrollbars. AKA the table's clip region. 
+ eg. if the table_box() is FL_NO_BOX, these values are the same as
+ tox/toyy/tow/toh. (Blue in the diagram above)
+ </td></tr></table>
+ 
+ CORE DEVELOPERS
+ 
+ - Greg Ercolano : 12/16/2002 - initial implementation 12/16/02. Fl_Table, Fl_Table_Row, docs.
+ - Jean-Marc Lienher : 02/22/2004 - added keyboard nav + mouse selection, and ported Fl_Table into fltk-utf8-1.1.4
+ 
+ OTHER CONTRIBUTORS
+ 
+ - Inspired by the Feb 2000 version of FLVW's Flvw_Table widget. Mucho thanks to those folks.
+ - Mister Satan : 04/07/2003 - MinGW porting mods, and singleinput.cxx; a cool Fl_Input oriented spreadsheet example
+ - Marek Paliwoda : 01/08/2003 - Porting mods for Borland
+ - Ori Berger : 03/16/2006 - Optimizations for >500k rows/cols
+ 
+ LICENSE
+ 
+ Greg added the following license to the original distribution of Fl_Table. He 
+ kindly gave his permission to integrate Fl_Table and Fl_Table_Row into FLTK,
+ allowing FLTK license to apply while his widgets are part of the library.
+ 
+ If used on its own, this is the license that applies:
+
+ \verbatim 
+ Fl_Table License
+ December 16, 2002
+ 
+ The Fl_Table library and included programs are provided under the terms
+ of the GNU Library General Public License (LGPL) with the following
+ exceptions:
+ 
+ 1. Modifications to the Fl_Table configure script, config
+ header file, and makefiles by themselves to support
+ a specific platform do not constitute a modified or
+ derivative work.
+ 
+ The authors do request that such modifications be
+ contributed to the Fl_Table project - send all
+ contributions to "erco at seriss dot com".
+ 
+ 2. Widgets that are subclassed from Fl_Table widgets do not
+ constitute a derivative work.
+ 
+ 3. Static linking of applications and widgets to the
+ Fl_Table library does not constitute a derivative work
+ and does not require the author to provide source
+ code for the application or widget, use the shared
+ Fl_Table libraries, or link their applications or
+ widgets against a user-supplied version of Fl_Table.
+ 
+ If you link the application or widget to a modified
+ version of Fl_Table, then the changes to Fl_Table must be
+ provided under the terms of the LGPL in sections
+ 1, 2, and 4.
+ 
+ 4. You do not have to provide a copy of the Fl_Table license
+ with programs that are linked to the Fl_Table library, nor
+ do you have to identify the Fl_Table license in your
+ program or documentation as required by section 6
+ of the LGPL.
+ 
+ However, programs must still identify their use of Fl_Table.
+ The following example statement can be included in user
+ documentation to satisfy this requirement:
+ 
+ [program/widget] is based in part on the work of
+ the Fl_Table project http://seriss.com/people/erco/fltk/Fl_Table/
+ \endverbatim
+ 
+ 
+ */
+class FL_EXPORT Fl_Table : public Fl_Group {
+public:
+  /**
+   The context bit flags for Fl_Table related callbacks (eg. draw_cell(), callback(), etc)
+   */
+  enum TableContext {
+    CONTEXT_NONE       = 0,	///< no known context
+    CONTEXT_STARTPAGE  = 0x01,	///< before a page is redrawn
+    CONTEXT_ENDPAGE    = 0x02,	///< after a page is redrawn
+    CONTEXT_ROW_HEADER = 0x04,	///< in the row header
+    CONTEXT_COL_HEADER = 0x08,	///< in the col header
+    CONTEXT_CELL       = 0x10,	///< in one of the cells
+    CONTEXT_TABLE      = 0x20,	///< in a dead zone of table
+    CONTEXT_RC_RESIZE  = 0x40 	///< column or row being resized
+  };
+  
+private:
+  int _rows, _cols;	// total rows/cols
+  int _row_header_w;	// width of row header
+  int _col_header_h;	// height of column header
+  int _row_position;	// last row_position set (not necessarily == toprow!)
+  int _col_position;	// last col_position set (not necessarily == leftcol!)
+  
+  char _row_header;	// row header enabled?
+  char _col_header;	// col header enabled?
+  char _row_resize;	// row resizing enabled?
+  char _col_resize;	// col resizing enabled?
+  int _row_resize_min;	// row minimum resizing height (default=1)
+  int _col_resize_min;	// col minimum resizing width (default=1)
+  
+  // OPTIMIZATION: partial row/column redraw variables
+  int _redraw_toprow;
+  int _redraw_botrow;
+  int _redraw_leftcol;
+  int _redraw_rightcol;
+  Fl_Color _row_header_color;
+  Fl_Color _col_header_color;
+  
+  int _auto_drag;
+  int _selecting;
+  
+  // An STL-ish vector without templates
+  class FL_EXPORT IntVector {
+    int *arr;
+    unsigned int _size;
+    void init() {
+      arr = NULL;
+      _size = 0;
+    }
+    void copy(int *newarr, unsigned int newsize) {
+      size(newsize);
+      memcpy(arr, newarr, newsize * sizeof(int));
+    }
+  public:
+    IntVector() { init(); }					// CTOR
+    ~IntVector() { if ( arr ) free(arr); arr = NULL; }		// DTOR
+    IntVector(IntVector&o) { init(); copy(o.arr, o._size); }	// COPY CTOR
+    IntVector& operator=(IntVector&o) {				// ASSIGN
+      init();
+      copy(o.arr, o._size);
+      return(*this);
+    }
+    int operator[](int x) const { return(arr[x]); }
+    int& operator[](int x) { return(arr[x]); }
+    unsigned int size() { return(_size); }
+    void size(unsigned int count) {
+      if ( count != _size ) {
+        arr = (int*)realloc(arr, count * sizeof(int));
+        _size = count;
+      }
+    }
+    int pop_back() { int tmp = arr[_size-1]; _size--; return(tmp); }
+    void push_back(int val) { unsigned int x = _size; size(_size+1); arr[x] = val; }
+    int back() { return(arr[_size-1]); }
+  };
+  
+  IntVector _colwidths;			// column widths in pixels
+  IntVector _rowheights;		// row heights in pixels
+  
+  Fl_Cursor _last_cursor;		// last mouse cursor before changed to 'resize' cursor
+  
+  // EVENT CALLBACK DATA
+  TableContext _callback_context;	// event context
+  int _callback_row, _callback_col;	// event row/col
+  
+  // handle() state variables.
+  //    Put here instead of local statics in handle(), so more
+  //    than one Fl_Table can exist without crosstalk between them.
+  //
+  int _resizing_col;			// column being dragged
+  int _resizing_row;			// row being dragged
+  int _dragging_x;			// starting x position for horiz drag
+  int _dragging_y;			// starting y position for vert drag
+  int _last_row;			// last row we FL_PUSH'ed
+  
+  // Redraw single cell
+  void _redraw_cell(TableContext context, int R, int C);
+  
+  void _start_auto_drag();
+  void _stop_auto_drag();
+  void _auto_drag_cb();
+  static void _auto_drag_cb2(void *d);
+  
+protected:
+  enum ResizeFlag {
+    RESIZE_NONE      = 0,
+    RESIZE_COL_LEFT  = 1,
+    RESIZE_COL_RIGHT = 2,
+    RESIZE_ROW_ABOVE = 3,
+    RESIZE_ROW_BELOW = 4
+  };
+  
+  int table_w, table_h;				// table's virtual size (in pixels)
+  int toprow, botrow, leftcol, rightcol;	// four corners of viewable table
+  
+  // selection
+  int current_row, current_col;
+  int select_row, select_col;
+  
+  // OPTIMIZATION: Precomputed scroll positions for the toprow/leftcol
+  int toprow_scrollpos;
+  int leftcol_scrollpos;
+  
+  // Dimensions
+  int tix, tiy, tiw, tih;			// data table inner dimension xywh
+  int tox, toy, tow, toh;			// data table outer dimension xywh
+  int wix, wiy, wiw, wih;			// widget inner dimension xywh
+  
+  Fl_Scroll *table;				// container for child fltk widgets (if any)
+  Fl_Scrollbar *vscrollbar; 			// vertical scrollbar
+  Fl_Scrollbar *hscrollbar;			// horizontal scrollbar
+  
+  // Fltk
+  int handle(int e);				// fltk handle() override
+  
+  // Class maintenance
+  void recalc_dimensions();
+  void table_resized();				// table resized; recalc
+  void table_scrolled();			// table scrolled; recalc
+  void get_bounds(TableContext context,		// return x/y/w/h bounds for context
+                  int &X, int &Y, int &W, int &H);
+  void change_cursor(Fl_Cursor newcursor);	// change mouse cursor to some other shape
+  TableContext cursor2rowcol(int &R, int &C, ResizeFlag &resizeflag);
+  // find r/c given current x/y event
+  int find_cell(TableContext context,		// find cell's x/y/w/h given r/c
+                int R, int C, int &X, int &Y, int &W, int &H);
+  int row_col_clamp(TableContext context, int &R, int &C);
+  // clamp r/c to known universe
+  
+  /**
+   Subclass should override this method to handle drawing the cells.
+   
+   This method will be called whenever the table is redrawn, once per cell.
+   
+   Only cells that are completely (or partially) visible will be told to draw.
+   
+   \p context will be one of the following:
+   
+   <table border=1>
+   <tr>
+   <td>\p Fl_Table::CONTEXT_STARTPAGE</td>
+   <td>When table, or parts of the table, are about to be redrawn.<br>
+       Use to initialize static data, such as font selections.<p>
+       R/C will be zero,<br>
+       X/Y/W/H will be the dimensions of the table's entire data area.<br>
+       (Useful for locking a database before accessing; see
+       also visible_cells())</td>
+   </tr><tr>
+   <td>\p Fl_Table::CONTEXT_ENDPAGE</td>
+   <td>When table has completed being redrawn.<br>
+       R/C will be zero, X/Y/W/H dimensions of table's data area.<br>
+       (Useful for unlocking a database after accessing)</td>
+   </tr><tr>
+   <td>\p Fl_Table::CONTEXT_ROW_HEADER</td>
+   <td>Whenever a row header cell needs to be drawn.<br>
+       R will be the row number of the header being redrawn,<br>
+       C will be zero,<br>
+       X/Y/W/H will be the fltk drawing area of the row header in the window </td>
+   </tr><tr>
+   <td>\p Fl_Table::CONTEXT_COL_HEADER</td>
+   <td>Whenever a column header cell needs to be drawn.<br>
+       R will be zero, <br>
+       C will be the column number of the header being redrawn,<br>
+       X/Y/W/H will be the fltk drawing area of the column header in the window </td>
+   </tr><tr>
+   <td>\p Fl_Table::CONTEXT_CELL</td>
+   <td>Whenever a data cell in the table needs to be drawn.<br>
+       R/C will be the row/column of the cell to be drawn,<br>
+       X/Y/W/H will be the fltk drawing area of the cell in the window </td>
+   </tr><tr>
+   <td>\p Fl_Table::CONTEXT_RC_RESIZE</td>
+   <td>Whenever table or row/column is resized or scrolled,
+       either interactively or via col_width() or row_height().<br>
+       R/C/X/Y/W/H will all be zero.
+       <p> 
+       Useful for fltk containers that need to resize or move
+       the child fltk widgets.</td>
+   </tr>
+   </table>
+   
+   \p row and \p col will be set to the row and column number
+   of the cell being drawn. In the case of row headers, \p col will be \a 0.
+   In the case of column headers, \p row will be \a 0.
+   
+   <tt>x/y/w/h</tt> will be the position and dimensions of where the cell
+   should be drawn.
+   
+   In the case of custom widgets, a minimal draw_cell() override might
+   look like the following. With custom widgets it is up to the caller to handle
+   drawing everything within the dimensions of the cell, including handling the
+   selection color.  Note all clipping must be handled as well; this allows drawing
+   outside the dimensions of the cell if so desired for 'custom effects'.
+   
+   \code
+   // This is called whenever Fl_Table wants you to draw a cell
+   void MyTable::draw_cell(TableContext context, int R=0, int C=0, int X=0, int Y=0, int W=0, int H=0) {
+       static char s[40];
+       sprintf(s, "%d/%d", R, C);              // text for each cell
+       switch ( context ) {
+	   case CONTEXT_STARTPAGE:             // Fl_Table telling us its starting to draw page
+	       fl_font(FL_HELVETICA, 16);
+	       return;
+       
+	   case CONTEXT_ROW_HEADER:            // Fl_Table telling us it's draw row/col headers
+	   case CONTEXT_COL_HEADER:
+	       fl_push_clip(X, Y, W, H);
+	       {
+		   fl_draw_box(FL_THIN_UP_BOX, X, Y, W, H, color());
+		   fl_color(FL_BLACK);
+		   fl_draw(s, X, Y, W, H, FL_ALIGN_CENTER);
+	       }
+	       fl_pop_clip();
+	       return;
+	   
+	   case CONTEXT_CELL:                  // Fl_Table telling us to draw cells
+	       fl_push_clip(X, Y, W, H);
+	       {
+		   // BG COLOR
+		   fl_color( row_selected(R) ? selection_color() : FL_WHITE);
+		   fl_rectf(X, Y, W, H);
+		   
+		   // TEXT
+		   fl_color(FL_BLACK);
+		   fl_draw(s, X, Y, W, H, FL_ALIGN_CENTER);
+		   
+		   // BORDER
+		   fl_color(FL_LIGHT2);
+		   fl_rect(X, Y, W, H);
+	       }
+	       fl_pop_clip();
+	       return;
+	   
+       default:
+	   return;
+       }
+       //NOTREACHED
+   }
+   \endcode
+   */
+  virtual void draw_cell(TableContext context, int R=0, int C=0, 
+                         int X=0, int Y=0, int W=0, int H=0)
+  { }						// overridden by deriving class
+  
+  long row_scroll_position(int row);		// find scroll position of row (in pixels)
+  long col_scroll_position(int col);		// find scroll position of col (in pixels)
+  
+  int is_fltk_container() { 			// does table contain fltk widgets?
+    return( Fl_Group::children() > 3 );		// (ie. more than box and 2 scrollbars?)
+  }
+  
+  static void scroll_cb(Fl_Widget*,void*);	// h/v scrollbar callback
+  
+  void damage_zone(int r1, int c1, int r2, int c2, int r3 = 0, int c3 = 0);
+  
+  void redraw_range(int toprow, int botrow, int leftcol, int rightcol) {
+    if ( _redraw_toprow == -1 ) {
+      // Initialize redraw range
+      _redraw_toprow = toprow;
+      _redraw_botrow = botrow;
+      _redraw_leftcol = leftcol;
+      _redraw_rightcol = rightcol;
+    } else {
+      // Extend redraw range
+      if ( toprow < _redraw_toprow ) _redraw_toprow = toprow;
+      if ( botrow > _redraw_botrow ) _redraw_botrow = botrow;
+      if ( leftcol < _redraw_leftcol ) _redraw_leftcol = leftcol;
+      if ( rightcol > _redraw_rightcol ) _redraw_rightcol = rightcol;
+    }
+    
+    // Indicate partial redraw needed of some cells
+    damage(FL_DAMAGE_CHILD);
+  }
+  
+public:
+  /**
+   The constructor for the Fl_Table.
+   This creates an empty table with no rows or columns,
+   with headers and row/column resize behavior disabled.
+   */
+  Fl_Table(int X, int Y, int W, int H, const char *l=0);
+  
+  /**
+   The destructor for the Fl_Table.
+   Destroys the table and its associated widgets.
+   */
+  ~Fl_Table();
+  
+  /**
+   Clears the table to zero rows, zero columns.
+   Same as rows(0); cols(0);
+   \see rows(int), cols(int)
+   */
+  virtual void clear() { rows(0); cols(0); }
+  
+  // \todo: add topline(), middleline(), bottomline()
+  
+  /**
+   Sets the kind of box drawn around the data table,
+   the default being FL_NO_BOX. Changing this value will cause the table
+   to redraw.
+   */
+  inline void table_box(Fl_Boxtype val) {
+    table->box(val);
+    table_resized();
+  }
+  
+  /**
+   Returns the current box type used for the data table.
+   */
+  inline Fl_Boxtype table_box( void ) {
+    return(table->box());
+  }
+  
+  /**
+   Sets the number of rows in the table, and the table is redrawn.
+   */
+  virtual void rows(int val);			// set/get number of rows
+  
+  /**
+   Returns the number of rows in the table.
+   */
+  inline int rows() {
+    return(_rows);
+  }
+  
+  /**
+   Set the number of columns in the table and redraw.
+   */
+  virtual void cols(int val);			// set/get number of columns
+  
+  /** 
+   Get the number of columns in the table.
+   */
+  inline int cols() {
+    return(_cols);
+  }
+  
+  /**
+   Returns the range of row and column numbers for all visible 
+   and partially visible cells in the table.
+   
+   These values can be used e.g. by your draw_cell() routine during
+   CONTEXT_STARTPAGE to figure out what cells are about to be redrawn
+   for the purposes of locking the data from a database before it's drawn.
+   
+   \code
+          leftcol             rightcol
+             :                   :
+   toprow .. .-------------------.
+             |                   |
+             |  V I S I B L E    |
+             |                   |
+             |    T A B L E      |
+             |                   |
+   botrow .. '-------------------`
+   \endcode
+   
+   e.g. in a table where the visible rows are 5-20, and the
+   visible columns are 100-120, then those variables would be:
+   
+   - toprow = 5
+   - botrow = 20
+   - leftcol = 100
+   - rightcol = 120
+   */
+  inline void visible_cells(int& r1, int& r2, int& c1, int& c2) {
+    r1 = toprow;
+    r2 = botrow;
+    c1 = leftcol;
+    c2 = rightcol;
+  } 
+  
+  /**
+   Returns 1 if someone is interactively resizing a row or column.
+   You can currently call this only from within your callback().
+   */
+  int is_interactive_resize() {
+    return(_resizing_row != -1 || _resizing_col != -1);
+  } 
+  
+  /**
+   Returns the current value of this flag.
+   */
+  inline int row_resize() {
+    return(_row_resize);
+  }
+  
+  /**
+   Allows/disallows row resizing by the user.
+   1=allow interactive resizing, 0=disallow interactive resizing.
+   Since interactive resizing is done via the row headers,
+   row_header() must also be enabled to allow resizing.
+   */   
+  void row_resize(int flag) {			// enable row resizing
+    _row_resize = flag;
+  }
+  
+  /**
+   Returns the current value of this flag.
+   */
+  inline int col_resize() {
+    return(_col_resize);
+  }
+  /**
+   Allows/disallows column resizing by the user.
+   1=allow interactive resizing, 0=disallow interactive resizing.
+   Since interactive resizing is done via the column headers,
+   \p col_header() must also be enabled to allow resizing.
+   */
+  void col_resize(int flag) {			// enable col resizing
+    _col_resize = flag;
+  }
+  
+  /**
+   Sets the current column minimum resize value.
+   This is used to prevent the user from interactively resizing
+   any column to be smaller than 'pixels'. Must be a value >=1.
+   */
+  inline int col_resize_min() {			// column minimum resizing width
+    return(_col_resize_min);
+  }
+  
+  /**
+   Returns the current column minimum resize value.
+   */
+  void col_resize_min(int val) {
+    _col_resize_min = ( val < 1 ) ? 1 : val;
+  } 
+  
+  /**
+   Returns the current row minimum resize value.
+   */
+  inline int row_resize_min() {			// column minimum resizing width
+    return(_row_resize_min);
+  }
+  
+  /**
+   Sets the current row minimum resize value.
+   This is used to prevent the user from interactively resizing
+   any row to be smaller than 'pixels'. Must be a value >=1.
+   */
+  void row_resize_min(int val) {
+    _row_resize_min = ( val < 1 ) ? 1 : val;
+  }
+  
+  /**
+   Returns the value of this flag.
+   */
+  inline int row_header() {			// set/get row header enable flag
+    return(_row_header);
+  }
+  
+  /**
+   Enables/disables showing the row headers. 1=enabled, 0=disabled.
+   If changed, the table is redrawn.
+   */
+  void row_header(int flag) {
+    _row_header = flag;
+    table_resized();
+    redraw();
+  }
+  
+  /**
+   Returns if column headers are enabled or not.
+   */
+  inline int col_header() {			// set/get col header enable flag
+    return(_col_header);
+  }
+  
+  /**
+   Enable or disable column headers.
+   If changed, the table is redrawn.
+   */
+  void col_header(int flag) {
+    _col_header = flag;
+    table_resized();
+    redraw();
+  }
+  
+  /**
+   Sets the height in pixels for column headers and redraws the table.
+   */
+  inline void col_header_height(int height) {	// set/get col header height
+    _col_header_h = height;
+    table_resized();
+    redraw();
+  }
+  
+  /**
+   Gets the column header height.
+   */
+  inline int col_header_height() {
+    return(_col_header_h);
+  }
+  
+  /**
+   Sets the row header width to n and causes the screen to redraw.
+   */
+  inline void row_header_width(int width) {	// set/get row header width
+    _row_header_w = width;
+    table_resized();
+    redraw();
+  }
+  
+  /**
+   Returns the current row header width (in pixels).
+   */
+  inline int row_header_width() {
+    return(_row_header_w);
+  }
+  
+  /**
+   Sets the row header color and causes the screen to redraw.
+   */
+  inline void row_header_color(Fl_Color val) {	// set/get row header color
+    _row_header_color = val;
+    redraw();
+  }
+  
+  /**
+   Returns the current row header color.
+   */
+  inline Fl_Color row_header_color() {
+    return(_row_header_color);
+  } 
+  
+  /**
+   Sets the color for column headers and redraws the table.
+   */
+  inline void col_header_color(Fl_Color val) {	// set/get col header color
+    _col_header_color = val;
+    redraw();
+  }
+  
+  /**
+   Gets the color for column headers.
+   */
+  inline Fl_Color col_header_color() {
+    return(_col_header_color);
+  }
+  
+  /**
+   Sets the height of the specified row in pixels,
+   and the table is redrawn.
+   callback() will be invoked with CONTEXT_RC_RESIZE
+   if the row's height was actually changed, and when() is FL_WHEN_CHANGED.
+   */
+  void row_height(int row, int height);		// set/get row height
+  
+  /**
+   Returns the current height of the specified row as a value in pixels.
+   */
+  inline int row_height(int row) {
+    return((row<0 || row>=(int)_rowheights.size()) ? 0 : _rowheights[row]);
+  }
+  
+  /**
+   Sets the width of the specified column in pixels, and the table is redrawn.
+   callback() will be invoked with CONTEXT_RC_RESIZE
+   if the column's width was actually changed, and when() is FL_WHEN_CHANGED.
+   */   
+  void col_width(int col, int width);		// set/get a column's width
+  
+  /**
+   Returns the current width of the specified column in pixels.
+   */
+  inline int col_width(int col) {
+    return((col<0 || col>=(int)_colwidths.size()) ? 0 : _colwidths[col]);
+  }
+  
+  /**
+   Convenience method to set the height of all rows to the
+   same value, in pixels. The screen is redrawn.
+   */
+  void row_height_all(int height) {		// set all row/col heights
+    for ( int r=0; r<rows(); r++ ) {
+      row_height(r, height);
+    }
+  }
+  
+  /**
+   Convenience method to set the width of all columns to the
+   same value, in pixels. The screen is redrawn.
+   */
+  void col_width_all(int width) {
+    for ( int c=0; c<cols(); c++ ) {
+      col_width(c, width);
+    }
+  }
+  
+  /**
+   Sets the row scroll position to 'row', and causes the screen to redraw.
+   */
+  void row_position(int row);			// set/get table's current scroll position
+  
+  /** 
+   Sets the column scroll position to column 'col', and causes the screen to redraw.
+   */
+  void col_position(int col);
+  
+  /**
+   Returns the current row scroll position as a row number.
+   */
+  int row_position() {				// current row position
+    return(_row_position);
+  }
+  
+  /**
+   Returns the current column scroll position as a column number.
+   */
+  int col_position() {				// current col position
+    return(_col_position);
+  }
+  
+  /**
+   Sets which row should be at the top of the table,
+   scrolling as necessary, and the table is redrawn. If the table
+   cannot be scrolled that far, it is scrolled as far as possible.
+   */
+  inline void top_row(int row) {		// set/get top row (deprecated)
+    row_position(row);
+  }
+  
+  /**
+   Returns the current top row shown in the table.
+   This row may be partially obscured.
+   */
+  inline int top_row() {
+    return(row_position());
+  }
+  int is_selected(int r, int c);		// selected cell
+  void get_selection(int &row_top, int &col_left, int &row_bot, int &col_right);
+  void set_selection(int row_top, int col_left, int row_bot, int col_right);
+  int move_cursor(int R, int C);
+  
+  /**
+   Changes the size of the Fl_Table, causing it to redraw.
+   */
+  void resize(int X, int Y, int W, int H);	// fltk resize() override
+  void draw(void);				// fltk draw() override
+  
+  // This crashes sortapp() during init.
+  //  void box(Fl_Boxtype val) {
+  //    Fl_Group::box(val);
+  //    if ( table ) {
+  //      resize(x(), y(), w(), h());
+  //    }
+  //  }
+  //  Fl_Boxtype box(void) const {
+  //    return(Fl_Group::box());
+  //  }
+  
+  // Child group
+  void init_sizes() {
+    table->init_sizes();
+    table->redraw();
+  }
+  void add(Fl_Widget& w) {
+    table->add(w);
+  }
+  void add(Fl_Widget* w) {
+    table->add(w);
+  }
+  void insert(Fl_Widget& w, int n) {
+    table->insert(w,n);
+  }
+  void insert(Fl_Widget& w, Fl_Widget* w2) {
+    table->insert(w,w2);
+  }
+  void remove(Fl_Widget& w) {
+    table->remove(w);
+  }
+  void begin() {
+    table->begin();
+  }
+  void end() {
+    table->end();
+    // HACK: Avoid showing Fl_Scroll; seems to erase screen
+    //       causing unnecessary flicker, even if its box() is FL_NO_BOX.
+    //
+    if ( table->children() > 2 ) {
+      table->show();
+    } else {
+      table->hide();
+    } 
+    Fl_Group::current(Fl_Group::parent());
+  }
+  Fl_Widget * const *array() {
+    return(table->array());
+  }
+  
+  /**
+   Returns the child widget by an index.
+   
+   When using the Fl_Table as a container for FLTK widgets, this method returns 
+   the widget pointer from the internal array of widgets in the container.
+   
+   Typically used in loops, eg:
+   \code
+   for ( int i=0; i<children(); i++ ) {
+     Fl_Widget *w = child(i);
+     [..]
+   }
+   \endcode
+   */
+  Fl_Widget *child(int n) const {
+    return(table->child(n));
+  }
+  
+  /**
+   Returns the number of children in the table.
+   
+   When using the Fl_Table as a container for FLTK widgets, this method returns 
+   how many child widgets the table has.
+   
+   \see child(int)
+   */
+  int children() const {
+    return(table->children()-2);    // -2: skip Fl_Scroll's h/v scrollbar widgets
+  }
+  int find(const Fl_Widget *w) const {
+    return(table->find(w));
+  }
+  int find(const Fl_Widget &w) const {
+    return(table->find(w));
+  } 
+  // CALLBACKS
+  
+  /**
+   * Returns the current row the event occurred on.
+   *
+   * This function should only be used from within the user's callback function
+   */
+  int callback_row() {
+    return(_callback_row);
+  }
+  
+  /**
+   * Returns the current column the event occurred on.
+   *
+   * This function should only be used from within the user's callback function
+   */
+  int callback_col() {
+    return(_callback_col);
+  }
+  
+  /**
+   * Returns the current 'table context'.
+   *
+   * This function should only be used from within the user's callback function
+   */
+  TableContext callback_context() {
+    return(_callback_context);
+  }
+  
+  void do_callback(TableContext context, int row, int col) {
+    _callback_context = context;
+    _callback_row = row;
+    _callback_col = col;
+    Fl_Widget::do_callback();
+  }
+  
+#if FL_DOXYGEN
+  /**
+   The Fl_Widget::when() function is used to set a group of flags, determining
+   when the widget callback is called:
+   
+   <table border=1>
+   <tr>
+   <td>\p FL_WHEN_CHANGED</td>
+   <td>
+   callback() will be called when rows or columns are resized (interactively or 
+   via col_width() or row_height()), passing CONTEXT_RC_RESIZE via 
+   callback_context().
+   </td>
+   </tr><tr>
+   <td>\p FL_WHEN_RELEASE</td>
+   <td>
+   callback() will be called during FL_RELEASE events, such as when someone 
+   releases a mouse button somewhere on the table.
+   </td>
+   </tr>
+   </table>
+   
+   The callback() routine is sent a TableContext that indicates the context the 
+   event occurred in, such as in a cell, in a header, or elsewhere on the table.  
+   When an event occurs in a cell or header, callback_row() and 
+   callback_col() can be used to determine the row and column. The callback can 
+   also look at the regular fltk event values (ie. Fl::event() and Fl::button()) 
+   to determine what kind of event is occurring.
+   */
+  void when(Fl_When flags);
+#endif
+  
+#if FL_DOXYGEN
+  /**
+   Callbacks will be called depending on the setting of Fl_Widget::when().
+   
+   Callback functions should use the following functions to determine the 
+   context/row/column:
+   
+   * Fl_Table::callback_row() returns current row
+   * Fl_Table::callback_col() returns current column
+   * Fl_Table::callback_context() returns current table context
+   
+   callback_row() and callback_col() will be set to the row and column number the 
+   event occurred on. If someone clicked on a row header, \p col will be \a 0.  
+   If someone clicked on a column header, \p row will be \a 0.
+   
+   callback_context() will return one of the following:
+   
+   <table border=1>
+   <tr><td><tt>Fl_Table::CONTEXT_ROW_HEADER</tt></td>
+   <td>Someone clicked on a row header. Excludes resizing.</td>
+   </tr><tr>
+   <td><tt>Fl_Table::CONTEXT_COL_HEADER</tt></td>
+   <td>Someone clicked on a column header. Excludes resizing.</td>
+   </tr><tr>
+   <td><tt>Fl_Table::CONTEXT_CELL</tt></td>
+   <td>
+   Someone clicked on a cell.
+   
+   To receive callbacks for FL_RELEASE events, you must set
+   when(FL_WHEN_RELEASE).
+   </td>
+   </tr><tr>
+   <td><tt>Fl_Table::CONTEXT_RC_RESIZE</tt></td>
+   <td>
+   Someone is resizing rows/columns either interactively,
+   or via the col_width() or row_height() API.
+   
+   Use is_interactive_resize()
+   to determine interactive resizing.
+   
+   If resizing a column, R=0 and C=column being resized.
+   
+   If resizing a row, C=0 and R=row being resized.
+   
+   NOTE: To receive resize events, you must set when(FL_WHEN_CHANGED).
+   </td>
+   </tr>
+   </table>
+   
+   \code
+   class MyTable : public Fl_Table {
+     [..]
+   private:
+     // Handle events that happen on the table
+     void event_callback2() {
+       int R = callback_row(),                         // row where event occurred
+       C = callback_col();                             // column where event occurred
+       TableContext context = callback_context();      // which part of table
+       fprintf(stderr, "callback: Row=%d Col=%d Context=%d Event=%d\n",
+               R, C, (int)context, (int)Fl::event());
+     }
+   
+     // Actual static callback
+     static void event_callback(Fl_Widget*, void* data) {
+       MyTable *o = (MyTable*)data;
+       o-&gt;event_callback2();
+     }
+     
+   public:
+     // Constructor
+     MyTable() {
+       [..]
+       table.callback(&event_callback, (void*)this);   // setup callback
+       table.when(FL_WHEN_CHANGED|FL_WHEN_RELEASE);    // when to call it
+     }
+   };
+   \endcode
+   */
+  void callback(Fl_Widget*, void*);
+#endif
+};
+
+#endif /*_FL_TABLE_H*/
+
+//
+// End of "$Id: Fl_Table.H 8301 2011-01-22 22:40:11Z AlbrechtS $".
+//