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_Table_Row.cxx b/common/fltk/src/Fl_Table_Row.cxx
new file mode 100644
index 0000000..6e24bba
--- /dev/null
+++ b/common/fltk/src/Fl_Table_Row.cxx
@@ -0,0 +1,316 @@
+//
+// "$Id: Fl_Table_Row.cxx 7950 2010-12-05 01:22:53Z greg.ercolano $"
+//
+// Fl_Table_Row -- A row oriented table widget
+//
+//    A class specializing in a table of rows.
+//    Handles row-specific selection behavior.
+//
+// Copyright 2002 by Greg Ercolano.
+//
+// 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 Row headings (only column headings supported currently)
+//
+
+#include <stdio.h>		// for debugging
+#include <FL/Fl.H>
+#include <FL/fl_draw.H>
+#include <FL/Fl_Table_Row.H>
+
+// Is row selected?
+int Fl_Table_Row::row_selected(int row) {
+  if ( row < 0 || row >= rows() ) return(-1);
+  return(_rowselect[row]);
+}
+
+// Change row selection type
+void Fl_Table_Row::type(TableRowSelectMode val) {
+  _selectmode = val;
+  switch ( _selectmode ) {
+    case SELECT_NONE: {
+      for ( int row=0; row<rows(); row++ ) {
+        _rowselect[row] = 0;
+      }
+      redraw();
+      break;
+    }
+    case SELECT_SINGLE: {
+      int count = 0;
+      for ( int row=0; row<rows(); row++ ) {
+        if ( _rowselect[row] ) {
+          if ( ++count > 1 ) {	// only one allowed
+            _rowselect[row] = 0;
+          }
+        }
+      }
+      redraw();
+      break;
+    }
+    case SELECT_MULTI:
+      break;
+  }
+}
+
+// Change selection state for row
+//
+//     flag:
+//        0 - clear selection
+//        1 - set selection
+//        2 - toggle selection
+//
+//     Returns:
+//        0 - selection state did not change
+//        1 - selection state changed
+//       -1 - row out of range or incorrect selection mode
+//
+int Fl_Table_Row::select_row(int row, int flag) {
+  int ret = 0;
+  if ( row < 0 || row >= rows() ) { return(-1); }
+  switch ( _selectmode ) {
+    case SELECT_NONE:
+      return(-1);
+      
+    case SELECT_SINGLE: {
+      int oldval;
+      for ( int t=0; t<rows(); t++ ) {
+        if ( t == row ) {
+          oldval = _rowselect[row];
+          if ( flag == 2 ) { _rowselect[row] ^= 1; }
+          else             { _rowselect[row] = flag; }
+          if ( oldval != _rowselect[row] ) {
+            redraw_range(row, row, leftcol, rightcol);
+            ret = 1;
+          }
+        }
+        else if ( _rowselect[t] ) {
+          _rowselect[t] = 0;
+          redraw_range(t, t, leftcol, rightcol);
+        }
+      }
+      break;
+    }
+      
+    case SELECT_MULTI: {
+      int oldval = _rowselect[row];
+      if ( flag == 2 ) { _rowselect[row] ^= 1; }
+      else             { _rowselect[row] = flag; }
+      if ( _rowselect[row] != oldval ) {		// select state changed?
+        if ( row >= toprow && row <= botrow ) {		// row visible?
+          // Extend partial redraw range
+          redraw_range(row, row, leftcol, rightcol);
+        }
+        ret = 1;
+      }
+    }
+  }
+  return(ret);
+}
+
+// Select all rows to a known state
+void Fl_Table_Row::select_all_rows(int flag) {
+  switch ( _selectmode ) {
+    case SELECT_NONE:
+      return;
+      
+    case SELECT_SINGLE:
+      if ( flag != 0 ) return;
+      //FALLTHROUGH
+      
+    case SELECT_MULTI: {
+      char changed = 0;
+      if ( flag == 2 ) {
+        for ( int row=0; row<(int)_rowselect.size(); row++ ) {
+          _rowselect[row] ^= 1;
+        }
+        changed = 1;
+      } else {
+        for ( int row=0; row<(int)_rowselect.size(); row++ ) {
+          changed |= (_rowselect[row] != flag)?1:0;
+          _rowselect[row] = flag; 
+        }
+      }
+      if ( changed ) {
+        redraw();
+      }
+    }
+  }
+}
+
+// Set number of rows
+void Fl_Table_Row::rows(int val) {
+  Fl_Table::rows(val);
+  while ( val > (int)_rowselect.size() ) { _rowselect.push_back(0); }	// enlarge
+  while ( val < (int)_rowselect.size() ) { _rowselect.pop_back(); }	// shrink
+}
+
+// #include "eventnames.h"		// debugging
+// #include <stdio.h>
+
+// Handle events
+int Fl_Table_Row::handle(int event) {
+  
+  //  fprintf(stderr, "** EVENT: %s: EVENT XY=%d,%d\n", 
+  //      eventnames[event], Fl::event_x(), Fl::event_y());	// debugging
+  
+  // Let base class handle event
+  int ret = Fl_Table::handle(event);
+  
+  // The following code disables cell selection.. why was it added? -erco 05/18/03
+  // if ( ret ) { _last_y = Fl::event_y(); return(1); }	// base class 'handled' it (eg. column resize)
+  
+  int shiftstate = (Fl::event_state() & FL_CTRL) ? FL_CTRL :
+  (Fl::event_state() & FL_SHIFT) ? FL_SHIFT : 0;
+  
+  // Which row/column are we over?
+  int R, C;  				// row/column being worked on
+  ResizeFlag resizeflag;		// which resizing area are we over? (0=none)
+  TableContext context = cursor2rowcol(R, C, resizeflag);
+  switch ( event ) {
+    case FL_PUSH:
+      if ( Fl::event_button() == 1 ) {
+        _last_push_x = Fl::event_x();	// save regardless of context
+        _last_push_y = Fl::event_y();	// " "
+        
+        // Handle selection in table.
+        //     Select cell under cursor, and enable drag selection mode.
+        //
+        if ( context == CONTEXT_CELL ) {
+          // Ctrl key? Toggle selection state
+          switch ( shiftstate ) {
+            case FL_CTRL:
+              select_row(R, 2);		// toggle
+              break;
+              
+            case FL_SHIFT: {
+              select_row(R, 1);
+              if ( _last_row > -1 ) {
+                int srow = R, erow = _last_row;
+                if ( srow > erow ) {
+                  srow = _last_row;
+                  erow = R;
+                }
+                for ( int row = srow; row <= erow; row++ ) {
+                  select_row(row, 1);
+                }
+              }
+              break;
+            }
+              
+            default:
+              select_all_rows(0);	// clear all previous selections
+              select_row(R, 1);
+              break;
+          }
+          
+          _last_row = R;
+          _dragging_select = 1;
+          ret = 1;      // FL_PUSH handled (ensures FL_DRAG will be sent)
+          // redraw();  // redraw() handled by select_row()
+        }
+      } 
+      break;
+      
+    case FL_DRAG: {
+      if ( _dragging_select ) {
+        // Dragged off table edges? Handle scrolling
+        int offtop = toy - _last_y;			// >0 if off top of table
+        int offbot = _last_y - (toy + toh);		// >0 if off bottom of table
+        
+        if ( offtop > 0 && row_position() > 0 ) {
+          // Only scroll in upward direction
+          int diff = _last_y - Fl::event_y();
+          if ( diff < 1 ) {
+            ret = 1;
+            break;
+          }
+          row_position(row_position() - diff);
+          context = CONTEXT_CELL; C = 0; R = row_position();  // HACK: fake it
+          if ( R < 0 || R > rows() ) { ret = 1; break; }      // HACK: ugly
+        }
+        else if ( offbot > 0 && botrow < rows() ) {
+          // Only scroll in downward direction
+          int diff = Fl::event_y() - _last_y;
+          if ( diff < 1 ) {
+            ret = 1;
+            break;
+          }
+          row_position(row_position() + diff);
+          context = CONTEXT_CELL; C = 0; R = botrow;		// HACK: fake it
+          if ( R < 0 || R > rows() ) { ret = 1; break; }	// HACK: ugly
+        }
+        if ( context == CONTEXT_CELL ) {
+          switch ( shiftstate ) {
+            case FL_CTRL:
+              if ( R != _last_row ) {		// toggle if dragged to new row
+                select_row(R, 2);		// 2=toggle
+              }
+              break;
+              
+            case FL_SHIFT:
+            default:
+              select_row(R, 1);
+              if ( _last_row > -1 ) {
+                int srow = R, erow = _last_row;
+                if ( srow > erow ) {
+                  srow = _last_row;
+                  erow = R;
+                }
+                for ( int row = srow; row <= erow; row++ ) {
+                  select_row(row, 1);
+                }
+              }
+              break;
+          }
+          ret = 1;				// drag handled
+          _last_row = R;
+        }
+      }
+      break;
+    }
+      
+    case FL_RELEASE:
+      if ( Fl::event_button() == 1 ) {
+        _dragging_select = 0;
+        ret = 1;			// release handled
+        // Clicked off edges of data table? 
+        //    A way for user to clear the current selection.
+        //
+        int databot = tiy + table_h,
+        dataright = tix + table_w;
+        if ( 
+            ( _last_push_x > dataright && Fl::event_x() > dataright ) ||
+            ( _last_push_y > databot && Fl::event_y() > databot )
+            ) {
+          select_all_rows(0);			// clear previous selections
+        }
+      }
+      break;
+      
+    default:
+      break;
+  }
+  _last_y = Fl::event_y();
+  return(ret);
+}
+
+//
+// End of "$Id: Fl_Table_Row.cxx 7950 2010-12-05 01:22:53Z greg.ercolano $".
+//