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_Widget.cxx b/common/fltk/src/Fl_Widget.cxx
new file mode 100644
index 0000000..96754a9
--- /dev/null
+++ b/common/fltk/src/Fl_Widget.cxx
@@ -0,0 +1,345 @@
+//
+// "$Id: Fl_Widget.cxx 7940 2010-12-02 17:58:58Z greg.ercolano $"
+//
+// Base widget class 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
+//
+
+#include <FL/Fl.H>
+#include <FL/Fl_Widget.H>
+#include <FL/Fl_Group.H>
+#include <FL/Fl_Tooltip.H>
+#include <FL/fl_draw.H>
+#include <stdlib.h>
+#include "flstring.h"
+
+
+////////////////////////////////////////////////////////////////
+// for compatibility with Forms, all widgets without callbacks are
+// inserted into a "queue" when they are activated, and the forms
+// compatibility interaction functions (fl_do_events, etc.) will
+// read one widget at a time from this queue and return it:
+
+const int QUEUE_SIZE = 20;
+
+static Fl_Widget *obj_queue[QUEUE_SIZE];
+static int obj_head, obj_tail;
+
+void Fl_Widget::default_callback(Fl_Widget *o, void * /*v*/) {
+#if 0
+  // This is necessary for strict forms compatibility but is confusing.
+  // Use the parent's callback if this widget does not have one.
+  for (Fl_Widget *p = o->parent(); p; p = p->parent())
+    if (p->callback() != default_callback) {
+      p->do_callback(o,v);
+      return;
+    }
+#endif
+  obj_queue[obj_head++] = o;
+  if (obj_head >= QUEUE_SIZE) obj_head = 0;
+  if (obj_head == obj_tail) {
+    obj_tail++;
+    if (obj_tail >= QUEUE_SIZE) obj_tail = 0;
+  }
+}
+/**
+    All Fl_Widgets that don't have a callback defined use a
+    default callback that puts a pointer to the widget in this queue,
+    and this method reads the oldest widget out of this queue.
+*/
+Fl_Widget *Fl::readqueue() {
+  if (obj_tail==obj_head) return 0;
+  Fl_Widget *o = obj_queue[obj_tail++];
+  if (obj_tail >= QUEUE_SIZE) obj_tail = 0;
+  return o;
+}
+/*
+    This static internal function removes all pending callbacks for a
+    specific widget from the default callback queue (Fl::readqueue()).
+    It is only called from Fl_Widget's destructor if the widget
+    doesn't have an own callback.
+    Note: There's no need to have this in the Fl:: namespace.
+*/
+static void cleanup_readqueue(Fl_Widget *w) {
+
+  if (obj_tail==obj_head) return;
+  
+  // Read the entire queue and copy over all valid entries.
+  // The new head will be determined after the last copied entry.
+
+  int old_head = obj_head;	// save newest entry
+  int entry = obj_tail;		// oldest entry
+  obj_head = obj_tail;		// new queue start
+  for (;;) {
+    Fl_Widget *o = obj_queue[entry++];
+    if (entry >= QUEUE_SIZE) entry = 0;
+    if (o != w) { // valid entry
+      obj_queue[obj_head++] = o;
+      if (obj_head >= QUEUE_SIZE) obj_head = 0;
+    } // valid entry
+    if (entry == old_head) break;
+  }
+  return;
+}
+////////////////////////////////////////////////////////////////
+
+int Fl_Widget::handle(int) {
+  return 0;
+}
+
+/** Default font size for widgets */
+Fl_Fontsize FL_NORMAL_SIZE = 14;
+
+Fl_Widget::Fl_Widget(int X, int Y, int W, int H, const char* L) {
+
+  x_ = X; y_ = Y; w_ = W; h_ = H;
+
+  label_.value	 = L;
+  label_.image   = 0;
+  label_.deimage = 0;
+  label_.type	 = FL_NORMAL_LABEL;
+  label_.font	 = FL_HELVETICA;
+  label_.size	 = FL_NORMAL_SIZE;
+  label_.color	 = FL_FOREGROUND_COLOR;
+  label_.align_	 = FL_ALIGN_CENTER;
+  tooltip_       = 0;
+  callback_	 = default_callback;
+  user_data_ 	 = 0;
+  type_		 = 0;
+  flags_	 = VISIBLE_FOCUS;
+  damage_	 = 0;
+  box_		 = FL_NO_BOX;
+  color_	 = FL_GRAY;
+  color2_	 = FL_GRAY;
+  when_		 = FL_WHEN_RELEASE;
+
+  parent_ = 0;
+  if (Fl_Group::current()) Fl_Group::current()->add(this);
+}
+
+void Fl_Widget::resize(int X, int Y, int W, int H) {
+  x_ = X; y_ = Y; w_ = W; h_ = H;
+}
+
+// this is useful for parent widgets to call to resize children:
+int Fl_Widget::damage_resize(int X, int Y, int W, int H) {
+  if (x() == X && y() == Y && w() == W && h() == H) return 0;
+  resize(X, Y, W, H);
+  redraw();
+  return 1;
+}
+
+int Fl_Widget::take_focus() {
+  if (!takesevents()) return 0;
+  if (!visible_focus()) return 0;
+  if (!handle(FL_FOCUS)) return 0; // see if it wants it
+  if (contains(Fl::focus())) return 1; // it called Fl::focus for us
+  Fl::focus(this);
+  return 1;
+}
+
+extern void fl_throw_focus(Fl_Widget*); // in Fl_x.cxx
+
+/**
+   Destroys the widget, taking care of throwing focus before if any.
+   Destruction removes the widget from any parent group! And groups when
+   destroyed destroy all their children. This is convenient and fast.
+*/
+Fl_Widget::~Fl_Widget() {
+  Fl::clear_widget_pointer(this);
+  if (flags() & COPIED_LABEL) free((void *)(label_.value));
+  if (flags() & COPIED_TOOLTIP) free((void *)(tooltip_));
+  // remove from parent group
+  if (parent_) parent_->remove(this);
+#ifdef DEBUG_DELETE
+  if (parent_) { // this should never happen
+    printf("*** Fl_Widget: parent_->remove(this) failed [%p,%p]\n",parent_,this);
+  }
+#endif // DEBUG_DELETE
+  parent_ = 0; // Don't throw focus to a parent widget.
+  fl_throw_focus(this);
+  // remove stale entries from default callback queue (Fl::readqueue())
+  if (callback_ == default_callback) cleanup_readqueue(this);
+}
+
+/** Draws a focus box for the widget at the given position and size */
+void
+Fl_Widget::draw_focus(Fl_Boxtype B, int X, int Y, int W, int H) const {
+  if (!Fl::visible_focus()) return;
+  switch (B) {
+    case FL_DOWN_BOX:
+    case FL_DOWN_FRAME:
+    case FL_THIN_DOWN_BOX:
+    case FL_THIN_DOWN_FRAME:
+      X ++;
+      Y ++;
+    default:
+      break;
+  }
+
+  fl_color(fl_contrast(FL_BLACK, color()));
+
+#if defined(USE_X11) || defined(__APPLE_QUARTZ__)
+  fl_line_style(FL_DOT);
+  fl_rect(X + Fl::box_dx(B), Y + Fl::box_dy(B),
+          W - Fl::box_dw(B) - 1, H - Fl::box_dh(B) - 1);
+  fl_line_style(FL_SOLID);
+#elif defined(WIN32) 
+  // Windows 95/98/ME do not implement the dotted line style, so draw
+  // every other pixel around the focus area...
+  //
+  // Also, QuickDraw (MacOS) does not support line styles specifically,
+  // and the hack we use in fl_line_style() will not draw horizontal lines
+  // on odd-numbered rows...
+  int i, xx, yy;
+
+  X += Fl::box_dx(B);
+  Y += Fl::box_dy(B);
+  W -= Fl::box_dw(B) + 2;
+  H -= Fl::box_dh(B) + 2;
+
+  for (xx = 0, i = 1; xx < W; xx ++, i ++) if (i & 1) fl_point(X + xx, Y);
+  for (yy = 0; yy < H; yy ++, i ++) if (i & 1) fl_point(X + W, Y + yy);
+  for (xx = W; xx > 0; xx --, i ++) if (i & 1) fl_point(X + xx, Y + H);
+  for (yy = H; yy > 0; yy --, i ++) if (i & 1) fl_point(X, Y + yy);
+#else
+# error unsupported platform
+#endif // WIN32
+}
+
+
+void Fl_Widget::activate() {
+  if (!active()) {
+    clear_flag(INACTIVE);
+    if (active_r()) {
+      redraw();
+      redraw_label();
+      handle(FL_ACTIVATE);
+      if (inside(Fl::focus())) Fl::focus()->take_focus();
+    }
+  }
+}
+
+void Fl_Widget::deactivate() {
+  if (active_r()) {
+    set_flag(INACTIVE);
+    redraw();
+    redraw_label();
+    handle(FL_DEACTIVATE);
+    fl_throw_focus(this);
+  } else {
+    set_flag(INACTIVE);
+  }
+}
+
+int Fl_Widget::active_r() const {
+  for (const Fl_Widget* o = this; o; o = o->parent())
+    if (!o->active()) return 0;
+  return 1;
+}
+
+void Fl_Widget::show() {
+  if (!visible()) {
+    clear_flag(INVISIBLE);
+    if (visible_r()) {
+      redraw();
+      redraw_label();
+      handle(FL_SHOW);
+      if (inside(Fl::focus())) Fl::focus()->take_focus();
+    }
+  }
+}
+
+void Fl_Widget::hide() {
+  if (visible_r()) {
+    set_flag(INVISIBLE);
+    for (Fl_Widget *p = parent(); p; p = p->parent())
+      if (p->box() || !p->parent()) {p->redraw(); break;}
+    handle(FL_HIDE);
+    fl_throw_focus(this);
+  } else {
+    set_flag(INVISIBLE);
+  }
+}
+
+int Fl_Widget::visible_r() const {
+  for (const Fl_Widget* o = this; o; o = o->parent())
+    if (!o->visible()) return 0;
+  return 1;
+}
+
+// return true if widget is inside (or equal to) this:
+// Returns false for null widgets.
+int Fl_Widget::contains(const Fl_Widget *o) const {
+  for (; o; o = o->parent_) if (o == this) return 1;
+  return 0;
+}
+
+
+void
+Fl_Widget::label(const char *a) {
+  if (flags() & COPIED_LABEL) {
+    // reassigning a copied label remains the same copied label
+    if (label_.value == a)
+      return;
+    free((void *)(label_.value));
+    clear_flag(COPIED_LABEL);
+  }
+  label_.value=a;
+  redraw_label();
+}
+
+
+void
+Fl_Widget::copy_label(const char *a) {
+  if (flags() & COPIED_LABEL) free((void *)(label_.value));
+  if (a) {
+    set_flag(COPIED_LABEL);
+    label_.value=strdup(a);
+  } else {
+    clear_flag(COPIED_LABEL);
+    label_.value=(char *)0;
+  }
+  redraw_label();
+}
+
+/** Calls the widget callback.
+
+  Causes a widget to invoke its callback function with arbitrary arguments.
+
+  \param[in] o call the callback with \p o as the widget argument
+  \param[in] arg use \p arg as the user data argument
+  \see callback()
+*/
+void
+Fl_Widget::do_callback(Fl_Widget* o,void* arg) {
+  Fl_Widget_Tracker wp(this);
+  callback_(o,arg);
+  if (wp.deleted()) return;
+  if (callback_ != default_callback)
+    clear_changed();
+}
+
+//
+// End of "$Id: Fl_Widget.cxx 7940 2010-12-02 17:58:58Z greg.ercolano $".
+//