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_Tooltip.cxx b/common/fltk/src/Fl_Tooltip.cxx
new file mode 100644
index 0000000..05b6e23
--- /dev/null
+++ b/common/fltk/src/Fl_Tooltip.cxx
@@ -0,0 +1,351 @@
+//
+// "$Id: Fl_Tooltip.cxx 8788 2011-06-08 14:35:22Z matt $"
+//
+// Tooltip source file for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2011 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_Tooltip.H>
+#include <FL/fl_draw.H>
+#include <FL/Fl_Menu_Window.H>
+
+#include <stdio.h>
+#include <string.h>	// strdup()
+
+float		Fl_Tooltip::delay_ = 1.0f;
+float		Fl_Tooltip::hoverdelay_ = 0.2f;
+Fl_Color	Fl_Tooltip::color_ = fl_color_cube(FL_NUM_RED - 1,
+		                                   FL_NUM_GREEN - 1,
+						   FL_NUM_BLUE - 2);
+Fl_Color	Fl_Tooltip::textcolor_ = FL_BLACK;
+Fl_Font         Fl_Tooltip::font_ = FL_HELVETICA;
+Fl_Fontsize     Fl_Tooltip::size_ = -1;
+
+#define MAX_WIDTH 400
+
+static const char* tip;
+/**
+    This widget creates a tooltip box window, with no caption.
+*/
+class Fl_TooltipBox : public Fl_Menu_Window {
+public:
+  /** Creates the box window */
+  Fl_TooltipBox() : Fl_Menu_Window(0, 0) {
+    set_override();
+    set_tooltip_window();
+    end();
+  }
+  void draw();
+  void layout();
+  /** Shows the tooltip windows only if a tooltip text is available. */
+  void show() {
+    if (!tip) return;
+    
+    Fl_Menu_Window::show();
+  }
+};
+
+Fl_Widget* Fl_Tooltip::widget_ = 0;
+static Fl_TooltipBox *window = 0;
+static int Y,H;
+
+#ifdef __APPLE__
+// returns the unique tooltip window
+Fl_Window *Fl_Tooltip::current_window(void)
+{
+  return (Fl_Window*)window;
+}
+#endif
+
+void Fl_TooltipBox::layout() {
+  fl_font(Fl_Tooltip::font(), Fl_Tooltip::size());
+  int ww, hh;
+  ww = MAX_WIDTH;
+  fl_measure(tip, ww, hh, FL_ALIGN_LEFT|FL_ALIGN_WRAP|FL_ALIGN_INSIDE);
+  ww += 6; hh += 6;
+
+  // find position on the screen of the widget:
+  int ox = Fl::event_x_root();
+  int oy = Y + H+2;
+  for (Fl_Widget* p = Fl_Tooltip::current(); p; p = p->window()) {
+    oy += p->y();
+  }
+  int scr_x, scr_y, scr_w, scr_h;
+  Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h);
+  if (ox+ww > scr_x+scr_w) ox = scr_x+scr_w - ww;
+  if (ox < scr_x) ox = scr_x;
+  if (H > 30) {
+    oy = Fl::event_y_root()+13;
+    if (oy+hh > scr_y+scr_h) oy -= 23+hh;
+  } else {
+    if (oy+hh > scr_y+scr_h) oy -= (4+hh+H);
+  }
+  if (oy < scr_y) oy = scr_y;
+
+  resize(ox, oy, ww, hh);
+}
+
+void Fl_TooltipBox::draw() {
+  draw_box(FL_BORDER_BOX, 0, 0, w(), h(), Fl_Tooltip::color());
+  fl_color(Fl_Tooltip::textcolor());
+  fl_font(Fl_Tooltip::font(), Fl_Tooltip::size());
+  fl_draw(tip, 3, 3, w()-6, h()-6, Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_WRAP));
+}
+
+static char recent_tooltip;
+
+static void recent_timeout(void*) {
+#ifdef DEBUG
+  puts("recent_timeout();");
+#endif // DEBUG
+
+  recent_tooltip = 0;
+}
+
+static char recursion;
+
+static void tooltip_timeout(void*) {
+#ifdef DEBUG
+  puts("tooltip_timeout();");
+#endif // DEBUG
+
+  if (recursion) return;
+  recursion = 1;
+  if (!tip || !*tip) {
+    if (window) window->hide();
+  } else {
+    int condition = 1;
+#if !(defined(__APPLE__) || defined(WIN32))
+    condition = (Fl::grab() == NULL);
+#endif
+    if ( condition ) {
+      if (!window) window = new Fl_TooltipBox;
+      // this cast bypasses the normal Fl_Window label() code:
+      ((Fl_Widget*)window)->label(tip);
+      window->layout();
+      window->redraw();
+  //    printf("tooltip_timeout: Showing window %p with tooltip \"%s\"...\n",
+  //           window, tip ? tip : "(null)");
+      window->show();
+    }
+  }
+
+  Fl::remove_timeout(recent_timeout);
+  recent_tooltip = 1;
+  recursion = 0;
+}
+
+/**
+   This method is called when the mouse pointer enters a widget.
+   <P>If this widget or one of its parents has a tooltip, enter it. This
+   will do nothing if this is the current widget (even if the mouse moved
+   out so an exit() was done and then moved back in). If no tooltip can
+   be found do Fl_Tooltip::exit_(). If you don't want this behavior (for instance
+   if you want the tooltip to reappear when the mouse moves back in)
+   call the fancier enter_area() below.
+*/
+void Fl_Tooltip::enter_(Fl_Widget* w) {
+#ifdef DEBUG
+  printf("Fl_Tooltip::enter_(w=%p)\n", w);
+  printf("    window=%p\n", window);
+#endif // DEBUG
+
+  // find the enclosing group with a tooltip:
+  Fl_Widget* tw = w;
+  for (;;) {
+    if (!tw) {exit_(0); return;}
+    if (tw == widget_) return;
+    if (tw->tooltip()) break;
+    tw = tw->parent();
+  }
+  enter_area(w, 0, 0, w->w(), w->h(), tw->tooltip());
+}
+/** 
+     Sets the current widget target. 
+     Acts as though enter(widget) was done but does not pop up a
+     tooltip.  This is useful to prevent a tooltip from reappearing when
+     a modal overlapping window is deleted. FLTK does this automatically
+     when you click the mouse button.
+*/
+void Fl_Tooltip::current(Fl_Widget* w) {
+#ifdef DEBUG
+  printf("Fl_Tooltip::current(w=%p)\n", w);
+#endif // DEBUG
+
+  exit_(0);
+  // find the enclosing group with a tooltip:
+  Fl_Widget* tw = w;
+  for (;;) {
+    if (!tw) return;
+    if (tw->tooltip()) break;
+    tw = tw->parent();
+  }
+  // act just like Fl_Tooltip::enter_() except we can remember a zero:
+  widget_ = w;
+}
+
+// Hide any visible tooltip.
+/**  This method is called when the mouse pointer leaves a  widget. */
+void Fl_Tooltip::exit_(Fl_Widget *w) {
+#ifdef DEBUG
+  printf("Fl_Tooltip::exit_(w=%p)\n", w);
+  printf("    widget=%p, window=%p\n", widget_, window);
+#endif // DEBUG
+
+  if (!widget_ || (w && w == window)) return;
+  widget_ = 0;
+  Fl::remove_timeout(tooltip_timeout);
+  Fl::remove_timeout(recent_timeout);
+  if (window && window->visible()) window->hide();
+  if (recent_tooltip) {
+    if (Fl::event_state() & FL_BUTTONS) recent_tooltip = 0;
+    else Fl::add_timeout(Fl_Tooltip::hoverdelay(), recent_timeout);
+  }
+}
+
+// Get ready to display a tooltip. The widget and the xywh box inside
+// it define an area the tooltip is for, this along with the current
+// mouse position places the tooltip (the mouse is assumed to point
+// inside or near the box).
+/**
+  You may be able to use this to provide tooltips for internal pieces
+  of your widget. Call this after setting Fl::belowmouse() to
+  your widget (because that calls the above enter() method). Then figure
+  out what thing the mouse is pointing at, and call this with the widget
+  (this pointer is used to remove the tooltip if the widget is deleted
+  or hidden, and to locate the tooltip), the rectangle surrounding the
+  area, relative to the top-left corner of the widget (used to calculate
+  where to put the tooltip), and the text of the tooltip (which must be
+  a pointer to static data as it is not copied).
+*/
+void Fl_Tooltip::enter_area(Fl_Widget* wid, int x,int y,int w,int h, const char* t)
+{
+  (void)x;
+  (void)w;
+
+#ifdef DEBUG
+  printf("Fl_Tooltip::enter_area(wid=%p, x=%d, y=%d, w=%d, h=%d, t=\"%s\")\n",
+         wid, x, y, w, h, t ? t : "(null)");
+  printf("    recursion=%d, window=%p\n", recursion, window);
+#endif // DEBUG
+
+  if (recursion) return;
+  if (!t || !*t || !enabled()) {
+    exit_(0);
+    return;
+  }
+  // do nothing if it is the same:
+  if (wid==widget_ /*&& x==X && y==Y && w==W && h==H*/ && t==tip) return;
+  Fl::remove_timeout(tooltip_timeout);
+  Fl::remove_timeout(recent_timeout);
+  // remember it:
+  widget_ = wid; Y = y; H = h; tip = t;
+  // popup the tooltip immediately if it was recently up:
+  if (recent_tooltip) {
+    if (window) window->hide();
+    Fl::add_timeout(Fl_Tooltip::hoverdelay(), tooltip_timeout);
+  } else if (Fl_Tooltip::delay() < .1) {
+#ifdef WIN32
+    // possible fix for the Windows titlebar, it seems to want the
+    // window to be destroyed, moving it messes up the parenting:
+    if (window && window->visible()) window->hide();
+#endif // WIN32
+    tooltip_timeout(0);
+  } else {
+    if (window && window->visible()) window->hide();
+    Fl::add_timeout(Fl_Tooltip::delay(), tooltip_timeout);
+  }
+
+#ifdef DEBUG
+  printf("    tip=\"%s\", window->shown()=%d\n", tip ? tip : "(null)",
+         window ? window->shown() : 0);
+#endif // DEBUG
+}
+
+void Fl_Tooltip::set_enter_exit_once_() {
+  static char beenhere = 0;
+  if (!beenhere) {
+    beenhere          = 1;
+    Fl_Tooltip::enter = Fl_Tooltip::enter_;
+    Fl_Tooltip::exit  = Fl_Tooltip::exit_;
+  }
+}
+
+/**
+  Sets the current tooltip text. 
+
+  Sets a string of text to display in a popup tooltip window when the user 
+  hovers the mouse over the widget. The string is <I>not</I> copied, so 
+  make sure any formatted string is stored in a static, global, 
+  or allocated buffer. If you want a copy made and managed for you,
+  use the copy_tooltip() method, which will manage the tooltip string
+  automatically.
+
+  If no tooltip is set, the tooltip of the parent is inherited. Setting a 
+  tooltip for a group and setting no tooltip for a child will show the 
+  group's tooltip instead. To avoid this behavior, you can set the child's 
+  tooltip to an empty string ("").
+  \param[in] text New tooltip text (no copy is made)
+  \see copy_tooltip(const char*), tooltip()
+*/
+void Fl_Widget::tooltip(const char *text) {
+  Fl_Tooltip::set_enter_exit_once_();
+  if (flags() & COPIED_TOOLTIP) {
+    // reassigning a copied tooltip remains the same copied tooltip
+    if (tooltip_ == text) return;
+    free((void*)(tooltip_));            // free maintained copy
+    clear_flag(COPIED_TOOLTIP);         // disable copy flag (WE don't make copies)
+  }
+  tooltip_ = text;
+}
+
+/**
+  Sets the current tooltip text. 
+  Unlike tooltip(), this method allocates a copy of the tooltip 
+  string instead of using the original string pointer.
+
+  The internal copy will automatically be freed whenever you assign
+  a new tooltip or when the widget is destroyed.
+
+  If no tooltip is set, the tooltip of the parent is inherited. Setting a 
+  tooltip for a group and setting no tooltip for a child will show the 
+  group's tooltip instead. To avoid this behavior, you can set the child's 
+  tooltip to an empty string ("").
+  \param[in] text New tooltip text (an internal copy is made and managed)
+  \see tooltip(const char*), tooltip()
+*/
+void Fl_Widget::copy_tooltip(const char *text) {
+  Fl_Tooltip::set_enter_exit_once_();
+  if (flags() & COPIED_TOOLTIP) free((void *)(tooltip_));
+  if (text) {
+    set_flag(COPIED_TOOLTIP);
+    tooltip_ = strdup(text);
+  } else {
+    clear_flag(COPIED_TOOLTIP);
+    tooltip_ = (char *)0;
+  }
+}
+
+//
+// End of "$Id: Fl_Tooltip.cxx 8788 2011-06-08 14:35:22Z matt $".
+//