diff options
| author | Yuval Adam <yuv.adm@gmail.com> | 2014-08-08 14:42:07 +0300 |
|---|---|---|
| committer | Yuval Adam <yuv.adm@gmail.com> | 2014-08-08 14:42:07 +0300 |
| commit | a6163888f3c56123b1db313743c6147ba498732c (patch) | |
| tree | ff7d15d991d1d09ba6cbc0cec80924f57445bfdd /third_party/windows/fltk-1.1.10/src | |
| parent | c3e4c9a25c2910d2d66d52215b3406b13d5b23d5 (diff) | |
Add third_party libs
Diffstat (limited to 'third_party/windows/fltk-1.1.10/src')
208 files changed, 69677 insertions, 0 deletions
diff --git a/third_party/windows/fltk-1.1.10/src/CMakeLists.txt b/third_party/windows/fltk-1.1.10/src/CMakeLists.txt new file mode 100644 index 0000000..95cae3b --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/CMakeLists.txt @@ -0,0 +1,208 @@ +SET(CPPFILES
+ Fl.cxx
+ Fl_Adjuster.cxx
+ Fl_Bitmap.cxx
+ Fl_Browser.cxx
+ Fl_Browser_.cxx
+ Fl_Browser_load.cxx
+ Fl_Box.cxx
+ Fl_Button.cxx
+ Fl_Chart.cxx
+ Fl_Check_Browser.cxx
+ Fl_Check_Button.cxx
+ Fl_Choice.cxx
+ Fl_Clock.cxx
+ Fl_Color_Chooser.cxx
+ Fl_Counter.cxx
+ Fl_Dial.cxx
+ Fl_Double_Window.cxx
+ Fl_File_Browser.cxx
+ Fl_File_Chooser.cxx
+ Fl_File_Chooser2.cxx
+ Fl_File_Icon.cxx
+ Fl_File_Input.cxx
+ Fl_Group.cxx
+ Fl_Help_View.cxx
+ Fl_Image.cxx
+ Fl_Input.cxx
+ Fl_Input_.cxx
+ Fl_Light_Button.cxx
+ Fl_Menu.cxx
+ Fl_Menu_.cxx
+ Fl_Menu_Bar.cxx
+ Fl_Sys_Menu_Bar.cxx
+ Fl_Menu_Button.cxx
+ Fl_Menu_Window.cxx
+ Fl_Menu_add.cxx
+ Fl_Menu_global.cxx
+ Fl_Multi_Label.cxx
+ Fl_Overlay_Window.cxx
+ Fl_Pack.cxx
+ Fl_Pixmap.cxx
+ Fl_Positioner.cxx
+ Fl_Preferences.cxx
+ Fl_Progress.cxx
+ Fl_Repeat_Button.cxx
+ Fl_Return_Button.cxx
+ Fl_Roller.cxx
+ Fl_Round_Button.cxx
+ Fl_Scroll.cxx
+ Fl_Scrollbar.cxx
+ Fl_Shared_Image.cxx
+ Fl_Single_Window.cxx
+ Fl_Slider.cxx
+ Fl_Tabs.cxx
+ Fl_Text_Buffer.cxx
+ Fl_Text_Display.cxx
+ Fl_Text_Editor.cxx
+ Fl_Tile.cxx
+ Fl_Tiled_Image.cxx
+ Fl_Tooltip.cxx
+ Fl_Valuator.cxx
+ Fl_Value_Input.cxx
+ Fl_Value_Output.cxx
+ Fl_Value_Slider.cxx
+ Fl_Widget.cxx
+ Fl_Window.cxx
+ Fl_Window_fullscreen.cxx
+ Fl_Window_hotspot.cxx
+ Fl_Window_iconize.cxx
+ Fl_Wizard.cxx
+ Fl_XBM_Image.cxx
+ Fl_XPM_Image.cxx
+ Fl_abort.cxx
+ Fl_add_idle.cxx
+ Fl_arg.cxx
+ Fl_compose.cxx
+ Fl_display.cxx
+ Fl_get_key.cxx
+ Fl_get_system_colors.cxx
+ Fl_grab.cxx
+ Fl_lock.cxx
+ Fl_own_colormap.cxx
+ Fl_visual.cxx
+ Fl_x.cxx
+ filename_absolute.cxx
+ filename_expand.cxx
+ filename_ext.cxx
+ filename_isdir.cxx
+ filename_list.cxx
+ filename_match.cxx
+ filename_setext.cxx
+ fl_arc.cxx
+ fl_arci.cxx
+ fl_ask.cxx
+ fl_boxtype.cxx
+ fl_color.cxx
+ fl_cursor.cxx
+ fl_curve.cxx
+ fl_diamond_box.cxx
+ fl_dnd.cxx
+ fl_draw.cxx
+ fl_draw_image.cxx
+ fl_draw_pixmap.cxx
+ fl_engraved_label.cxx
+ fl_file_dir.cxx
+ fl_font.cxx
+ fl_gtk.cxx
+ fl_labeltype.cxx
+ fl_line_style.cxx
+ fl_open_uri.cxx
+ fl_oval_box.cxx
+ fl_overlay.cxx
+ fl_overlay_visual.cxx
+ fl_plastic.cxx
+ fl_read_image.cxx
+ fl_rect.cxx
+ fl_round_box.cxx
+ fl_rounded_box.cxx
+ fl_set_font.cxx
+ fl_set_fonts.cxx
+ fl_scroll_area.cxx
+ fl_shadow_box.cxx
+ fl_shortcut.cxx
+ fl_show_colormap.cxx
+ fl_symbols.cxx
+ fl_vertex.cxx
+ screen_xywh.cxx
+ )
+SET(FLCPPFILES
+ forms_compatability.cxx
+ forms_bitmap.cxx
+ forms_free.cxx
+ forms_fselect.cxx
+ forms_pixmap.cxx
+ forms_timer.cxx
+ )
+SET(GLCPPFILES
+ Fl_Gl_Choice.cxx
+ Fl_Gl_Overlay.cxx
+ Fl_Gl_Window.cxx
+ freeglut_geometry.cxx
+ freeglut_stroke_mono_roman.cxx
+ freeglut_stroke_roman.cxx
+ freeglut_teapot.cxx
+ gl_draw.cxx
+ gl_start.cxx
+ glut_compatability.cxx
+ glut_font.cxx
+ )
+SET(IMGCPPFILES
+ fl_images_core.cxx
+ Fl_BMP_Image.cxx
+ Fl_File_Icon2.cxx
+ Fl_GIF_Image.cxx
+ Fl_Help_Dialog.cxx
+ Fl_JPEG_Image.cxx
+ Fl_PNG_Image.cxx
+ Fl_PNM_Image.cxx
+ )
+
+SET(CFILES
+ fl_call_main.c
+ flstring.c
+ scandir.c
+ numericsort.c
+ vsnprintf.c
+ )
+
+ADD_LIBRARY(fltk ${CPPFILES} ${CFILES})
+INSTALL_TARGETS(/lib fltk)
+SET_TARGET_PROPERTIES(fltk
+ PROPERTIES
+ VERSION ${FLTK_VERSION_MAJOR}.${FLTK_VERSION_MINOR}
+ SOVERSION ${FLTK_VERSION_PATCH})
+
+TARGET_LINK_LIBRARIES(fltk ${FLTK_PLATFORM_DEPENDENT_LIBS} ${CMAKE_THREAD_LIBS_INIT})
+
+IF(X11_FOUND)
+ TARGET_LINK_LIBRARIES(fltk ${X11_LIBRARIES})
+ENDIF(X11_FOUND)
+
+IF(OPENGL_FOUND)
+ ADD_LIBRARY(fltk_gl ${GLCPPFILES})
+ INSTALL_TARGETS(/lib fltk_gl)
+ TARGET_LINK_LIBRARIES(fltk_gl fltk ${OPENGL_LIBRARIES})
+ SET_TARGET_PROPERTIES(fltk_gl
+ PROPERTIES
+ VERSION ${FLTK_VERSION_MAJOR}.${FLTK_VERSION_MINOR}
+ SOVERSION ${FLTK_VERSION_PATCH})
+ENDIF(OPENGL_FOUND)
+
+ADD_LIBRARY(fltk_forms ${FLCPPFILES})
+INSTALL_TARGETS(/lib fltk_forms)
+TARGET_LINK_LIBRARIES(fltk_forms fltk)
+SET_TARGET_PROPERTIES(fltk_forms
+ PROPERTIES
+ VERSION ${FLTK_VERSION_MAJOR}.${FLTK_VERSION_MINOR}
+ SOVERSION ${FLTK_VERSION_PATCH})
+
+ADD_LIBRARY(fltk_images ${IMGCPPFILES})
+INSTALL_TARGETS(/lib fltk_images)
+TARGET_LINK_LIBRARIES(fltk_images fltk ${FLTK_PNG_LIBRARIES}
+ ${FLTK_JPEG_LIBRARIES} ${FLTK_ZLIB_LIBRARIES})
+SET_TARGET_PROPERTIES(fltk_images
+ PROPERTIES
+ VERSION ${FLTK_VERSION_MAJOR}.${FLTK_VERSION_MINOR}
+ SOVERSION ${FLTK_VERSION_PATCH})
+
diff --git a/third_party/windows/fltk-1.1.10/src/Fl.cxx b/third_party/windows/fltk-1.1.10/src/Fl.cxx new file mode 100644 index 0000000..63a9d8c --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl.cxx @@ -0,0 +1,1311 @@ +//
+// "$Id: Fl.cxx 6474 2008-10-19 20:15:48Z matt $"
+//
+// Main event handling code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2006 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
+//
+
+// warning: the Apple Quartz version still uses some Quickdraw calls,
+// mostly to get around the single active context in QD and
+// to implement clipping. This should be changed into pure
+// Quartz calls in the near future.
+
+#include <FL/Fl.H>
+#include <FL/Fl_Window.H>
+#include <FL/x.H>
+#include <FL/Fl_Tooltip.H>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "flstring.h"
+
+#ifdef DEBUG
+# include <stdio.h>
+#endif // DEBUG
+
+#ifdef WIN32
+# include <ole2.h>
+void fl_free_fonts(void);
+HBRUSH fl_brush_action(int action);
+void fl_cleanup_pens(void);
+void fl_release_dc(HWND,HDC);
+void fl_cleanup_dc_list(void);
+#endif // WIN32
+
+//
+// Globals...
+//
+
+Fl_Widget *Fl::belowmouse_,
+ *Fl::pushed_,
+ *Fl::focus_,
+ *Fl::selection_owner_;
+int Fl::damage_,
+ Fl::e_number,
+ Fl::e_x,
+ Fl::e_y,
+ Fl::e_x_root,
+ Fl::e_y_root,
+ Fl::e_dx,
+ Fl::e_dy,
+ Fl::e_state,
+ Fl::e_clicks,
+ Fl::e_is_click,
+ Fl::e_keysym,
+ Fl::e_original_keysym;
+char *Fl::e_text = (char *)"";
+int Fl::e_length;
+int Fl::visible_focus_ = 1,
+ Fl::dnd_text_ops_ = 1;
+
+
+Fl_Window *fl_xfocus; // which window X thinks has focus
+Fl_Window *fl_xmousewin;// which window X thinks has FL_ENTER
+Fl_Window *Fl::grab_; // most recent Fl::grab()
+Fl_Window *Fl::modal_; // topmost modal() window
+
+//
+// 'Fl::version()' - Return the API version number...
+//
+
+double
+Fl::version() {
+ return FL_VERSION;
+}
+
+
+//
+// 'Fl:event_inside()' - Return whether or not the mouse event is inside
+// the given rectangle.
+//
+
+int Fl::event_inside(int xx,int yy,int ww,int hh) /*const*/ {
+ int mx = e_x - xx;
+ int my = e_y - yy;
+ return (mx >= 0 && mx < ww && my >= 0 && my < hh);
+}
+
+int Fl::event_inside(const Fl_Widget *o) /*const*/ {
+ int mx = e_x - o->x();
+ int my = e_y - o->y();
+ return (mx >= 0 && mx < o->w() && my >= 0 && my < o->h());
+}
+
+//
+//
+// timer support
+//
+
+#ifdef WIN32
+
+/// implementation in Fl_win32.cxx
+
+#elif defined(__APPLE__)
+
+/// implementation in Fl_mac.cxx
+
+#else
+
+//
+// X11 timers
+//
+
+
+////////////////////////////////////////////////////////////////
+// Timeouts are stored in a sorted list, so only the first one needs
+// to be checked to see if any should be called.
+
+struct Timeout {
+ double time;
+ void (*cb)(void*);
+ void* arg;
+ Timeout* next;
+};
+static Timeout* first_timeout, *free_timeout;
+static int first_timeout_count, free_timeout_count;
+
+#include <sys/time.h>
+
+// I avoid the overhead of getting the current time when we have no
+// timeouts by setting this flag instead of getting the time.
+// In this case calling elapse_timeouts() does nothing, but records
+// the current time, and the next call will actualy elapse time.
+static char reset_clock = 1;
+
+static void elapse_timeouts() {
+ static struct timeval prevclock;
+ struct timeval newclock;
+ gettimeofday(&newclock, NULL);
+ double elapsed = newclock.tv_sec - prevclock.tv_sec +
+ (newclock.tv_usec - prevclock.tv_usec)/1000000.0;
+ prevclock.tv_sec = newclock.tv_sec;
+ prevclock.tv_usec = newclock.tv_usec;
+ if (reset_clock) {
+ reset_clock = 0;
+ } else if (elapsed > 0) {
+ for (Timeout* t = first_timeout; t; t = t->next) t->time -= elapsed;
+ }
+}
+
+// Continuously-adjusted error value, this is a number <= 0 for how late
+// we were at calling the last timeout. This appears to make repeat_timeout
+// very accurate even when processing takes a significant portion of the
+// time interval:
+static double missed_timeout_by;
+
+void Fl::add_timeout(double time, Fl_Timeout_Handler cb, void *argp) {
+ elapse_timeouts();
+ repeat_timeout(time, cb, argp);
+}
+
+void Fl::repeat_timeout(double time, Fl_Timeout_Handler cb, void *argp) {
+ time += missed_timeout_by; if (time < -.05) time = 0;
+ Timeout* t = free_timeout;
+ if (t) {
+ free_timeout = t->next;
+ --free_timeout_count;
+ } else {
+ t = new Timeout;
+ }
+ t->time = time;
+ t->cb = cb;
+ t->arg = argp;
+ // insert-sort the new timeout:
+ Timeout** p = &first_timeout;
+ while (*p && (*p)->time <= time) p = &((*p)->next);
+ t->next = *p;
+ *p = t;
+}
+
+int Fl::has_timeout(Fl_Timeout_Handler cb, void *argp) {
+ for (Timeout* t = first_timeout; t; t = t->next)
+ if (t->cb == cb && t->arg == argp) return 1;
+ return 0;
+}
+
+void Fl::remove_timeout(Fl_Timeout_Handler cb, void *argp) {
+ // This version removes all matching timeouts, not just the first one.
+ // This may change in the future.
+ for (Timeout** p = &first_timeout; *p;) {
+ Timeout* t = *p;
+ if (t->cb == cb && (t->arg == argp || !argp)) {
+ *p = t->next;
+ t->next = free_timeout;
+ free_timeout = t;
+ } else {
+ p = &(t->next);
+ }
+ }
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////
+// Checks are just stored in a list. They are called in the reverse
+// order that they were added (this may change in the future).
+// This is a bit messy because I want to allow checks to be added,
+// removed, and have wait() called from inside them, to do this
+// next_check points at the next unprocessed one for the outermost
+// call to Fl::wait().
+
+struct Check {
+ void (*cb)(void*);
+ void* arg;
+ Check* next;
+};
+static Check *first_check, *next_check, *free_check;
+
+void Fl::add_check(Fl_Timeout_Handler cb, void *argp) {
+ Check* t = free_check;
+ if (t) free_check = t->next;
+ else t = new Check;
+ t->cb = cb;
+ t->arg = argp;
+ t->next = first_check;
+ if (next_check == first_check) next_check = t;
+ first_check = t;
+}
+
+void Fl::remove_check(Fl_Timeout_Handler cb, void *argp) {
+ for (Check** p = &first_check; *p;) {
+ Check* t = *p;
+ if (t->cb == cb && t->arg == argp) {
+ if (next_check == t) next_check = t->next;
+ *p = t->next;
+ t->next = free_check;
+ free_check = t;
+ } else {
+ p = &(t->next);
+ }
+ }
+}
+
+/**
+ * Return 1, if a check with the same handler and data pointer
+ * is pending, 0 otherwise.
+ */
+int Fl::has_check(Fl_Timeout_Handler cb, void *argp) {
+ for (Check** p = &first_check; *p;) {
+ Check* t = *p;
+ if (t->cb == cb && t->arg == argp) {
+ return 1;
+ } else {
+ p = &(t->next);
+ }
+ }
+ return 0;
+}
+
+static void run_checks()
+{
+ // checks are a bit messy so that add/remove and wait may be called
+ // from inside them without causing an infinite loop:
+ if (next_check == first_check) {
+ while (next_check) {
+ Check* checkp = next_check;
+ next_check = checkp->next;
+ (checkp->cb)(checkp->arg);
+ }
+ next_check = first_check;
+ }
+}
+
+#ifndef WIN32
+static char in_idle;
+#endif
+
+////////////////////////////////////////////////////////////////
+// wait/run/check/ready:
+
+void (*Fl::idle)(); // see Fl_add_idle.cxx for the add/remove functions
+
+extern int fl_ready(); // in Fl_<platform>.cxx
+extern int fl_wait(double time); // in Fl_<platform>.cxx
+
+double Fl::wait(double time_to_wait) {
+ // delete all widgets that were listed during callbacks
+ do_widget_deletion();
+
+#ifdef WIN32
+
+ return fl_wait(time_to_wait);
+
+#elif defined(__APPLE__)
+
+ run_checks();
+ if (idle) {
+ if (!in_idle) {
+ in_idle = 1;
+ idle();
+ in_idle = 0;
+ }
+ // the idle function may turn off idle, we can then wait:
+ if (idle) time_to_wait = 0.0;
+ }
+ flush();
+ if (idle && !in_idle) // 'idle' may have been set within flush()
+ time_to_wait = 0.0;
+ return fl_wait(time_to_wait);
+
+#else
+
+ if (first_timeout) {
+ elapse_timeouts();
+ Timeout *t;
+ while ((t = first_timeout)) {
+ if (t->time > 0) break;
+ // The first timeout in the array has expired.
+ missed_timeout_by = t->time;
+ // We must remove timeout from array before doing the callback:
+ void (*cb)(void*) = t->cb;
+ void *argp = t->arg;
+ first_timeout = t->next;
+ t->next = free_timeout;
+ free_timeout = t;
+ ++free_timeout_count;
+ --first_timeout_count;
+ // Now it is safe for the callback to do add_timeout:
+ cb(argp);
+ }
+ } else {
+ reset_clock = 1; // we are not going to check the clock
+ }
+ run_checks();
+// if (idle && !fl_ready()) {
+ if (idle) {
+ if (!in_idle) {
+ in_idle = 1;
+ idle();
+ in_idle = 0;
+ }
+ // the idle function may turn off idle, we can then wait:
+ if (idle) time_to_wait = 0.0;
+ }
+ if (first_timeout && first_timeout->time < time_to_wait)
+ time_to_wait = first_timeout->time;
+ if (time_to_wait <= 0.0) {
+ // do flush second so that the results of events are visible:
+ int ret = fl_wait(0.0);
+ flush();
+ return ret;
+ } else {
+ // do flush first so that user sees the display:
+ flush();
+ if (idle && !in_idle) // 'idle' may have been set within flush()
+ time_to_wait = 0.0;
+ return fl_wait(time_to_wait);
+ }
+#endif
+}
+
+#define FOREVER 1e20
+
+int Fl::run() {
+ while (Fl_X::first) wait(FOREVER);
+ return 0;
+}
+
+#ifdef WIN32
+class Fl_Win32_At_Exit {
+public:
+ Fl_Win32_At_Exit() { }
+ ~Fl_Win32_At_Exit() {
+ fl_free_fonts(); // do some WIN32 cleanup
+ fl_cleanup_pens();
+ OleUninitialize();
+ fl_brush_action(1);
+ fl_cleanup_dc_list();
+ }
+};
+static Fl_Win32_At_Exit win32_at_exit;
+#endif
+
+
+
+int Fl::wait() {
+ if (!Fl_X::first) return 0;
+ wait(FOREVER);
+ return Fl_X::first != 0; // return true if there is a window
+}
+
+int Fl::check() {
+ wait(0.0);
+ return Fl_X::first != 0; // return true if there is a window
+}
+
+int Fl::ready() {
+#if ! defined( WIN32 ) && ! defined(__APPLE__)
+ if (first_timeout) {
+ elapse_timeouts();
+ if (first_timeout->time <= 0) return 1;
+ } else {
+ reset_clock = 1;
+ }
+#endif
+ return fl_ready();
+}
+
+////////////////////////////////////////////////////////////////
+// Window list management:
+
+Fl_X* Fl_X::first;
+
+Fl_Window* fl_find(Window xid) {
+ Fl_X *window;
+ for (Fl_X **pp = &Fl_X::first; (window = *pp); pp = &window->next)
+#ifdef __APPLE_QD__
+ if (window->xid == xid && !window->w->window()) {
+#elif defined(__APPLE_QUARTZ__)
+ if (window->xid == xid && !window->w->window()) {
+#else
+ if (window->xid == xid) {
+#endif // __APPLE__
+ if (window != Fl_X::first && !Fl::modal()) {
+ // make this window be first to speed up searches
+ // this is not done if modal is true to avoid messing up modal stack
+ *pp = window->next;
+ window->next = Fl_X::first;
+ Fl_X::first = window;
+ }
+ return window->w;
+ }
+ return 0;
+}
+
+Fl_Window* Fl::first_window() {
+ Fl_X* i = Fl_X::first;
+ return i ? i->w : 0;
+}
+
+Fl_Window* Fl::next_window(const Fl_Window* window) {
+ Fl_X* i = Fl_X::i(window)->next;
+ return i ? i->w : 0;
+}
+
+void Fl::first_window(Fl_Window* window) {
+ if (!window || !window->shown()) return;
+ fl_find(fl_xid(window));
+}
+
+void Fl::redraw() {
+ for (Fl_X* i = Fl_X::first; i; i = i->next) i->w->redraw();
+}
+
+void Fl::flush() {
+ if (damage()) {
+ damage_ = 0;
+ for (Fl_X* i = Fl_X::first; i; i = i->next) {
+ if (i->wait_for_expose) {damage_ = 1; continue;}
+ Fl_Window* wi = i->w;
+ if (!wi->visible_r()) continue;
+ if (wi->damage()) {i->flush(); wi->clear_damage();}
+ // destroy damage regions for windows that don't use them:
+ if (i->region) {XDestroyRegion(i->region); i->region = 0;}
+ }
+ }
+
+#ifdef WIN32
+ GdiFlush();
+#elif defined(__APPLE_QD__)
+ GrafPtr port;
+ GetPort( &port );
+ if ( port )
+ QDFlushPortBuffer( port, 0 );
+#elif defined (__APPLE_QUARTZ__)
+ if (fl_gc)
+ CGContextFlush(fl_gc);
+#else
+ if (fl_display) XFlush(fl_display);
+#endif
+}
+
+////////////////////////////////////////////////////////////////
+// Event handlers:
+
+struct handler_link {
+ int (*handle)(int);
+ handler_link *next;
+};
+
+static handler_link *handlers = 0;
+
+void Fl::add_handler(int (*ha)(int)) {
+ handler_link *l = new handler_link;
+ l->handle = ha;
+ l->next = handlers;
+ handlers = l;
+}
+
+void Fl::remove_handler(int (*ha)(int)) {
+ handler_link *l, *p;
+
+ // Search for the handler in the list...
+ for (l = handlers, p = 0; l && l->handle != ha; p = l, l = l->next);
+
+ if (l) {
+ // Found it, so remove it from the list...
+ if (p) p->next = l->next;
+ else handlers = l->next;
+
+ // And free the record...
+ delete l;
+ }
+}
+
+int (*fl_local_grab)(int); // used by fl_dnd.cxx
+
+static int send_handlers(int e) {
+ for (const handler_link *hl = handlers; hl; hl = hl->next)
+ if (hl->handle(e)) return 1;
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////
+
+Fl_Widget* fl_oldfocus; // kludge for Fl_Group...
+
+void Fl::focus(Fl_Widget *o) {
+ if (o && !o->visible_focus()) return;
+ if (grab()) return; // don't do anything while grab is on
+ Fl_Widget *p = focus_;
+ if (o != p) {
+ Fl::compose_reset();
+ focus_ = o;
+ // make sure that fl_xfocus is set to the top level window
+ // of this widget, or fl_fix_focus will clear our focus again
+ if (o) {
+ Fl_Window *win = 0, *w1 = o->window();
+ while (w1) { win=w1; w1=win->window(); }
+ if (win) fl_xfocus = win;
+ }
+ // take focus from the old focused window
+ fl_oldfocus = 0;
+ int old_event = e_number;
+ e_number = FL_UNFOCUS;
+ for (; p; p = p->parent()) {
+ p->handle(FL_UNFOCUS);
+ fl_oldfocus = p;
+ }
+ e_number = old_event;
+ }
+}
+
+static char dnd_flag = 0; // make 'belowmouse' send DND_LEAVE instead of LEAVE
+
+void Fl::belowmouse(Fl_Widget *o) {
+ if (grab()) return; // don't do anything while grab is on
+ Fl_Widget *p = belowmouse_;
+ if (o != p) {
+ belowmouse_ = o;
+ int old_event = e_number;
+ e_number = dnd_flag ? FL_DND_LEAVE : FL_LEAVE;
+ for (; p && !p->contains(o); p = p->parent()) {
+ p->handle(e_number);
+ }
+ e_number = old_event;
+ }
+}
+
+void Fl::pushed(Fl_Widget *o) {
+ pushed_ = o;
+}
+
+static void nothing(Fl_Widget *) {}
+void (*Fl_Tooltip::enter)(Fl_Widget *) = nothing;
+void (*Fl_Tooltip::exit)(Fl_Widget *) = nothing;
+
+// Update modal(), focus() and other state according to system state,
+// and send FL_ENTER, FL_LEAVE, FL_FOCUS, and/or FL_UNFOCUS events.
+// This is the only function that produces these events in response
+// to system activity.
+// This is called whenever a window is added or hidden, and whenever
+// X says the focus or mouse window have changed.
+
+void fl_fix_focus() {
+#ifdef DEBUG
+ puts("fl_fix_focus();");
+#endif // DEBUG
+
+ if (Fl::grab()) return; // don't do anything while grab is on.
+
+ // set focus based on Fl::modal() and fl_xfocus
+ Fl_Widget* w = fl_xfocus;
+ if (w) {
+ int saved = Fl::e_keysym;
+ if (Fl::e_keysym < (FL_Button + FL_LEFT_MOUSE) ||
+ Fl::e_keysym > (FL_Button + FL_RIGHT_MOUSE))
+ Fl::e_keysym = 0; // make sure widgets don't think a keystroke moved focus
+ while (w->parent()) w = w->parent();
+ if (Fl::modal()) w = Fl::modal();
+ if (!w->contains(Fl::focus()))
+ if (!w->take_focus()) Fl::focus(w);
+ Fl::e_keysym = saved;
+ } else
+ Fl::focus(0);
+
+// MRS: Originally we checked the button state, but a user reported that it
+// broke click-to-focus in FLWM?!?
+// if (!(Fl::event_state() & 0x7f00000 /*FL_BUTTONS*/)) {
+ if (!Fl::pushed()) {
+ // set belowmouse based on Fl::modal() and fl_xmousewin:
+ w = fl_xmousewin;
+ if (w) {
+ if (Fl::modal()) w = Fl::modal();
+ if (!w->contains(Fl::belowmouse())) {
+ int old_event = Fl::e_number;
+ w->handle(Fl::e_number = FL_ENTER);
+ Fl::e_number = old_event;
+ if (!w->contains(Fl::belowmouse())) Fl::belowmouse(w);
+ } else {
+ // send a FL_MOVE event so the enter/leave state is up to date
+ Fl::e_x = Fl::e_x_root-fl_xmousewin->x();
+ Fl::e_y = Fl::e_y_root-fl_xmousewin->y();
+ int old_event = Fl::e_number;
+ w->handle(Fl::e_number = FL_MOVE);
+ Fl::e_number = old_event;
+ }
+ } else {
+ Fl::belowmouse(0);
+ Fl_Tooltip::enter(0);
+ }
+ }
+}
+
+#ifndef WIN32
+extern Fl_Widget *fl_selection_requestor; // from Fl_x.cxx
+#endif
+
+// This function is called by ~Fl_Widget() and by Fl_Widget::deactivate
+// and by Fl_Widget::hide(). It indicates that the widget does not want
+// to receive any more events, and also removes all global variables that
+// point at the widget.
+// I changed this from the 1.0.1 behavior, the older version could send
+// FL_LEAVE or FL_UNFOCUS events to the widget. This appears to not be
+// desirable behavior and caused flwm to crash.
+
+void fl_throw_focus(Fl_Widget *o) {
+#ifdef DEBUG
+ printf("fl_throw_focus(o=%p)\n", o);
+#endif // DEBUG
+
+ if (o->contains(Fl::pushed())) Fl::pushed_ = 0;
+#ifndef WIN32
+ if (o->contains(fl_selection_requestor)) fl_selection_requestor = 0;
+#endif
+ if (o->contains(Fl::belowmouse())) Fl::belowmouse_ = 0;
+ if (o->contains(Fl::focus())) Fl::focus_ = 0;
+ if (o == fl_xfocus) fl_xfocus = 0;
+ if (o == Fl_Tooltip::current()) Fl_Tooltip::current(0);
+ if (o == fl_xmousewin) fl_xmousewin = 0;
+ Fl_Tooltip::exit(o);
+ fl_fix_focus();
+}
+
+////////////////////////////////////////////////////////////////
+
+// Call to->handle but first replace the mouse x/y with the correct
+// values to account for nested X windows. 'window' is the outermost
+// window the event was posted to by X:
+static int send(int event, Fl_Widget* to, Fl_Window* window) {
+ int dx, dy;
+ int old_event = Fl::e_number;
+ if (window) {
+ dx = window->x();
+ dy = window->y();
+ } else {
+ dx = dy = 0;
+ }
+ for (const Fl_Widget* w = to; w; w = w->parent())
+ if (w->type()>=FL_WINDOW) {dx -= w->x(); dy -= w->y();}
+ int save_x = Fl::e_x; Fl::e_x += dx;
+ int save_y = Fl::e_y; Fl::e_y += dy;
+ int ret = to->handle(Fl::e_number = event);
+ Fl::e_number = old_event;
+ Fl::e_y = save_y;
+ Fl::e_x = save_x;
+ return ret;
+}
+
+int Fl::handle(int e, Fl_Window* window)
+{
+ e_number = e;
+ if (fl_local_grab) return fl_local_grab(e);
+
+ Fl_Widget* wi = window;
+
+ switch (e) {
+
+ case FL_CLOSE:
+ if (grab() || modal() && window != modal()) return 0;
+ wi->do_callback();
+ return 1;
+
+ case FL_SHOW:
+ wi->show(); // this calls Fl_Widget::show(), not Fl_Window::show()
+ return 1;
+
+ case FL_HIDE:
+ wi->hide(); // this calls Fl_Widget::hide(), not Fl_Window::hide()
+ return 1;
+
+ case FL_PUSH:
+#ifdef DEBUG
+ printf("Fl::handle(e=%d, window=%p);\n", e, window);
+#endif // DEBUG
+
+ if (grab()) wi = grab();
+ else if (modal() && wi != modal()) return 0;
+ pushed_ = wi;
+ Fl_Tooltip::current(wi);
+ if (send(e, wi, window)) return 1;
+ // raise windows that are clicked on:
+ window->show();
+ return 1;
+
+ case FL_DND_ENTER:
+ case FL_DND_DRAG:
+ dnd_flag = 1;
+ break;
+
+ case FL_DND_LEAVE:
+ dnd_flag = 1;
+ belowmouse(0);
+ dnd_flag = 0;
+ return 1;
+
+ case FL_DND_RELEASE:
+ wi = belowmouse();
+ break;
+
+ case FL_MOVE:
+ case FL_DRAG:
+ fl_xmousewin = window; // this should already be set, but just in case.
+ if (pushed()) {
+ wi = pushed();
+ if (grab()) wi = grab();
+ e_number = e = FL_DRAG;
+ break;
+ }
+ if (modal() && wi != modal()) wi = 0;
+ if (grab()) wi = grab();
+ {Fl_Widget* pbm = belowmouse();
+ int ret = (wi && send(e, wi, window));
+ if (pbm != belowmouse()) {
+#ifdef DEBUG
+ printf("Fl::handle(e=%d, window=%p);\n", e, window);
+#endif // DEBUG
+ Fl_Tooltip::enter(belowmouse());
+ }
+ return ret;}
+
+ case FL_RELEASE: {
+// printf("FL_RELEASE: window=%p, pushed() = %p, grab() = %p, modal() = %p\n",
+// window, pushed(), grab(), modal());
+
+ if (grab()) {
+ wi = grab();
+ pushed_ = 0; // must be zero before callback is done!
+ } else if (pushed()) {
+ wi = pushed();
+ pushed_ = 0; // must be zero before callback is done!
+ } else if (modal() && wi != modal()) return 0;
+ int r = send(e, wi, window);
+ fl_fix_focus();
+ return r;}
+
+ case FL_UNFOCUS:
+ window = 0;
+ case FL_FOCUS:
+ fl_xfocus = window;
+ fl_fix_focus();
+ return 1;
+
+ case FL_KEYUP:
+ // Send the key-up to the current focus. This is not
+ // always the same widget that received the corresponding
+ // FL_KEYBOARD event because focus may have changed.
+ // Sending the KEYUP to the right KEYDOWN is possible, but
+ // would require that we track the KEYDOWN for every possible
+ // key stroke (users may hold down multiple keys!) and then
+ // make sure that the widget still exists before sending
+ // a KEYUP there. I believe that the current solution is
+ // "close enough".
+ for (wi = grab() ? grab() : focus(); wi; wi = wi->parent())
+ if (send(FL_KEYUP, wi, window)) return 1;
+ return 0;
+
+ case FL_KEYBOARD:
+#ifdef DEBUG
+ printf("Fl::handle(e=%d, window=%p);\n", e, window);
+#endif // DEBUG
+
+ Fl_Tooltip::enter((Fl_Widget*)0);
+
+ fl_xfocus = window; // this should not happen! But maybe it does:
+
+ // Try it as keystroke, sending it to focus and all parents:
+ for (wi = grab() ? grab() : focus(); wi; wi = wi->parent())
+ if (send(FL_KEYBOARD, wi, window)) return 1;
+
+ // recursive call to try shortcut:
+ if (handle(FL_SHORTCUT, window)) return 1;
+
+ // and then try a shortcut with the case of the text swapped, by
+ // changing the text and falling through to FL_SHORTCUT case:
+ {unsigned char* c = (unsigned char*)event_text(); // cast away const
+ if (!isalpha(*c)) return 0;
+ *c = isupper(*c) ? tolower(*c) : toupper(*c);}
+ e_number = e = FL_SHORTCUT;
+
+ case FL_SHORTCUT:
+ if (grab()) {wi = grab(); break;} // send it to grab window
+
+ // Try it as shortcut, sending to mouse widget and all parents:
+ wi = belowmouse();
+ if (!wi) {
+ wi = modal();
+ if (!wi) wi = window;
+ } else if (wi->window() != first_window()) {
+ if (send(FL_SHORTCUT, first_window(), first_window())) return 1;
+ }
+
+ for (; wi; wi = wi->parent()) {
+ if (send(FL_SHORTCUT, wi, wi->window())) return 1;
+ }
+
+ // try using add_handle() functions:
+ if (send_handlers(FL_SHORTCUT)) return 1;
+
+ // make Escape key close windows:
+ if (event_key()==FL_Escape) {
+ wi = modal(); if (!wi) wi = window;
+ wi->do_callback();
+ return 1;
+ }
+
+ return 0;
+
+ case FL_ENTER:
+#ifdef DEBUG
+ printf("Fl::handle(e=%d, window=%p);\n", e, window);
+#endif // DEBUG
+
+ fl_xmousewin = window;
+ fl_fix_focus();
+ Fl_Tooltip::enter(belowmouse());
+ return 1;
+
+ case FL_LEAVE:
+#ifdef DEBUG
+ printf("Fl::handle(e=%d, window=%p);\n", e, window);
+#endif // DEBUG
+
+ if (!pushed_) {
+ belowmouse(0);
+ Fl_Tooltip::enter(0);
+ }
+ if (window == fl_xmousewin) {fl_xmousewin = 0; fl_fix_focus();}
+ return 1;
+
+ case FL_MOUSEWHEEL:
+ fl_xfocus = window; // this should not happen! But maybe it does:
+
+ // Try sending it to the "grab" first
+ if (grab() && grab()!=modal() && grab()!=window) {
+ if (send(FL_MOUSEWHEEL, grab(), window)) return 1;
+ }
+ // Now try sending it to the "modal" window
+ if (modal()) {
+ send(FL_MOUSEWHEEL, modal(), window);
+ return 1;
+ }
+ // Finally try sending it to the window, the event occured in
+ if (send(FL_MOUSEWHEEL, window, window)) return 1;
+ default:
+ break;
+ }
+ if (wi && send(e, wi, window)) {
+ dnd_flag = 0;
+ return 1;
+ }
+ dnd_flag = 0;
+ return send_handlers(e);
+}
+
+////////////////////////////////////////////////////////////////
+// hide() destroys the X window, it does not do unmap!
+
+#if !defined(WIN32) && USE_XFT
+extern void fl_destroy_xft_draw(Window);
+#endif
+
+void Fl_Window::hide() {
+ clear_visible();
+
+ if (!shown()) return;
+
+ // remove from the list of windows:
+ Fl_X* ip = i;
+ Fl_X** pp = &Fl_X::first;
+ for (; *pp != ip; pp = &(*pp)->next) if (!*pp) return;
+ *pp = ip->next;
+#ifdef __APPLE__
+ MacUnlinkWindow(ip);
+ // MacOS X manages a single pointer per application. Make sure that hiding
+ // a toplevel window will not leave us with some random pointer shape, or
+ // worst case, an invisible pointer
+ if (!parent()) cursor(FL_CURSOR_DEFAULT);
+#endif
+ i = 0;
+
+ // recursively remove any subwindows:
+ for (Fl_X *wi = Fl_X::first; wi;) {
+ Fl_Window* W = wi->w;
+ if (W->window() == this) {
+ W->hide();
+ W->set_visible();
+ wi = Fl_X::first;
+ } else wi = wi->next;
+ }
+
+ if (this == Fl::modal_) { // we are closing the modal window, find next one:
+ Fl_Window* W;
+ for (W = Fl::first_window(); W; W = Fl::next_window(W))
+ if (W->modal()) break;
+ Fl::modal_ = W;
+ }
+
+ // Make sure no events are sent to this window:
+ fl_throw_focus(this);
+ handle(FL_HIDE);
+
+#ifdef WIN32
+ // this little trick keeps the current clipboard alive, even if we are about
+ // to destroy the window that owns the selection.
+ if (GetClipboardOwner()==ip->xid) {
+ Fl_Window *w1 = Fl::first_window();
+ if (w1 && OpenClipboard(fl_xid(w1))) {
+ EmptyClipboard();
+ SetClipboardData(CF_TEXT, NULL);
+ CloseClipboard();
+ }
+ }
+ // Send a message to myself so that I'll get out of the event loop...
+ PostMessage(ip->xid, WM_APP, 0, 0);
+ if (ip->private_dc) fl_release_dc(ip->xid, ip->private_dc);
+ if (ip->xid == fl_window && fl_gc) {
+ fl_release_dc(fl_window, fl_gc);
+ fl_window = (HWND)-1;
+ fl_gc = 0;
+ }
+#elif defined(__APPLE_QD__)
+ if ( ip->xid == fl_window && !parent() )
+ fl_window = 0;
+#elif defined(__APPLE_QUARTZ__)
+ Fl_X::q_release_context(ip);
+ if ( ip->xid == fl_window && !parent() )
+ fl_window = 0;
+#endif
+
+ if (ip->region) XDestroyRegion(ip->region);
+
+#ifdef WIN32
+ // this little trickery seems to avoid the popup window stacking problem
+ HWND p = GetForegroundWindow();
+ if (p==GetParent(ip->xid)) {
+ ShowWindow(ip->xid, SW_HIDE);
+ ShowWindow(p, SW_SHOWNA);
+ }
+ XDestroyWindow(fl_display, ip->xid);
+#elif defined(__APPLE_QD__)
+ MacDestroyWindow(this, ip->xid);
+#elif defined(__APPLE_QUARTZ__)
+ MacDestroyWindow(this, ip->xid);
+#else
+# if USE_XFT
+ fl_destroy_xft_draw(ip->xid);
+# endif
+ XDestroyWindow(fl_display, ip->xid);
+#endif
+
+#ifdef WIN32
+ // Try to stop the annoying "raise another program" behavior
+ if (non_modal() && Fl::first_window() && Fl::first_window()->shown())
+ Fl::first_window()->show();
+#endif
+ delete ip;
+}
+
+Fl_Window::~Fl_Window() {
+ hide();
+}
+
+// FL_SHOW and FL_HIDE are called whenever the visibility of this widget
+// or any parent changes. We must correctly map/unmap the system's window.
+
+// For top-level windows it is assummed the window has already been
+// mapped or unmapped!!! This is because this should only happen when
+// Fl_Window::show() or Fl_Window::hide() is called, or in response to
+// iconize/deiconize events from the system.
+
+int Fl_Window::handle(int ev)
+{
+ if (parent()) {
+ switch (ev) {
+ case FL_SHOW:
+ if (!shown()) show();
+ else {
+#ifdef __APPLE_QD__
+ MacMapWindow(this, fl_xid(this));
+#elif defined(__APPLE_QUARTZ__)
+ MacMapWindow(this, fl_xid(this));
+#else
+ XMapWindow(fl_display, fl_xid(this)); // extra map calls are harmless
+#endif // __APPLE__
+ }
+ break;
+ case FL_HIDE:
+ if (shown()) {
+ // Find what really turned invisible, if is was a parent window
+ // we do nothing. We need to avoid unnecessary unmap calls
+ // because they cause the display to blink when the parent is
+ // remapped. However if this or any intermediate non-window
+ // widget has really had hide() called directly on it, we must
+ // unmap because when the parent window is remapped we don't
+ // want to reappear.
+ if (visible()) {
+ Fl_Widget* p = parent(); for (;p->visible();p = p->parent()) {}
+ if (p->type() >= FL_WINDOW) break; // don't do the unmap
+ }
+#ifdef __APPLE_QD__
+ MacUnmapWindow(this, fl_xid(this));
+#elif defined(__APPLE_QUARTZ__)
+ MacUnmapWindow(this, fl_xid(this));
+#else
+ XUnmapWindow(fl_display, fl_xid(this));
+#endif // __APPLE__
+ }
+ break;
+ }
+// } else if (ev == FL_FOCUS || ev == FL_UNFOCUS) {
+// Fl_Tooltip::exit(Fl_Tooltip::current());
+ }
+
+ return Fl_Group::handle(ev);
+}
+
+////////////////////////////////////////////////////////////////
+// Back compatability cut & paste functions for fltk 1.1 only:
+
+void Fl::selection_owner(Fl_Widget *owner) {selection_owner_ = owner;}
+
+void Fl::selection(Fl_Widget &owner, const char* text, int len) {
+ selection_owner_ = &owner;
+ Fl::copy(text, len, 0);
+}
+
+void Fl::paste(Fl_Widget &receiver) {
+ Fl::paste(receiver, 0);
+}
+
+////////////////////////////////////////////////////////////////
+
+#include <FL/fl_draw.H>
+
+void Fl_Widget::redraw() {
+ damage(FL_DAMAGE_ALL);
+}
+
+void Fl_Widget::redraw_label() {
+ if (window()) {
+ if (box() == FL_NO_BOX) {
+ // Widgets with the FL_NO_BOX boxtype need a parent to
+ // redraw, since it is responsible for redrawing the
+ // background...
+ int X = x() > 0 ? x() - 1 : 0;
+ int Y = y() > 0 ? y() - 1 : 0;
+ window()->damage(FL_DAMAGE_ALL, X, Y, w() + 2, h() + 2);
+ }
+
+ if (align() && !(align() & FL_ALIGN_INSIDE) && window()->shown()) {
+ // If the label is not inside the widget, compute the location of
+ // the label and redraw the window within that bounding box...
+ int W = 0, H = 0;
+ label_.measure(W, H);
+ W += 5; // Add a little to the size of the label to cover overflow
+ H += 5;
+
+ if (align() & FL_ALIGN_BOTTOM) {
+ window()->damage(FL_DAMAGE_EXPOSE, x(), y() + h(), w(), H);
+ } else if (align() & FL_ALIGN_TOP) {
+ window()->damage(FL_DAMAGE_EXPOSE, x(), y() - H, w(), H);
+ } else if (align() & FL_ALIGN_LEFT) {
+ window()->damage(FL_DAMAGE_EXPOSE, x() - W, y(), W, h());
+ } else if (align() & FL_ALIGN_RIGHT) {
+ window()->damage(FL_DAMAGE_EXPOSE, x() + w(), y(), W, h());
+ } else {
+ window()->damage(FL_DAMAGE_ALL);
+ }
+ } else {
+ // The label is inside the widget, so just redraw the widget itself...
+ damage(FL_DAMAGE_ALL);
+ }
+ }
+}
+
+void Fl_Widget::damage(uchar fl) {
+ if (type() < FL_WINDOW) {
+ // damage only the rectangle covered by a child widget:
+ damage(fl, x(), y(), w(), h());
+ } else {
+ // damage entire window by deleting the region:
+ Fl_X* i = Fl_X::i((Fl_Window*)this);
+ if (!i) return; // window not mapped, so ignore it
+ if (i->region) {XDestroyRegion(i->region); i->region = 0;}
+ damage_ |= fl;
+ Fl::damage(FL_DAMAGE_CHILD);
+ }
+}
+
+void Fl_Widget::damage(uchar fl, int X, int Y, int W, int H) {
+ Fl_Widget* wi = this;
+ // mark all parent widgets between this and window with FL_DAMAGE_CHILD:
+ while (wi->type() < FL_WINDOW) {
+ wi->damage_ |= fl;
+ wi = wi->parent();
+ if (!wi) return;
+ fl = FL_DAMAGE_CHILD;
+ }
+ Fl_X* i = Fl_X::i((Fl_Window*)wi);
+ if (!i) return; // window not mapped, so ignore it
+
+ // clip the damage to the window and quit if none:
+ if (X < 0) {W += X; X = 0;}
+ if (Y < 0) {H += Y; Y = 0;}
+ if (W > wi->w()-X) W = wi->w()-X;
+ if (H > wi->h()-Y) H = wi->h()-Y;
+ if (W <= 0 || H <= 0) return;
+
+ if (!X && !Y && W==wi->w() && H==wi->h()) {
+ // if damage covers entire window delete region:
+ wi->damage(fl);
+ return;
+ }
+
+ if (wi->damage()) {
+ // if we already have damage we must merge with existing region:
+ if (i->region) {
+#ifdef WIN32
+ Fl_Region R = XRectangleRegion(X, Y, W, H);
+ CombineRgn(i->region, i->region, R, RGN_OR);
+ XDestroyRegion(R);
+#elif defined(__APPLE_QD__)
+ Fl_Region R = NewRgn();
+ SetRectRgn(R, X, Y, X+W, Y+H);
+ UnionRgn(R, i->region, i->region);
+ DisposeRgn(R);
+#elif defined(__APPLE_QUARTZ__)
+ Fl_Region R = NewRgn();
+ SetRectRgn(R, X, Y, X+W, Y+H);
+ UnionRgn(R, i->region, i->region);
+ DisposeRgn(R);
+#else
+ XRectangle R;
+ R.x = X; R.y = Y; R.width = W; R.height = H;
+ XUnionRectWithRegion(&R, i->region, i->region);
+#endif
+ }
+ wi->damage_ |= fl;
+ } else {
+ // create a new region:
+ if (i->region) XDestroyRegion(i->region);
+ i->region = XRectangleRegion(X,Y,W,H);
+ wi->damage_ = fl;
+ }
+ Fl::damage(FL_DAMAGE_CHILD);
+}
+
+void Fl_Window::flush() {
+ make_current();
+//if (damage() == FL_DAMAGE_EXPOSE && can_boxcheat(box())) fl_boxcheat = this;
+ fl_clip_region(i->region); i->region = 0;
+ draw();
+}
+
+#ifdef WIN32
+# include "Fl_win32.cxx"
+#elif defined(__APPLE__)
+# include "Fl_mac.cxx"
+#endif
+
+//
+// The following methods allow callbacks to schedule the deletion of
+// widgets at "safe" times.
+//
+
+static int num_dwidgets = 0, alloc_dwidgets = 0;
+static Fl_Widget **dwidgets = 0;
+
+void
+Fl::delete_widget(Fl_Widget *wi) {
+ if (!wi) return;
+
+ if (num_dwidgets >= alloc_dwidgets) {
+ Fl_Widget **temp;
+
+ temp = new Fl_Widget *[alloc_dwidgets + 10];
+ if (alloc_dwidgets) {
+ memcpy(temp, dwidgets, alloc_dwidgets * sizeof(Fl_Widget *));
+ delete[] dwidgets;
+ }
+
+ dwidgets = temp;
+ alloc_dwidgets += 10;
+ }
+
+ dwidgets[num_dwidgets] = wi;
+ num_dwidgets ++;
+}
+
+
+void
+Fl::do_widget_deletion() {
+ if (!num_dwidgets) return;
+
+ for (int i = 0; i < num_dwidgets; i ++)
+ delete dwidgets[i];
+
+ num_dwidgets = 0;
+}
+
+static Fl_Widget ***widget_watch = 0;
+static int num_widget_watch = 0;
+static int max_widget_watch = 0;
+
+void Fl::watch_widget_pointer(Fl_Widget *&w)
+{
+ Fl_Widget **wp = &w;
+ int i;
+ for (i=0; i<num_widget_watch; ++i) {
+ if (widget_watch[i]==wp) return;
+ }
+ for (i=0; i<num_widget_watch; ++i) {
+ if (widget_watch[i]==0L) {
+ widget_watch[i] = wp;
+ return;
+ }
+ }
+ if (num_widget_watch==max_widget_watch) {
+ max_widget_watch += 8;
+ widget_watch = (Fl_Widget***)realloc(widget_watch, sizeof(Fl_Widget**)*max_widget_watch);
+ }
+ widget_watch[num_widget_watch++] = wp;
+}
+
+void Fl::release_widget_pointer(Fl_Widget *&w)
+{
+ Fl_Widget **wp = &w;
+ int i;
+ for (i=0; i<num_widget_watch; ++i) {
+ if (widget_watch[i]==wp) {
+ widget_watch[i] = 0L;
+ return;
+ }
+ }
+}
+
+void Fl::clear_widget_pointer(Fl_Widget const *w)
+{
+ if (w==0L) return;
+ int i;
+ for (i=0; i<num_widget_watch; ++i) {
+ if (widget_watch[i] && *widget_watch[i]==w) {
+ *widget_watch[i] = 0L;
+ }
+ }
+}
+
+
+//
+// End of "$Id: Fl.cxx 6474 2008-10-19 20:15:48Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Adjuster.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Adjuster.cxx new file mode 100644 index 0000000..df91adf --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Adjuster.cxx @@ -0,0 +1,171 @@ +//
+// "$Id: Fl_Adjuster.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Adjuster widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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_Adjuster.H>
+#include <FL/Fl_Bitmap.H>
+#include <FL/fl_draw.H>
+
+#include "fastarrow.h"
+static Fl_Bitmap fastarrow(fastarrow_bits, fastarrow_width, fastarrow_height);
+#include "mediumarrow.h"
+static Fl_Bitmap mediumarrow(mediumarrow_bits, mediumarrow_width, mediumarrow_height);
+#include "slowarrow.h"
+static Fl_Bitmap slowarrow(slowarrow_bits, slowarrow_width, slowarrow_height);
+
+// changing the value does not change the appearance:
+void Fl_Adjuster::value_damage() {}
+
+void Fl_Adjuster::draw() {
+ int dx, dy, W, H;
+ if (w()>=h()) {
+ dx = W = w()/3;
+ dy = 0; H = h();
+ } else {
+ dx = 0; W = w();
+ dy = H = h()/3;
+ }
+ draw_box(drag==1?FL_DOWN_BOX:box(), x(), y()+2*dy, W, H, color());
+ draw_box(drag==2?FL_DOWN_BOX:box(), x()+dx, y()+dy, W, H, color());
+ draw_box(drag==3?FL_DOWN_BOX:box(), x()+2*dx, y(), W, H, color());
+ if (active_r())
+ fl_color(selection_color());
+ else
+ fl_color(fl_inactive(selection_color()));
+ fastarrow.draw(x()+(W-fastarrow_width)/2,
+ y()+2*dy+(H-fastarrow_height)/2, W, H);
+ mediumarrow.draw(x()+dx+(W-mediumarrow_width)/2,
+ y()+dy+(H-mediumarrow_height)/2, W, H);
+ slowarrow.draw(x()+2*dx+(W-slowarrow_width)/2,
+ y()+(H-slowarrow_width)/2, W, H);
+ if (Fl::focus() == this) draw_focus();
+}
+
+int Fl_Adjuster::handle(int event) {
+ double v;
+ int delta;
+ int mx = Fl::event_x();
+ switch (event) {
+ case FL_PUSH:
+ if (Fl::visible_focus()) Fl::focus(this);
+ ix = mx;
+ if (w()>=h())
+ drag = 3*(mx-x())/w() + 1;
+ else
+ drag = 3-3*(Fl::event_y()-y()-1)/h();
+ handle_push();
+ redraw();
+ return 1;
+ case FL_DRAG:
+ if (w() >= h()) {
+ delta = x()+(drag-1)*w()/3; // left edge of button
+ if (mx < delta)
+ delta = mx-delta;
+ else if (mx > (delta+w()/3)) // right edge of button
+ delta = mx-delta-w()/3;
+ else
+ delta = 0;
+ } else {
+ if (mx < x())
+ delta = mx-x();
+ else if (mx > (x()+w()))
+ delta = mx-x()-w();
+ else
+ delta = 0;
+ }
+ switch (drag) {
+ case 3: v = increment(previous_value(), delta); break;
+ case 2: v = increment(previous_value(), delta*10); break;
+ default:v = increment(previous_value(), delta*100); break;
+ }
+ handle_drag(soft() ? softclamp(v) : clamp(v));
+ return 1;
+ case FL_RELEASE:
+ if (Fl::event_is_click()) { // detect click but no drag
+ if (Fl::event_state()&0xF0000) delta = -10;
+ else delta = 10;
+ switch (drag) {
+ case 3: v = increment(previous_value(), delta); break;
+ case 2: v = increment(previous_value(), delta*10); break;
+ default:v = increment(previous_value(), delta*100); break;
+ }
+ handle_drag(soft() ? softclamp(v) : clamp(v));
+ }
+ drag = 0;
+ redraw();
+ handle_release();
+ return 1;
+ case FL_KEYBOARD :
+ switch (Fl::event_key()) {
+ case FL_Up:
+ if (w() > h()) return 0;
+ handle_drag(clamp(increment(value(),-1)));
+ return 1;
+ case FL_Down:
+ if (w() > h()) return 0;
+ handle_drag(clamp(increment(value(),1)));
+ return 1;
+ case FL_Left:
+ if (w() < h()) return 0;
+ handle_drag(clamp(increment(value(),-1)));
+ return 1;
+ case FL_Right:
+ if (w() < h()) return 0;
+ handle_drag(clamp(increment(value(),1)));
+ return 1;
+ default:
+ return 0;
+ }
+ // break not required because of switch...
+
+ case FL_FOCUS:
+ case FL_UNFOCUS:
+ if (Fl::visible_focus()) {
+ redraw();
+ return 1;
+ } else return 0;
+
+ case FL_ENTER :
+ case FL_LEAVE :
+ return 1;
+ }
+ return 0;
+}
+
+Fl_Adjuster::Fl_Adjuster(int X, int Y, int W, int H, const char* l)
+ : Fl_Valuator(X, Y, W, H, l) {
+ box(FL_UP_BOX);
+ step(1, 10000);
+ selection_color(FL_SELECTION_COLOR);
+ drag = 0;
+ soft_ = 1;
+}
+
+//
+// End of "$Id: Fl_Adjuster.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_BMP_Image.cxx b/third_party/windows/fltk-1.1.10/src/Fl_BMP_Image.cxx new file mode 100644 index 0000000..13537d3 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_BMP_Image.cxx @@ -0,0 +1,493 @@ +//
+// "$Id: Fl_BMP_Image.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Fl_BMP_Image routines.
+//
+// Copyright 1997-2005 by Easy Software Products.
+// Image support donated by Matthias Melcher, Copyright 2000.
+//
+// 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
+//
+// Contents:
+//
+// Fl_BMP_Image::Fl_BMP_Image() - Load a BMP image file.
+//
+
+//
+// Include necessary header files...
+//
+
+#include <FL/Fl_BMP_Image.H>
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+//
+// BMP definitions...
+//
+
+#ifndef BI_RGB
+# define BI_RGB 0 // No compression - straight BGR data
+# define BI_RLE8 1 // 8-bit run-length compression
+# define BI_RLE4 2 // 4-bit run-length compression
+# define BI_BITFIELDS 3 // RGB bitmap with RGB masks
+#endif // !BI_RGB
+
+
+//
+// Local functions...
+//
+
+static int read_long(FILE *fp);
+static unsigned short read_word(FILE *fp);
+static unsigned int read_dword(FILE *fp);
+
+
+//
+// 'Fl_BMP_Image::Fl_BMP_Image()' - Load a BMP image file.
+//
+
+Fl_BMP_Image::Fl_BMP_Image(const char *bmp) // I - File to read
+ : Fl_RGB_Image(0,0,0) {
+ FILE *fp; // File pointer
+ int info_size, // Size of info header
+ depth, // Depth of image (bits)
+ bDepth = 3, // Depth of image (bytes)
+ compression, // Type of compression
+ colors_used, // Number of colors used
+ x, y, // Looping vars
+ color, // Color of RLE pixel
+ repcount, // Number of times to repeat
+ temp, // Temporary color
+ align, // Alignment bytes
+ dataSize, // number of bytes in image data set
+ row_order, // 1 = normal; -1 = flipped row order
+ start_y, // Beginning Y
+ end_y; // Ending Y
+ long offbits; // Offset to image data
+ uchar bit, // Bit in image
+ byte; // Byte in image
+ uchar *ptr; // Pointer into pixels
+ uchar colormap[256][3];// Colormap
+ uchar havemask; // Single bit mask follows image data
+ int use_5_6_5; // Use 5:6:5 for R:G:B channels in 16 bit images
+
+
+ // Open the file...
+ if ((fp = fopen(bmp, "rb")) == NULL) return;
+
+ // Get the header...
+ byte = (uchar)getc(fp); // Check "BM" sync chars
+ bit = (uchar)getc(fp);
+ if (byte != 'B' || bit != 'M') {
+ fclose(fp);
+ return;
+ }
+
+ read_dword(fp); // Skip size
+ read_word(fp); // Skip reserved stuff
+ read_word(fp);
+ offbits = (long)read_dword(fp);// Read offset to image data
+
+ // Then the bitmap information...
+ info_size = read_dword(fp);
+
+// printf("offbits = %ld, info_size = %d\n", offbits, info_size);
+
+ havemask = 0;
+ row_order = -1;
+ use_5_6_5 = 0;
+
+ if (info_size < 40) {
+ // Old Windows/OS2 BMP header...
+ w(read_word(fp));
+ h(read_word(fp));
+ read_word(fp);
+ depth = read_word(fp);
+ compression = BI_RGB;
+ colors_used = 0;
+
+ repcount = info_size - 12;
+ } else {
+ // New BMP header...
+ w(read_long(fp));
+ // If the height is negative, the row order is flipped
+ temp = read_long(fp);
+ if (temp < 0) row_order = 1;
+ h(abs(temp));
+ read_word(fp);
+ depth = read_word(fp);
+ compression = read_dword(fp);
+ dataSize = read_dword(fp);
+ read_long(fp);
+ read_long(fp);
+ colors_used = read_dword(fp);
+ read_dword(fp);
+
+ repcount = info_size - 40;
+
+ if (!compression && depth>=8 && w()>32/depth) {
+ int Bpp = depth/8;
+ int maskSize = (((w()*Bpp+3)&~3)*h()) + (((((w()+7)/8)+3)&~3)*h());
+ if (maskSize==2*dataSize) {
+ havemask = 1;
+ h(h()/2);
+ bDepth = 4;
+ }
+ }
+ }
+
+// printf("w() = %d, h() = %d, depth = %d, compression = %d, colors_used = %d, repcount = %d\n",
+// w(), h(), depth, compression, colors_used, repcount);
+
+ // Skip remaining header bytes...
+ while (repcount > 0) {
+ getc(fp);
+ repcount --;
+ }
+
+ // Check header data...
+ if (!w() || !h() || !depth) {
+ fclose(fp);
+ return;
+ }
+
+ // Get colormap...
+ if (colors_used == 0 && depth <= 8)
+ colors_used = 1 << depth;
+
+ for (repcount = 0; repcount < colors_used; repcount ++) {
+ // Read BGR color...
+ fread(colormap[repcount], 1, 3, fp);
+
+ // Skip pad byte for new BMP files...
+ if (info_size > 12) getc(fp);
+ }
+
+ // Read first dword of colormap. It tells us if 5:5:5 or 5:6:5 for 16 bit
+ if (depth == 16)
+ use_5_6_5 = (read_dword(fp) == 0xf800);
+
+ // Set byte depth for RGBA images
+ if (depth == 32)
+ bDepth=4;
+
+ // Setup image and buffers...
+ d(bDepth);
+ if (offbits) fseek(fp, offbits, SEEK_SET);
+
+ array = new uchar[w() * h() * d()];
+ alloc_array = 1;
+
+ // Read the image data...
+ color = 0;
+ repcount = 0;
+ align = 0;
+ byte = 0;
+ temp = 0;
+
+ if (row_order < 0) {
+ start_y = h() - 1;
+ end_y = -1;
+ } else {
+ start_y = 0;
+ end_y = h();
+ }
+
+ for (y = start_y; y != end_y; y += row_order) {
+ ptr = (uchar *)array + y * w() * d();
+
+ switch (depth)
+ {
+ case 1 : // Bitmap
+ for (x = w(), bit = 128; x > 0; x --) {
+ if (bit == 128) byte = (uchar)getc(fp);
+
+ if (byte & bit) {
+ *ptr++ = colormap[1][2];
+ *ptr++ = colormap[1][1];
+ *ptr++ = colormap[1][0];
+ } else {
+ *ptr++ = colormap[0][2];
+ *ptr++ = colormap[0][1];
+ *ptr++ = colormap[0][0];
+ }
+
+ if (bit > 1)
+ bit >>= 1;
+ else
+ bit = 128;
+ }
+
+ // Read remaining bytes to align to 32 bits...
+ for (temp = (w() + 7) / 8; temp & 3; temp ++) {
+ getc(fp);
+ }
+ break;
+
+ case 4 : // 16-color
+ for (x = w(), bit = 0xf0; x > 0; x --) {
+ // Get a new repcount as needed...
+ if (repcount == 0) {
+ if (compression != BI_RLE4) {
+ repcount = 2;
+ color = -1;
+ } else {
+ while (align > 0) {
+ align --;
+ getc(fp);
+ }
+
+ if ((repcount = getc(fp)) == 0) {
+ if ((repcount = getc(fp)) == 0) {
+ // End of line...
+ x ++;
+ continue;
+ } else if (repcount == 1) {
+ // End of image...
+ break;
+ } else if (repcount == 2) {
+ // Delta...
+ repcount = getc(fp) * getc(fp) * w();
+ color = 0;
+ } else {
+ // Absolute...
+ color = -1;
+ align = ((4 - (repcount & 3)) / 2) & 1;
+ }
+ } else {
+ color = getc(fp);
+ }
+ }
+ }
+
+ // Get a new color as needed...
+ repcount --;
+
+ // Extract the next pixel...
+ if (bit == 0xf0) {
+ // Get the next color byte as needed...
+ if (color < 0) temp = getc(fp);
+ else temp = color;
+
+ // Copy the color value...
+ *ptr++ = colormap[(temp >> 4) & 15][2];
+ *ptr++ = colormap[(temp >> 4) & 15][1];
+ *ptr++ = colormap[(temp >> 4) & 15][0];
+
+ bit = 0x0f;
+ } else {
+ bit = 0xf0;
+
+ // Copy the color value...
+ *ptr++ = colormap[temp & 15][2];
+ *ptr++ = colormap[temp & 15][1];
+ *ptr++ = colormap[temp & 15][0];
+ }
+
+ }
+
+ if (!compression) {
+ // Read remaining bytes to align to 32 bits...
+ for (temp = (w() + 1) / 2; temp & 3; temp ++) {
+ getc(fp);
+ }
+ }
+ break;
+
+ case 8 : // 256-color
+ for (x = w(); x > 0; x --) {
+ // Get a new repcount as needed...
+ if (compression != BI_RLE8) {
+ repcount = 1;
+ color = -1;
+ }
+
+ if (repcount == 0) {
+ while (align > 0) {
+ align --;
+ getc(fp);
+ }
+
+ if ((repcount = getc(fp)) == 0) {
+ if ((repcount = getc(fp)) == 0) {
+ // End of line...
+ x ++;
+ continue;
+ } else if (repcount == 1) {
+ // End of image...
+ break;
+ } else if (repcount == 2) {
+ // Delta...
+ repcount = getc(fp) * getc(fp) * w();
+ color = 0;
+ } else {
+ // Absolute...
+ color = -1;
+ align = (2 - (repcount & 1)) & 1;
+ }
+ } else {
+ color = getc(fp);
+ }
+ }
+
+ // Get a new color as needed...
+ if (color < 0) temp = getc(fp);
+ else temp = color;
+
+ repcount --;
+
+ // Copy the color value...
+ *ptr++ = colormap[temp][2];
+ *ptr++ = colormap[temp][1];
+ *ptr++ = colormap[temp][0];
+ if (havemask) ptr++;
+ }
+
+ if (!compression) {
+ // Read remaining bytes to align to 32 bits...
+ for (temp = w(); temp & 3; temp ++) {
+ getc(fp);
+ }
+ }
+ break;
+
+ case 16 : // 16-bit 5:5:5 or 5:6:5 RGB
+ for (x = w(); x > 0; x --, ptr += bDepth) {
+ uchar b = getc(fp), a = getc(fp) ;
+ if (use_5_6_5) {
+ ptr[2] = (uchar)(( b << 3 ) & 0xf8);
+ ptr[1] = (uchar)(((a << 5) & 0xe0) | ((b >> 3) & 0x1c));
+ ptr[0] = (uchar)(a & 0xf8);
+ } else {
+ ptr[2] = (uchar)((b << 3) & 0xf8);
+ ptr[1] = (uchar)(((a << 6) & 0xc0) | ((b >> 2) & 0x38));
+ ptr[0] = (uchar)((a<<1) & 0xf8);
+ }
+ }
+
+ // Read remaining bytes to align to 32 bits...
+ for (temp = w() * 2; temp & 3; temp ++) {
+ getc(fp);
+ }
+ break;
+
+ case 24 : // 24-bit RGB
+ for (x = w(); x > 0; x --, ptr += bDepth) {
+ ptr[2] = (uchar)getc(fp);
+ ptr[1] = (uchar)getc(fp);
+ ptr[0] = (uchar)getc(fp);
+ }
+
+ // Read remaining bytes to align to 32 bits...
+ for (temp = w() * 3; temp & 3; temp ++) {
+ getc(fp);
+ }
+ break;
+
+ case 32 : // 32-bit RGBA
+ for (x = w(); x > 0; x --, ptr += bDepth) {
+ ptr[2] = (uchar)getc(fp);
+ ptr[1] = (uchar)getc(fp);
+ ptr[0] = (uchar)getc(fp);
+ ptr[3] = (uchar)getc(fp);
+ }
+ break;
+ }
+ }
+
+ if (havemask) {
+ for (y = h() - 1; y >= 0; y --) {
+ ptr = (uchar *)array + y * w() * d() + 3;
+ for (x = w(), bit = 128; x > 0; x --, ptr+=bDepth) {
+ if (bit == 128) byte = (uchar)getc(fp);
+ if (byte & bit)
+ *ptr = 0;
+ else
+ *ptr = 255;
+ if (bit > 1)
+ bit >>= 1;
+ else
+ bit = 128;
+ }
+ // Read remaining bytes to align to 32 bits...
+ for (temp = (w() + 7) / 8; temp & 3; temp ++)
+ getc(fp);
+ }
+ }
+
+ // Close the file and return...
+ fclose(fp);
+}
+
+
+//
+// 'read_word()' - Read a 16-bit unsigned integer.
+//
+
+static unsigned short // O - 16-bit unsigned integer
+read_word(FILE *fp) { // I - File to read from
+ unsigned char b0, b1; // Bytes from file
+
+ b0 = (uchar)getc(fp);
+ b1 = (uchar)getc(fp);
+
+ return ((b1 << 8) | b0);
+}
+
+
+//
+// 'read_dword()' - Read a 32-bit unsigned integer.
+//
+
+static unsigned int // O - 32-bit unsigned integer
+read_dword(FILE *fp) { // I - File to read from
+ unsigned char b0, b1, b2, b3; // Bytes from file
+
+ b0 = (uchar)getc(fp);
+ b1 = (uchar)getc(fp);
+ b2 = (uchar)getc(fp);
+ b3 = (uchar)getc(fp);
+
+ return ((((((b3 << 8) | b2) << 8) | b1) << 8) | b0);
+}
+
+
+//
+// 'read_long()' - Read a 32-bit signed integer.
+//
+
+static int // O - 32-bit signed integer
+read_long(FILE *fp) { // I - File to read from
+ unsigned char b0, b1, b2, b3; // Bytes from file
+
+ b0 = (uchar)getc(fp);
+ b1 = (uchar)getc(fp);
+ b2 = (uchar)getc(fp);
+ b3 = (uchar)getc(fp);
+
+ return ((int)(((((b3 << 8) | b2) << 8) | b1) << 8) | b0);
+}
+
+
+//
+// End of "$Id: Fl_BMP_Image.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Bitmap.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Bitmap.cxx new file mode 100644 index 0000000..09a67cb --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Bitmap.cxx @@ -0,0 +1,518 @@ +//
+// "$Id: Fl_Bitmap.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Bitmap drawing routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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/x.H>
+#include <FL/fl_draw.H>
+#include <FL/Fl_Widget.H>
+#include <FL/Fl_Menu_Item.H>
+#include <FL/Fl_Bitmap.H>
+#include "flstring.h"
+
+#ifdef __APPLE_QD__ // MacOS bitmask functions
+Fl_Bitmask fl_create_bitmask(int w, int h, const uchar *array) {
+ Rect srcRect;
+ srcRect.left = 0; srcRect.right = w;
+ srcRect.top = 0; srcRect.bottom = h;
+ GrafPtr savePort;
+
+ GetPort(&savePort); // remember the current port
+
+ Fl_Bitmask gw;
+ NewGWorld( &gw, 1, &srcRect, 0L, 0L, 0 );
+ PixMapHandle pm = GetGWorldPixMap( gw );
+ if ( pm )
+ {
+ LockPixels( pm );
+ if ( *pm )
+ {
+ uchar *base = (uchar*)GetPixBaseAddr( pm );
+ if ( base )
+ {
+ PixMapPtr pmp = *pm;
+ // verify the parameters for direct memory write
+ if ( pmp->pixelType == 0 || pmp->pixelSize == 1 || pmp->cmpCount == 1 || pmp->cmpSize == 1 )
+ {
+ static uchar reverse[16] = /* Bit reversal lookup table */
+ { 0x00, 0x88, 0x44, 0xcc, 0x22, 0xaa, 0x66, 0xee, 0x11, 0x99, 0x55, 0xdd, 0x33, 0xbb, 0x77, 0xff };
+ uchar *dst = base;
+ const uchar *src = array;
+ int rowBytesSrc = (w+7)>>3 ;
+ int rowPatch = (pmp->rowBytes&0x3fff) - rowBytesSrc;
+ for ( int j=0; j<h; j++,dst+=rowPatch )
+ for ( int i=0; i<rowBytesSrc; i++,src++ )
+ *dst++ = (reverse[*src & 0x0f] & 0xf0) | (reverse[(*src >> 4) & 0x0f] & 0x0f);
+ }
+ }
+ UnlockPixels( pm );
+ }
+ }
+
+ SetPort(savePort);
+ return gw; /* tell caller we succeeded! */
+}
+
+void fl_delete_bitmask(Fl_Bitmask id) {
+ if (id) DisposeGWorld(id);
+}
+#elif defined(__APPLE_QUARTZ__)
+Fl_Bitmask fl_create_bitmask(int w, int h, const uchar *array) {
+ static uchar reverse[16] = /* Bit reversal lookup table */
+ { 0x00, 0x88, 0x44, 0xcc, 0x22, 0xaa, 0x66, 0xee,
+ 0x11, 0x99, 0x55, 0xdd, 0x33, 0xbb, 0x77, 0xff };
+ int rowBytes = (w+7)>>3 ;
+ uchar *bmask = (uchar*)malloc(rowBytes*h), *dst = bmask;
+ const uchar *src = array;
+ for ( int i=rowBytes*h; i>0; i--,src++ ) {
+ *dst++ = ((reverse[*src & 0x0f] & 0xf0) | (reverse[(*src >> 4) & 0x0f] & 0x0f))^0xff;
+ }
+ CGDataProviderRef srcp = CGDataProviderCreateWithData( 0L, bmask, rowBytes*h, 0L);
+ CGImageRef id = CGImageMaskCreate( w, h, 1, 1, rowBytes, srcp, 0L, false);
+ CGDataProviderRelease(srcp);
+ return (Fl_Bitmask)id;
+}
+void fl_delete_bitmask(Fl_Bitmask id) {
+ if (id) CGImageRelease((CGImageRef)id);
+}
+#elif defined(WIN32) // Windows bitmask functions...
+// 'fl_create_bitmap()' - Create a 1-bit bitmap for drawing...
+static Fl_Bitmask fl_create_bitmap(int w, int h, const uchar *data) {
+ // we need to pad the lines out to words & swap the bits
+ // in each byte.
+ int w1 = (w+7)/8;
+ int w2 = ((w+15)/16)*2;
+ uchar* newarray = new uchar[w2*h];
+ const uchar* src = data;
+ uchar* dest = newarray;
+ Fl_Bitmask id;
+ static uchar reverse[16] = /* Bit reversal lookup table */
+ { 0x00, 0x88, 0x44, 0xcc, 0x22, 0xaa, 0x66, 0xee,
+ 0x11, 0x99, 0x55, 0xdd, 0x33, 0xbb, 0x77, 0xff };
+
+ for (int y=0; y < h; y++) {
+ for (int n = 0; n < w1; n++, src++)
+ *dest++ = (uchar)((reverse[*src & 0x0f] & 0xf0) |
+ (reverse[(*src >> 4) & 0x0f] & 0x0f));
+ dest += w2-w1;
+ }
+
+ id = CreateBitmap(w, h, 1, 1, newarray);
+
+ delete[] newarray;
+
+ return id;
+}
+
+// 'fl_create_bitmask()' - Create an N-bit bitmap for masking...
+Fl_Bitmask fl_create_bitmask(int w, int h, const uchar *data) {
+ // this won't work when the user changes display mode during run or
+ // has two screens with differnet depths
+ Fl_Bitmask id;
+ static uchar hiNibble[16] =
+ { 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+ 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0 };
+ static uchar loNibble[16] =
+ { 0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e,
+ 0x01, 0x09, 0x05, 0x0d, 0x03, 0x0b, 0x07, 0x0f };
+ int np = GetDeviceCaps(fl_gc, PLANES); //: was always one on sample machines
+ int bpp = GetDeviceCaps(fl_gc, BITSPIXEL);//: 1,4,8,16,24,32 and more odd stuff?
+ int Bpr = (bpp*w+7)/8; //: bytes per row
+ int pad = Bpr&1, w1 = (w+7)/8, shr = ((w-1)&7)+1;
+ if (bpp==4) shr = (shr+1)/2;
+ uchar *newarray = new uchar[(Bpr+pad)*h];
+ uchar *dst = newarray;
+ const uchar *src = data;
+
+ for (int i=0; i<h; i++) {
+ // This is slooow, but we do it only once per pixmap
+ for (int j=w1; j>0; j--) {
+ uchar b = *src++;
+ if (bpp==1) {
+ *dst++ = (uchar)( hiNibble[b&15] ) | ( loNibble[(b>>4)&15] );
+ } else if (bpp==4) {
+ for (int k=(j==1)?shr:4; k>0; k--) {
+ *dst++ = (uchar)("\377\360\017\000"[b&3]);
+ b = b >> 2;
+ }
+ } else {
+ for (int k=(j==1)?shr:8; k>0; k--) {
+ if (b&1) {
+ *dst++=0;
+ if (bpp>8) *dst++=0;
+ if (bpp>16) *dst++=0;
+ if (bpp>24) *dst++=0;
+ } else {
+ *dst++=0xff;
+ if (bpp>8) *dst++=0xff;
+ if (bpp>16) *dst++=0xff;
+ if (bpp>24) *dst++=0xff;
+ }
+
+ b = b >> 1;
+ }
+ }
+ }
+
+ dst += pad;
+ }
+
+ id = CreateBitmap(w, h, np, bpp, newarray);
+ delete[] newarray;
+
+ return id;
+}
+
+#if 0 // This doesn't appear to be used anywhere...
+Fl_Bitmask fl_create_bitmask(int w, int h, const uchar *data, int for_mask) {
+ // we need to pad the lines out to words & swap the bits
+ // in each byte.
+ int w1 = (w+7)/8;
+ int w2 = ((w+15)/16)*2;
+ uchar* newarray = new uchar[w2*h];
+ const uchar* src = data;
+ uchar* dest = newarray;
+ Fl_Bitmask id;
+ static uchar reverse[16] = /* Bit reversal lookup table */
+ { 0x00, 0x88, 0x44, 0xcc, 0x22, 0xaa, 0x66, 0xee,
+ 0x11, 0x99, 0x55, 0xdd, 0x33, 0xbb, 0x77, 0xff };
+
+ for (int y=0; y < h; y++) {
+ for (int n = 0; n < w1; n++, src++)
+ *dest++ = (reverse[*src & 0x0f] & 0xf0) |
+ (reverse[(*src >> 4) & 0x0f] & 0x0f);
+ dest += w2-w1;
+ }
+
+ id = CreateBitmap(w, h, 1, 1, newarray);
+
+ delete[] newarray;
+
+ return (id);
+}
+# endif // 0
+
+void fl_delete_bitmask(Fl_Bitmask bm) {
+ DeleteObject((HGDIOBJ)bm);
+}
+#else // X11 bitmask functions
+Fl_Bitmask fl_create_bitmask(int w, int h, const uchar *data) {
+ return XCreateBitmapFromData(fl_display, fl_window, (const char *)data,
+ (w+7)&-8, h);
+}
+
+void fl_delete_bitmask(Fl_Bitmask bm) {
+ fl_delete_offscreen((Fl_Offscreen)bm);
+}
+#endif // __APPLE__
+
+
+// MRS: Currently it appears that CopyDeepMask() does not work with an 8-bit alpha mask.
+// If you want to test/fix this, uncomment the "#ifdef __APPLE__" and comment out
+// the "#if 0" here. Also see Fl_Image.cxx for a similar check...
+
+//#ifdef __APPLE_QD__
+#if 0
+// Create an 8-bit mask used for alpha blending
+Fl_Bitmask fl_create_alphamask(int w, int h, int d, int ld, const uchar *array) {
+ Rect srcRect;
+ srcRect.left = 0; srcRect.right = w;
+ srcRect.top = 0; srcRect.bottom = h;
+ GrafPtr savePort;
+
+ GetPort(&savePort); // remember the current port
+
+ Fl_Bitmask gw;
+ NewGWorld( &gw, 8, &srcRect, 0L, 0L, 0 );
+ PixMapHandle pm = GetGWorldPixMap( gw );
+ if ( pm )
+ {
+ LockPixels( pm );
+ if ( *pm )
+ {
+ uchar *base = (uchar*)GetPixBaseAddr( pm );
+ if ( base )
+ {
+ PixMapPtr pmp = *pm;
+ // verify the parameters for direct memory write
+ if ( pmp->pixelType == 0 || pmp->pixelSize == 8 || pmp->cmpCount == 1 || pmp->cmpSize == 8 )
+ {
+ // Copy alpha values from the source array to the pixmap...
+ array += d - 1;
+ int rowoffset = (pmp->rowBytes & 0x3fff) - w;
+ for (int y = h; y > 0; y --, array += ld, base += rowoffset) {
+ for (int x = w; x > 0; x --, array += d) {
+ *base++ = 255 /*255 - *array*/;
+ }
+ }
+ }
+ }
+ UnlockPixels( pm );
+ }
+ }
+
+ SetPort(savePort);
+ return gw; /* tell caller we succeeded! */
+}
+#else
+// Create a 1-bit mask used for alpha blending
+Fl_Bitmask fl_create_alphamask(int w, int h, int d, int ld, const uchar *array) {
+ Fl_Bitmask mask;
+ int bmw = (w + 7) / 8;
+ uchar *bitmap = new uchar[bmw * h];
+ uchar *bitptr, bit;
+ const uchar *dataptr;
+ int x, y;
+ static uchar dither[16][16] = { // Simple 16x16 Floyd dither
+ { 0, 128, 32, 160, 8, 136, 40, 168,
+ 2, 130, 34, 162, 10, 138, 42, 170 },
+ { 192, 64, 224, 96, 200, 72, 232, 104,
+ 194, 66, 226, 98, 202, 74, 234, 106 },
+ { 48, 176, 16, 144, 56, 184, 24, 152,
+ 50, 178, 18, 146, 58, 186, 26, 154 },
+ { 240, 112, 208, 80, 248, 120, 216, 88,
+ 242, 114, 210, 82, 250, 122, 218, 90 },
+ { 12, 140, 44, 172, 4, 132, 36, 164,
+ 14, 142, 46, 174, 6, 134, 38, 166 },
+ { 204, 76, 236, 108, 196, 68, 228, 100,
+ 206, 78, 238, 110, 198, 70, 230, 102 },
+ { 60, 188, 28, 156, 52, 180, 20, 148,
+ 62, 190, 30, 158, 54, 182, 22, 150 },
+ { 252, 124, 220, 92, 244, 116, 212, 84,
+ 254, 126, 222, 94, 246, 118, 214, 86 },
+ { 3, 131, 35, 163, 11, 139, 43, 171,
+ 1, 129, 33, 161, 9, 137, 41, 169 },
+ { 195, 67, 227, 99, 203, 75, 235, 107,
+ 193, 65, 225, 97, 201, 73, 233, 105 },
+ { 51, 179, 19, 147, 59, 187, 27, 155,
+ 49, 177, 17, 145, 57, 185, 25, 153 },
+ { 243, 115, 211, 83, 251, 123, 219, 91,
+ 241, 113, 209, 81, 249, 121, 217, 89 },
+ { 15, 143, 47, 175, 7, 135, 39, 167,
+ 13, 141, 45, 173, 5, 133, 37, 165 },
+ { 207, 79, 239, 111, 199, 71, 231, 103,
+ 205, 77, 237, 109, 197, 69, 229, 101 },
+ { 63, 191, 31, 159, 55, 183, 23, 151,
+ 61, 189, 29, 157, 53, 181, 21, 149 },
+ { 254, 127, 223, 95, 247, 119, 215, 87,
+ 253, 125, 221, 93, 245, 117, 213, 85 }
+ };
+
+ // Generate a 1-bit "screen door" alpha mask; not always pretty, but
+ // definitely fast... In the future we may be able to support things
+ // like the RENDER extension in XFree86, when available, to provide
+ // true RGBA-blended rendering. See:
+ //
+ // http://www.xfree86.org/~keithp/render/protocol.html
+ //
+ // for more info on XRender...
+ //
+ // MacOS already provides alpha blending support and has its own
+ // fl_create_alphamask() function...
+ memset(bitmap, 0, bmw * h);
+
+ for (dataptr = array + d - 1, y = 0; y < h; y ++, dataptr += ld)
+ for (bitptr = bitmap + y * bmw, bit = 1, x = 0; x < w; x ++, dataptr += d) {
+ if (*dataptr > dither[x & 15][y & 15])
+ *bitptr |= bit;
+ if (bit < 128) bit <<= 1;
+ else {
+ bit = 1;
+ bitptr ++;
+ }
+ }
+
+ mask = fl_create_bitmask(w, h, bitmap);
+ delete[] bitmap;
+
+ return (mask);
+}
+#endif // __APPLE__
+
+void Fl_Bitmap::draw(int XP, int YP, int WP, int HP, int cx, int cy) {
+ if (!array) {
+ draw_empty(XP, YP);
+ return;
+ }
+
+ // account for current clip region (faster on Irix):
+ int X,Y,W,H; fl_clip_box(XP,YP,WP,HP,X,Y,W,H);
+ cx += X-XP; cy += Y-YP;
+ // clip the box down to the size of image, quit if empty:
+ if (cx < 0) {W += cx; X -= cx; cx = 0;}
+ if ((cx+W) > w()) W = w()-cx;
+ if (W <= 0) return;
+ if (cy < 0) {H += cy; Y -= cy; cy = 0;}
+ if ((cy+H) > h()) H = h()-cy;
+ if (H <= 0) return;
+#ifdef WIN32
+ if (!id) id = fl_create_bitmap(w(), h(), array);
+
+ HDC tempdc = CreateCompatibleDC(fl_gc);
+ int save = SaveDC(tempdc);
+ SelectObject(tempdc, (HGDIOBJ)id);
+ SelectObject(fl_gc, fl_brush());
+ // secret bitblt code found in old MSWindows reference manual:
+ BitBlt(fl_gc, X, Y, W, H, tempdc, cx, cy, 0xE20746L);
+ RestoreDC(tempdc, save);
+ DeleteDC(tempdc);
+#elif defined(__APPLE_QD__)
+ if (!id) id = fl_create_bitmask(w(), h(), array);
+ GrafPtr dstPort;
+ GetPort( &dstPort );
+ Rect src, dst;
+ GetPortBounds( (Fl_Offscreen)id, &src );
+ SetRect( &src, cx, cy, cx+W, cy+H );
+ SetRect( &dst, X, Y, X+W, Y+H );
+ CopyBits(GetPortBitMapForCopyBits((Fl_Offscreen)id), // srcBits
+ GetPortBitMapForCopyBits(dstPort), // dstBits
+ &src, // src bounds
+ &dst, // dst bounds
+ srcOr, // mode
+ 0L); // mask region
+#elif defined(__APPLE_QUARTZ__)
+ if (!id) id = fl_create_bitmask(w(), h(), array);
+ if (id && fl_gc) {
+ CGRect rect = { { X, Y }, { W, H } };
+ Fl_X::q_begin_image(rect, cx, cy, w(), h());
+ CGContextDrawImage(fl_gc, rect, (CGImageRef)id);
+ Fl_X::q_end_image();
+ }
+#else
+ if (!id) id = fl_create_bitmask(w(), h(), array);
+
+ XSetStipple(fl_display, fl_gc, id);
+ int ox = X-cx; if (ox < 0) ox += w();
+ int oy = Y-cy; if (oy < 0) oy += h();
+ XSetTSOrigin(fl_display, fl_gc, ox, oy);
+ XSetFillStyle(fl_display, fl_gc, FillStippled);
+ XFillRectangle(fl_display, fl_window, fl_gc, X, Y, W, H);
+ XSetFillStyle(fl_display, fl_gc, FillSolid);
+#endif
+}
+
+Fl_Bitmap::~Fl_Bitmap() {
+ uncache();
+ if (alloc_array) delete[] (uchar *)array;
+}
+
+void Fl_Bitmap::uncache() {
+ if (id) {
+ fl_delete_bitmask((Fl_Offscreen)id);
+ id = 0;
+ }
+}
+
+void Fl_Bitmap::label(Fl_Widget* widget) {
+ widget->image(this);
+}
+
+void Fl_Bitmap::label(Fl_Menu_Item* m) {
+ Fl::set_labeltype(_FL_IMAGE_LABEL, labeltype, measure);
+ m->label(_FL_IMAGE_LABEL, (const char*)this);
+}
+
+Fl_Image *Fl_Bitmap::copy(int W, int H) {
+ Fl_Bitmap *new_image; // New RGB image
+ uchar *new_array; // New array for image data
+
+ // Optimize the simple copy where the width and height are the same...
+ if (W == w() && H == h()) {
+ new_array = new uchar [H * ((W + 7) / 8)];
+ memcpy(new_array, array, H * ((W + 7) / 8));
+
+ new_image = new Fl_Bitmap(new_array, W, H);
+ new_image->alloc_array = 1;
+
+ return new_image;
+ }
+ if (W <= 0 || H <= 0) return 0;
+
+ // OK, need to resize the image data; allocate memory and
+ uchar *new_ptr, // Pointer into new array
+ new_bit, // Bit for new array
+ old_bit; // Bit for old array
+ const uchar *old_ptr; // Pointer into old array
+ int sx, sy, // Source coordinates
+ dx, dy, // Destination coordinates
+ xerr, yerr, // X & Y errors
+ xmod, ymod, // X & Y moduli
+ xstep, ystep; // X & Y step increments
+
+
+ // Figure out Bresenheim step/modulus values...
+ xmod = w() % W;
+ xstep = w() / W;
+ ymod = h() % H;
+ ystep = h() / H;
+
+ // Allocate memory for the new image...
+ new_array = new uchar [H * ((W + 7) / 8)];
+ new_image = new Fl_Bitmap(new_array, W, H);
+ new_image->alloc_array = 1;
+
+ memset(new_array, 0, H * ((W + 7) / 8));
+
+ // Scale the image using a nearest-neighbor algorithm...
+ for (dy = H, sy = 0, yerr = H, new_ptr = new_array; dy > 0; dy --) {
+ for (dx = W, xerr = W, old_ptr = array + sy * ((w() + 7) / 8), sx = 0, new_bit = 1;
+ dx > 0;
+ dx --) {
+ old_bit = (uchar)(1 << (sx & 7));
+ if (old_ptr[sx / 8] & old_bit) *new_ptr |= new_bit;
+
+ if (new_bit < 128) new_bit <<= 1;
+ else {
+ new_bit = 1;
+ new_ptr ++;
+ }
+
+ sx += xstep;
+ xerr -= xmod;
+
+ if (xerr <= 0) {
+ xerr += W;
+ sx ++;
+ }
+ }
+
+ if (new_bit > 1) new_ptr ++;
+
+ sy += ystep;
+ yerr -= ymod;
+ if (yerr <= 0) {
+ yerr += H;
+ sy ++;
+ }
+ }
+
+ return new_image;
+}
+
+
+//
+// End of "$Id: Fl_Bitmap.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Box.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Box.cxx new file mode 100644 index 0000000..bc44d08 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Box.cxx @@ -0,0 +1,44 @@ +//
+// "$Id: Fl_Box.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Box widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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_Widget.H>
+#include <FL/Fl_Box.H>
+
+void Fl_Box::draw() {
+ draw_box();
+ draw_label();
+}
+
+int Fl_Box::handle(int event) {
+ if (event == FL_ENTER || event == FL_LEAVE) return 1;
+ else return 0;
+}
+
+
+//
+// End of "$Id: Fl_Box.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Browser.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Browser.cxx new file mode 100644 index 0000000..e31c6e0 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Browser.cxx @@ -0,0 +1,551 @@ +//
+// "$Id: Fl_Browser.cxx 5987 2007-11-20 21:57:17Z mike $"
+//
+// Browser widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2007 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_Browser.H>
+#include <FL/fl_draw.H>
+#include "flstring.h"
+#include <stdlib.h>
+#include <math.h>
+
+// I modified this from the original Forms data to use a linked list
+// so that the number of items in the browser and size of those items
+// is unlimited. The only problem is that the old browser used an
+// index number to identify a line, and it is slow to convert from/to
+// a pointer. I use a cache of the last match to try to speed this
+// up.
+
+// Also added the ability to "hide" a line. This set's it's height to
+// zero, so the Fl_Browser_ cannot pick it.
+
+#define SELECTED 1
+#define NOTDISPLAYED 2
+
+struct FL_BLINE { // data is in a linked list of these
+ FL_BLINE* prev;
+ FL_BLINE* next;
+ void* data;
+ short length; // sizeof(txt)-1, may be longer than string
+ char flags; // selected, displayed
+ char txt[1]; // start of allocated array
+};
+
+void* Fl_Browser::item_first() const {return first;}
+
+void* Fl_Browser::item_next(void* l) const {return ((FL_BLINE*)l)->next;}
+
+void* Fl_Browser::item_prev(void* l) const {return ((FL_BLINE*)l)->prev;}
+
+int Fl_Browser::item_selected(void* l) const {
+ return ((FL_BLINE*)l)->flags&SELECTED;}
+
+void Fl_Browser::item_select(void* l, int v) {
+ if (v) ((FL_BLINE*)l)->flags |= SELECTED;
+ else ((FL_BLINE*)l)->flags &= ~SELECTED;
+}
+
+FL_BLINE* Fl_Browser::find_line(int line) const {
+ int n; FL_BLINE* l;
+ if (line == cacheline) return cache;
+ if (cacheline && line > (cacheline/2) && line < ((cacheline+lines)/2)) {
+ n = cacheline; l = cache;
+ } else if (line <= (lines/2)) {
+ n = 1; l = first;
+ } else {
+ n = lines; l = last;
+ }
+ for (; n < line && l; n++) l = l->next;
+ for (; n > line && l; n--) l = l->prev;
+ ((Fl_Browser*)this)->cacheline = line;
+ ((Fl_Browser*)this)->cache = l;
+ return l;
+}
+
+int Fl_Browser::lineno(void* v) const {
+ FL_BLINE* l = (FL_BLINE*)v;
+ if (!l) return 0;
+ if (l == cache) return cacheline;
+ if (l == first) return 1;
+ if (l == last) return lines;
+ if (!cache) {
+ ((Fl_Browser*)this)->cache = first;
+ ((Fl_Browser*)this)->cacheline = 1;
+ }
+ // assumme it is near cache, search both directions:
+ FL_BLINE* b = cache->prev;
+ int bnum = cacheline-1;
+ FL_BLINE* f = cache->next;
+ int fnum = cacheline+1;
+ int n = 0;
+ for (;;) {
+ if (b == l) {n = bnum; break;}
+ if (f == l) {n = fnum; break;}
+ if (b) {b = b->prev; bnum--;}
+ if (f) {f = f->next; fnum++;}
+ }
+ ((Fl_Browser*)this)->cache = l;
+ ((Fl_Browser*)this)->cacheline = n;
+ return n;
+}
+
+FL_BLINE* Fl_Browser::_remove(int line) {
+ FL_BLINE* ttt = find_line(line);
+ deleting(ttt);
+
+ cacheline = line-1;
+ cache = ttt->prev;
+ lines--;
+ full_height_ -= item_height(ttt);
+ if (ttt->prev) ttt->prev->next = ttt->next;
+ else first = ttt->next;
+ if (ttt->next) ttt->next->prev = ttt->prev;
+ else last = ttt->prev;
+
+ return(ttt);
+}
+
+void Fl_Browser::remove(int line) {
+ if (line < 1 || line > lines) return;
+ free(_remove(line));
+}
+
+void Fl_Browser::insert(int line, FL_BLINE* t) {
+ if (!first) {
+ t->prev = t->next = 0;
+ first = last = t;
+ } else if (line <= 1) {
+ inserting(first, t);
+ t->prev = 0;
+ t->next = first;
+ t->next->prev = t;
+ first = t;
+ } else if (line > lines) {
+ t->prev = last;
+ t->prev->next = t;
+ t->next = 0;
+ last = t;
+ } else {
+ FL_BLINE* n = find_line(line);
+ inserting(n, t);
+ t->next = n;
+ t->prev = n->prev;
+ t->prev->next = t;
+ n->prev = t;
+ }
+ cacheline = line;
+ cache = t;
+ lines++;
+ full_height_ += item_height(t);
+ redraw_line(t);
+}
+
+void Fl_Browser::insert(int line, const char* newtext, void* d) {
+ int l = strlen(newtext);
+ FL_BLINE* t = (FL_BLINE*)malloc(sizeof(FL_BLINE)+l);
+ t->length = (short)l;
+ t->flags = 0;
+ strcpy(t->txt, newtext);
+ t->data = d;
+ insert(line, t);
+}
+
+void Fl_Browser::move(int to, int from) {
+ if (from < 1 || from > lines) return;
+ insert(to, _remove(from));
+}
+
+void Fl_Browser::text(int line, const char* newtext) {
+ if (line < 1 || line > lines) return;
+ FL_BLINE* t = find_line(line);
+ int l = strlen(newtext);
+ if (l > t->length) {
+ FL_BLINE* n = (FL_BLINE*)malloc(sizeof(FL_BLINE)+l);
+ replacing(t, n);
+ cache = n;
+ n->data = t->data;
+ n->length = (short)l;
+ n->flags = t->flags;
+ n->prev = t->prev;
+ if (n->prev) n->prev->next = n; else first = n;
+ n->next = t->next;
+ if (n->next) n->next->prev = n; else last = n;
+ free(t);
+ t = n;
+ }
+ strcpy(t->txt, newtext);
+ redraw_line(t);
+}
+
+void Fl_Browser::data(int line, void* d) {
+ if (line < 1 || line > lines) return;
+ find_line(line)->data = d;
+}
+
+int Fl_Browser::item_height(void* lv) const {
+ FL_BLINE* l = (FL_BLINE*)lv;
+ if (l->flags & NOTDISPLAYED) return 0;
+
+ int hmax = 2; // use 2 to insure we don't return a zero!
+
+ if (!l->txt[0]) {
+ // For blank lines set the height to exactly 1 line!
+ fl_font(textfont(), textsize());
+ int hh = fl_height();
+ if (hh > hmax) hmax = hh;
+ }
+ else {
+ const int* i = column_widths();
+ // do each column separately as they may all set different fonts:
+ for (char* str = l->txt; str && *str; str++) {
+ Fl_Font font = textfont(); // default font
+ int tsize = textsize(); // default size
+ while (*str==format_char()) {
+ str++;
+ switch (*str++) {
+ case 'l': case 'L': tsize = 24; break;
+ case 'm': case 'M': tsize = 18; break;
+ case 's': tsize = 11; break;
+ case 'b': font = (Fl_Font)(font|FL_BOLD); break;
+ case 'i': font = (Fl_Font)(font|FL_ITALIC); break;
+ case 'f': case 't': font = FL_COURIER; break;
+ case 'B':
+ case 'C': strtol(str, &str, 10); break;// skip a color number
+ case 'F': font = (Fl_Font)strtol(str,&str,10); break;
+ case 'S': tsize = strtol(str,&str,10); break;
+ case 0: case '@': str--;
+ case '.': goto END_FORMAT;
+ }
+ }
+ END_FORMAT:
+ char* ptr = str;
+ if (ptr && *i++) str = strchr(str, column_char());
+ else str = NULL;
+ if((!str && *ptr) || (str && ptr < str)) {
+ fl_font(font, tsize); int hh = fl_height();
+ if (hh > hmax) hmax = hh;
+ }
+ if (!str || !*str) break;
+ }
+ }
+
+ return hmax; // previous version returned hmax+2!
+}
+
+int Fl_Browser::item_width(void* v) const {
+ char* str = ((FL_BLINE*)v)->txt;
+ const int* i = column_widths();
+ int ww = 0;
+
+ while (*i) { // add up all tab-seperated fields
+ char* e;
+ e = strchr(str, column_char());
+ if (!e) break; // last one occupied by text
+ str = e+1;
+ ww += *i++;
+ }
+
+ // OK, we gotta parse the string and find the string width...
+ int tsize = textsize();
+ Fl_Font font = textfont();
+ int done = 0;
+
+ while (*str == format_char_ && str[1] && str[1] != format_char_) {
+ str ++;
+ switch (*str++) {
+ case 'l': case 'L': tsize = 24; break;
+ case 'm': case 'M': tsize = 18; break;
+ case 's': tsize = 11; break;
+ case 'b': font = (Fl_Font)(font|FL_BOLD); break;
+ case 'i': font = (Fl_Font)(font|FL_ITALIC); break;
+ case 'f': case 't': font = FL_COURIER; break;
+ case 'B':
+ case 'C': strtol(str, &str, 10); break;// skip a color number
+ case 'F': font = (Fl_Font)strtol(str, &str, 10); break;
+ case 'S': tsize = strtol(str, &str, 10); break;
+ case '.':
+ done = 1;
+ break;
+ case '@':
+ str--;
+ done = 1;
+ }
+
+ if (done)
+ break;
+ }
+
+ if (*str == format_char_ && str[1])
+ str ++;
+
+ fl_font(font, tsize);
+ return ww + int(fl_width(str)) + 6;
+}
+
+int Fl_Browser::full_height() const {
+ return full_height_;
+}
+
+int Fl_Browser::incr_height() const {
+ return textsize()+2;
+}
+
+void Fl_Browser::item_draw(void* v, int X, int Y, int W, int H) const {
+ char* str = ((FL_BLINE*)v)->txt;
+ const int* i = column_widths();
+
+ while (W > 6) { // do each tab-seperated field
+ int w1 = W; // width for this field
+ char* e = 0; // pointer to end of field or null if none
+ if (*i) { // find end of field and temporarily replace with 0
+ e = strchr(str, column_char());
+ if (e) {*e = 0; w1 = *i++;}
+ }
+ int tsize = textsize();
+ Fl_Font font = textfont();
+ Fl_Color lcol = textcolor();
+ Fl_Align talign = FL_ALIGN_LEFT;
+ // check for all the @-lines recognized by XForms:
+ while (*str == format_char() && *++str && *str != format_char()) {
+ switch (*str++) {
+ case 'l': case 'L': tsize = 24; break;
+ case 'm': case 'M': tsize = 18; break;
+ case 's': tsize = 11; break;
+ case 'b': font = (Fl_Font)(font|FL_BOLD); break;
+ case 'i': font = (Fl_Font)(font|FL_ITALIC); break;
+ case 'f': case 't': font = FL_COURIER; break;
+ case 'c': talign = FL_ALIGN_CENTER; break;
+ case 'r': talign = FL_ALIGN_RIGHT; break;
+ case 'B':
+ if (!(((FL_BLINE*)v)->flags & SELECTED)) {
+ fl_color((Fl_Color)strtol(str, &str, 10));
+ fl_rectf(X, Y, w1, H);
+ } else strtol(str, &str, 10);
+ break;
+ case 'C':
+ lcol = (Fl_Color)strtol(str, &str, 10);
+ break;
+ case 'F':
+ font = (Fl_Font)strtol(str, &str, 10);
+ break;
+ case 'N':
+ lcol = FL_INACTIVE_COLOR;
+ break;
+ case 'S':
+ tsize = strtol(str, &str, 10);
+ break;
+ case '-':
+ fl_color(FL_DARK3);
+ fl_line(X+3, Y+H/2, X+w1-3, Y+H/2);
+ fl_color(FL_LIGHT3);
+ fl_line(X+3, Y+H/2+1, X+w1-3, Y+H/2+1);
+ break;
+ case 'u':
+ case '_':
+ fl_color(lcol);
+ fl_line(X+3, Y+H-1, X+w1-3, Y+H-1);
+ break;
+ case '.':
+ goto BREAK;
+ case '@':
+ str--; goto BREAK;
+ }
+ }
+ BREAK:
+ fl_font(font, tsize);
+ if (((FL_BLINE*)v)->flags & SELECTED)
+ lcol = fl_contrast(lcol, selection_color());
+ if (!active_r()) lcol = fl_inactive(lcol);
+ fl_color(lcol);
+ fl_draw(str, X+3, Y, w1-6, H, e ? Fl_Align(talign|FL_ALIGN_CLIP) : talign, 0, 0);
+ if (!e) break; // no more fields...
+ *e = column_char(); // put the seperator back
+ X += w1;
+ W -= w1;
+ str = e+1;
+ }
+}
+
+static const int no_columns[1] = {0};
+
+Fl_Browser::Fl_Browser(int X, int Y, int W, int H, const char*l)
+ : Fl_Browser_(X, Y, W, H, l) {
+ column_widths_ = no_columns;
+ lines = 0;
+ full_height_ = 0;
+ cacheline = 0;
+ format_char_ = '@';
+ column_char_ = '\t';
+ first = last = cache = 0;
+}
+
+void Fl_Browser::lineposition(int line, Fl_Line_Position pos) {
+ if (line<1) line = 1;
+ if (line>lines) line = lines;
+ int p = 0;
+
+ FL_BLINE* l;
+ for (l=first; l && line>1; l = l->next) {
+ line--; p += item_height(l);
+ }
+ if (l && (pos == BOTTOM)) p += item_height (l);
+
+ int final = p, X, Y, W, H;
+ bbox(X, Y, W, H);
+
+ switch(pos) {
+ case TOP: break;
+ case BOTTOM: final -= H; break;
+ case MIDDLE: final -= H/2; break;
+ }
+
+ if (final > (full_height() - H)) final = full_height() -H;
+ position(final);
+}
+
+int Fl_Browser::topline() const {
+ return lineno(top());
+}
+
+void Fl_Browser::clear() {
+ for (FL_BLINE* l = first; l;) {
+ FL_BLINE* n = l->next;
+ free(l);
+ l = n;
+ }
+ full_height_ = 0;
+ first = 0;
+ lines = 0;
+ new_list();
+}
+
+void Fl_Browser::add(const char* newtext, void* d) {
+ insert(lines+1, newtext, d);
+ //Fl_Browser_::display(last);
+}
+
+const char* Fl_Browser::text(int line) const {
+ if (line < 1 || line > lines) return 0;
+ return find_line(line)->txt;
+}
+
+void* Fl_Browser::data(int line) const {
+ if (line < 1 || line > lines) return 0;
+ return find_line(line)->data;
+}
+
+int Fl_Browser::select(int line, int v) {
+ if (line < 1 || line > lines) return 0;
+ return Fl_Browser_::select(find_line(line), v);
+}
+
+int Fl_Browser::selected(int line) const {
+ if (line < 1 || line > lines) return 0;
+ return find_line(line)->flags & SELECTED;
+}
+
+void Fl_Browser::show(int line) {
+ FL_BLINE* t = find_line(line);
+ if (t->flags & NOTDISPLAYED) {
+ t->flags &= ~NOTDISPLAYED;
+ full_height_ += item_height(t);
+ if (Fl_Browser_::displayed(t)) redraw();
+ }
+}
+
+void Fl_Browser::hide(int line) {
+ FL_BLINE* t = find_line(line);
+ if (!(t->flags & NOTDISPLAYED)) {
+ full_height_ -= item_height(t);
+ t->flags |= NOTDISPLAYED;
+ if (Fl_Browser_::displayed(t)) redraw();
+ }
+}
+
+void Fl_Browser::display(int line, int v) {
+ if (line < 1 || line > lines) return;
+ if (v) show(line); else hide(line);
+}
+
+int Fl_Browser::visible(int line) const {
+ if (line < 1 || line > lines) return 0;
+ return !(find_line(line)->flags&NOTDISPLAYED);
+}
+
+int Fl_Browser::value() const {
+ return lineno(selection());
+}
+
+// SWAP TWO LINES
+void Fl_Browser::swap(FL_BLINE *a, FL_BLINE *b) {
+
+ if ( a == b || !a || !b) return; // nothing to do
+ swapping(a, b);
+ FL_BLINE *aprev = a->prev;
+ FL_BLINE *anext = a->next;
+ FL_BLINE *bprev = b->prev;
+ FL_BLINE *bnext = b->next;
+ if ( b->prev == a ) { // A ADJACENT TO B
+ if ( aprev ) aprev->next = b; else first = b;
+ b->next = a;
+ a->next = bnext;
+ b->prev = aprev;
+ a->prev = b;
+ if ( bnext ) bnext->prev = a; else last = a;
+ } else if ( a->prev == b ) { // B ADJACENT TO A
+ if ( bprev ) bprev->next = a; else first = a;
+ a->next = b;
+ b->next = anext;
+ a->prev = bprev;
+ b->prev = a;
+ if ( anext ) anext->prev = b; else last = b;
+ } else { // A AND B NOT ADJACENT
+ // handle prev's
+ b->prev = aprev;
+ if ( anext ) anext->prev = b; else last = b;
+ a->prev = bprev;
+ if ( bnext ) bnext->prev = a; else last = a;
+ // handle next's
+ if ( aprev ) aprev->next = b; else first = b;
+ b->next = anext;
+ if ( bprev ) bprev->next = a; else first = a;
+ a->next = bnext;
+ }
+ // Disable cache -- we played around with positions
+ cacheline = 0;
+ cache = 0;
+}
+
+void Fl_Browser::swap(int ai, int bi) {
+ if (ai < 1 || ai > lines || bi < 1 || bi > lines) return;
+ FL_BLINE* a = find_line(ai);
+ FL_BLINE* b = find_line(bi);
+ swap(a,b);
+}
+
+//
+// End of "$Id: Fl_Browser.cxx 5987 2007-11-20 21:57:17Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Browser_.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Browser_.cxx new file mode 100644 index 0000000..ae97f2d --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Browser_.cxx @@ -0,0 +1,842 @@ +//
+// "$Id: Fl_Browser_.cxx 5992 2007-12-15 16:20:16Z mike $"
+//
+// Base Browser widget class for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2006 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
+//
+
+#define DISPLAY_SEARCH_BOTH_WAYS_AT_ONCE
+
+#include <stdio.h>
+#include <FL/Fl.H>
+#include <FL/Fl_Widget.H>
+#include <FL/Fl_Browser_.H>
+#include <FL/fl_draw.H>
+
+
+// This is the base class for browsers. To be useful it must be
+// subclassed and several virtual functions defined. The
+// Forms-compatable browser and the file chooser's browser are
+// subclassed off of this.
+
+// Yes, I know this should be a template...
+
+// This has been designed so that the subclass has complete control
+// over the storage of the data, although because next() and prev()
+// functions are used to index, it works best as a linked list or as a
+// large block of characters in which the line breaks must be searched
+// for.
+
+// A great deal of work has been done so that the "height" of a data
+// object does not need to be determined until it is drawn. This was
+// done for the file chooser, because the height requires doing stat()
+// to see if the file is a directory, which can be annoyingly slow
+// over the network.
+
+/* redraw bits:
+ 1 = redraw children (the scrollbar)
+ 2 = redraw one or two items
+ 4 = redraw all items
+*/
+
+static void scrollbar_callback(Fl_Widget* s, void*) {
+ ((Fl_Browser_*)(s->parent()))->position(int(((Fl_Scrollbar*)s)->value()));
+}
+
+static void hscrollbar_callback(Fl_Widget* s, void*) {
+ ((Fl_Browser_*)(s->parent()))->hposition(int(((Fl_Scrollbar*)s)->value()));
+}
+
+// Scrollbar size should be part of the Fl class, but is left here for
+// binary compatibility in 1.1.x - M. Sweet
+int Fl_Browser_::scrollbar_width_ = 16;
+
+// Get the standard scrollbar size
+int Fl::scrollbar_size() {
+ return Fl_Browser_::scrollbar_width();
+}
+
+// Set the standard scrollbar size
+void Fl::scrollbar_size(int W) {
+ Fl_Browser_::scrollbar_width(W);
+}
+
+// return where to draw the actual box:
+void Fl_Browser_::bbox(int& X, int& Y, int& W, int& H) const {
+ Fl_Boxtype b = box() ? box() : FL_DOWN_BOX;
+ X = x()+Fl::box_dx(b);
+ Y = y()+Fl::box_dy(b);
+ W = w()-Fl::box_dw(b);
+ H = h()-Fl::box_dh(b);
+ if (scrollbar.visible()) {
+ W -= scrollbar_width_;
+ if (scrollbar.align() & FL_ALIGN_LEFT) X += scrollbar_width_;
+ }
+ if (W < 0) W = 0;
+ if (hscrollbar.visible()) {
+ H -= scrollbar_width_;
+ if (scrollbar.align() & FL_ALIGN_TOP) Y += scrollbar_width_;
+ }
+ if (H < 0) H = 0;
+}
+
+int Fl_Browser_::leftedge() const {
+ int X, Y, W, H; bbox(X, Y, W, H);
+ return X;
+}
+
+// The scrollbars may be moved again by draw(), since each one's size
+// depends on whether the other is visible or not. This skips over
+// Fl_Group::resize since it moves the scrollbars uselessly.
+void Fl_Browser_::resize(int X, int Y, int W, int H) {
+ Fl_Widget::resize(X, Y, W, H);
+ // move the scrollbars so they can respond to events:
+ bbox(X,Y,W,H);
+ scrollbar.resize(
+ scrollbar.align()&FL_ALIGN_LEFT ? X-scrollbar_width_ : X+W,
+ Y, scrollbar_width_, H);
+ hscrollbar.resize(
+ X, scrollbar.align()&FL_ALIGN_TOP ? Y-scrollbar_width_ : Y+H,
+ W, scrollbar_width_);
+}
+
+// Cause minimal update to redraw the given item:
+void Fl_Browser_::redraw_line(void* l) {
+ if (!redraw1 || redraw1 == l) {redraw1 = l; damage(FL_DAMAGE_EXPOSE);}
+ else if (!redraw2 || redraw2 == l) {redraw2 = l; damage(FL_DAMAGE_EXPOSE);}
+ else damage(FL_DAMAGE_SCROLL);
+}
+
+// Figure out top() based on position():
+void Fl_Browser_::update_top() {
+ if (!top_) top_ = item_first();
+ if (position_ != real_position_) {
+ void* l;
+ int ly;
+ int yy = position_;
+ // start from either head or current position, whichever is closer:
+ if (!top_ || yy <= (real_position_/2)) {
+ l = item_first();
+ ly = 0;
+ } else {
+ l = top_;
+ ly = real_position_-offset_;
+ }
+ if (!l) {
+ top_ = 0;
+ offset_ = 0;
+ real_position_ = 0;
+ } else {
+ int hh = item_quick_height(l);
+ // step through list until we find line containing this point:
+ while (ly > yy) {
+ void* l1 = item_prev(l);
+ if (!l1) {ly = 0; break;} // hit the top
+ l = l1;
+ hh = item_quick_height(l);
+ ly -= hh;
+ }
+ while ((ly+hh) <= yy) {
+ void* l1 = item_next(l);
+ if (!l1) {yy = ly+hh-1; break;}
+ l = l1;
+ ly += hh;
+ hh = item_quick_height(l);
+ }
+ // top item must *really* be visible, use slow height:
+ for (;;) {
+ hh = item_height(l);
+ if ((ly+hh) > yy) break; // it is big enough to see
+ // go up to top of previous item:
+ void* l1 = item_prev(l);
+ if (!l1) {ly = yy = 0; break;} // hit the top
+ l = l1; yy = position_ = ly = ly-item_quick_height(l);
+ }
+ // use it:
+ top_ = l;
+ offset_ = yy-ly;
+ real_position_ = yy;
+ }
+ damage(FL_DAMAGE_SCROLL);
+ }
+}
+
+// Change position(), top() will update when update_top() is called
+// (probably by draw() or handle()):
+void Fl_Browser_::position(int yy) {
+ if (yy < 0) yy = 0;
+ if (yy == position_) return;
+ position_ = yy;
+ if (yy != real_position_) redraw_lines();
+}
+
+void Fl_Browser_::hposition(int xx) {
+ if (xx < 0) xx = 0;
+ if (xx == hposition_) return;
+ hposition_ = xx;
+ if (xx != real_hposition_) redraw_lines();
+}
+
+// Tell whether item is currently displayed:
+int Fl_Browser_::displayed(void* p) const {
+ int X, Y, W, H; bbox(X, Y, W, H);
+ int yy = H+offset_;
+ for (void* l = top_; l && yy > 0; l = item_next(l)) {
+ if (l == p) return 1;
+ yy -= item_height(l);
+ }
+ return 0;
+}
+
+// Ensure this item is displayed:
+// Messy because we have no idea if it is before top or after bottom:
+void Fl_Browser_::display(void* p) {
+
+ // First special case - want to display first item in the list?
+ update_top();
+ if (p == item_first()) {position(0); return;}
+
+ int X, Y, W, H, Yp; bbox(X, Y, W, H);
+ void* l = top_;
+ Y = Yp = -offset_;
+ int h1;
+
+ // 2nd special case - want to display item already displayed at top of browser?
+ if (l == p) {position(real_position_+Y); return;} // scroll up a bit
+
+ // 3rd special case - want to display item just above top of browser?
+ void* lp = item_prev(l);
+ if (lp == p) {position(real_position_+Y-item_quick_height(lp)); return;}
+
+#ifdef DISPLAY_SEARCH_BOTH_WAYS_AT_ONCE
+ // search for item. We search both up and down the list at the same time,
+ // this evens up the execution time for the two cases - the old way was
+ // much slower for going up than for going down.
+ while (l || lp) {
+ if (l) {
+ h1 = item_quick_height(l);
+ if (l == p) {
+ if (Y <= H) { // it is visible or right at bottom
+ Y = Y+h1-H; // find where bottom edge is
+ if (Y > 0) position(real_position_+Y); // scroll down a bit
+ } else {
+ position(real_position_+Y-(H-h1)/2); // center it
+ }
+ return;
+ }
+ Y += h1;
+ l = item_next(l);
+ }
+ if (lp) {
+ h1 = item_quick_height(lp);
+ Yp -= h1;
+ if (lp == p) {
+ if ((Yp + h1) >= 0) position(real_position_+Yp);
+ else position(real_position_+Yp-(H-h1)/2);
+ return;
+ }
+ lp = item_prev(lp);
+ }
+ }
+#else
+ // Old version went forwards and then backwards:
+ // search forward for it:
+ l = top_;
+ for (; l; l = item_next(l)) {
+ h1 = item_quick_height(l);
+ if (l == p) {
+ if (Y <= H) { // it is visible or right at bottom
+ Y = Y+h1-H; // find where bottom edge is
+ if (Y > 0) position(real_position_+Y); // scroll down a bit
+ } else {
+ position(real_position_+Y-(H-h1)/2); // center it
+ }
+ return;
+ }
+ Y += h1;
+ }
+ // search backward for it, if found center it:
+ l = lp;
+ Y = -offset_;
+ for (; l; l = item_prev(l)) {
+ h1 = item_quick_height(l);
+ Y -= h1;
+ if (l == p) {
+ if ((Y + h1) >= 0) position(real_position_+Y);
+ else position(real_position_+Y-(H-h1)/2);
+ return;
+ }
+ }
+#endif
+}
+
+// redraw, has side effect of updating top and setting scrollbar:
+
+void Fl_Browser_::draw() {
+ int drawsquare = 0;
+ update_top();
+ int full_width_ = full_width();
+ int full_height_ = full_height();
+ int X, Y, W, H; bbox(X, Y, W, H);
+ int dont_repeat = 0;
+J1:
+ if (damage() & FL_DAMAGE_ALL) { // redraw the box if full redraw
+ Fl_Boxtype b = box() ? box() : FL_DOWN_BOX;
+ draw_box(b, x(), y(), w(), h(), color());
+ drawsquare = 1;
+ }
+ // see if scrollbar needs to be switched on/off:
+ if ((has_scrollbar_ & VERTICAL) && (
+ (has_scrollbar_ & ALWAYS_ON) || position_ || full_height_ > H)) {
+ if (!scrollbar.visible()) {
+ scrollbar.set_visible();
+ drawsquare = 1;
+ bbox(X, Y, W, H);
+ }
+ } else {
+ top_ = item_first(); real_position_ = offset_ = 0;
+ if (scrollbar.visible()) {
+ scrollbar.clear_visible();
+ clear_damage((uchar)(damage()|FL_DAMAGE_SCROLL));
+ }
+ }
+
+ if ((has_scrollbar_ & HORIZONTAL) && (
+ (has_scrollbar_ & ALWAYS_ON) || hposition_ || full_width_ > W)) {
+ if (!hscrollbar.visible()) {
+ hscrollbar.set_visible();
+ drawsquare = 1;
+ bbox(X, Y, W, H);
+ }
+ } else {
+ real_hposition_ = 0;
+ if (hscrollbar.visible()) {
+ hscrollbar.clear_visible();
+ clear_damage((uchar)(damage()|FL_DAMAGE_SCROLL));
+ }
+ }
+
+ // Check the vertical scrollbar again, just in case it needs to be drawn
+ // because the horizontal one is drawn. There should be a cleaner way
+ // to do this besides copying the same code...
+ if ((has_scrollbar_ & VERTICAL) && (
+ (has_scrollbar_ & ALWAYS_ON) || position_ || full_height_ > H)) {
+ if (!scrollbar.visible()) {
+ scrollbar.set_visible();
+ drawsquare = 1;
+ bbox(X, Y, W, H);
+ }
+ } else {
+ top_ = item_first(); real_position_ = offset_ = 0;
+ if (scrollbar.visible()) {
+ scrollbar.clear_visible();
+ clear_damage((uchar)(damage()|FL_DAMAGE_SCROLL));
+ }
+ }
+
+ bbox(X, Y, W, H);
+
+ fl_clip(X, Y, W, H);
+ // for each line, draw it if full redraw or scrolled. Erase background
+ // if not a full redraw or if it is selected:
+ void* l = top();
+ int yy = -offset_;
+ for (; l && yy < H; l = item_next(l)) {
+ int hh = item_height(l);
+ if (hh <= 0) continue;
+ if ((damage()&(FL_DAMAGE_SCROLL|FL_DAMAGE_ALL)) || l == redraw1 || l == redraw2) {
+ if (item_selected(l)) {
+ fl_color(active_r() ? selection_color() : fl_inactive(selection_color()));
+ fl_rectf(X, yy+Y, W, hh);
+ } else if (!(damage()&FL_DAMAGE_ALL)) {
+ fl_push_clip(X, yy+Y, W, hh);
+ draw_box(box() ? box() : FL_DOWN_BOX, x(), y(), w(), h(), color());
+ fl_pop_clip();
+ }
+ item_draw(l, X-hposition_, yy+Y, W+hposition_, hh);
+ if (l == selection_ && Fl::focus() == this) {
+ draw_box(FL_BORDER_FRAME, X, yy+Y, W, hh, color());
+ draw_focus(FL_NO_BOX, X, yy+Y, W+1, hh+1);
+ }
+ int ww = item_width(l);
+ if (ww > max_width) {max_width = ww; max_width_item = l;}
+ }
+ yy += hh;
+ }
+ // erase the area below last line:
+ if (!(damage()&FL_DAMAGE_ALL) && yy < H) {
+ fl_push_clip(X, yy+Y, W, H-yy);
+ draw_box(box() ? box() : FL_DOWN_BOX, x(), y(), w(), h(), color());
+ fl_pop_clip();
+ }
+ fl_pop_clip();
+ redraw1 = redraw2 = 0;
+
+ if (!dont_repeat) {
+ dont_repeat = 1;
+ // see if changes to full_height caused by calls to slow_height
+ // caused scrollbar state to change, in which case we have to redraw:
+ full_height_ = full_height();
+ full_width_ = full_width();
+ if ((has_scrollbar_ & VERTICAL) &&
+ ((has_scrollbar_ & ALWAYS_ON) || position_ || full_height_>H)) {
+ if (!scrollbar.visible()) { damage(FL_DAMAGE_ALL); goto J1; }
+ } else {
+ if (scrollbar.visible()) { damage(FL_DAMAGE_ALL); goto J1; }
+ }
+ if ((has_scrollbar_ & HORIZONTAL) &&
+ ((has_scrollbar_ & ALWAYS_ON) || hposition_ || full_width_>W)) {
+ if (!hscrollbar.visible()) { damage(FL_DAMAGE_ALL); goto J1; }
+ } else {
+ if (hscrollbar.visible()) { damage(FL_DAMAGE_ALL); goto J1; }
+ }
+ }
+
+ // update the scrollbars and redraw them:
+ int dy = top_ ? item_quick_height(top_) : 0; if (dy < 10) dy = 10;
+ if (scrollbar.visible()) {
+ scrollbar.damage_resize(
+ scrollbar.align()&FL_ALIGN_LEFT ? X-scrollbar_width_ : X+W,
+ Y, scrollbar_width_, H);
+ scrollbar.value(position_, H, 0, full_height_);
+ scrollbar.linesize(dy);
+ if (drawsquare) draw_child(scrollbar);
+ else update_child(scrollbar);
+ }
+ if (hscrollbar.visible()) {
+ hscrollbar.damage_resize(
+ X, scrollbar.align()&FL_ALIGN_TOP ? Y-scrollbar_width_ : Y+H,
+ W, scrollbar_width_);
+ hscrollbar.value(hposition_, W, 0, full_width_);
+ hscrollbar.linesize(dy);
+ if (drawsquare) draw_child(hscrollbar);
+ else update_child(hscrollbar);
+ }
+
+ // draw that little square between the scrollbars:
+ if (drawsquare && scrollbar.visible() && hscrollbar.visible()) {
+ fl_color(parent()->color());
+ fl_rectf(scrollbar.x(), hscrollbar.y(), scrollbar_width_,scrollbar_width_);
+ }
+
+ real_hposition_ = hposition_;
+}
+
+// Quick way to delete and reset everything:
+void Fl_Browser_::new_list() {
+ top_ = 0;
+ position_ = real_position_ = 0;
+ hposition_ = real_hposition_ = 0;
+ selection_ = 0;
+ offset_ = 0;
+ max_width = 0;
+ max_width_item = 0;
+ redraw_lines();
+}
+
+// Tell it that this item is going away, and that this must remove
+// all pointers to it:
+void Fl_Browser_::deleting(void* l) {
+ if (displayed(l)) {
+ redraw_lines();
+ if (l == top_) {
+ real_position_ -= offset_;
+ offset_ = 0;
+ top_ = item_next(l);
+ if (!top_) top_ = item_prev(l);
+ }
+ } else {
+ // we don't know where this item is, recalculate top...
+ real_position_ = 0;
+ offset_ = 0;
+ top_ = 0;
+ }
+ if (l == selection_) selection_ = 0;
+ if (l == max_width_item) {max_width_item = 0; max_width = 0;}
+}
+
+void Fl_Browser_::replacing(void* a, void* b) {
+ redraw_line(a);
+ if (a == selection_) selection_ = b;
+ if (a == top_) top_ = b;
+ if (a == max_width_item) {max_width_item = 0; max_width = 0;}
+}
+
+void Fl_Browser_::swapping(void* a, void* b) {
+ redraw_line(a);
+ redraw_line(b);
+ if (a == selection_) selection_ = b;
+ else if (b == selection_) selection_ = a;
+ if (a == top_) top_ = b;
+ else if (b == top_) top_ = a;
+}
+
+void Fl_Browser_::inserting(void* a, void* b) {
+ if (displayed(a)) redraw_lines();
+ if (a == top_) top_ = b;
+}
+
+void* Fl_Browser_::find_item(int my) {
+ update_top();
+ int X, Y, W, H; bbox(X, Y, W, H);
+ void* l;
+ int yy = Y-offset_;
+ for (l = top_; l; l = item_next(l)) {
+ int hh = item_height(l); if (hh <= 0) continue;
+ yy += hh;
+ if (my <= yy || yy>=(Y+H)) return l;
+ }
+ return 0;
+}
+
+int Fl_Browser_::select(void* l, int i, int docallbacks) {
+ if (type() == FL_MULTI_BROWSER) {
+ if (selection_ != l) {
+ if (selection_) redraw_line(selection_);
+ selection_ = l;
+ redraw_line(l);
+ }
+ if ((!i)==(!item_selected(l))) return 0;
+ item_select(l, i);
+ redraw_line(l);
+ } else {
+ if (i && selection_ == l) return 0;
+ if (!i && selection_ != l) return 0;
+ if (selection_) {
+ item_select(selection_, 0);
+ redraw_line(selection_);
+ selection_ = 0;
+ }
+ if (i) {
+ item_select(l, 1);
+ selection_ = l;
+ redraw_line(l);
+ display(l);
+ }
+ }
+ if (docallbacks) {
+ set_changed();
+ do_callback();
+ }
+ return 1;
+}
+
+int Fl_Browser_::deselect(int docallbacks) {
+ if (type() == FL_MULTI_BROWSER) {
+ int change = 0;
+ for (void* p = item_first(); p; p = item_next(p))
+ change |= select(p, 0, docallbacks);
+ return change;
+ } else {
+ if (!selection_) return 0;
+ item_select(selection_, 0);
+ redraw_line(selection_);
+ selection_ = 0;
+ return 1;
+ }
+}
+
+int Fl_Browser_::select_only(void* l, int docallbacks) {
+ if (!l) return deselect(docallbacks);
+ int change = 0;
+ if (type() == FL_MULTI_BROWSER) {
+ for (void* p = item_first(); p; p = item_next(p))
+ if (p != l) change |= select(p, 0, docallbacks);
+ }
+ change |= select(l, 1, docallbacks);
+ display(l);
+ return change;
+}
+
+int Fl_Browser_::handle(int event) {
+ // must do shortcuts first or the scrollbar will get them...
+ if (event == FL_ENTER || event == FL_LEAVE) return 1;
+ if (event == FL_KEYBOARD && type() >= FL_HOLD_BROWSER) {
+ void* l1 = selection_;
+ void* l = l1; if (!l) l = top_; if (!l) l = item_first();
+ if (l) {
+ if (type()==FL_HOLD_BROWSER) {
+ switch (Fl::event_key()) {
+ case FL_Down:
+ while ((l = item_next(l)))
+ if (item_height(l)>0) {select_only(l, when()); break;}
+ return 1;
+ case FL_Up:
+ while ((l = item_prev(l))) if (item_height(l)>0) {
+ select_only(l, when()); break;}
+ return 1;
+ }
+ } else {
+ switch (Fl::event_key()) {
+ case FL_Enter:
+ case FL_KP_Enter:
+ select_only(l, when() & ~FL_WHEN_ENTER_KEY);
+ if (when() & FL_WHEN_ENTER_KEY) {
+ set_changed();
+ do_callback();
+ }
+ return 1;
+ case ' ':
+ selection_ = l;
+ select(l, !item_selected(l), when() & ~FL_WHEN_ENTER_KEY);
+ return 1;
+ case FL_Down:
+ while ((l = item_next(l))) {
+ if (Fl::event_state(FL_SHIFT|FL_CTRL))
+ select(l, l1 ? item_selected(l1) : 1, when());
+ if (item_height(l)>0) goto J1;
+ }
+ return 1;
+ case FL_Up:
+ while ((l = item_prev(l))) {
+ if (Fl::event_state(FL_SHIFT|FL_CTRL))
+ select(l, l1 ? item_selected(l1) : 1, when());
+ if (item_height(l)>0) goto J1;
+ }
+ return 1;
+J1:
+ if (selection_) redraw_line(selection_);
+ selection_ = l; redraw_line(l);
+ display(l);
+ return 1;
+ }
+ }
+ }
+ }
+
+ if (Fl_Group::handle(event)) return 1;
+ int X, Y, W, H; bbox(X, Y, W, H);
+ int my;
+// NOTE:
+// instead of:
+// change = select_only(find_item(my), when() & FL_WHEN_CHANGED)
+// we use the construct:
+// change = select_only(find_item(my), 0);
+// if (change && (when() & FL_WHEN_CHANGED)) {
+// set_changed();
+// do_callback();
+// }
+// See str #834
+// The first form calls the callback *before* setting change.
+// The callback may execute an Fl::wait(), resulting in another
+// call of Fl_Browser_::handle() for the same widget. The sequence
+// of events can be an FL_PUSH followed by an FL_RELEASE.
+// This second call of Fl_Browser_::handle() may result in a -
+// somewhat unexpected - second concurrent invocation of the callback.
+
+ static char change;
+ static char whichway;
+ static int py;
+ switch (event) {
+ case FL_PUSH:
+ if (!Fl::event_inside(X, Y, W, H)) return 0;
+ if (Fl::visible_focus()) {
+ Fl::focus(this);
+ redraw();
+ }
+ my = py = Fl::event_y();
+ change = 0;
+ if (type() == FL_NORMAL_BROWSER || !top_)
+ ;
+ else if (type() != FL_MULTI_BROWSER) {
+ change = select_only(find_item(my), 0);
+ if (change && (when() & FL_WHEN_CHANGED)) {
+ set_changed();
+ do_callback();
+ }
+ } else {
+ void* l = find_item(my);
+ whichway = 1;
+ if (Fl::event_state(FL_CTRL)) { // toggle selection:
+ TOGGLE:
+ if (l) {
+ whichway = !item_selected(l);
+ change = select(l, whichway, 0);
+ if (change && (when() & FL_WHEN_CHANGED)) {
+ set_changed();
+ do_callback();
+ }
+ }
+ } else if (Fl::event_state(FL_SHIFT)) { // extend selection:
+ if (l == selection_) goto TOGGLE;
+ // state of previous selection determines new value:
+ whichway = l ? !item_selected(l) : 1;
+ // see which of the new item or previous selection is earlier,
+ // by searching from the previous forward for this one:
+ int down;
+ if (!l) down = 1;
+ else {for (void* m = selection_; ; m = item_next(m)) {
+ if (m == l) {down = 1; break;}
+ if (!m) {down = 0; break;}
+ }}
+ if (down) {
+ for (void* m = selection_; m != l; m = item_next(m))
+ select(m, whichway, when() & FL_WHEN_CHANGED);
+ } else {
+ void* e = selection_;
+ for (void* m = item_next(l); m; m = item_next(m)) {
+ select(m, whichway, when() & FL_WHEN_CHANGED);
+ if (m == e) break;
+ }
+ }
+ // do the clicked item last so the select box is around it:
+ change = 1;
+ if (l) select(l, whichway, when() & FL_WHEN_CHANGED);
+ } else { // select only this item
+ change = select_only(l, 0);
+ if (change && (when() & FL_WHEN_CHANGED)) {
+ set_changed();
+ do_callback();
+ }
+ }
+ }
+ return 1;
+ case FL_DRAG:
+ // do the scrolling first:
+ my = Fl::event_y();
+ if (my < Y && my < py) {
+ int p = real_position_+my-Y;
+ if (p<0) p = 0;
+ position(p);
+ } else if (my > (Y+H) && my > py) {
+ int p = real_position_+my-(Y+H);
+ int hh = full_height()-H; if (p > hh) p = hh;
+ if (p<0) p = 0;
+ position(p);
+ }
+ if (type() == FL_NORMAL_BROWSER || !top_)
+ ;
+ else if (type() == FL_MULTI_BROWSER) {
+ void* l = find_item(my);
+ void* t; void* b; // this will be the range to change
+ if (my > py) { // go down
+ t = selection_ ? item_next(selection_) : 0;
+ b = l ? item_next(l) : 0;
+ } else { // go up
+ t = l;
+ b = selection_;
+ }
+ for (; t && t != b; t = item_next(t)) {
+ char change_t;
+ change_t = select(t, whichway, 0);
+ change |= change_t;
+ if (change_t && (when() & FL_WHEN_CHANGED)) {
+ set_changed();
+ do_callback();
+ }
+ }
+ if (l) selection_ = l;
+ } else {
+ void* l1 = selection_;
+ void* l =
+ (Fl::event_x()<x() || Fl::event_x()>x()+w()) ? selection_ :
+ find_item(my);
+ change = (l != l1);
+ select_only(l, when() & FL_WHEN_CHANGED);
+ }
+ py = my;
+ return 1;
+ case FL_RELEASE:
+ if (type() == FL_SELECT_BROWSER) {
+ void* t = selection_; deselect(); selection_ = t;
+ }
+ if (change) {
+ set_changed();
+ if (when() & FL_WHEN_RELEASE) do_callback();
+ } else {
+ if (when() & FL_WHEN_NOT_CHANGED) do_callback();
+ }
+
+ // double click calls the callback: (like Enter Key)
+ if (Fl::event_clicks() && (when() & FL_WHEN_ENTER_KEY)) {
+ set_changed();
+ do_callback();
+ }
+ return 1;
+ case FL_FOCUS:
+ case FL_UNFOCUS:
+ if (type() >= FL_HOLD_BROWSER && Fl::visible_focus()) {
+ redraw();
+ return 1;
+ } else return 0;
+ }
+
+ return 0;
+}
+
+Fl_Browser_::Fl_Browser_(int X, int Y, int W, int H, const char* l)
+ : Fl_Group(X, Y, W, H, l),
+ scrollbar(0, 0, 0, 0, 0), // they will be resized by draw()
+ hscrollbar(0, 0, 0, 0, 0)
+{
+ box(FL_NO_BOX);
+ align(FL_ALIGN_BOTTOM);
+ position_ = real_position_ = 0;
+ hposition_ = real_hposition_ = 0;
+ offset_ = 0;
+ top_ = 0;
+ when(FL_WHEN_RELEASE_ALWAYS);
+ selection_ = 0;
+ color(FL_BACKGROUND2_COLOR, FL_SELECTION_COLOR);
+ scrollbar.callback(scrollbar_callback);
+//scrollbar.align(FL_ALIGN_LEFT|FL_ALIGN_BOTTOM); // back compatability?
+ hscrollbar.callback(hscrollbar_callback);
+ hscrollbar.type(FL_HORIZONTAL);
+ textfont_ = FL_HELVETICA;
+ textsize_ = (uchar)FL_NORMAL_SIZE;
+ textcolor_ = FL_FOREGROUND_COLOR;
+ has_scrollbar_ = BOTH;
+ max_width = 0;
+ max_width_item = 0;
+ redraw1 = redraw2 = 0;
+ end();
+}
+
+// Default versions of some of the virtual functions:
+
+int Fl_Browser_::item_quick_height(void* l) const {
+ return item_height(l);
+}
+
+int Fl_Browser_::incr_height() const {
+ return item_quick_height(item_first());
+}
+
+int Fl_Browser_::full_height() const {
+ int t = 0;
+ for (void* p = item_first(); p; p = item_next(p))
+ t += item_quick_height(p);
+ return t;
+}
+
+int Fl_Browser_::full_width() const {
+ return max_width;
+}
+
+void Fl_Browser_::item_select(void*, int) {}
+
+int Fl_Browser_::item_selected(void* l) const {return l==selection_;}
+
+//
+// End of "$Id: Fl_Browser_.cxx 5992 2007-12-15 16:20:16Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Browser_load.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Browser_load.cxx new file mode 100644 index 0000000..f0ee771 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Browser_load.cxx @@ -0,0 +1,57 @@ +//
+// "$Id: Fl_Browser_load.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// File loading routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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_Browser.H>
+#include <stdio.h>
+
+int Fl_Browser::load(const char *filename) {
+#define MAXFL_BLINE 1024
+ char newtext[MAXFL_BLINE];
+ int c;
+ int i;
+ clear();
+ if (!filename || !(filename[0])) return 1;
+ FILE *fl = fopen(filename,"r");
+ if (!fl) return 0;
+ i = 0;
+ do {
+ c = getc(fl);
+ if (c == '\n' || c <= 0 || i>=(MAXFL_BLINE-1)) {
+ newtext[i] = 0;
+ add(newtext);
+ i = 0;
+ } else
+ newtext[i++] = c;
+ } while (c >= 0);
+ fclose(fl);
+ return 1;
+}
+
+//
+// End of "$Id: Fl_Browser_load.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Button.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Button.cxx new file mode 100644 index 0000000..3f480d1 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Button.cxx @@ -0,0 +1,175 @@ +//
+// "$Id: Fl_Button.cxx 6589 2008-12-17 10:47:09Z fabien $"
+//
+// Button widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2006 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_Button.H>
+#include <FL/Fl_Group.H>
+#include <FL/Fl_Window.H>
+
+// There are a lot of subclasses, named Fl_*_Button. Some of
+// them are implemented by setting the type() value and testing it
+// here. This includes Fl_Radio_Button and Fl_Toggle_Button
+
+int Fl_Button::value(int v) {
+ v = v ? 1 : 0;
+ oldval = v;
+ clear_changed();
+ if (value_ != v) {
+ value_ = v;
+ if (box()) redraw();
+ else redraw_label();
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+void Fl_Button::setonly() { // set this radio button on, turn others off
+ value(1);
+ Fl_Group* g = (Fl_Group*)parent();
+ Fl_Widget*const* a = g->array();
+ for (int i = g->children(); i--;) {
+ Fl_Widget* o = *a++;
+ if (o != this && o->type()==FL_RADIO_BUTTON) ((Fl_Button*)o)->value(0);
+ }
+}
+
+void Fl_Button::draw() {
+ if (type() == FL_HIDDEN_BUTTON) return;
+ Fl_Color col = value() ? selection_color() : color();
+ draw_box(value() ? (down_box()?down_box():fl_down(box())) : box(), col);
+ if (labeltype() == FL_NORMAL_LABEL && value()) {
+ Fl_Color c = labelcolor();
+ labelcolor(fl_contrast(c, col));
+ draw_label();
+ labelcolor(c);
+ } else draw_label();
+ if (Fl::focus() == this) draw_focus();
+}
+
+int Fl_Button::handle(int event) {
+ int newval;
+ switch (event) {
+ case FL_ENTER:
+ case FL_LEAVE:
+// if ((value_?selection_color():color())==FL_GRAY) redraw();
+ return 1;
+ case FL_PUSH:
+ if (Fl::visible_focus() && handle(FL_FOCUS)) Fl::focus(this);
+ case FL_DRAG:
+ if (Fl::event_inside(this)) {
+ if (type() == FL_RADIO_BUTTON) newval = 1;
+ else newval = !oldval;
+ } else
+ {
+ clear_changed();
+ newval = oldval;
+ }
+ if (newval != value_) {
+ value_ = newval;
+ set_changed();
+ redraw();
+ if (when() & FL_WHEN_CHANGED) do_callback();
+ }
+ return 1;
+ case FL_RELEASE:
+ if (value_ == oldval) {
+ if (when() & FL_WHEN_NOT_CHANGED) do_callback();
+ return 1;
+ }
+ set_changed();
+ if (type() == FL_RADIO_BUTTON) setonly();
+ else if (type() == FL_TOGGLE_BUTTON) oldval = value_;
+ else {
+ value(oldval);
+ set_changed();
+ if (when() & FL_WHEN_CHANGED) do_callback();
+ }
+ if (when() & FL_WHEN_RELEASE) do_callback();
+ return 1;
+ case FL_SHORTCUT:
+ if (!(shortcut() ?
+ Fl::test_shortcut(shortcut()) : test_shortcut())) return 0;
+
+ if (Fl::visible_focus() && handle(FL_FOCUS)) Fl::focus(this);
+
+ if (type() == FL_RADIO_BUTTON && !value_) {
+ setonly();
+ set_changed();
+ if (when() & (FL_WHEN_CHANGED|FL_WHEN_RELEASE))
+ do_callback();
+ } else if (type() == FL_TOGGLE_BUTTON) {
+ value(!value());
+ set_changed();
+ if (when() & (FL_WHEN_CHANGED|FL_WHEN_RELEASE))
+ do_callback();
+ } else if (when() & FL_WHEN_RELEASE) do_callback();
+ return 1;
+ case FL_FOCUS :
+ case FL_UNFOCUS :
+ if (Fl::visible_focus()) {
+ if (box() == FL_NO_BOX) {
+ // Widgets with the FL_NO_BOX boxtype need a parent to
+ // redraw, since it is responsible for redrawing the
+ // background...
+ int X = x() > 0 ? x() - 1 : 0;
+ int Y = y() > 0 ? y() - 1 : 0;
+ if (window()) window()->damage(FL_DAMAGE_ALL, X, Y, w() + 2, h() + 2);
+ } else redraw();
+ return 1;
+ } else return 0;
+ case FL_KEYBOARD :
+ if (Fl::focus() == this && Fl::event_key() == ' ' &&
+ !(Fl::event_state() & (FL_SHIFT | FL_CTRL | FL_ALT | FL_META))) {
+ set_changed();
+ if (type() == FL_RADIO_BUTTON && !value_) {
+ setonly();
+ if (when() & FL_WHEN_CHANGED) do_callback();
+ } else if (type() == FL_TOGGLE_BUTTON) {
+ value(!value());
+ if (when() & FL_WHEN_CHANGED) do_callback();
+ }
+ if (when() & FL_WHEN_RELEASE) do_callback();
+ return 1;
+ }
+ default:
+ return 0;
+ }
+}
+
+Fl_Button::Fl_Button(int X, int Y, int W, int H, const char *l)
+: Fl_Widget(X,Y,W,H,l) {
+ box(FL_UP_BOX);
+ down_box(FL_NO_BOX);
+ value_ = oldval = 0;
+ shortcut_ = 0;
+ set_flag(SHORTCUT_LABEL);
+}
+
+//
+// End of "$Id: Fl_Button.cxx 6589 2008-12-17 10:47:09Z fabien $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Chart.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Chart.cxx new file mode 100644 index 0000000..003a892 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Chart.cxx @@ -0,0 +1,390 @@ +//
+// "$Id: Fl_Chart.cxx 5942 2007-10-06 17:33:17Z matt $"
+//
+// Forms-compatible chart widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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/math.h>
+#include <FL/Fl.H>
+#include <FL/Fl_Chart.H>
+#include <FL/fl_draw.H>
+#include "flstring.h"
+#include <stdlib.h>
+
+#define ARCINC (2.0*M_PI/360.0)
+
+// this function is in fl_boxtype.cxx:
+void fl_rectbound(int x,int y,int w,int h, Fl_Color color);
+
+/* Widget specific information */
+
+static void draw_barchart(int x,int y,int w,int h,
+ int numb, FL_CHART_ENTRY entries[],
+ double min, double max, int autosize, int maxnumb,
+ Fl_Color textcolor)
+/* Draws a bar chart. x,y,w,h is the bounding box, entries the array of
+ numb entries and min and max the boundaries. */
+{
+ double incr;
+ int zeroh;
+ double lh = fl_height();
+ if (max == min) incr = h;
+ else incr = h/(max-min);
+ if ( (-min*incr) < lh) {
+ incr = (h - lh + min*incr)/(max-min);
+ zeroh = int(y+h-lh);
+ } else {
+ zeroh = (int)rint(y+h+min * incr);
+ }
+ int bwidth = (int)rint(w/double(autosize?numb:maxnumb));
+ /* Draw base line */
+ fl_color(textcolor);
+ fl_line(x, zeroh, x+w, zeroh);
+ if (min == 0.0 && max == 0.0) return; /* Nothing else to draw */
+ int i;
+ /* Draw the bars */
+ for (i=0; i<numb; i++) {
+ int hh = (int)rint(entries[i].val*incr);
+ if (hh < 0)
+ fl_rectbound(x+i*bwidth,zeroh,bwidth+1,-hh+1, (Fl_Color)entries[i].col);
+ else if (hh > 0)
+ fl_rectbound(x+i*bwidth,zeroh-hh,bwidth+1,hh+1,(Fl_Color)entries[i].col);
+ }
+ /* Draw the labels */
+ fl_color(textcolor);
+ for (i=0; i<numb; i++)
+ fl_draw(entries[i].str,
+ x+i*bwidth+bwidth/2,zeroh,0,0,
+ FL_ALIGN_TOP);
+}
+
+static void draw_horbarchart(int x,int y,int w,int h,
+ int numb, FL_CHART_ENTRY entries[],
+ double min, double max, int autosize, int maxnumb,
+ Fl_Color textcolor)
+/* Draws a horizontal bar chart. x,y,w,h is the bounding box, entries the
+ array of numb entries and min and max the boundaries. */
+{
+ int i;
+ double lw = 0.0; /* Maximal label width */
+ /* Compute maximal label width */
+ for (i=0; i<numb; i++) {
+ double w1 = fl_width(entries[i].str);
+ if (w1 > lw) lw = w1;
+ }
+ if (lw > 0.0) lw += 4.0;
+ double incr;
+ int zeroh;
+ if (max == min) incr = w;
+ else incr = w/(max-min);
+ if ( (-min*incr) < lw) {
+ incr = (w - lw + min*incr)/(max-min);
+ zeroh = x+(int)rint(lw);
+ } else {
+ zeroh = (int)rint(x-min * incr);
+ }
+ int bwidth = (int)rint(h/double(autosize?numb:maxnumb));
+ /* Draw base line */
+ fl_color(textcolor);
+ fl_line(zeroh, y, zeroh, y+h);
+ if (min == 0.0 && max == 0.0) return; /* Nothing else to draw */
+ /* Draw the bars */
+ for (i=0; i<numb; i++) {
+ int ww = (int)rint(entries[i].val*incr);
+ if (ww > 0)
+ fl_rectbound(zeroh,y+i*bwidth,ww+1,bwidth+1, (Fl_Color)entries[i].col);
+ else if (ww < 0)
+ fl_rectbound(zeroh+ww,y+i*bwidth,-ww+1,bwidth+1,(Fl_Color)entries[i].col);
+ }
+ /* Draw the labels */
+ fl_color(textcolor);
+ for (i=0; i<numb; i++)
+ fl_draw(entries[i].str,
+ zeroh-2,y+i*bwidth+bwidth/2,0,0,
+ FL_ALIGN_RIGHT);
+}
+
+static void draw_linechart(int type, int x,int y,int w,int h,
+ int numb, FL_CHART_ENTRY entries[],
+ double min, double max, int autosize, int maxnumb,
+ Fl_Color textcolor)
+/* Draws a line chart. x,y,w,h is the bounding box, entries the array of
+ numb entries and min and max the boundaries. */
+{
+ int i;
+ double lh = fl_height();
+ double incr;
+ if (max == min) incr = h-2.0*lh;
+ else incr = (h-2.0*lh)/ (max-min);
+ int zeroh = (int)rint(y+h-lh+min * incr);
+ double bwidth = w/double(autosize?numb:maxnumb);
+ /* Draw the values */
+ for (i=0; i<numb; i++) {
+ int x0 = x + (int)rint((i-.5)*bwidth);
+ int x1 = x + (int)rint((i+.5)*bwidth);
+ int yy0 = i ? zeroh - (int)rint(entries[i-1].val*incr) : 0;
+ int yy1 = zeroh - (int)rint(entries[i].val*incr);
+ if (type == FL_SPIKE_CHART) {
+ fl_color((Fl_Color)entries[i].col);
+ fl_line(x1, zeroh, x1, yy1);
+ } else if (type == FL_LINE_CHART && i != 0) {
+ fl_color((Fl_Color)entries[i-1].col);
+ fl_line(x0,yy0,x1,yy1);
+ } else if (type == FL_FILLED_CHART && i != 0) {
+ fl_color((Fl_Color)entries[i-1].col);
+ if ((entries[i-1].val>0.0)!=(entries[i].val>0.0)) {
+ double ttt = entries[i-1].val/(entries[i-1].val-entries[i].val);
+ int xt = x + (int)rint((i-.5+ttt)*bwidth);
+ fl_polygon(x0,zeroh, x0,yy0, xt,zeroh);
+ fl_polygon(xt,zeroh, x1,yy1, x1,zeroh);
+ } else {
+ fl_polygon(x0,zeroh, x0,yy0, x1,yy1, x1,zeroh);
+ }
+ fl_color(textcolor);
+ fl_line(x0,yy0,x1,yy1);
+ }
+ }
+ /* Draw base line */
+ fl_color(textcolor);
+ fl_line(x,zeroh,x+w,zeroh);
+ /* Draw the labels */
+ for (i=0; i<numb; i++)
+ fl_draw(entries[i].str,
+ x+(int)rint((i+.5)*bwidth), zeroh - (int)rint(entries[i].val*incr),0,0,
+ entries[i].val>=0 ? FL_ALIGN_BOTTOM : FL_ALIGN_TOP);
+}
+
+static void draw_piechart(int x,int y,int w,int h,
+ int numb, FL_CHART_ENTRY entries[], int special,
+ Fl_Color textcolor)
+/* Draws a pie chart. x,y,w,h is the bounding box, entries the array of
+ numb entries */
+{
+ int i;
+ double xc,yc,rad; /* center and radius */
+ double tot; /* sum of values */
+ double incr; /* increment in angle */
+ double curang; /* current angle we are drawing */
+ double txc,tyc; /* temporary center */
+ double lh = fl_height();
+ /* compute center and radius */
+ double h_denom = (special ? 2.3 : 2.0);
+ rad = (h - 2*lh)/h_denom/1.1;
+ xc = x+w/2.0; yc = y+h-1.1*rad-lh;
+ /* compute sum of values */
+ tot = 0.0;
+ for (i=0; i<numb; i++)
+ if (entries[i].val > 0.0) tot += entries[i].val;
+ if (tot == 0.0) return;
+ incr = 360.0/tot;
+ /* Draw the pie */
+ curang = 0.0;
+ for (i=0; i<numb; i++)
+ if (entries[i].val > 0.0)
+ {
+ txc = xc; tyc = yc;
+ /* Correct for special pies */
+ if (special && i==0)
+ {
+ txc += 0.3*rad*cos(ARCINC*(curang+0.5*incr*entries[i].val));
+ tyc -= 0.3*rad*sin(ARCINC*(curang+0.5*incr*entries[i].val));
+ }
+ fl_color((Fl_Color)entries[i].col);
+ fl_begin_polygon(); fl_vertex(txc,tyc);
+ fl_arc(txc,tyc,rad,curang, curang+incr*entries[i].val);
+ fl_end_polygon();
+ fl_color(textcolor);
+ fl_begin_loop(); fl_vertex(txc,tyc);
+ fl_arc(txc,tyc,rad,curang, curang+incr*entries[i].val);
+ fl_end_loop();
+ curang += 0.5 * incr * entries[i].val;
+ /* draw the label */
+ double xl = txc + 1.1*rad*cos(ARCINC*curang);
+ fl_draw(entries[i].str,
+ (int)rint(xl),
+ (int)rint(tyc - 1.1*rad*sin(ARCINC*curang)),
+ 0, 0,
+ xl<txc ? FL_ALIGN_RIGHT : FL_ALIGN_LEFT);
+ curang += 0.5 * incr * entries[i].val;
+ }
+}
+
+void Fl_Chart::draw() {
+
+ draw_box();
+ Fl_Boxtype b = box();
+ int xx = x()+Fl::box_dx(b); // was 9 instead of dx...
+ int yy = y()+Fl::box_dy(b);
+ int ww = w()-Fl::box_dw(b);
+ int hh = h()-Fl::box_dh(b);
+ fl_push_clip(xx, yy, ww, hh);
+
+ ww--; hh--; // adjust for line thickness
+
+ if (min >= max) {
+ min = max = 0.0;
+ for (int i=0; i<numb; i++) {
+ if (entries[i].val < min) min = entries[i].val;
+ if (entries[i].val > max) max = entries[i].val;
+ }
+ }
+
+ fl_font(textfont(),textsize());
+
+ switch (type()) {
+ case FL_BAR_CHART:
+ ww++; // makes the bars fill box correctly
+ draw_barchart(xx,yy,ww,hh, numb, entries, min, max,
+ autosize(), maxnumb, textcolor());
+ break;
+ case FL_HORBAR_CHART:
+ hh++; // makes the bars fill box correctly
+ draw_horbarchart(xx,yy,ww,hh, numb, entries, min, max,
+ autosize(), maxnumb, textcolor());
+ break;
+ case FL_PIE_CHART:
+ draw_piechart(xx,yy,ww,hh,numb,entries,0, textcolor());
+ break;
+ case FL_SPECIALPIE_CHART:
+ draw_piechart(xx,yy,ww,hh,numb,entries,1,textcolor());
+ break;
+ default:
+ draw_linechart(type(),xx,yy,ww,hh, numb, entries, min, max,
+ autosize(), maxnumb, textcolor());
+ break;
+ }
+ draw_label();
+ fl_pop_clip();
+}
+
+/*------------------------------*/
+
+#define FL_CHART_BOXTYPE FL_BORDER_BOX
+#define FL_CHART_COL1 FL_COL1
+#define FL_CHART_LCOL FL_LCOL
+#define FL_CHART_ALIGN FL_ALIGN_BOTTOM
+
+Fl_Chart::Fl_Chart(int X, int Y, int W, int H,const char *l) :
+Fl_Widget(X,Y,W,H,l) {
+ box(FL_BORDER_BOX);
+ align(FL_ALIGN_BOTTOM);
+ numb = 0;
+ maxnumb = 0;
+ sizenumb = FL_CHART_MAX;
+ autosize_ = 1;
+ min = max = 0;
+ textfont_ = FL_HELVETICA;
+ textsize_ = 10;
+ textcolor_ = FL_FOREGROUND_COLOR;
+ entries = (FL_CHART_ENTRY *)calloc(sizeof(FL_CHART_ENTRY), FL_CHART_MAX + 1);
+}
+
+Fl_Chart::~Fl_Chart() {
+ free(entries);
+}
+
+void Fl_Chart::clear() {
+ numb = 0;
+ redraw();
+}
+
+void Fl_Chart::add(double val, const char *str, unsigned col) {
+ /* Allocate more entries if required */
+ if (numb >= sizenumb) {
+ sizenumb += FL_CHART_MAX;
+ entries = (FL_CHART_ENTRY *)realloc(entries, sizeof(FL_CHART_ENTRY) * (sizenumb + 1));
+ }
+ // Shift entries as needed
+ if (numb >= maxnumb && maxnumb > 0) {
+ memmove(entries, entries + 1, sizeof(FL_CHART_ENTRY) * (numb - 1));
+ numb --;
+ }
+ entries[numb].val = float(val);
+ entries[numb].col = col;
+ if (str) {
+ strlcpy(entries[numb].str,str,FL_CHART_LABEL_MAX + 1);
+ } else {
+ entries[numb].str[0] = 0;
+ }
+ numb++;
+ redraw();
+}
+
+void Fl_Chart::insert(int ind, double val, const char *str, unsigned col) {
+ int i;
+ if (ind < 1 || ind > numb+1) return;
+ /* Allocate more entries if required */
+ if (numb >= sizenumb) {
+ sizenumb += FL_CHART_MAX;
+ entries = (FL_CHART_ENTRY *)realloc(entries, sizeof(FL_CHART_ENTRY) * (sizenumb + 1));
+ }
+ // Shift entries as needed
+ for (i=numb; i >= ind; i--) entries[i] = entries[i-1];
+ if (numb < maxnumb || maxnumb == 0) numb++;
+ /* Fill in the new entry */
+ entries[ind-1].val = float(val);
+ entries[ind-1].col = col;
+ if (str) {
+ strlcpy(entries[ind-1].str,str,FL_CHART_LABEL_MAX+1);
+ } else {
+ entries[ind-1].str[0] = 0;
+ }
+ redraw();
+}
+
+void Fl_Chart::replace(int ind,double val, const char *str, unsigned col) {
+ if (ind < 1 || ind > numb) return;
+ entries[ind-1].val = float(val);
+ entries[ind-1].col = col;
+ if (str) {
+ strlcpy(entries[ind-1].str,str,FL_CHART_LABEL_MAX+1);
+ } else {
+ entries[ind-1].str[0] = 0;
+ }
+ redraw();
+}
+
+void Fl_Chart::bounds(double mymin, double mymax) {
+ this->min = mymin;
+ this->max = mymax;
+ redraw();
+}
+
+void Fl_Chart::maxsize(int m) {
+ int i;
+ /* Fill in the new number */
+ if (m < 0) return;
+ maxnumb = m;
+ /* Shift entries if required */
+ if (numb > maxnumb) {
+ for (i = 0; i<maxnumb; i++)
+ entries[i] = entries[i+numb-maxnumb];
+ numb = maxnumb;
+ redraw();
+ }
+}
+
+//
+// End of "$Id: Fl_Chart.cxx 5942 2007-10-06 17:33:17Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Check_Browser.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Check_Browser.cxx new file mode 100644 index 0000000..1811409 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Check_Browser.cxx @@ -0,0 +1,309 @@ +//
+// "$Id: Fl_Check_Browser.cxx 5985 2007-11-20 21:15:08Z mike $"
+//
+// Fl_Check_Browser header file for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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 <stdio.h>
+#include <stdlib.h>
+#include "flstring.h"
+#include <FL/fl_draw.H>
+#include <FL/Fl_Check_Browser.H>
+
+/* This uses a cache for faster access when you're scanning the list
+either forwards or backwards. */
+
+Fl_Check_Browser::cb_item *Fl_Check_Browser::find_item(int n) const {
+ int i = n;
+ cb_item *p = first;
+
+ if (n <= 0 || n > nitems_ || p == 0) {
+ return 0;
+ }
+
+ if (n == cached_item) {
+ p = cache;
+ n = 1;
+ } else if (n == cached_item + 1) {
+ p = cache->next;
+ n = 1;
+ } else if (n == cached_item - 1) {
+ p = cache->prev;
+ n = 1;
+ }
+
+ while (--n) {
+ p = p->next;
+ }
+
+ /* Cast to not const and cache it. */
+
+ ((Fl_Check_Browser *)this)->cache = p;
+ ((Fl_Check_Browser *)this)->cached_item = i;
+
+ return p;
+}
+
+int Fl_Check_Browser::lineno(cb_item *p0) const {
+ cb_item *p = first;
+
+ if (p == 0) {
+ return 0;
+ }
+
+ int i = 1;
+ while (p) {
+ if (p == p0) {
+ return i;
+ }
+ i++;
+ p = p->next;
+ }
+
+ return 0;
+}
+
+Fl_Check_Browser::Fl_Check_Browser(int X, int Y, int W, int H, const char *l)
+ : Fl_Browser_(X, Y, W, H, l) {
+ type(FL_SELECT_BROWSER);
+ when(FL_WHEN_NEVER);
+ first = last = 0;
+ nitems_ = nchecked_ = 0;
+ cached_item = -1;
+}
+
+void *Fl_Check_Browser::item_first() const {
+ return first;
+}
+
+void *Fl_Check_Browser::item_next(void *l) const {
+ return ((cb_item *)l)->next;
+}
+
+void *Fl_Check_Browser::item_prev(void *l) const {
+ return ((cb_item *)l)->prev;
+}
+
+int Fl_Check_Browser::item_height(void *) const {
+ return textsize() + 2;
+}
+
+#define CHECK_SIZE (textsize()-2)
+
+int Fl_Check_Browser::item_width(void *v) const {
+ fl_font(textfont(), textsize());
+ return int(fl_width(((cb_item *)v)->text)) + CHECK_SIZE + 8;
+}
+
+void Fl_Check_Browser::item_draw(void *v, int X, int Y, int, int) const {
+ cb_item *i = (cb_item *)v;
+ char *s = i->text;
+ int tsize = textsize();
+ Fl_Color col = active_r() ? textcolor() : fl_inactive(textcolor());
+ int cy = Y + (tsize + 1 - CHECK_SIZE) / 2;
+ X += 2;
+
+ fl_color(active_r() ? FL_FOREGROUND_COLOR : fl_inactive(FL_FOREGROUND_COLOR));
+ fl_loop(X, cy, X, cy + CHECK_SIZE,
+ X + CHECK_SIZE, cy + CHECK_SIZE, X + CHECK_SIZE, cy);
+ if (i->checked) {
+ int tx = X + 3;
+ int tw = CHECK_SIZE - 4;
+ int d1 = tw/3;
+ int d2 = tw-d1;
+ int ty = cy + (CHECK_SIZE+d2)/2-d1-2;
+ for (int n = 0; n < 3; n++, ty++) {
+ fl_line(tx, ty, tx+d1, ty+d1);
+ fl_line(tx+d1, ty+d1, tx+tw-1, ty+d1-d2+1);
+ }
+ }
+ fl_font(textfont(), tsize);
+ if (i->selected) {
+ col = fl_contrast(col, selection_color());
+ }
+ fl_color(col);
+ fl_draw(s, X + CHECK_SIZE + 8, Y + tsize - 1);
+}
+
+void Fl_Check_Browser::item_select(void *v, int state) {
+ cb_item *i = (cb_item *)v;
+
+ if (state) {
+ if (i->checked) {
+ i->checked = 0;
+ nchecked_--;
+ } else {
+ i->checked = 1;
+ nchecked_++;
+ }
+ }
+}
+
+int Fl_Check_Browser::item_selected(void *v) const {
+ cb_item *i = (cb_item *)v;
+ return i->selected;
+}
+
+int Fl_Check_Browser::add(char *s) {
+ return (add(s, 0));
+}
+
+int Fl_Check_Browser::add(char *s, int b) {
+ cb_item *p = (cb_item *)malloc(sizeof(cb_item));
+ p->next = 0;
+ p->prev = 0;
+ p->checked = b;
+ p->selected = 0;
+ p->text = strdup(s);
+
+ if (b) {
+ nchecked_++;
+ }
+
+ if (last == 0) {
+ first = last = p;
+ } else {
+ last->next = p;
+ p->prev = last;
+ last = p;
+ }
+ nitems_++;
+
+ return (nitems_);
+}
+
+int Fl_Check_Browser::remove(int item) {
+ cb_item *p = find_item(item);
+
+ // line at item exists
+ if(p) {
+ // tell the Browser_ what we will do
+ deleting(p);
+
+ // fix checked count
+ if(p->checked)
+ --nchecked_;
+
+ // remove the node
+ if (p->prev)
+ p->prev->next = p->next;
+ else
+ first = p->next;
+ if (p->next)
+ p->next->prev = p->prev;
+ else
+ last = p->prev;
+
+ free(p->text);
+ free(p);
+
+ --nitems_;
+ cached_item = -1;
+ }
+
+ return (nitems_);
+}
+
+void Fl_Check_Browser::clear() {
+ cb_item *p = first;
+ cb_item *next;
+
+ if (p == 0) {
+ return;
+ }
+
+ new_list();
+ do {
+ next = p->next;
+ free(p->text);
+ free(p);
+ p = next;
+ } while (p);
+
+ first = last = 0;
+ nitems_ = nchecked_ = 0;
+ cached_item = -1;
+}
+
+int Fl_Check_Browser::checked(int i) const {
+ cb_item *p = find_item(i);
+
+ if (p) return p->checked;
+ return 0;
+}
+
+void Fl_Check_Browser::checked(int i, int b) {
+ cb_item *p = find_item(i);
+
+ if (p && (p->checked ^ b)) {
+ p->checked = b;
+ if (b) {
+ nchecked_++;
+ } else {
+ nchecked_--;
+ }
+ redraw();
+ }
+}
+
+int Fl_Check_Browser::value() const {
+ return lineno((cb_item *)selection());
+}
+
+char *Fl_Check_Browser::text(int i) const {
+ cb_item *p = find_item(i);
+
+ if (p) return p->text;
+ return 0;
+}
+
+void Fl_Check_Browser::check_all() {
+ cb_item *p;
+
+ nchecked_ = nitems_;
+ for (p = first; p; p = p->next) {
+ p->checked = 1;
+ }
+ redraw();
+}
+
+void Fl_Check_Browser::check_none() {
+ cb_item *p;
+
+ nchecked_ = 0;
+ for (p = first; p; p = p->next) {
+ p->checked = 0;
+ }
+ redraw();
+}
+
+int Fl_Check_Browser::handle(int event) {
+ if (event==FL_PUSH)
+ deselect();
+ return Fl_Browser_::handle(event);
+}
+
+//
+// End of "$Id: Fl_Check_Browser.cxx 5985 2007-11-20 21:15:08Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Check_Button.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Check_Button.cxx new file mode 100644 index 0000000..3c2643d --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Check_Button.cxx @@ -0,0 +1,40 @@ +//
+// "$Id: Fl_Check_Button.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Check button widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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_Check_Button.H>
+
+// A subclass of Fl_Button that always draws as a diamond box. This
+// diamond is smaller than the widget size and can be surchecked by
+// another box type, for compatability with Forms.
+
+Fl_Check_Button::Fl_Check_Button(int X, int Y, int W, int H, const char *l)
+: Fl_Light_Button(X, Y, W, H, l) {
+ box(FL_NO_BOX);
+ down_box(FL_DOWN_BOX);
+ selection_color(FL_FOREGROUND_COLOR);
+}
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Choice.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Choice.cxx new file mode 100644 index 0000000..e742a10 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Choice.cxx @@ -0,0 +1,191 @@ +//
+// "$Id: Fl_Choice.cxx 6872 2009-09-16 07:04:37Z AlbrechtS $"
+//
+// Choice widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2006 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_Choice.H>
+#include <FL/fl_draw.H>
+#include "flstring.h"
+
+// Emulates the Forms choice widget. This is almost exactly the same
+// as an Fl_Menu_Button. The only difference is the appearance of the
+// button: it draws the text of the current pick and a down-arrow.
+
+void Fl_Choice::draw() {
+ int dx = Fl::box_dx(FL_DOWN_BOX);
+ int dy = Fl::box_dy(FL_DOWN_BOX);
+ int H = h() - 2 * dy;
+ int W = (H > 20) ? 20 : H;
+ int X = x() + w() - W - dx;
+ int Y = y() + dy;
+ int w1 = (W - 4) / 3; if (w1 < 1) w1 = 1;
+ int x1 = X + (W - 2 * w1 - 1) / 2;
+ int y1 = Y + (H - w1 - 1) / 2;
+
+ if (Fl::scheme()) {
+ draw_box(FL_UP_BOX, color());
+
+ fl_color(active_r() ? labelcolor() : fl_inactive(labelcolor()));
+ if (!strcmp(Fl::scheme(), "plastic")) {
+ // Show larger up/down arrows...
+ fl_polygon(x1, y1 + 3, x1 + w1, y1 + w1 + 3, x1 + 2 * w1, y1 + 3);
+ fl_polygon(x1, y1 + 1, x1 + w1, y1 - w1 + 1, x1 + 2 * w1, y1 + 1);
+ } else {
+ // Show smaller up/down arrows with a divider...
+ x1 = x() + w() - 13 - dx;
+ y1 = y() + h() / 2;
+ fl_polygon(x1, y1 - 2, x1 + 3, y1 - 5, x1 + 6, y1 - 2);
+ fl_polygon(x1, y1 + 2, x1 + 3, y1 + 5, x1 + 6, y1 + 2);
+
+ fl_color(fl_darker(color()));
+ fl_yxline(x1 - 7, y1 - 8, y1 + 8);
+
+ fl_color(fl_lighter(color()));
+ fl_yxline(x1 - 6, y1 - 8, y1 + 8);
+ }
+ } else {
+ if (fl_contrast(textcolor(), FL_BACKGROUND2_COLOR) == textcolor()) {
+ draw_box(FL_DOWN_BOX, FL_BACKGROUND2_COLOR);
+ } else {
+ draw_box(FL_DOWN_BOX, fl_lighter(color()));
+ }
+ draw_box(FL_UP_BOX,X,Y,W,H,color());
+
+ fl_color(active_r() ? labelcolor() : fl_inactive(labelcolor()));
+ fl_polygon(x1, y1, x1 + w1, y1 + w1, x1 + 2 * w1, y1);
+ }
+
+ W += 2 * dx;
+
+ if (mvalue()) {
+ Fl_Menu_Item m = *mvalue();
+ if (active_r()) m.activate(); else m.deactivate();
+
+ // ERCO
+ int xx = x() + dx, yy = y() + dy + 1, ww = w() - W, hh = H - 2;
+
+ fl_clip(xx, yy, ww, hh);
+
+ if ( Fl::scheme()) {
+ Fl_Label l;
+ l.value = m.text;
+ l.image = 0;
+ l.deimage = 0;
+ l.type = m.labeltype_;
+ l.font = m.labelsize_ || m.labelfont_ ? m.labelfont_ : uchar(textfont());
+ l.size = m.labelsize_ ? m.labelsize_ : textsize();
+ l.color= m.labelcolor_ ? m.labelcolor_ : textcolor();
+ if (!m.active()) l.color = fl_inactive((Fl_Color)l.color);
+ fl_draw_shortcut = 2; // hack value to make '&' disappear
+ l.draw(xx+3, yy, ww>6 ? ww-6 : 0, hh, FL_ALIGN_LEFT);
+ fl_draw_shortcut = 0;
+ if ( Fl::focus() == this ) draw_focus(box(), xx, yy, ww, hh);
+ }
+ else {
+ fl_draw_shortcut = 2; // hack value to make '&' disappear
+ m.draw(xx, yy, ww, hh, this, Fl::focus() == this);
+ fl_draw_shortcut = 0;
+ }
+
+ fl_pop_clip();
+ }
+
+ draw_label();
+}
+
+Fl_Choice::Fl_Choice(int X, int Y, int W, int H, const char *l)
+: Fl_Menu_(X,Y,W,H,l) {
+ align(FL_ALIGN_LEFT);
+ when(FL_WHEN_RELEASE);
+ textfont(FL_HELVETICA);
+ box(FL_FLAT_BOX);
+ down_box(FL_BORDER_BOX);
+}
+
+int Fl_Choice::value(const Fl_Menu_Item *v) {
+ if (!Fl_Menu_::value(v)) return 0;
+ redraw();
+ return 1;
+}
+
+int Fl_Choice::value(int v) {
+ if (v == -1) return value((const Fl_Menu_Item *)0);
+ if (v < 0 || v >= (size() - 1)) return 0;
+ if (!Fl_Menu_::value(v)) return 0;
+ redraw();
+ return 1;
+}
+
+int Fl_Choice::handle(int e) {
+ if (!menu() || !menu()->text) return 0;
+ const Fl_Menu_Item* v;
+ switch (e) {
+ case FL_ENTER:
+ case FL_LEAVE:
+ return 1;
+
+ case FL_KEYBOARD:
+ if (Fl::event_key() != ' ' ||
+ (Fl::event_state() & (FL_SHIFT | FL_CTRL | FL_ALT | FL_META))) return 0;
+ case FL_PUSH:
+ if (Fl::visible_focus()) Fl::focus(this);
+ J1:
+ if (Fl::scheme()
+ || fl_contrast(textcolor(), FL_BACKGROUND2_COLOR) != textcolor()) {
+ v = menu()->pulldown(x(), y(), w(), h(), mvalue(), this);
+ } else {
+ // In order to preserve the old look-n-feel of "white" menus,
+ // temporarily override the color() of this widget...
+ Fl_Color c = color();
+ color(FL_BACKGROUND2_COLOR);
+ v = menu()->pulldown(x(), y(), w(), h(), mvalue(), this);
+ color(c);
+ }
+ if (!v || v->submenu()) return 1;
+ if (v != mvalue()) redraw();
+ picked(v);
+ return 1;
+ case FL_SHORTCUT:
+ if (Fl_Widget::test_shortcut()) goto J1;
+ v = menu()->test_shortcut();
+ if (!v) return 0;
+ if (v != mvalue()) redraw();
+ picked(v);
+ return 1;
+ case FL_FOCUS:
+ case FL_UNFOCUS:
+ if (Fl::visible_focus()) {
+ redraw();
+ return 1;
+ } else return 0;
+ default:
+ return 0;
+ }
+}
+
+//
+// End of "$Id: Fl_Choice.cxx 6872 2009-09-16 07:04:37Z AlbrechtS $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Clock.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Clock.cxx new file mode 100644 index 0000000..fb46384 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Clock.cxx @@ -0,0 +1,177 @@ +//
+// "$Id: Fl_Clock.cxx 5472 2006-09-20 03:03:14Z mike $"
+//
+// Clock widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2006 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_Clock.H>
+#include <FL/fl_draw.H>
+#include <math.h>
+#include <time.h>
+#ifndef WIN32
+# include <sys/time.h>
+#endif /* !WIN32 */
+
+// Original clock display written by Paul Haeberli at SGI.
+// Modifications by Mark Overmars for Forms
+// Further changes by Bill Spitzak for fltk
+
+const float hourhand[4][2] = {{-0.5f, 0}, {0, 1.5f}, {0.5f, 0}, {0, -7.0f}};
+const float minhand[4][2] = {{-0.5f, 0}, {0, 1.5f}, {0.5f, 0}, {0, -11.5f}};
+const float sechand[4][2] = {{-0.1f, 0}, {0, 2.0f}, {0.1f, 0}, {0, -11.5f}};
+
+static void drawhand(double ang,const float v[][2],Fl_Color fill,Fl_Color line)
+{
+ fl_push_matrix();
+ fl_rotate(ang);
+ fl_color(fill); fl_begin_polygon();
+ int i; for (i=0; i<4; i++) fl_vertex(v[i][0],v[i][1]); fl_end_polygon();
+ fl_color(line); fl_begin_loop();
+ for (i=0; i<4; i++) fl_vertex(v[i][0],v[i][1]); fl_end_loop();
+ fl_pop_matrix();
+}
+
+void Fl_Clock_Output::drawhands(Fl_Color fill, Fl_Color line) {
+ if (!active_r()) {
+ fill = fl_inactive(fill);
+ line = fl_inactive(line);
+ }
+ drawhand(-360*(hour()+minute()/60.0)/12, hourhand, fill, line);
+ drawhand(-360*(minute()+second()/60.0)/60, minhand, fill, line);
+ drawhand(-360*(second()/60.0), sechand, fill, line);
+}
+
+static void rect(double x, double y, double w, double h) {
+ double r = x+w;
+ double t = y+h;
+ fl_begin_polygon();
+ fl_vertex(x, y);
+ fl_vertex(r, y);
+ fl_vertex(r, t);
+ fl_vertex(x, t);
+ fl_end_polygon();
+}
+
+void Fl_Clock_Output::draw(int X, int Y, int W, int H) {
+ Fl_Color box_color = type()==FL_ROUND_CLOCK ? FL_GRAY : color();
+ Fl_Color shadow_color = fl_color_average(box_color, FL_BLACK, 0.5);
+ draw_box(box(), X, Y, W, H, box_color);
+ fl_push_matrix();
+ fl_translate(X+W/2.0-.5, Y+H/2.0-.5);
+ fl_scale((W-1)/28.0, (H-1)/28.0);
+ if (type() == FL_ROUND_CLOCK) {
+ fl_color(active_r() ? color() : fl_inactive(color()));
+ fl_begin_polygon(); fl_circle(0,0,14); fl_end_polygon();
+ fl_color(active_r() ? FL_FOREGROUND_COLOR : fl_inactive(FL_FOREGROUND_COLOR));
+ fl_begin_loop(); fl_circle(0,0,14); fl_end_loop();
+ }
+ // draw the shadows:
+ fl_push_matrix();
+ fl_translate(0.60, 0.60);
+ drawhands(shadow_color, shadow_color);
+ fl_pop_matrix();
+ // draw the tick marks:
+ fl_push_matrix();
+ fl_color(active_r() ? FL_FOREGROUND_COLOR : fl_inactive(FL_FOREGROUND_COLOR));
+ for (int i=0; i<12; i++) {
+ if (i==6) rect(-0.5, 9, 1, 2);
+ else if (i==3 || i==0 || i== 9) rect(-0.5, 9.5, 1, 1);
+ else rect(-0.25, 9.5, .5, 1);
+ fl_rotate(-30);
+ }
+ fl_pop_matrix();
+ // draw the hands:
+ drawhands(selection_color(), FL_FOREGROUND_COLOR); // color was 54
+ fl_pop_matrix();
+}
+
+void Fl_Clock_Output::draw() {
+ draw(x(), y(), w(), h());
+ draw_label();
+}
+
+void Fl_Clock_Output::value(int H, int m, int s) {
+ if (H!=hour_ || m!=minute_ || s!=second_) {
+ hour_ = H; minute_ = m; second_ = s;
+ value_ = (H * 60 + m) * 60 + s;
+ damage(FL_DAMAGE_CHILD);
+ }
+}
+
+void Fl_Clock_Output::value(ulong v) {
+ value_ = v;
+ struct tm *timeofday;
+ // Some platforms, notably Windows, now use a 64-bit time_t value...
+ time_t vv = (time_t)v;
+ timeofday = localtime(&vv);
+ value(timeofday->tm_hour, timeofday->tm_min, timeofday->tm_sec);
+}
+
+Fl_Clock_Output::Fl_Clock_Output(int X, int Y, int W, int H, const char *l)
+: Fl_Widget(X, Y, W, H, l) {
+ box(FL_UP_BOX);
+ selection_color(fl_gray_ramp(5));
+ align(FL_ALIGN_BOTTOM);
+ hour_ = 0;
+ minute_ = 0;
+ second_ = 0;
+ value_ = 0;
+}
+
+////////////////////////////////////////////////////////////////
+
+Fl_Clock::Fl_Clock(int X, int Y, int W, int H, const char *l)
+ : Fl_Clock_Output(X, Y, W, H, l) {}
+
+Fl_Clock::Fl_Clock(uchar t, int X, int Y, int W, int H, const char *l)
+ : Fl_Clock_Output(X, Y, W, H, l) {
+ type(t);
+ box(t==FL_ROUND_CLOCK ? FL_NO_BOX : FL_UP_BOX);
+}
+
+static void tick(void *v) {
+ ((Fl_Clock*)v)->value(time(0));
+ Fl::add_timeout(1.0, tick, v);
+}
+
+int Fl_Clock::handle(int event) {
+ switch (event) {
+ case FL_SHOW:
+ tick(this);
+ break;
+ case FL_HIDE:
+ Fl::remove_timeout(tick, this);
+ break;
+ }
+ return Fl_Clock_Output::handle(event);
+}
+
+Fl_Clock::~Fl_Clock() {
+ Fl::remove_timeout(tick, this);
+}
+
+//
+// End of "$Id: Fl_Clock.cxx 5472 2006-09-20 03:03:14Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Color_Chooser.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Color_Chooser.cxx new file mode 100644 index 0000000..212a8bd --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Color_Chooser.cxx @@ -0,0 +1,529 @@ +//
+// "$Id: Fl_Color_Chooser.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Color chooser for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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_Color_Chooser.H>
+#include <FL/fl_draw.H>
+#include <FL/math.h>
+#include <stdio.h>
+
+// Besides being a useful object on it's own, the Fl_Color_Chooser was
+// an attempt to make a complex composite object that could be easily
+// imbedded into a user interface. If you wish to make complex objects
+// of your own, be sure to read this code.
+
+// The function fl_color_chooser() creates a window containing a color
+// chooser and a few buttons and current-color indicators. It is an
+// easier interface for simple programs that just need a color.
+
+// The "hue box" can be a circle or rectilinear.
+// You get a circle by defining this:
+#define CIRCLE 1
+// And the "hue box" can auto-update when the value changes
+// you get this by defining this:
+#define UPDATE_HUE_BOX 1
+
+void Fl_Color_Chooser::hsv2rgb(
+ double H, double S, double V, double& R, double& G, double& B) {
+ if (S < 5.0e-6) {
+ R = G = B = V;
+ } else {
+ int i = (int)H;
+ double f = H - (float)i;
+ double p1 = V*(1.0-S);
+ double p2 = V*(1.0-S*f);
+ double p3 = V*(1.0-S*(1.0-f));
+ switch (i) {
+ case 0: R = V; G = p3; B = p1; break;
+ case 1: R = p2; G = V; B = p1; break;
+ case 2: R = p1; G = V; B = p3; break;
+ case 3: R = p1; G = p2; B = V; break;
+ case 4: R = p3; G = p1; B = V; break;
+ case 5: R = V; G = p1; B = p2; break;
+ }
+ }
+}
+
+void Fl_Color_Chooser::rgb2hsv(
+ double R, double G, double B, double& H, double& S, double& V) {
+ double maxv = R > G ? R : G; if (B > maxv) maxv = B;
+ V = maxv;
+ if (maxv>0) {
+ double minv = R < G ? R : G; if (B < minv) minv = B;
+ S = 1.0 - double(minv)/maxv;
+ if (maxv > minv) {
+ if (maxv == R) {H = (G-B)/double(maxv-minv); if (H<0) H += 6.0;}
+ else if (maxv == G) H = 2.0+(B-R)/double(maxv-minv);
+ else H = 4.0+(R-G)/double(maxv-minv);
+ }
+ }
+}
+
+enum {M_RGB, M_BYTE, M_HEX, M_HSV}; // modes
+static Fl_Menu_Item mode_menu[] = {
+ {"rgb"},
+ {"byte"},
+ {"hex"},
+ {"hsv"},
+ {0}
+};
+
+int Flcc_Value_Input::format(char* buf) {
+ Fl_Color_Chooser* c = (Fl_Color_Chooser*)parent();
+ if (c->mode() == M_HEX) return sprintf(buf,"0x%02X", int(value()));
+ else return Fl_Valuator::format(buf);
+}
+
+void Fl_Color_Chooser::set_valuators() {
+ switch (mode()) {
+ case M_RGB:
+ rvalue.range(0,1); rvalue.step(1,1000); rvalue.value(r_);
+ gvalue.range(0,1); gvalue.step(1,1000); gvalue.value(g_);
+ bvalue.range(0,1); bvalue.step(1,1000); bvalue.value(b_);
+ break;
+ case M_BYTE:
+ case M_HEX:
+ rvalue.range(0,255); rvalue.step(1); rvalue.value(int(255*r_+.5));
+ gvalue.range(0,255); gvalue.step(1); gvalue.value(int(255*g_+.5));
+ bvalue.range(0,255); bvalue.step(1); bvalue.value(int(255*b_+.5));
+ break;
+ case M_HSV:
+ rvalue.range(0,6); rvalue.step(1,1000); rvalue.value(hue_);
+ gvalue.range(0,1); gvalue.step(1,1000); gvalue.value(saturation_);
+ bvalue.range(0,1); bvalue.step(1,1000); bvalue.value(value_);
+ break;
+ }
+}
+
+int Fl_Color_Chooser::rgb(double R, double G, double B) {
+ if (R == r_ && G == g_ && B == b_) return 0;
+ r_ = R; g_ = G; b_ = B;
+ double ph = hue_;
+ double ps = saturation_;
+ double pv = value_;
+ rgb2hsv(R,G,B,hue_,saturation_,value_);
+ set_valuators();
+ set_changed();
+ if (value_ != pv) {
+#ifdef UPDATE_HUE_BOX
+ huebox.damage(FL_DAMAGE_SCROLL);
+#endif
+ valuebox.damage(FL_DAMAGE_EXPOSE);}
+ if (hue_ != ph || saturation_ != ps) {
+ huebox.damage(FL_DAMAGE_EXPOSE);
+ valuebox.damage(FL_DAMAGE_SCROLL);
+ }
+ return 1;
+}
+
+int Fl_Color_Chooser::hsv(double H, double S, double V) {
+ H = fmod(H,6.0); if (H < 0.0) H += 6.0;
+ if (S < 0.0) S = 0.0; else if (S > 1.0) S = 1.0;
+ if (V < 0.0) V = 0.0; else if (V > 1.0) V = 1.0;
+ if (H == hue_ && S == saturation_ && V == value_) return 0;
+ double ph = hue_;
+ double ps = saturation_;
+ double pv = value_;
+ hue_ = H; saturation_ = S; value_ = V;
+ if (value_ != pv) {
+#ifdef UPDATE_HUE_BOX
+ huebox.damage(FL_DAMAGE_SCROLL);
+#endif
+ valuebox.damage(FL_DAMAGE_EXPOSE);}
+ if (hue_ != ph || saturation_ != ps) {
+ huebox.damage(FL_DAMAGE_EXPOSE);
+ valuebox.damage(FL_DAMAGE_SCROLL);
+ }
+ hsv2rgb(H,S,V,r_,g_,b_);
+ set_valuators();
+ set_changed();
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////
+
+static void tohs(double x, double y, double& h, double& s) {
+#ifdef CIRCLE
+ x = 2*x-1;
+ y = 1-2*y;
+ s = sqrt(x*x+y*y); if (s > 1.0) s = 1.0;
+ h = (3.0/M_PI)*atan2(y,x);
+ if (h<0) h += 6.0;
+#else
+ h = fmod(6.0*x,6.0); if (h < 0.0) h += 6.0;
+ s = 1.0-y; if (s < 0.0) s = 0.0; else if (s > 1.0) s = 1.0;
+#endif
+}
+
+int Flcc_HueBox::handle(int e) {
+ static double ih, is;
+ Fl_Color_Chooser* c = (Fl_Color_Chooser*)parent();
+ switch (e) {
+ case FL_PUSH:
+ if (Fl::visible_focus()) {
+ Fl::focus(this);
+ redraw();
+ }
+ ih = c->hue();
+ is = c->saturation();
+ case FL_DRAG: {
+ double Xf, Yf, H, S;
+ Xf = (Fl::event_x()-x()-Fl::box_dx(box()))/double(w()-Fl::box_dw(box()));
+ Yf = (Fl::event_y()-y()-Fl::box_dy(box()))/double(h()-Fl::box_dh(box()));
+ tohs(Xf, Yf, H, S);
+ if (fabs(H-ih) < 3*6.0/w()) H = ih;
+ if (fabs(S-is) < 3*1.0/h()) S = is;
+ if (Fl::event_state(FL_CTRL)) H = ih;
+ if (c->hsv(H, S, c->value())) c->do_callback();
+ } return 1;
+ case FL_FOCUS :
+ case FL_UNFOCUS :
+ if (Fl::visible_focus()) {
+ redraw();
+ return 1;
+ }
+ else return 1;
+ case FL_KEYBOARD :
+ return handle_key(Fl::event_key());
+ default:
+ return 0;
+ }
+}
+
+static void generate_image(void* vv, int X, int Y, int W, uchar* buf) {
+ Flcc_HueBox* v = (Flcc_HueBox*)vv;
+ int iw = v->w()-Fl::box_dw(v->box());
+ double Yf = double(Y)/(v->h()-Fl::box_dh(v->box()));
+#ifdef UPDATE_HUE_BOX
+ const double V = ((Fl_Color_Chooser*)(v->parent()))->value();
+#else
+ const double V = 1.0;
+#endif
+ for (int x = X; x < X+W; x++) {
+ double Xf = double(x)/iw;
+ double H,S; tohs(Xf,Yf,H,S);
+ double r,g,b;
+ Fl_Color_Chooser::hsv2rgb(H,S,V,r,g,b);
+ *buf++ = uchar(255*r+.5);
+ *buf++ = uchar(255*g+.5);
+ *buf++ = uchar(255*b+.5);
+ }
+}
+
+int Flcc_HueBox::handle_key(int key) {
+ int w1 = w()-Fl::box_dw(box())-6;
+ int h1 = h()-Fl::box_dh(box())-6;
+ Fl_Color_Chooser* c = (Fl_Color_Chooser*)parent();
+
+#ifdef CIRCLE
+ int X = int(.5*(cos(c->hue()*(M_PI/3.0))*c->saturation()+1) * w1);
+ int Y = int(.5*(1-sin(c->hue()*(M_PI/3.0))*c->saturation()) * h1);
+#else
+ int X = int(c->hue()/6.0*w1);
+ int Y = int((1-c->saturation())*h1);
+#endif
+
+ switch (key) {
+ case FL_Up :
+ Y -= 3;
+ break;
+ case FL_Down :
+ Y += 3;
+ break;
+ case FL_Left :
+ X -= 3;
+ break;
+ case FL_Right :
+ X += 3;
+ break;
+ default :
+ return 0;
+ }
+
+ double Xf, Yf, H, S;
+ Xf = (double)X/(double)w1;
+ Yf = (double)Y/(double)h1;
+ tohs(Xf, Yf, H, S);
+ if (c->hsv(H, S, c->value())) c->do_callback();
+
+ return 1;
+}
+
+void Flcc_HueBox::draw() {
+ if (damage()&FL_DAMAGE_ALL) draw_box();
+ int x1 = x()+Fl::box_dx(box());
+ int yy1 = y()+Fl::box_dy(box());
+ int w1 = w()-Fl::box_dw(box());
+ int h1 = h()-Fl::box_dh(box());
+ if (damage() == FL_DAMAGE_EXPOSE) fl_clip(x1+px,yy1+py,6,6);
+ fl_draw_image(generate_image, this, x1, yy1, w1, h1);
+ if (damage() == FL_DAMAGE_EXPOSE) fl_pop_clip();
+ Fl_Color_Chooser* c = (Fl_Color_Chooser*)parent();
+#ifdef CIRCLE
+ int X = int(.5*(cos(c->hue()*(M_PI/3.0))*c->saturation()+1) * (w1-6));
+ int Y = int(.5*(1-sin(c->hue()*(M_PI/3.0))*c->saturation()) * (h1-6));
+#else
+ int X = int(c->hue()/6.0*(w1-6));
+ int Y = int((1-c->saturation())*(h1-6));
+#endif
+ if (X < 0) X = 0; else if (X > w1-6) X = w1-6;
+ if (Y < 0) Y = 0; else if (Y > h1-6) Y = h1-6;
+ // fl_color(c->value()>.75 ? FL_BLACK : FL_WHITE);
+ draw_box(FL_UP_BOX,x1+X,yy1+Y,6,6,Fl::focus() == this ? FL_FOREGROUND_COLOR : FL_GRAY);
+ px = X; py = Y;
+}
+
+////////////////////////////////////////////////////////////////
+
+int Flcc_ValueBox::handle(int e) {
+ static double iv;
+ Fl_Color_Chooser* c = (Fl_Color_Chooser*)parent();
+ switch (e) {
+ case FL_PUSH:
+ if (Fl::visible_focus()) {
+ Fl::focus(this);
+ redraw();
+ }
+ iv = c->value();
+ case FL_DRAG: {
+ double Yf;
+ Yf = 1-(Fl::event_y()-y()-Fl::box_dy(box()))/double(h()-Fl::box_dh(box()));
+ if (fabs(Yf-iv)<(3*1.0/h())) Yf = iv;
+ if (c->hsv(c->hue(),c->saturation(),Yf)) c->do_callback();
+ } return 1;
+ case FL_FOCUS :
+ case FL_UNFOCUS :
+ if (Fl::visible_focus()) {
+ redraw();
+ return 1;
+ }
+ else return 1;
+ case FL_KEYBOARD :
+ return handle_key(Fl::event_key());
+ default:
+ return 0;
+ }
+}
+
+static double tr, tg, tb;
+static void generate_vimage(void* vv, int X, int Y, int W, uchar* buf) {
+ Flcc_ValueBox* v = (Flcc_ValueBox*)vv;
+ double Yf = 255*(1.0-double(Y)/(v->h()-Fl::box_dh(v->box())));
+ uchar r = uchar(tr*Yf+.5);
+ uchar g = uchar(tg*Yf+.5);
+ uchar b = uchar(tb*Yf+.5);
+ for (int x = X; x < X+W; x++) {
+ *buf++ = r; *buf++ = g; *buf++ = b;
+ }
+}
+
+void Flcc_ValueBox::draw() {
+ if (damage()&FL_DAMAGE_ALL) draw_box();
+ Fl_Color_Chooser* c = (Fl_Color_Chooser*)parent();
+ c->hsv2rgb(c->hue(),c->saturation(),1.0,tr,tg,tb);
+ int x1 = x()+Fl::box_dx(box());
+ int yy1 = y()+Fl::box_dy(box());
+ int w1 = w()-Fl::box_dw(box());
+ int h1 = h()-Fl::box_dh(box());
+ if (damage() == FL_DAMAGE_EXPOSE) fl_clip(x1,yy1+py,w1,6);
+ fl_draw_image(generate_vimage, this, x1, yy1, w1, h1);
+ if (damage() == FL_DAMAGE_EXPOSE) fl_pop_clip();
+ int Y = int((1-c->value()) * (h1-6));
+ if (Y < 0) Y = 0; else if (Y > h1-6) Y = h1-6;
+ draw_box(FL_UP_BOX,x1,yy1+Y,w1,6,Fl::focus() == this ? FL_FOREGROUND_COLOR : FL_GRAY);
+ py = Y;
+}
+
+int Flcc_ValueBox::handle_key(int key) {
+ int h1 = h()-Fl::box_dh(box())-6;
+ Fl_Color_Chooser* c = (Fl_Color_Chooser*)parent();
+
+ int Y = int((1-c->value()) * h1);
+ if (Y < 0) Y = 0; else if (Y > h1) Y = h1;
+
+ switch (key) {
+ case FL_Up :
+ Y -= 3;
+ break;
+ case FL_Down :
+ Y += 3;
+ break;
+ default :
+ return 0;
+ }
+
+ double Yf;
+ Yf = 1-((double)Y/(double)h1);
+ if (c->hsv(c->hue(),c->saturation(),Yf)) c->do_callback();
+
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////
+
+void Fl_Color_Chooser::rgb_cb(Fl_Widget* o, void*) {
+ Fl_Color_Chooser* c = (Fl_Color_Chooser*)(o->parent());
+ double R = c->rvalue.value();
+ double G = c->gvalue.value();
+ double B = c->bvalue.value();
+ if (c->mode() == M_HSV) {
+ if (c->hsv(R,G,B)) c->do_callback();
+ return;
+ }
+ if (c->mode() != M_RGB) {
+ R = R/255;
+ G = G/255;
+ B = B/255;
+ }
+ if (c->rgb(R,G,B)) c->do_callback();
+}
+
+void Fl_Color_Chooser::mode_cb(Fl_Widget* o, void*) {
+ Fl_Color_Chooser* c = (Fl_Color_Chooser*)(o->parent());
+ // force them to redraw even if value is the same:
+ c->rvalue.value(-1);
+ c->gvalue.value(-1);
+ c->bvalue.value(-1);
+ c->set_valuators();
+}
+
+////////////////////////////////////////////////////////////////
+
+Fl_Color_Chooser::Fl_Color_Chooser(int X, int Y, int W, int H, const char* L)
+ : Fl_Group(0,0,195,115,L),
+ huebox(0,0,115,115),
+ valuebox(115,0,20,115),
+ choice(140,0,55,25),
+ rvalue(140,30,55,25),
+ gvalue(140,60,55,25),
+ bvalue(140,90,55,25),
+ resize_box(0,0,115,115)
+{
+ end();
+ resizable(resize_box);
+ resize(X,Y,W,H);
+ r_ = g_ = b_ = 0;
+ hue_ = 0.0;
+ saturation_ = 0.0;
+ value_ = 0.0;
+ huebox.box(FL_DOWN_FRAME);
+ valuebox.box(FL_DOWN_FRAME);
+ choice.menu(mode_menu);
+ set_valuators();
+ rvalue.callback(rgb_cb);
+ gvalue.callback(rgb_cb);
+ bvalue.callback(rgb_cb);
+ choice.callback(mode_cb);
+ choice.box(FL_THIN_UP_BOX);
+ choice.textfont(FL_HELVETICA_BOLD_ITALIC);
+}
+
+////////////////////////////////////////////////////////////////
+// fl_color_chooser():
+
+#include <FL/Fl_Window.H>
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Return_Button.H>
+
+class ColorChip : public Fl_Widget {
+ void draw();
+public:
+ uchar r,g,b;
+ ColorChip(int X, int Y, int W, int H) : Fl_Widget(X,Y,W,H) {
+ box(FL_ENGRAVED_FRAME);}
+};
+
+void ColorChip::draw() {
+ if (damage()&FL_DAMAGE_ALL) draw_box();
+ fl_rectf(x()+Fl::box_dx(box()),
+ y()+Fl::box_dy(box()),
+ w()-Fl::box_dw(box()),
+ h()-Fl::box_dh(box()),r,g,b);
+}
+
+static void chooser_cb(Fl_Object* o, void* vv) {
+ Fl_Color_Chooser* c = (Fl_Color_Chooser*)o;
+ ColorChip* v = (ColorChip*)vv;
+ v->r = uchar(255*c->r()+.5);
+ v->g = uchar(255*c->g()+.5);
+ v->b = uchar(255*c->b()+.5);
+ v->damage(FL_DAMAGE_EXPOSE);
+}
+
+extern const char* fl_ok;
+extern const char* fl_cancel;
+
+int fl_color_chooser(const char* name, double& r, double& g, double& b) {
+ Fl_Window window(215,200,name);
+ Fl_Color_Chooser chooser(10, 10, 195, 115);
+ ColorChip ok_color(10, 130, 95, 25);
+ Fl_Return_Button ok_button(10, 165, 95, 25, fl_ok);
+ ColorChip cancel_color(110, 130, 95, 25);
+ cancel_color.r = uchar(255*r+.5); ok_color.r = cancel_color.r;
+ ok_color.g = cancel_color.g = uchar(255*g+.5);
+ ok_color.b = cancel_color.b = uchar(255*b+.5);
+ Fl_Button cancel_button(110, 165, 95, 25, fl_cancel);
+ window.resizable(chooser);
+ chooser.rgb(r,g,b);
+ chooser.callback(chooser_cb, &ok_color);
+ window.end();
+ window.set_modal();
+ window.hotspot(window);
+ window.show();
+ while (window.shown()) {
+ Fl::wait();
+ for (;;) {
+ Fl_Widget* o = Fl::readqueue();
+ if (!o) break;
+ if (o == &ok_button) {
+ r = chooser.r();
+ g = chooser.g();
+ b = chooser.b();
+ return 1;
+ }
+ if (o == &window || o == &cancel_button) return 0;
+ }
+ }
+ return 0;
+}
+
+int fl_color_chooser(const char* name, uchar& r, uchar& g, uchar& b) {
+ double dr = r/255.0;
+ double dg = g/255.0;
+ double db = b/255.0;
+ if (fl_color_chooser(name,dr,dg,db)) {
+ r = uchar(255*dr+.5);
+ g = uchar(255*dg+.5);
+ b = uchar(255*db+.5);
+ return 1;
+ }
+ return 0;
+}
+
+//
+// End of "$Id: Fl_Color_Chooser.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Counter.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Counter.cxx new file mode 100644 index 0000000..3bc6363 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Counter.cxx @@ -0,0 +1,197 @@ +//
+// "$Id: Fl_Counter.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Counter widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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_Counter.H>
+#include <FL/fl_draw.H>
+
+void Fl_Counter::draw() {
+ int i; Fl_Boxtype boxtype[5];
+ Fl_Color selcolor;
+
+ boxtype[0] = box();
+ if (boxtype[0] == FL_UP_BOX) boxtype[0] = FL_DOWN_BOX;
+ if (boxtype[0] == FL_THIN_UP_BOX) boxtype[0] = FL_THIN_DOWN_BOX;
+ for (i=1; i<5; i++)
+ if (mouseobj == i)
+ boxtype[i] = fl_down(box());
+ else
+ boxtype[i] = box();
+
+ int xx[5], ww[5];
+ if (type() == FL_NORMAL_COUNTER) {
+ int W = w()*15/100;
+ xx[1] = x(); ww[1] = W;
+ xx[2] = x()+1*W; ww[2] = W;
+ xx[0] = x()+2*W; ww[0] = w()-4*W;
+ xx[3] = x()+w()-2*W; ww[3] = W;
+ xx[4] = x()+w()-1*W; ww[4] = W;
+ } else {
+ int W = w()*20/100;
+ xx[1] = 0; ww[1] = 0;
+ xx[2] = x(); ww[2] = W;
+ xx[0] = x()+W; ww[0] = w()-2*W;
+ xx[3] = x()+w()-1*W; ww[3] = W;
+ xx[4] = 0; ww[4] = 0;
+ }
+
+ draw_box(boxtype[0], xx[0], y(), ww[0], h(), FL_BACKGROUND2_COLOR);
+ fl_font(textfont(), textsize());
+ fl_color(active_r() ? textcolor() : fl_inactive(textcolor()));
+ char str[128]; format(str);
+ fl_draw(str, xx[0], y(), ww[0], h(), FL_ALIGN_CENTER);
+ if (Fl::focus() == this) draw_focus(boxtype[0], xx[0], y(), ww[0], h());
+ if (!(damage()&FL_DAMAGE_ALL)) return; // only need to redraw text
+
+ if (active_r())
+ selcolor = labelcolor();
+ else
+ selcolor = fl_inactive(labelcolor());
+
+ if (type() == FL_NORMAL_COUNTER) {
+ draw_box(boxtype[1], xx[1], y(), ww[1], h(), color());
+ fl_draw_symbol("@-4<<", xx[1], y(), ww[1], h(), selcolor);
+ }
+ draw_box(boxtype[2], xx[2], y(), ww[2], h(), color());
+ fl_draw_symbol("@-4<", xx[2], y(), ww[2], h(), selcolor);
+ draw_box(boxtype[3], xx[3], y(), ww[3], h(), color());
+ fl_draw_symbol("@-4>", xx[3], y(), ww[3], h(), selcolor);
+ if (type() == FL_NORMAL_COUNTER) {
+ draw_box(boxtype[4], xx[4], y(), ww[4], h(), color());
+ fl_draw_symbol("@-4>>", xx[4], y(), ww[4], h(), selcolor);
+ }
+}
+
+void Fl_Counter::increment_cb() {
+ if (!mouseobj) return;
+ double v = value();
+ switch (mouseobj) {
+ case 1: v -= lstep_; break;
+ case 2: v = increment(v, -1); break;
+ case 3: v = increment(v, 1); break;
+ case 4: v += lstep_; break;
+ }
+ handle_drag(clamp(round(v)));
+}
+
+#define INITIALREPEAT .5
+#define REPEAT .1
+
+void Fl_Counter::repeat_callback(void* v) {
+ Fl_Counter* b = (Fl_Counter*)v;
+ if (b->mouseobj) {
+ Fl::add_timeout(REPEAT, repeat_callback, b);
+ b->increment_cb();
+ }
+}
+
+int Fl_Counter::calc_mouseobj() {
+ if (type() == FL_NORMAL_COUNTER) {
+ int W = w()*15/100;
+ if (Fl::event_inside(x(), y(), W, h())) return 1;
+ if (Fl::event_inside(x()+W, y(), W, h())) return 2;
+ if (Fl::event_inside(x()+w()-2*W, y(), W, h())) return 3;
+ if (Fl::event_inside(x()+w()-W, y(), W, h())) return 4;
+ } else {
+ int W = w()*20/100;
+ if (Fl::event_inside(x(), y(), W, h())) return 2;
+ if (Fl::event_inside(x()+w()-W, y(), W, h())) return 3;
+ }
+ return -1;
+}
+
+int Fl_Counter::handle(int event) {
+ int i;
+ switch (event) {
+ case FL_RELEASE:
+ if (mouseobj) {
+ Fl::remove_timeout(repeat_callback, this);
+ mouseobj = 0;
+ redraw();
+ }
+ handle_release();
+ return 1;
+ case FL_PUSH:
+ if (Fl::visible_focus()) Fl::focus(this);
+ handle_push();
+ case FL_DRAG:
+ i = calc_mouseobj();
+ if (i != mouseobj) {
+ Fl::remove_timeout(repeat_callback, this);
+ mouseobj = (uchar)i;
+ if (i) Fl::add_timeout(INITIALREPEAT, repeat_callback, this);
+ increment_cb();
+ redraw();
+ }
+ return 1;
+ case FL_KEYBOARD :
+ switch (Fl::event_key()) {
+ case FL_Left:
+ handle_drag(clamp(increment(value(),-1)));
+ return 1;
+ case FL_Right:
+ handle_drag(clamp(increment(value(),1)));
+ return 1;
+ default:
+ return 0;
+ }
+ // break not required because of switch...
+ case FL_FOCUS :
+ case FL_UNFOCUS :
+ if (Fl::visible_focus()) {
+ redraw();
+ return 1;
+ } else return 0;
+ case FL_ENTER :
+ case FL_LEAVE :
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+Fl_Counter::~Fl_Counter() {
+ Fl::remove_timeout(repeat_callback, this);
+}
+
+Fl_Counter::Fl_Counter(int X, int Y, int W, int H, const char* l)
+ : Fl_Valuator(X, Y, W, H, l) {
+ box(FL_UP_BOX);
+ selection_color(FL_INACTIVE_COLOR); // was FL_BLUE
+ align(FL_ALIGN_BOTTOM);
+ bounds(-1000000.0, 1000000.0);
+ Fl_Valuator::step(1, 10);
+ lstep_ = 1.0;
+ mouseobj = 0;
+ textfont_ = FL_HELVETICA;
+ textsize_ = (uchar)FL_NORMAL_SIZE;
+ textcolor_ = FL_FOREGROUND_COLOR;
+}
+
+//
+// End of "$Id: Fl_Counter.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Dial.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Dial.cxx new file mode 100644 index 0000000..3f8a32d --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Dial.cxx @@ -0,0 +1,147 @@ +//
+// "$Id: Fl_Dial.cxx 5472 2006-09-20 03:03:14Z mike $"
+//
+// Circular dial widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2006 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_Dial.H>
+#include <FL/fl_draw.H>
+#include <stdlib.h>
+#include <FL/math.h>
+
+// All angles are measured with 0 to the right and counter-clockwise
+
+void Fl_Dial::draw(int X, int Y, int W, int H) {
+ if (damage()&FL_DAMAGE_ALL) draw_box(box(), X, Y, W, H, color());
+ X += Fl::box_dx(box());
+ Y += Fl::box_dy(box());
+ W -= Fl::box_dw(box());
+ H -= Fl::box_dh(box());
+ double angle = (a2-a1)*(value()-minimum())/(maximum()-minimum()) + a1;
+ if (type() == FL_FILL_DIAL) {
+ // foo: draw this nicely in certain round box types
+ int foo = (box() > _FL_ROUND_UP_BOX && Fl::box_dx(box()));
+ if (foo) {X--; Y--; W+=2; H+=2;}
+ if (active_r()) fl_color(color());
+ else fl_color(fl_inactive(color()));
+ fl_pie(X, Y, W, H, 270-a1, angle > a1 ? 360+270-angle : 270-360-angle);
+ if (active_r()) fl_color(selection_color());
+ else fl_color(fl_inactive(selection_color()));
+ fl_pie(X, Y, W, H, 270-angle, 270-a1);
+ if (foo) {
+ if (active_r()) fl_color(FL_FOREGROUND_COLOR);
+ else fl_color(fl_inactive(FL_FOREGROUND_COLOR));
+ fl_arc(X, Y, W, H, 0, 360);
+ }
+ return;
+ }
+ if (!(damage()&FL_DAMAGE_ALL)) {
+ if (active_r()) fl_color(color());
+ else fl_color(fl_inactive(color()));
+ fl_pie(X+1, Y+1, W-2, H-2, 0, 360);
+ }
+ fl_push_matrix();
+ fl_translate(X+W/2-.5, Y+H/2-.5);
+ fl_scale(W-1, H-1);
+ fl_rotate(45-angle);
+ if (active_r()) fl_color(selection_color());
+ else fl_color(fl_inactive(selection_color()));
+ if (type()) { // FL_LINE_DIAL
+ fl_begin_polygon();
+ fl_vertex(0.0, 0.0);
+ fl_vertex(-0.04, 0.0);
+ fl_vertex(-0.25, 0.25);
+ fl_vertex(0.0, 0.04);
+ fl_end_polygon();
+ if (active_r()) fl_color(FL_FOREGROUND_COLOR);
+ else fl_color(fl_inactive(FL_FOREGROUND_COLOR));
+ fl_begin_loop();
+ fl_vertex(0.0, 0.0);
+ fl_vertex(-0.04, 0.0);
+ fl_vertex(-0.25, 0.25);
+ fl_vertex(0.0, 0.04);
+ fl_end_loop();
+ } else {
+ fl_begin_polygon(); fl_circle(-0.20, 0.20, 0.07); fl_end_polygon();
+ if (active_r()) fl_color(FL_FOREGROUND_COLOR);
+ else fl_color(fl_inactive(FL_FOREGROUND_COLOR));
+ fl_begin_loop(); fl_circle(-0.20, 0.20, 0.07); fl_end_loop();
+ }
+ fl_pop_matrix();
+}
+
+void Fl_Dial::draw() {
+ draw(x(), y(), w(), h());
+ draw_label();
+}
+
+int Fl_Dial::handle(int event, int X, int Y, int W, int H) {
+ switch (event) {
+ case FL_PUSH:
+ handle_push();
+ case FL_DRAG: {
+ int mx = (Fl::event_x()-X-W/2)*H;
+ int my = (Fl::event_y()-Y-H/2)*W;
+ if (!mx && !my) return 1;
+ double angle = 270-atan2((float)-my, (float)mx)*180/M_PI;
+ double oldangle = (a2-a1)*(value()-minimum())/(maximum()-minimum()) + a1;
+ while (angle < oldangle-180) angle += 360;
+ while (angle > oldangle+180) angle -= 360;
+ double val;
+ if ((a1<a2) ? (angle <= a1) : (angle >= a1)) {
+ val = minimum();
+ } else if ((a1<a2) ? (angle >= a2) : (angle <= a2)) {
+ val = maximum();
+ } else {
+ val = minimum() + (maximum()-minimum())*(angle-a1)/(a2-a1);
+ }
+ handle_drag(clamp(round(val)));
+ } return 1;
+ case FL_RELEASE:
+ handle_release();
+ return 1;
+ case FL_ENTER :
+ case FL_LEAVE :
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+int Fl_Dial::handle(int e) {
+ return handle(e, x(), y(), w(), h());
+}
+
+Fl_Dial::Fl_Dial(int X, int Y, int W, int H, const char* l)
+ : Fl_Valuator(X, Y, W, H, l) {
+ box(FL_OVAL_BOX);
+ selection_color(FL_INACTIVE_COLOR); // was 37
+ a1 = 45;
+ a2 = 315;
+}
+
+//
+// End of "$Id: Fl_Dial.cxx 5472 2006-09-20 03:03:14Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Double_Window.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Double_Window.cxx new file mode 100644 index 0000000..eaaacfb --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Double_Window.cxx @@ -0,0 +1,452 @@ +//
+// "$Id: Fl_Double_Window.cxx 5829 2007-05-14 15:51:00Z matt $"
+//
+// Double-buffered window code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2007 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 <config.h>
+#include <FL/Fl.H>
+#include <FL/Fl_Double_Window.H>
+#include <FL/x.H>
+#include <FL/fl_draw.H>
+
+// On systems that support double buffering "naturally" the base
+// Fl_Window class will probably do double-buffer and this subclass
+// does nothing.
+
+#if USE_XDBE
+
+#include <X11/extensions/Xdbe.h>
+
+static int use_xdbe;
+
+static int can_xdbe() {
+ static int tried;
+ if (!tried) {
+ tried = 1;
+ int event_base, error_base;
+ if (!XdbeQueryExtension(fl_display, &event_base, &error_base)) return 0;
+ Drawable root = RootWindow(fl_display,fl_screen);
+ int numscreens = 1;
+ XdbeScreenVisualInfo *a = XdbeGetVisualInfo(fl_display,&root,&numscreens);
+ if (!a) return 0;
+ for (int j = 0; j < a->count; j++)
+ if (a->visinfo[j].visual == fl_visual->visualid
+ /*&& a->visinfo[j].perflevel > 0*/) {use_xdbe = 1; break;}
+ XdbeFreeVisualInfo(a);
+ }
+ return use_xdbe;
+}
+#endif
+
+void Fl_Double_Window::show() {
+ Fl_Window::show();
+}
+
+#ifdef WIN32
+
+// Code used to switch output to an off-screen window. See macros in
+// win32.H which save the old state in local variables.
+
+typedef struct { BYTE a; BYTE b; BYTE c; BYTE d; } FL_BLENDFUNCTION;
+typedef BOOL (WINAPI* fl_alpha_blend_func)
+ (HDC,int,int,int,int,HDC,int,int,int,int,FL_BLENDFUNCTION);
+static fl_alpha_blend_func fl_alpha_blend = NULL;
+static FL_BLENDFUNCTION blendfunc = { 0, 0, 255, 1};
+
+/*
+ * This function checks if the version of MSWindows that we
+ * curently run on supports alpha blending for bitmap transfers
+ * and finds the required function if so.
+ */
+char fl_can_do_alpha_blending() {
+ static char been_here = 0;
+ static char can_do = 0;
+ // do this test only once
+ if (been_here) return can_do;
+ been_here = 1;
+ // load the library that implements alpha blending
+ HMODULE hMod = LoadLibrary("MSIMG32.DLL");
+ // give up if that doesn't exist (Win95?)
+ if (!hMod) return 0;
+ // now find the blending function inside that dll
+ fl_alpha_blend = (fl_alpha_blend_func)GetProcAddress(hMod, "AlphaBlend");
+ // give up if we can't find it (Win95)
+ if (!fl_alpha_blend) return 0;
+ // we have the call, but does our display support alpha blending?
+ HDC dc = 0L;//fl_gc;
+ // get the current or the desktop's device context
+ if (!dc) dc = GetDC(0L);
+ if (!dc) return 0;
+ // check the device capabilities flags. However GetDeviceCaps
+ // does not return anything useful, so we have to do it manually:
+
+ HBITMAP bm = CreateCompatibleBitmap(dc, 1, 1);
+ HDC new_gc = CreateCompatibleDC(dc);
+ int save = SaveDC(new_gc);
+ SelectObject(new_gc, bm);
+ /*COLORREF set = */ SetPixel(new_gc, 0, 0, 0x01010101);
+ BOOL alpha_ok = fl_alpha_blend(dc, 0, 0, 1, 1, new_gc, 0, 0, 1, 1, blendfunc);
+ RestoreDC(new_gc, save);
+ DeleteDC(new_gc);
+ DeleteObject(bm);
+
+ if (!fl_gc) ReleaseDC(0L, dc);
+ if (alpha_ok) can_do = 1;
+ return can_do;
+}
+
+HDC fl_makeDC(HBITMAP bitmap) {
+ HDC new_gc = CreateCompatibleDC(fl_gc);
+ SetTextAlign(new_gc, TA_BASELINE|TA_LEFT);
+ SetBkMode(new_gc, TRANSPARENT);
+#if USE_COLORMAP
+ if (fl_palette) SelectPalette(new_gc, fl_palette, FALSE);
+#endif
+ SelectObject(new_gc, bitmap);
+ return new_gc;
+}
+
+void fl_copy_offscreen(int x,int y,int w,int h,HBITMAP bitmap,int srcx,int srcy) {
+ HDC new_gc = CreateCompatibleDC(fl_gc);
+ int save = SaveDC(new_gc);
+ SelectObject(new_gc, bitmap);
+ BitBlt(fl_gc, x, y, w, h, new_gc, srcx, srcy, SRCCOPY);
+ RestoreDC(new_gc, save);
+ DeleteDC(new_gc);
+}
+
+void fl_copy_offscreen_with_alpha(int x,int y,int w,int h,HBITMAP bitmap,int srcx,int srcy) {
+ HDC new_gc = CreateCompatibleDC(fl_gc);
+ int save = SaveDC(new_gc);
+ SelectObject(new_gc, bitmap);
+ BOOL alpha_ok = 0;
+ // first try to alpha blend
+ if (fl_can_do_alpha_blending())
+ alpha_ok = fl_alpha_blend(fl_gc, x, y, w, h, new_gc, srcx, srcy, w, h, blendfunc);
+ // if that failed (it shouldn,t), still copy the bitmap over, but now alpha is 1
+ if (!alpha_ok)
+ BitBlt(fl_gc, x, y, w, h, new_gc, srcx, srcy, SRCCOPY);
+ RestoreDC(new_gc, save);
+ DeleteDC(new_gc);
+}
+
+extern void fl_restore_clip();
+
+#elif defined(__APPLE_QD__)
+
+char fl_can_do_alpha_blending() {
+ return 0;
+}
+
+GWorldPtr fl_create_offscreen(int w, int h) {
+ GWorldPtr gw;
+ Rect bounds;
+ bounds.left=0; bounds.right=w; bounds.top=0; bounds.bottom=h;
+ QDErr err = NewGWorld(&gw, 0, &bounds, 0L, 0L, 0); // 'useTempMem' should not be used (says the Carbon port manual)
+ if ( err == -108 )
+ { }
+// fl_message( "The application memory is low. Please increase the initial memory assignment.\n" );
+ if (err!=noErr || gw==0L) return 0L;
+ return gw;
+}
+
+void fl_copy_offscreen(int x,int y,int w,int h,GWorldPtr gWorld,int srcx,int srcy) {
+ Rect src;
+ if ( !gWorld ) return;
+ src.top = srcy; src.left = srcx; src.bottom = srcy+h; src.right = srcx+w;
+ Rect dst;
+ GrafPtr dstPort; GetPort(&dstPort);
+ dst.top = y; dst.left = x; dst.bottom = y+h; dst.right = x+w;
+ RGBColor rgb, oldbg, oldfg;
+ GetForeColor(&oldfg);
+ GetBackColor(&oldbg);
+ rgb.red = 0xffff; rgb.green = 0xffff; rgb.blue = 0xffff;
+ RGBBackColor( &rgb );
+ rgb.red = 0x0000; rgb.green = 0x0000; rgb.blue = 0x0000;
+ RGBForeColor( &rgb );
+ CopyBits(GetPortBitMapForCopyBits(gWorld), GetPortBitMapForCopyBits(dstPort), &src, &dst, srcCopy, 0L);
+ RGBBackColor(&oldbg);
+ RGBForeColor(&oldfg);
+}
+
+void fl_delete_offscreen(GWorldPtr gWorld) {
+ DisposeGWorld(gWorld);
+}
+
+static GrafPtr prevPort;
+static GDHandle prevGD;
+
+void fl_begin_offscreen(GWorldPtr gWorld) {
+ GetGWorld( &prevPort, &prevGD );
+ if ( gWorld )
+ {
+ SetGWorld( gWorld, 0 ); // sets the correct port
+ PixMapHandle pm = GetGWorldPixMap(gWorld);
+ Boolean ret = LockPixels(pm);
+ if ( ret == false )
+ {
+ Rect rect;
+ GetPortBounds( gWorld, &rect );
+ UpdateGWorld( &gWorld, 0, &rect, 0, 0, 0 );
+ pm = GetGWorldPixMap( gWorld );
+ LockPixels( pm );
+ }
+ fl_window = 0;
+ }
+ fl_push_no_clip();
+}
+
+void fl_end_offscreen() {
+ GWorldPtr currPort;
+ GDHandle currGD;
+ GetGWorld( &currPort, &currGD );
+ fl_pop_clip();
+ PixMapHandle pm = GetGWorldPixMap(currPort);
+ UnlockPixels(pm);
+ SetGWorld( prevPort, prevGD );
+ fl_window = GetWindowFromPort( prevPort );
+}
+
+extern void fl_restore_clip();
+
+#elif defined(__APPLE_QUARTZ__)
+
+char fl_can_do_alpha_blending() {
+ return 1;
+}
+
+Fl_Offscreen fl_create_offscreen(int w, int h) {
+ void *data = calloc(w*h,4);
+ CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB();
+ CGContextRef ctx = CGBitmapContextCreate(
+ data, w, h, 8, w*4, lut, kCGImageAlphaNoneSkipLast);
+ CGColorSpaceRelease(lut);
+ return (Fl_Offscreen)ctx;
+}
+
+Fl_Offscreen fl_create_offscreen_with_alpha(int w, int h) {
+ void *data = calloc(w*h,4);
+ CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB();
+ CGContextRef ctx = CGBitmapContextCreate(
+ data, w, h, 8, w*4, lut, kCGImageAlphaPremultipliedLast);
+ CGColorSpaceRelease(lut);
+ return (Fl_Offscreen)ctx;
+}
+
+void fl_copy_offscreen(int x,int y,int w,int h,Fl_Offscreen osrc,int srcx,int srcy) {
+ CGContextRef src = (CGContextRef)osrc;
+ void *data = CGBitmapContextGetData(src);
+ int sw = CGBitmapContextGetWidth(src);
+ int sh = CGBitmapContextGetHeight(src);
+ CGImageAlphaInfo alpha = CGBitmapContextGetAlphaInfo(src);
+ CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB();
+ CGDataProviderRef src_bytes = CGDataProviderCreateWithData( 0L, data, sw*sh*4, 0L);
+ CGImageRef img = CGImageCreate( sw, sh, 8, 4*8, 4*sw, lut, alpha,
+ src_bytes, 0L, false, kCGRenderingIntentDefault);
+ // fl_push_clip();
+ CGRect rect = { { x, y }, { w, h } };
+ Fl_X::q_begin_image(rect, srcx, srcy, sw, sh);
+ CGContextDrawImage(fl_gc, rect, img);
+ Fl_X::q_end_image();
+ CGImageRelease(img);
+ CGColorSpaceRelease(lut);
+ CGDataProviderRelease(src_bytes);
+}
+
+void fl_delete_offscreen(Fl_Offscreen ctx) {
+ if (!ctx) return;
+ void *data = CGBitmapContextGetData((CGContextRef)ctx);
+ CGContextRelease((CGContextRef)ctx);
+ if (!data) return;
+ free(data);
+}
+
+const int stack_max = 16;
+static int stack_ix = 0;
+static CGContextRef stack_gc[stack_max];
+static Window stack_window[stack_max];
+
+void fl_begin_offscreen(Fl_Offscreen ctx) {
+ if (stack_ix<stack_max) {
+ stack_gc[stack_ix] = fl_gc;
+ stack_window[stack_ix] = fl_window;
+ } else
+ fprintf(stderr, "FLTK CGContext Stack overflow error\n");
+ stack_ix++;
+
+ fl_gc = (CGContextRef)ctx;
+ fl_window = 0;
+ //fl_push_no_clip();
+ CGContextSaveGState(fl_gc);
+ Fl_X::q_fill_context();
+}
+
+void fl_end_offscreen() {
+ Fl_X::q_release_context();
+ //fl_pop_clip();
+ if (stack_ix>0)
+ stack_ix--;
+ else
+ fprintf(stderr, "FLTK CGContext Stack underflow error\n");
+ if (stack_ix<stack_max) {
+ fl_gc = stack_gc[stack_ix];
+ fl_window = stack_window[stack_ix];
+ }
+}
+
+extern void fl_restore_clip();
+
+#else // X11
+
+// maybe someone feels inclined to implement alpha blending on X11?
+char fl_can_do_alpha_blending() {
+ return 0;
+}
+
+#endif
+
+// Fl_Overlay_Window relies on flush(1) copying the back buffer to the
+// front everywhere, even if damage() == 0, thus erasing the overlay,
+// and leaving the clip region set to the entire window.
+
+void Fl_Double_Window::flush() {flush(0);}
+
+void Fl_Double_Window::flush(int eraseoverlay) {
+ make_current(); // make sure fl_gc is non-zero
+ Fl_X *myi = Fl_X::i(this);
+ if (!myi->other_xid) {
+#if USE_XDBE
+ if (can_xdbe()) {
+ myi->other_xid =
+ XdbeAllocateBackBufferName(fl_display, fl_xid(this), XdbeCopied);
+ myi->backbuffer_bad = 1;
+ } else
+#endif
+#ifdef __APPLE_QD__
+ if ( ( !QDIsPortBuffered( GetWindowPort(myi->xid) ) )
+ || force_doublebuffering_ ) {
+ myi->other_xid = fl_create_offscreen(w(), h());
+ clear_damage(FL_DAMAGE_ALL);
+ }
+#elif defined(__APPLE_QUARTZ__)
+ if (force_doublebuffering_) {
+ myi->other_xid = fl_create_offscreen(w(), h());
+ clear_damage(FL_DAMAGE_ALL);
+ }
+#else
+ myi->other_xid = fl_create_offscreen(w(), h());
+ clear_damage(FL_DAMAGE_ALL);
+#endif
+ }
+#if USE_XDBE
+ if (use_xdbe) {
+ if (myi->backbuffer_bad) {
+ // Make sure we do a complete redraw...
+ if (myi->region) {XDestroyRegion(myi->region); myi->region = 0;}
+ clear_damage(FL_DAMAGE_ALL);
+ myi->backbuffer_bad = 0;
+ }
+
+ // Redraw as needed...
+ if (damage()) {
+ fl_clip_region(myi->region); myi->region = 0;
+ fl_window = myi->other_xid;
+ draw();
+ fl_window = myi->xid;
+ }
+
+ // Copy contents of back buffer to window...
+ XdbeSwapInfo s;
+ s.swap_window = fl_xid(this);
+ s.swap_action = XdbeCopied;
+ XdbeSwapBuffers(fl_display, &s, 1);
+ return;
+ } else
+#endif
+ if (damage() & ~FL_DAMAGE_EXPOSE) {
+ fl_clip_region(myi->region); myi->region = 0;
+#ifdef WIN32
+ HDC _sgc = fl_gc;
+ fl_gc = fl_makeDC(myi->other_xid);
+ int save = SaveDC(fl_gc);
+ fl_restore_clip(); // duplicate region into new gc
+ draw();
+ RestoreDC(fl_gc, save);
+ DeleteDC(fl_gc);
+ fl_gc = _sgc;
+#elif defined(__APPLE__)
+ if ( myi->other_xid ) {
+ fl_begin_offscreen( myi->other_xid );
+ fl_clip_region( 0 );
+ draw();
+ fl_end_offscreen();
+ } else {
+ draw();
+ }
+#else // X:
+ fl_window = myi->other_xid;
+ draw();
+ fl_window = myi->xid;
+#endif
+ }
+ if (eraseoverlay) fl_clip_region(0);
+ // on Irix (at least) it is faster to reduce the area copied to
+ // the current clip region:
+ int X,Y,W,H; fl_clip_box(0,0,w(),h(),X,Y,W,H);
+ if (myi->other_xid) fl_copy_offscreen(X, Y, W, H, myi->other_xid, X, Y);
+}
+
+void Fl_Double_Window::resize(int X,int Y,int W,int H) {
+ int ow = w();
+ int oh = h();
+ Fl_Window::resize(X,Y,W,H);
+#if USE_XDBE
+ if (use_xdbe) return;
+#endif
+ Fl_X* myi = Fl_X::i(this);
+ if (myi && myi->other_xid && (ow != w() || oh != h())) {
+ fl_delete_offscreen(myi->other_xid);
+ myi->other_xid = 0;
+ }
+}
+
+void Fl_Double_Window::hide() {
+ Fl_X* myi = Fl_X::i(this);
+ if (myi && myi->other_xid) {
+#if USE_XDBE
+ if (!use_xdbe)
+#endif
+ fl_delete_offscreen(myi->other_xid);
+ }
+ Fl_Window::hide();
+}
+
+Fl_Double_Window::~Fl_Double_Window() {
+ hide();
+}
+
+//
+// End of "$Id: Fl_Double_Window.cxx 5829 2007-05-14 15:51:00Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_File_Browser.cxx b/third_party/windows/fltk-1.1.10/src/Fl_File_Browser.cxx new file mode 100644 index 0000000..aa37a76 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_File_Browser.cxx @@ -0,0 +1,639 @@ +//
+// "$Id: Fl_File_Browser.cxx 5635 2007-01-23 15:02:00Z mike $"
+//
+// Fl_File_Browser routines.
+//
+// Copyright 1999-2006 by Michael Sweet.
+//
+// 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
+//
+// Contents:
+//
+// Fl_File_Browser::full_height() - Return the height of the list.
+// Fl_File_Browser::item_height() - Return the height of a list item.
+// Fl_File_Browser::item_width() - Return the width of a list item.
+// Fl_File_Browser::item_draw() - Draw a list item.
+// Fl_File_Browser::Fl_File_Browser() - Create a Fl_File_Browser widget.
+// Fl_File_Browser::load() - Load a directory into the browser.
+// Fl_File_Browser::filter() - Set the filename filter.
+//
+
+//
+// Include necessary header files...
+//
+
+#include <FL/Fl_File_Browser.H>
+#include <FL/fl_draw.H>
+#include <FL/filename.H>
+#include <stdio.h>
+#include <stdlib.h>
+#include "flstring.h"
+
+#ifdef __CYGWIN__
+# include <mntent.h>
+#elif defined(WIN32)
+# include <windows.h>
+# include <direct.h>
+// Apparently Borland C++ defines DIRECTORY in <direct.h>, which
+// interfers with the Fl_File_Icon enumeration of the same name.
+# ifdef DIRECTORY
+# undef DIRECTORY
+# endif // DIRECTORY
+#endif // __CYGWIN__
+
+#ifdef __EMX__
+# define INCL_DOS
+# define INCL_DOSMISC
+# include <os2.h>
+#endif // __EMX__
+
+// CodeWarrior (__MWERKS__) gets its include paths confused, so we
+// temporarily disable this...
+#if defined(__APPLE__) && !defined(__MWERKS__)
+# include <sys/param.h>
+# include <sys/ucred.h>
+# include <sys/mount.h>
+#endif // __APPLE__ && !__MWERKS__
+
+
+//
+// FL_BLINE definition from "Fl_Browser.cxx"...
+//
+
+#define SELECTED 1
+#define NOTDISPLAYED 2
+
+struct FL_BLINE // data is in a linked list of these
+{
+ FL_BLINE *prev; // Previous item in list
+ FL_BLINE *next; // Next item in list
+ void *data; // Pointer to data (function)
+ short length; // sizeof(txt)-1, may be longer than string
+ char flags; // selected, displayed
+ char txt[1]; // start of allocated array
+};
+
+
+//
+// 'Fl_File_Browser::full_height()' - Return the height of the list.
+//
+
+int // O - Height in pixels
+Fl_File_Browser::full_height() const
+{
+ int i, // Looping var
+ th; // Total height of list.
+
+
+ for (i = 0, th = 0; i < size(); i ++)
+ th += item_height(find_line(i));
+
+ return (th);
+}
+
+
+//
+// 'Fl_File_Browser::item_height()' - Return the height of a list item.
+//
+
+int // O - Height in pixels
+Fl_File_Browser::item_height(void *p) const // I - List item data
+{
+ FL_BLINE *line; // Pointer to line
+ char *t; // Pointer into text
+ int height; // Width of line
+ int textheight; // Height of text
+
+
+ // Figure out the standard text height...
+ fl_font(textfont(), textsize());
+ textheight = fl_height();
+
+ // We always have at least 1 line...
+ height = textheight;
+
+ // Scan for newlines...
+ line = (FL_BLINE *)p;
+
+ if (line != NULL)
+ for (t = line->txt; *t != '\0'; t ++)
+ if (*t == '\n')
+ height += textheight;
+
+ // If we have enabled icons then add space for them...
+ if (Fl_File_Icon::first() != NULL && height < iconsize_)
+ height = iconsize_;
+
+ // Add space for the selection border..
+ height += 2;
+
+ // Return the height
+ return (height);
+}
+
+
+//
+// 'Fl_File_Browser::item_width()' - Return the width of a list item.
+//
+
+int // O - Width in pixels
+Fl_File_Browser::item_width(void *p) const // I - List item data
+{
+ int i; // Looping var
+ FL_BLINE *line; // Pointer to line
+ char *t, // Pointer into text
+ *ptr, // Pointer into fragment
+ fragment[10240]; // Fragment of text
+ int width, // Width of line
+ tempwidth; // Width of fragment
+ int column; // Current column
+ const int *columns; // Columns
+
+
+ // Scan for newlines...
+ line = (FL_BLINE *)p;
+ columns = column_widths();
+
+ // Set the font and size...
+ if (line->txt[strlen(line->txt) - 1] == '/')
+ fl_font(textfont() | FL_BOLD, textsize());
+ else
+ fl_font(textfont(), textsize());
+
+ if (strchr(line->txt, '\n') == NULL &&
+ strchr(line->txt, column_char()) == NULL)
+ {
+ // Do a fast width calculation...
+ width = (int)fl_width(line->txt);
+ }
+ else
+ {
+ // More than 1 line or have columns; find the maximum width...
+ width = 0;
+ tempwidth = 0;
+ column = 0;
+
+ for (t = line->txt, ptr = fragment; *t != '\0'; t ++)
+ if (*t == '\n')
+ {
+ // Newline - nul terminate this fragment and get the width...
+ *ptr = '\0';
+
+ tempwidth += (int)fl_width(fragment);
+
+ // Update the max width as needed...
+ if (tempwidth > width)
+ width = tempwidth;
+
+ // Point back to the start of the fragment...
+ ptr = fragment;
+ tempwidth = 0;
+ column = 0;
+ }
+ else if (*t == column_char())
+ {
+ // Advance to the next column...
+ column ++;
+ if (columns)
+ {
+ for (i = 0, tempwidth = 0; i < column && columns[i]; i ++)
+ tempwidth += columns[i];
+ }
+ else
+ tempwidth = column * (int)(fl_height() * 0.6 * 8.0);
+
+ if (tempwidth > width)
+ width = tempwidth;
+
+ ptr = fragment;
+ }
+ else
+ *ptr++ = *t;
+
+ if (ptr > fragment)
+ {
+ // Nul terminate this fragment and get the width...
+ *ptr = '\0';
+
+ tempwidth += (int)fl_width(fragment);
+
+ // Update the max width as needed...
+ if (tempwidth > width)
+ width = tempwidth;
+ }
+ }
+
+ // If we have enabled icons then add space for them...
+ if (Fl_File_Icon::first() != NULL)
+ width += iconsize_ + 8;
+
+ // Add space for the selection border..
+ width += 2;
+
+ // Return the width
+ return (width);
+}
+
+
+//
+// 'Fl_File_Browser::item_draw()' - Draw a list item.
+//
+
+void
+Fl_File_Browser::item_draw(void *p, // I - List item data
+ int X, // I - Upper-lefthand X coordinate
+ int Y, // I - Upper-lefthand Y coordinate
+ int W, // I - Width of item
+ int) const // I - Height of item
+{
+ int i; // Looping var
+ FL_BLINE *line; // Pointer to line
+ Fl_Color c; // Text color
+ char *t, // Pointer into text
+ *ptr, // Pointer into fragment
+ fragment[10240]; // Fragment of text
+ int width, // Width of line
+ height; // Height of line
+ int column; // Current column
+ const int *columns; // Columns
+
+
+ // Draw the list item text...
+ line = (FL_BLINE *)p;
+
+ if (line->txt[strlen(line->txt) - 1] == '/')
+ fl_font(textfont() | FL_BOLD, textsize());
+ else
+ fl_font(textfont(), textsize());
+
+ if (line->flags & SELECTED)
+ c = fl_contrast(textcolor(), selection_color());
+ else
+ c = textcolor();
+
+ if (Fl_File_Icon::first() == NULL)
+ {
+ // No icons, just draw the text...
+ X ++;
+ W -= 2;
+ }
+ else
+ {
+ // Draw the icon if it is set...
+ if (line->data)
+ ((Fl_File_Icon *)line->data)->draw(X, Y, iconsize_, iconsize_,
+ (line->flags & SELECTED) ? FL_YELLOW :
+ FL_LIGHT2,
+ active_r());
+
+ // Draw the text offset to the right...
+ X += iconsize_ + 9;
+ W -= iconsize_ - 10;
+
+ // Center the text vertically...
+ height = fl_height();
+
+ for (t = line->txt; *t != '\0'; t ++)
+ if (*t == '\n')
+ height += fl_height();
+
+ if (height < iconsize_)
+ Y += (iconsize_ - height) / 2;
+ }
+
+ // Draw the text...
+ line = (FL_BLINE *)p;
+ columns = column_widths();
+ width = 0;
+ column = 0;
+
+ if (active_r())
+ fl_color(c);
+ else
+ fl_color(fl_inactive(c));
+
+ for (t = line->txt, ptr = fragment; *t != '\0'; t ++)
+ if (*t == '\n')
+ {
+ // Newline - nul terminate this fragment and draw it...
+ *ptr = '\0';
+
+ fl_draw(fragment, X + width, Y, W - width, fl_height(),
+ (Fl_Align)(FL_ALIGN_LEFT | FL_ALIGN_CLIP), 0, 0);
+
+ // Point back to the start of the fragment...
+ ptr = fragment;
+ width = 0;
+ Y += fl_height();
+ column = 0;
+ }
+ else if (*t == column_char())
+ {
+ // Tab - nul terminate this fragment and draw it...
+ *ptr = '\0';
+
+ int cW = W - width; // Clip width...
+
+ if (columns)
+ {
+ // Try clipping inside this column...
+ for (i = 0; i < column && columns[i]; i ++);
+
+ if (columns[i])
+ cW = columns[i];
+ }
+
+ fl_draw(fragment, X + width, Y, cW, fl_height(),
+ (Fl_Align)(FL_ALIGN_LEFT | FL_ALIGN_CLIP), 0, 0);
+
+ // Advance to the next column...
+ column ++;
+ if (columns)
+ {
+ for (i = 0, width = 0; i < column && columns[i]; i ++)
+ width += columns[i];
+ }
+ else
+ width = column * (int)(fl_height() * 0.6 * 8.0);
+
+ ptr = fragment;
+ }
+ else
+ *ptr++ = *t;
+
+ if (ptr > fragment)
+ {
+ // Nul terminate this fragment and draw it...
+ *ptr = '\0';
+
+ fl_draw(fragment, X + width, Y, W - width, fl_height(),
+ (Fl_Align)(FL_ALIGN_LEFT | FL_ALIGN_CLIP), 0, 0);
+ }
+}
+
+
+//
+// 'Fl_File_Browser::Fl_File_Browser()' - Create a Fl_File_Browser widget.
+//
+
+Fl_File_Browser::Fl_File_Browser(int X, // I - Upper-lefthand X coordinate
+ int Y, // I - Upper-lefthand Y coordinate
+ int W, // I - Width in pixels
+ int H, // I - Height in pixels
+ const char *l) // I - Label text
+ : Fl_Browser(X, Y, W, H, l)
+{
+ // Initialize the filter pattern, current directory, and icon size...
+ pattern_ = "*";
+ directory_ = "";
+ iconsize_ = (uchar)(3 * textsize() / 2);
+ filetype_ = FILES;
+}
+
+
+//
+// 'Fl_File_Browser::load()' - Load a directory into the browser.
+//
+
+int // O - Number of files loaded
+Fl_File_Browser::load(const char *directory,// I - Directory to load
+ Fl_File_Sort_F *sort) // I - Sort function to use
+{
+ int i; // Looping var
+ int num_files; // Number of files in directory
+ int num_dirs; // Number of directories in list
+ char filename[4096]; // Current file
+ Fl_File_Icon *icon; // Icon to use
+
+
+// printf("Fl_File_Browser::load(\"%s\")\n", directory);
+
+ clear();
+
+ directory_ = directory;
+
+ if (!directory)
+ return (0);
+
+ if (directory_[0] == '\0')
+ {
+ //
+ // No directory specified; for UNIX list all mount points. For DOS
+ // list all valid drive letters...
+ //
+
+ num_files = 0;
+ if ((icon = Fl_File_Icon::find("any", Fl_File_Icon::DEVICE)) == NULL)
+ icon = Fl_File_Icon::find("any", Fl_File_Icon::DIRECTORY);
+
+#ifdef WIN32
+# ifdef __CYGWIN__
+ //
+ // Cygwin provides an implementation of setmntent() to get the list
+ // of available drives...
+ //
+ FILE *m = setmntent("/-not-used-", "r");
+ struct mntent *p;
+
+ while ((p = getmntent (m)) != NULL) {
+ add(p->mnt_dir, icon);
+ num_files ++;
+ }
+
+ endmntent(m);
+# else
+ //
+ // Normal WIN32 code uses drive bits...
+ //
+ DWORD drives; // Drive available bits
+
+ drives = GetLogicalDrives();
+ for (i = 'A'; i <= 'Z'; i ++, drives >>= 1)
+ if (drives & 1)
+ {
+ sprintf(filename, "%c:/", i);
+
+ if (i < 'C') // see also: GetDriveType and GetVolumeInformation in WIN32
+ add(filename, icon);
+ else
+ add(filename, icon);
+
+ num_files ++;
+ }
+# endif // __CYGWIN__
+#elif defined(__EMX__)
+ //
+ // OS/2 code uses drive bits...
+ //
+ ULONG curdrive; // Current drive
+ ULONG drives; // Drive available bits
+ int start = 3; // 'C' (MRS - dunno if this is correct!)
+
+
+ DosQueryCurrentDisk(&curdrive, &drives);
+ drives >>= start - 1;
+ for (i = 'A'; i <= 'Z'; i ++, drives >>= 1)
+ if (drives & 1)
+ {
+ sprintf(filename, "%c:/", i);
+ add(filename, icon);
+
+ num_files ++;
+ }
+#elif defined(__APPLE__) && !defined(__MWERKS__)
+ // MacOS X and Darwin use getfsstat() system call...
+ int numfs; // Number of file systems
+ struct statfs *fs; // Buffer for file system info
+
+
+ // We always have the root filesystem.
+ add("/", icon);
+
+ // Get the mounted filesystems...
+ numfs = getfsstat(NULL, 0, MNT_NOWAIT);
+ if (numfs > 0) {
+ // We have file systems, get them...
+ fs = new struct statfs[numfs];
+ getfsstat(fs, sizeof(struct statfs) * numfs, MNT_NOWAIT);
+
+ // Add filesystems to the list...
+ for (i = 0; i < numfs; i ++) {
+ // Ignore "/", "/dev", and "/.vol"...
+ if (fs[i].f_mntonname[1] && strcmp(fs[i].f_mntonname, "/dev") &&
+ strcmp(fs[i].f_mntonname, "/.vol")) {
+ snprintf(filename, sizeof(filename), "%s/", fs[i].f_mntonname);
+ add(filename, icon);
+ }
+ num_files ++;
+ }
+
+ // Free the memory used for the file system info array...
+ delete[] fs;
+ }
+#else
+ //
+ // UNIX code uses /etc/fstab or similar...
+ //
+ FILE *mtab; // /etc/mtab or /etc/mnttab file
+ char line[1024]; // Input line
+
+ //
+ // Open the file that contains a list of mounted filesystems...
+ //
+
+ mtab = fopen("/etc/mnttab", "r"); // Fairly standard
+ if (mtab == NULL)
+ mtab = fopen("/etc/mtab", "r"); // More standard
+ if (mtab == NULL)
+ mtab = fopen("/etc/fstab", "r"); // Otherwise fallback to full list
+ if (mtab == NULL)
+ mtab = fopen("/etc/vfstab", "r"); // Alternate full list file
+
+ if (mtab != NULL)
+ {
+ while (fgets(line, sizeof(line), mtab) != NULL)
+ {
+ if (line[0] == '#' || line[0] == '\n')
+ continue;
+ if (sscanf(line, "%*s%4095s", filename) != 1)
+ continue;
+
+ strlcat(filename, "/", sizeof(filename));
+
+// printf("Fl_File_Browser::load() - adding \"%s\" to list...\n", filename);
+ add(filename, icon);
+ num_files ++;
+ }
+
+ fclose(mtab);
+ }
+#endif // WIN32 || __EMX__
+ }
+ else
+ {
+ dirent **files; // Files in in directory
+
+
+ //
+ // Build the file list...
+ //
+
+#if (defined(WIN32) && !defined(__CYGWIN__)) || defined(__EMX__)
+ strlcpy(filename, directory_, sizeof(filename));
+ i = strlen(filename) - 1;
+
+ if (i == 2 && filename[1] == ':' &&
+ (filename[2] == '/' || filename[2] == '\\'))
+ filename[2] = '/';
+ else if (filename[i] != '/' && filename[i] != '\\')
+ strlcat(filename, "/", sizeof(filename));
+
+ num_files = fl_filename_list(filename, &files, sort);
+#else
+ num_files = fl_filename_list(directory_, &files, sort);
+#endif /* WIN32 || __EMX__ */
+
+ if (num_files <= 0)
+ return (0);
+
+ for (i = 0, num_dirs = 0; i < num_files; i ++) {
+ if (strcmp(files[i]->d_name, "./")) {
+ snprintf(filename, sizeof(filename), "%s/%s", directory_,
+ files[i]->d_name);
+
+ icon = Fl_File_Icon::find(filename);
+ if ((icon && icon->type() == Fl_File_Icon::DIRECTORY) ||
+ _fl_filename_isdir_quick(filename)) {
+ num_dirs ++;
+ insert(num_dirs, files[i]->d_name, icon);
+ } else if (filetype_ == FILES &&
+ fl_filename_match(files[i]->d_name, pattern_)) {
+ add(files[i]->d_name, icon);
+ }
+ }
+
+ free(files[i]);
+ }
+
+ free(files);
+ }
+
+ return (num_files);
+}
+
+
+//
+// 'Fl_File_Browser::filter()' - Set the filename filter.
+//
+
+void
+Fl_File_Browser::filter(const char *pattern) // I - Pattern string
+{
+ // If pattern is NULL set the pattern to "*"...
+ if (pattern)
+ pattern_ = pattern;
+ else
+ pattern_ = "*";
+}
+
+
+//
+// End of "$Id: Fl_File_Browser.cxx 5635 2007-01-23 15:02:00Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_File_Chooser.cxx b/third_party/windows/fltk-1.1.10/src/Fl_File_Chooser.cxx new file mode 100644 index 0000000..ca1a7cb --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_File_Chooser.cxx @@ -0,0 +1,444 @@ +//
+// "$Id: Fl_File_Chooser.cxx 6092 2008-04-11 12:57:37Z matt $"
+//
+// Fl_File_Chooser dialog for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// generated by Fast Light User Interface Designer (fluid) version 1.0108
+
+#include "../FL/Fl_File_Chooser.H"
+#include <FL/fl_draw.H>
+
+void Fl_File_Chooser::cb_window_i(Fl_Double_Window*, void*) {
+ fileName->value("");
+fileList->deselect();
+Fl::remove_timeout((Fl_Timeout_Handler)previewCB, this);
+window->hide();
+}
+void Fl_File_Chooser::cb_window(Fl_Double_Window* o, void* v) {
+ ((Fl_File_Chooser*)(o->user_data()))->cb_window_i(o,v);
+}
+
+void Fl_File_Chooser::cb_showChoice_i(Fl_Choice*, void*) {
+ showChoiceCB();
+}
+void Fl_File_Chooser::cb_showChoice(Fl_Choice* o, void* v) {
+ ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_showChoice_i(o,v);
+}
+
+void Fl_File_Chooser::cb_favoritesButton_i(Fl_Menu_Button*, void*) {
+ favoritesButtonCB();
+}
+void Fl_File_Chooser::cb_favoritesButton(Fl_Menu_Button* o, void* v) {
+ ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_favoritesButton_i(o,v);
+}
+
+void Fl_File_Chooser::cb_newButton_i(Fl_Button*, void*) {
+ newdir();
+}
+void Fl_File_Chooser::cb_newButton(Fl_Button* o, void* v) {
+ ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_newButton_i(o,v);
+}
+
+#include <FL/Fl_Bitmap.H>
+static unsigned char idata_new[] =
+{0,0,120,0,132,0,2,1,1,254,1,128,49,128,49,128,253,128,253,128,49,128,49,
+128,1,128,1,128,255,255,0,0};
+static Fl_Bitmap image_new(idata_new, 16, 16);
+
+void Fl_File_Chooser::cb__i(Fl_Tile*, void*) {
+ update_preview();
+}
+void Fl_File_Chooser::cb_(Fl_Tile* o, void* v) {
+ ((Fl_File_Chooser*)(o->parent()->user_data()))->cb__i(o,v);
+}
+
+void Fl_File_Chooser::cb_fileList_i(Fl_File_Browser*, void*) {
+ fileListCB();
+}
+void Fl_File_Chooser::cb_fileList(Fl_File_Browser* o, void* v) {
+ ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_fileList_i(o,v);
+}
+
+void Fl_File_Chooser::cb_previewButton_i(Fl_Check_Button*, void*) {
+ preview(previewButton->value());
+}
+void Fl_File_Chooser::cb_previewButton(Fl_Check_Button* o, void* v) {
+ ((Fl_File_Chooser*)(o->parent()->parent()->parent()->user_data()))->cb_previewButton_i(o,v);
+}
+
+void Fl_File_Chooser::cb_fileName_i(Fl_File_Input*, void*) {
+ fileNameCB();
+}
+void Fl_File_Chooser::cb_fileName(Fl_File_Input* o, void* v) {
+ ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_fileName_i(o,v);
+}
+
+void Fl_File_Chooser::cb_okButton_i(Fl_Return_Button*, void*) {
+ window->hide();
+
+// Do any callback that is registered...
+if (callback_)
+ (*callback_)(this, data_);
+}
+void Fl_File_Chooser::cb_okButton(Fl_Return_Button* o, void* v) {
+ ((Fl_File_Chooser*)(o->parent()->parent()->parent()->user_data()))->cb_okButton_i(o,v);
+}
+
+void Fl_File_Chooser::cb_cancelButton_i(Fl_Button*, void*) {
+ fileName->value("");
+fileList->deselect();
+Fl::remove_timeout((Fl_Timeout_Handler)previewCB, this);
+window->hide();
+}
+void Fl_File_Chooser::cb_cancelButton(Fl_Button* o, void* v) {
+ ((Fl_File_Chooser*)(o->parent()->parent()->parent()->user_data()))->cb_cancelButton_i(o,v);
+}
+
+void Fl_File_Chooser::cb_favList_i(Fl_File_Browser*, void*) {
+ favoritesCB(favList);
+}
+void Fl_File_Chooser::cb_favList(Fl_File_Browser* o, void* v) {
+ ((Fl_File_Chooser*)(o->parent()->user_data()))->cb_favList_i(o,v);
+}
+
+void Fl_File_Chooser::cb_favUpButton_i(Fl_Button*, void*) {
+ favoritesCB(favUpButton);
+}
+void Fl_File_Chooser::cb_favUpButton(Fl_Button* o, void* v) {
+ ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_favUpButton_i(o,v);
+}
+
+void Fl_File_Chooser::cb_favDeleteButton_i(Fl_Button*, void*) {
+ favoritesCB(favDeleteButton);
+}
+void Fl_File_Chooser::cb_favDeleteButton(Fl_Button* o, void* v) {
+ ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_favDeleteButton_i(o,v);
+}
+
+void Fl_File_Chooser::cb_favDownButton_i(Fl_Button*, void*) {
+ favoritesCB(favDownButton);
+}
+void Fl_File_Chooser::cb_favDownButton(Fl_Button* o, void* v) {
+ ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_favDownButton_i(o,v);
+}
+
+void Fl_File_Chooser::cb_favCancelButton_i(Fl_Button*, void*) {
+ favWindow->hide();
+}
+void Fl_File_Chooser::cb_favCancelButton(Fl_Button* o, void* v) {
+ ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_favCancelButton_i(o,v);
+}
+
+void Fl_File_Chooser::cb_favOkButton_i(Fl_Return_Button*, void*) {
+ favoritesCB(favOkButton);
+}
+void Fl_File_Chooser::cb_favOkButton(Fl_Return_Button* o, void* v) {
+ ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_favOkButton_i(o,v);
+}
+
+Fl_File_Chooser::Fl_File_Chooser(const char *d, const char *p, int t, const char *title) {
+ Fl_Group *prev_current = Fl_Group::current();
+ { window = new Fl_Double_Window(490, 380, "Choose File");
+ window->callback((Fl_Callback*)cb_window, (void*)(this));
+ { Fl_Group* o = new Fl_Group(10, 10, 470, 25);
+ { showChoice = new Fl_Choice(65, 10, 215, 25, "Show:");
+ showChoice->down_box(FL_BORDER_BOX);
+ showChoice->labelfont(1);
+ showChoice->callback((Fl_Callback*)cb_showChoice);
+ Fl_Group::current()->resizable(showChoice);
+ showChoice->label(show_label);
+ } // Fl_Choice* showChoice
+ { favoritesButton = new Fl_Menu_Button(290, 10, 155, 25, "Favorites");
+ favoritesButton->down_box(FL_BORDER_BOX);
+ favoritesButton->callback((Fl_Callback*)cb_favoritesButton);
+ favoritesButton->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
+ favoritesButton->label(favorites_label);
+ } // Fl_Menu_Button* favoritesButton
+ { Fl_Button* o = newButton = new Fl_Button(455, 10, 25, 25);
+ newButton->image(image_new);
+ newButton->labelsize(8);
+ newButton->callback((Fl_Callback*)cb_newButton);
+ o->tooltip(new_directory_tooltip);
+ } // Fl_Button* newButton
+ o->end();
+ } // Fl_Group* o
+ { Fl_Tile* o = new Fl_Tile(10, 45, 470, 225);
+ o->callback((Fl_Callback*)cb_);
+ { fileList = new Fl_File_Browser(10, 45, 295, 225);
+ fileList->type(2);
+ fileList->callback((Fl_Callback*)cb_fileList);
+ fileList->window()->hotspot(fileList);
+ } // Fl_File_Browser* fileList
+ { previewBox = new Fl_Box(305, 45, 175, 225, "?");
+ previewBox->box(FL_DOWN_BOX);
+ previewBox->labelsize(100);
+ previewBox->align(FL_ALIGN_CLIP|FL_ALIGN_INSIDE);
+ } // Fl_Box* previewBox
+ o->end();
+ Fl_Group::current()->resizable(o);
+ } // Fl_Tile* o
+ { Fl_Group* o = new Fl_Group(10, 275, 470, 95);
+ { Fl_Group* o = new Fl_Group(10, 275, 470, 20);
+ { previewButton = new Fl_Check_Button(10, 275, 73, 20, "Preview");
+ previewButton->down_box(FL_DOWN_BOX);
+ previewButton->value(1);
+ previewButton->shortcut(0x80070);
+ previewButton->callback((Fl_Callback*)cb_previewButton);
+ previewButton->label(preview_label);
+ } // Fl_Check_Button* previewButton
+ { Fl_Box* o = new Fl_Box(115, 275, 365, 20);
+ Fl_Group::current()->resizable(o);
+ } // Fl_Box* o
+ o->end();
+ } // Fl_Group* o
+ { fileName = new Fl_File_Input(115, 300, 365, 35);
+ fileName->labelfont(1);
+ fileName->callback((Fl_Callback*)cb_fileName);
+ fileName->when(FL_WHEN_ENTER_KEY);
+ Fl_Group::current()->resizable(fileName);
+ fileName->when(FL_WHEN_CHANGED | FL_WHEN_ENTER_KEY);
+ } // Fl_File_Input* fileName
+ { Fl_Box* o = new Fl_Box(10, 310, 105, 25, "Filename:");
+ o->labelfont(1);
+ o->align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE);
+ o->label(filename_label);
+ } // Fl_Box* o
+ { Fl_Group* o = new Fl_Group(10, 345, 470, 25);
+ { okButton = new Fl_Return_Button(313, 345, 85, 25, "OK");
+ okButton->callback((Fl_Callback*)cb_okButton);
+ okButton->label(fl_ok);
+ } // Fl_Return_Button* okButton
+ { Fl_Button* o = cancelButton = new Fl_Button(408, 345, 72, 25, "Cancel");
+ cancelButton->callback((Fl_Callback*)cb_cancelButton);
+ o->label(fl_cancel);
+ } // Fl_Button* cancelButton
+ { Fl_Box* o = new Fl_Box(10, 345, 30, 25);
+ Fl_Group::current()->resizable(o);
+ } // Fl_Box* o
+ o->end();
+ } // Fl_Group* o
+ o->end();
+ } // Fl_Group* o
+ if (title) window->label(title);
+ window->set_modal();
+ window->end();
+ } // Fl_Double_Window* window
+ { favWindow = new Fl_Double_Window(355, 150, "Manage Favorites");
+ favWindow->user_data((void*)(this));
+ { favList = new Fl_File_Browser(10, 10, 300, 95);
+ favList->type(2);
+ favList->callback((Fl_Callback*)cb_favList);
+ Fl_Group::current()->resizable(favList);
+ } // Fl_File_Browser* favList
+ { Fl_Group* o = new Fl_Group(320, 10, 25, 95);
+ { favUpButton = new Fl_Button(320, 10, 25, 25, "@8>");
+ favUpButton->callback((Fl_Callback*)cb_favUpButton);
+ } // Fl_Button* favUpButton
+ { favDeleteButton = new Fl_Button(320, 45, 25, 25, "X");
+ favDeleteButton->labelfont(1);
+ favDeleteButton->callback((Fl_Callback*)cb_favDeleteButton);
+ Fl_Group::current()->resizable(favDeleteButton);
+ } // Fl_Button* favDeleteButton
+ { favDownButton = new Fl_Button(320, 80, 25, 25, "@2>");
+ favDownButton->callback((Fl_Callback*)cb_favDownButton);
+ } // Fl_Button* favDownButton
+ o->end();
+ } // Fl_Group* o
+ { Fl_Group* o = new Fl_Group(10, 113, 335, 29);
+ { favCancelButton = new Fl_Button(273, 115, 72, 25, "Cancel");
+ favCancelButton->callback((Fl_Callback*)cb_favCancelButton);
+ favCancelButton->label(fl_cancel);
+ } // Fl_Button* favCancelButton
+ { favOkButton = new Fl_Return_Button(181, 115, 79, 25, "Save");
+ favOkButton->callback((Fl_Callback*)cb_favOkButton);
+ favOkButton->label(save_label);
+ } // Fl_Return_Button* favOkButton
+ { Fl_Box* o = new Fl_Box(10, 115, 161, 25);
+ Fl_Group::current()->resizable(o);
+ } // Fl_Box* o
+ o->end();
+ } // Fl_Group* o
+ favWindow->label(manage_favorites_label);
+ favWindow->set_modal();
+ favWindow->size_range(181, 150);
+ favWindow->end();
+ } // Fl_Double_Window* favWindow
+ callback_ = 0;
+data_ = 0;
+directory_[0] = 0;
+window->size_range(window->w(), window->h(), Fl::w(), Fl::h());
+type(t);
+filter(p);
+update_favorites();
+value(d);
+type(t);
+int e;
+prefs_.get("preview", e, 1);
+preview(e);
+Fl_Group::current(prev_current);
+}
+
+Fl_File_Chooser::~Fl_File_Chooser() {
+ Fl::remove_timeout((Fl_Timeout_Handler)previewCB, this);
+delete window;
+delete favWindow;
+}
+
+void Fl_File_Chooser::callback(void (*cb)(Fl_File_Chooser *, void *), void *d ) {
+ callback_ = cb;
+data_ = d;
+}
+
+void Fl_File_Chooser::color(Fl_Color c) {
+ fileList->color(c);
+}
+
+Fl_Color Fl_File_Chooser::color() {
+ return (fileList->color());
+}
+
+char * Fl_File_Chooser::directory() {
+ return directory_;
+}
+
+const char * Fl_File_Chooser::filter() {
+ return (fileList->filter());
+}
+
+int Fl_File_Chooser::filter_value() {
+ return showChoice->value();
+}
+
+void Fl_File_Chooser::filter_value(int f) {
+ showChoice->value(f);
+showChoiceCB();
+}
+
+void Fl_File_Chooser::hide() {
+ window->hide();
+}
+
+void Fl_File_Chooser::iconsize(uchar s) {
+ fileList->iconsize(s);
+}
+
+uchar Fl_File_Chooser::iconsize() {
+ return (fileList->iconsize());
+}
+
+void Fl_File_Chooser::label(const char *l) {
+ window->label(l);
+}
+
+const char * Fl_File_Chooser::label() {
+ return (window->label());
+}
+
+void Fl_File_Chooser::ok_label(const char *l) {
+ okButton->label(l);
+int w=0, h=0;
+okButton->measure_label(w, h);
+okButton->resize(cancelButton->x() - 50 - w, cancelButton->y(),
+ w + 40, 25);
+okButton->parent()->init_sizes();
+}
+
+const char * Fl_File_Chooser::ok_label() {
+ return (okButton->label());
+}
+
+void Fl_File_Chooser::show() {
+ window->hotspot(fileList);
+window->show();
+Fl::flush();
+fl_cursor(FL_CURSOR_WAIT);
+rescan_keep_filename();
+fl_cursor(FL_CURSOR_DEFAULT);
+fileName->take_focus();
+}
+
+int Fl_File_Chooser::shown() {
+ return window->shown();
+}
+
+void Fl_File_Chooser::textcolor(Fl_Color c) {
+ fileList->textcolor(c);
+}
+
+Fl_Color Fl_File_Chooser::textcolor() {
+ return (fileList->textcolor());
+}
+
+void Fl_File_Chooser::textfont(uchar f) {
+ fileList->textfont(f);
+}
+
+uchar Fl_File_Chooser::textfont() {
+ return (fileList->textfont());
+}
+
+void Fl_File_Chooser::textsize(uchar s) {
+ fileList->textsize(s);
+}
+
+uchar Fl_File_Chooser::textsize() {
+ return (fileList->textsize());
+}
+
+void Fl_File_Chooser::type(int t) {
+ type_ = t;
+if (t & MULTI)
+ fileList->type(FL_MULTI_BROWSER);
+else
+ fileList->type(FL_HOLD_BROWSER);
+if (t & CREATE)
+ newButton->activate();
+else
+ newButton->deactivate();
+if (t & DIRECTORY)
+ fileList->filetype(Fl_File_Browser::DIRECTORIES);
+else
+ fileList->filetype(Fl_File_Browser::FILES);
+}
+
+int Fl_File_Chooser::type() {
+ return (type_);
+}
+
+void * Fl_File_Chooser::user_data() const {
+ return (data_);
+}
+
+void Fl_File_Chooser::user_data(void *d) {
+ data_ = d;
+}
+
+int Fl_File_Chooser::visible() {
+ return window->visible();
+}
+
+//
+// End of "$Id: Fl_File_Chooser.cxx 6092 2008-04-11 12:57:37Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_File_Chooser.fl b/third_party/windows/fltk-1.1.10/src/Fl_File_Chooser.fl new file mode 100644 index 0000000..934e4d4 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_File_Chooser.fl @@ -0,0 +1,426 @@ +# data file for the Fltk User Interface Designer (fluid)
+version 1.0108
+header_name {../FL/Fl_File_Chooser.H}
+code_name {.cxx}
+comment {//
+// "$Id: Fl_File_Chooser.fl 6092 2008-04-11 12:57:37Z matt $"
+//
+// Fl_File_Chooser dialog for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+} {in_source in_header
+}
+
+decl {\#include <FL/fl_draw.H>} {}
+
+class FL_EXPORT Fl_File_Chooser {open
+} {
+ decl {enum { SINGLE = 0, MULTI = 1, CREATE = 2, DIRECTORY = 4 };} {public
+ }
+ decl {static Fl_Preferences prefs_;} {}
+ decl {void (*callback_)(Fl_File_Chooser*, void *);} {}
+ decl {void *data_;} {}
+ decl {char directory_[1024];} {}
+ decl {char pattern_[1024];} {}
+ decl {char preview_text_[2048];} {}
+ decl {int type_;} {}
+ decl {void favoritesButtonCB();} {}
+ decl {void favoritesCB(Fl_Widget *w);} {}
+ decl {void fileListCB();} {}
+ decl {void fileNameCB();} {}
+ decl {void newdir();} {}
+ decl {static void previewCB(Fl_File_Chooser *fc);} {}
+ decl {void showChoiceCB();} {}
+ decl {void update_favorites();} {}
+ decl {void update_preview();} {}
+ Function {Fl_File_Chooser(const char *d, const char *p, int t, const char *title)} {open
+ } {
+ code {Fl_Group *prev_current = Fl_Group::current();} {}
+ Fl_Window window {
+ label {Choose File}
+ callback {fileName->value("");
+fileList->deselect();
+Fl::remove_timeout((Fl_Timeout_Handler)previewCB, this);
+window->hide();} open
+ private xywh {388 284 490 380} type Double resizable
+ code0 {if (title) window->label(title);}
+ code1 {\#include <stdio.h>}
+ code2 {\#include <stdlib.h>}
+ code3 {\#include <string.h>} modal visible
+ } {
+ Fl_Group {} {
+ private xywh {10 10 470 25}
+ } {
+ Fl_Choice showChoice {
+ label {Show:}
+ callback {showChoiceCB();} open
+ private xywh {65 10 215 25} down_box BORDER_BOX labelfont 1 resizable
+ code0 {showChoice->label(show_label);}
+ } {}
+ Fl_Menu_Button favoritesButton {
+ label Favorites
+ callback {favoritesButtonCB();} open
+ private xywh {290 10 155 25} down_box BORDER_BOX align 20
+ code0 {favoritesButton->label(favorites_label);}
+ } {}
+ Fl_Button newButton {
+ callback {newdir();}
+ image {new.xbm} xywh {455 10 25 25} labelsize 8
+ code0 {\#include <FL/Fl_Preferences.H>}
+ code1 {o->tooltip(new_directory_tooltip);}
+ }
+ }
+ Fl_Tile {} {
+ callback {update_preview();}
+ private xywh {10 45 470 225} resizable
+ } {
+ Fl_File_Browser fileList {
+ callback {fileListCB();}
+ private xywh {10 45 295 225} type Hold hotspot
+ code0 {\#include <FL/Fl_File_Browser.H>}
+ }
+ Fl_Box previewBox {
+ label {?} selected
+ private xywh {305 45 175 225} box DOWN_BOX labelsize 100 align 80
+ }
+ }
+ Fl_Group {} {open
+ private xywh {10 275 470 95}
+ } {
+ Fl_Group {} {open
+ private xywh {10 275 470 20}
+ } {
+ Fl_Check_Button previewButton {
+ label Preview
+ callback {preview(previewButton->value());}
+ xywh {10 275 73 20} down_box DOWN_BOX shortcut 0x80070 value 1
+ code0 {previewButton->label(preview_label);}
+ }
+ Fl_Box {} {
+ private xywh {115 275 365 20} resizable
+ }
+ }
+ Fl_File_Input fileName {
+ callback {fileNameCB();}
+ private xywh {115 300 365 35} labelfont 1 when 8 resizable
+ code0 {fileName->when(FL_WHEN_CHANGED | FL_WHEN_ENTER_KEY);}
+ }
+ Fl_Box {} {
+ label {Filename:}
+ private xywh {10 310 105 25} labelfont 1 align 24
+ code0 {o->label(filename_label);}
+ }
+ Fl_Group {} {open
+ private xywh {10 345 470 25}
+ } {
+ Fl_Return_Button okButton {
+ label OK
+ callback {window->hide();
+
+// Do any callback that is registered...
+if (callback_)
+ (*callback_)(this, data_);}
+ private xywh {313 345 85 25}
+ code0 {\#include <FL/fl_ask.H>}
+ code1 {okButton->label(fl_ok);}
+ }
+ Fl_Button cancelButton {
+ label Cancel
+ callback {fileName->value("");
+fileList->deselect();
+Fl::remove_timeout((Fl_Timeout_Handler)previewCB, this);
+window->hide();}
+ private xywh {408 345 72 25}
+ code0 {o->label(fl_cancel);}
+ }
+ Fl_Box {} {
+ private xywh {10 345 30 25} resizable
+ }
+ }
+ }
+ }
+ Fl_Window favWindow {
+ label {Manage Favorites}
+ private xywh {413 100 355 150} type Double resizable
+ code0 {favWindow->label(manage_favorites_label);} modal size_range {181 150 0 0} visible
+ } {
+ Fl_File_Browser favList {
+ callback {favoritesCB(favList);}
+ private xywh {10 10 300 95} type Hold resizable
+ }
+ Fl_Group {} {open
+ xywh {320 10 25 95}
+ } {
+ Fl_Button favUpButton {
+ label {@8>}
+ callback {favoritesCB(favUpButton);}
+ private xywh {320 10 25 25}
+ }
+ Fl_Button favDeleteButton {
+ label X
+ callback {favoritesCB(favDeleteButton);}
+ private xywh {320 45 25 25} labelfont 1 resizable
+ }
+ Fl_Button favDownButton {
+ label {@2>}
+ callback {favoritesCB(favDownButton);}
+ private xywh {320 80 25 25}
+ }
+ }
+ Fl_Group {} {open
+ xywh {10 113 335 29}
+ } {
+ Fl_Button favCancelButton {
+ label Cancel
+ callback {favWindow->hide();}
+ private xywh {273 115 72 25}
+ code0 {favCancelButton->label(fl_cancel);}
+ }
+ Fl_Return_Button favOkButton {
+ label Save
+ callback {favoritesCB(favOkButton);}
+ private xywh {181 115 79 25}
+ code0 {\#include <FL/fl_ask.H>}
+ code1 {favOkButton->label(save_label);}
+ }
+ Fl_Box {} {
+ xywh {10 115 161 25} resizable
+ }
+ }
+ }
+ code {callback_ = 0;
+data_ = 0;
+directory_[0] = 0;
+window->size_range(window->w(), window->h(), Fl::w(), Fl::h());
+type(t);
+filter(p);
+update_favorites();
+value(d);
+type(t);
+int e;
+prefs_.get("preview", e, 1);
+preview(e);
+Fl_Group::current(prev_current);} {}
+ }
+ Function {~Fl_File_Chooser()} {} {
+ code {Fl::remove_timeout((Fl_Timeout_Handler)previewCB, this);
+delete window;
+delete favWindow;} {}
+ }
+ Function {callback(void (*cb)(Fl_File_Chooser *, void *), void *d = 0)} {return_type void
+ } {
+ code {callback_ = cb;
+data_ = d;} {}
+ }
+ Function {color(Fl_Color c)} {} {
+ code {fileList->color(c);} {}
+ }
+ Function {color()} {return_type Fl_Color
+ } {
+ code {return (fileList->color());} {}
+ }
+ decl {int count();} {public
+ }
+ decl {void directory(const char *d);} {public
+ }
+ Function {directory()} {return_type {char *}
+ } {
+ code {return directory_;} {}
+ }
+ decl {void filter(const char *p);} {public
+ }
+ Function {filter()} {return_type {const char *}
+ } {
+ code {return (fileList->filter());} {}
+ }
+ Function {filter_value()} {return_type int
+ } {
+ code {return showChoice->value();} {}
+ }
+ Function {filter_value(int f)} {return_type void
+ } {
+ code {showChoice->value(f);
+showChoiceCB();} {}
+ }
+ Function {hide()} {return_type void
+ } {
+ code {window->hide();} {}
+ }
+ Function {iconsize(uchar s)} {return_type void
+ } {
+ code {fileList->iconsize(s);} {}
+ }
+ Function {iconsize()} {return_type uchar
+ } {
+ code {return (fileList->iconsize());} {}
+ }
+ Function {label(const char *l)} {return_type void
+ } {
+ code {window->label(l);} {}
+ }
+ Function {label()} {return_type {const char *}
+ } {
+ code {return (window->label());} {}
+ }
+ Function {ok_label(const char *l)} {return_type void
+ } {
+ code {okButton->label(l);
+int w=0, h=0;
+okButton->measure_label(w, h);
+okButton->resize(cancelButton->x() - 50 - w, cancelButton->y(),
+ w + 40, 25);
+okButton->parent()->init_sizes();} {}
+ }
+ Function {ok_label()} {return_type {const char *}
+ } {
+ code {return (okButton->label());} {}
+ }
+ decl {void preview(int e);} {public
+ }
+ decl {int preview() const { return previewButton->value(); }} {public
+ }
+ decl {void rescan();} {public
+ }
+ decl {void rescan_keep_filename();} {public
+ }
+ Function {show()} {open return_type void
+ } {
+ code {window->hotspot(fileList);
+window->show();
+Fl::flush();
+fl_cursor(FL_CURSOR_WAIT);
+rescan_keep_filename();
+fl_cursor(FL_CURSOR_DEFAULT);
+fileName->take_focus();} {}
+ }
+ Function {shown()} {return_type int
+ } {
+ code {return window->shown();} {}
+ }
+ Function {textcolor(Fl_Color c)} {return_type void
+ } {
+ code {fileList->textcolor(c);} {}
+ }
+ Function {textcolor()} {return_type Fl_Color
+ } {
+ code {return (fileList->textcolor());} {}
+ }
+ Function {textfont(uchar f)} {return_type void
+ } {
+ code {fileList->textfont(f);} {}
+ }
+ Function {textfont()} {return_type uchar
+ } {
+ code {return (fileList->textfont());} {}
+ }
+ Function {textsize(uchar s)} {return_type void
+ } {
+ code {fileList->textsize(s);} {}
+ }
+ Function {textsize()} {return_type uchar
+ } {
+ code {return (fileList->textsize());} {}
+ }
+ Function {type(int t)} {return_type void
+ } {
+ code {type_ = t;
+if (t & MULTI)
+ fileList->type(FL_MULTI_BROWSER);
+else
+ fileList->type(FL_HOLD_BROWSER);
+if (t & CREATE)
+ newButton->activate();
+else
+ newButton->deactivate();
+if (t & DIRECTORY)
+ fileList->filetype(Fl_File_Browser::DIRECTORIES);
+else
+ fileList->filetype(Fl_File_Browser::FILES);} {}
+ }
+ Function {type()} {return_type int
+ } {
+ code {return (type_);} {}
+ }
+ Function {user_data() const} {return_type {void *}
+ } {
+ code {return (data_);} {}
+ }
+ Function {user_data(void *d)} {return_type void
+ } {
+ code {data_ = d;} {}
+ }
+ decl {const char *value(int f = 1);} {public
+ }
+ decl {void value(const char *filename);} {public
+ }
+ Function {visible()} {return_type int
+ } {
+ code {return window->visible();} {}
+ }
+ decl {static const char *add_favorites_label;} {public
+ }
+ decl {static const char *all_files_label;} {public
+ }
+ decl {static const char *custom_filter_label;} {public
+ }
+ decl {static const char *existing_file_label;} {public
+ }
+ decl {static const char *favorites_label;} {public
+ }
+ decl {static const char *filename_label;} {public
+ }
+ decl {static const char *filesystems_label;} {public
+ }
+ decl {static const char *manage_favorites_label;} {public
+ }
+ decl {static const char *new_directory_label;} {public
+ }
+ decl {static const char *new_directory_tooltip;} {public
+ }
+ decl {static const char *preview_label;} {public
+ }
+ decl {static const char *save_label;} {public
+ }
+ decl {static const char *show_label;} {public
+ }
+ decl {static Fl_File_Sort_F *sort;} {public
+ }
+}
+
+decl {FL_EXPORT char *fl_dir_chooser(const char *message,const char *fname,int relative=0);} {public
+}
+
+decl {FL_EXPORT char *fl_file_chooser(const char *message,const char *pat,const char *fname,int relative=0);} {public
+}
+
+decl {FL_EXPORT void fl_file_chooser_callback(void (*cb)(const char*));} {public
+}
+
+decl {FL_EXPORT void fl_file_chooser_ok_label(const char*l);} {public
+}
+
+comment {
+//
+// End of "$Id: Fl_File_Chooser.fl 6092 2008-04-11 12:57:37Z matt $".
+//} {in_source in_header
+}
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_File_Chooser2.cxx b/third_party/windows/fltk-1.1.10/src/Fl_File_Chooser2.cxx new file mode 100644 index 0000000..b147546 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_File_Chooser2.cxx @@ -0,0 +1,1308 @@ +//
+// "$Id: Fl_File_Chooser2.cxx 6092 2008-04-11 12:57:37Z matt $"
+//
+// More Fl_File_Chooser routines.
+//
+// Copyright 1999-2005 by Michael Sweet.
+//
+// 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
+//
+// Contents:
+//
+// Fl_File_Chooser::count() - Return the number of selected files.
+// Fl_File_Chooser::directory() - Set the directory in the file chooser.
+// Fl_File_Chooser::filter() - Set the filter(s) for the chooser.
+// Fl_File_Chooser::newdir() - Make a new directory.
+// Fl_File_Chooser::value() - Return a selected filename.
+// Fl_File_Chooser::rescan() - Rescan the current directory.
+// Fl_File_Chooser::favoritesButtonCB() - Handle favorites selections.
+// Fl_File_Chooser::fileListCB() - Handle clicks (and double-clicks)
+// in the Fl_File_Browser.
+// Fl_File_Chooser::fileNameCB() - Handle text entry in the FileBrowser.
+// Fl_File_Chooser::showChoiceCB() - Handle show selections.
+// compare_dirnames() - Compare two directory names.
+// quote_pathname() - Quote a pathname for a menu.
+// unquote_pathname() - Unquote a pathname from a menu.
+//
+
+//
+// Include necessary headers.
+//
+
+#include <FL/Fl_File_Chooser.H>
+#include <FL/filename.H>
+#include <FL/fl_ask.H>
+#include <FL/x.H>
+#include <FL/Fl_Shared_Image.H>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "flstring.h"
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#if defined(WIN32) && ! defined (__CYGWIN__)
+# include <direct.h>
+# include <io.h>
+// Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs
+// on Windows, which is supposed to be POSIX compliant...
+# define access _access
+# define mkdir _mkdir
+// Apparently Borland C++ defines DIRECTORY in <direct.h>, which
+// interfers with the Fl_File_Icon enumeration of the same name.
+# ifdef DIRECTORY
+# undef DIRECTORY
+# endif // DIRECTORY
+#else
+# include <unistd.h>
+# include <pwd.h>
+#endif /* WIN32 */
+
+
+//
+// File chooser label strings and sort function...
+//
+
+Fl_Preferences Fl_File_Chooser::prefs_(Fl_Preferences::USER, "fltk.org", "filechooser");
+
+const char *Fl_File_Chooser::add_favorites_label = "Add to Favorites";
+const char *Fl_File_Chooser::all_files_label = "All Files (*)";
+const char *Fl_File_Chooser::custom_filter_label = "Custom Filter";
+const char *Fl_File_Chooser::existing_file_label = "Please choose an existing file!";
+const char *Fl_File_Chooser::favorites_label = "Favorites";
+const char *Fl_File_Chooser::filename_label = "Filename:";
+#ifdef WIN32
+const char *Fl_File_Chooser::filesystems_label = "My Computer";
+#else
+const char *Fl_File_Chooser::filesystems_label = "File Systems";
+#endif // WIN32
+const char *Fl_File_Chooser::manage_favorites_label = "Manage Favorites";
+const char *Fl_File_Chooser::new_directory_label = "New Directory?";
+const char *Fl_File_Chooser::new_directory_tooltip = "Create a new directory.";
+const char *Fl_File_Chooser::preview_label = "Preview";
+const char *Fl_File_Chooser::save_label = "Save";
+const char *Fl_File_Chooser::show_label = "Show:";
+Fl_File_Sort_F *Fl_File_Chooser::sort = fl_numericsort;
+
+
+//
+// Local functions...
+//
+
+static int compare_dirnames(const char *a, const char *b);
+static void quote_pathname(char *, const char *, int);
+static void unquote_pathname(char *, const char *, int);
+
+
+//
+// 'Fl_File_Chooser::count()' - Return the number of selected files.
+//
+
+int // O - Number of selected files
+Fl_File_Chooser::count() {
+ int i; // Looping var
+ int fcount; // Number of selected files
+ const char *filename; // Filename in input field or list
+
+
+ filename = fileName->value();
+
+ if (!(type_ & MULTI)) {
+ // Check to see if the file name input field is blank...
+ if (!filename || !filename[0]) return 0;
+ else return 1;
+ }
+
+ for (i = 1, fcount = 0; i <= fileList->size(); i ++)
+ if (fileList->selected(i)) {
+ // See if this file is a directory...
+ // matt: why would we do that? It is perfectly legal to select multiple
+ // directories in a DIR chooser. They are visually selected and value(i)
+ // returns all of them as expected
+ //filename = (char *)fileList->text(i);
+
+ //if (filename[strlen(filename) - 1] != '/')
+ fcount ++;
+ }
+
+ if (fcount) return fcount;
+ else if (!filename || !filename[0]) return 0;
+ else return 1;
+}
+
+
+//
+// 'Fl_File_Chooser::directory()' - Set the directory in the file chooser.
+//
+
+void
+Fl_File_Chooser::directory(const char *d)// I - Directory to change to
+{
+ char *dirptr; // Pointer into directory
+
+
+// printf("Fl_File_Chooser::directory(\"%s\")\n", d == NULL ? "(null)" : d);
+
+ // NULL == current directory
+ if (d == NULL)
+ d = ".";
+
+#ifdef WIN32
+ // See if the filename contains backslashes...
+ char *slash; // Pointer to slashes
+ char fixpath[1024]; // Path with slashes converted
+ if (strchr(d, '\\')) {
+ // Convert backslashes to slashes...
+ strlcpy(fixpath, d, sizeof(fixpath));
+
+ for (slash = strchr(fixpath, '\\'); slash; slash = strchr(slash + 1, '\\'))
+ *slash = '/';
+
+ d = fixpath;
+ }
+#endif // WIN32
+
+ if (d[0] != '\0')
+ {
+ // Make the directory absolute...
+#if (defined(WIN32) && ! defined(__CYGWIN__))|| defined(__EMX__)
+ if (d[0] != '/' && d[0] != '\\' && d[1] != ':')
+#else
+ if (d[0] != '/' && d[0] != '\\')
+#endif /* WIN32 || __EMX__ */
+ fl_filename_absolute(directory_, d);
+ else
+ strlcpy(directory_, d, sizeof(directory_));
+
+ // Strip any trailing slash...
+ dirptr = directory_ + strlen(directory_) - 1;
+ if ((*dirptr == '/' || *dirptr == '\\') && dirptr > directory_)
+ *dirptr = '\0';
+
+ // See if we have a trailing .. or . in the filename...
+ dirptr = directory_ + strlen(directory_) - 3;
+ if (dirptr >= directory_ && strcmp(dirptr, "/..") == 0) {
+ // Yes, we have "..", so strip the trailing path...
+ *dirptr = '\0';
+ while (dirptr > directory_) {
+ if (*dirptr == '/') break;
+ dirptr --;
+ }
+
+ if (dirptr >= directory_ && *dirptr == '/')
+ *dirptr = '\0';
+ } else if ((dirptr + 1) >= directory_ && strcmp(dirptr + 1, "/.") == 0) {
+ // Strip trailing "."...
+ dirptr[1] = '\0';
+ }
+ }
+ else
+ directory_[0] = '\0';
+
+ if (shown()) {
+ // Rescan the directory...
+ rescan();
+ }
+}
+
+
+//
+// 'Fl_File_Chooser::favoritesButtonCB()' - Handle favorites selections.
+//
+
+void
+Fl_File_Chooser::favoritesButtonCB()
+{
+ int v; // Current selection
+ char pathname[1024], // Pathname
+ menuname[2048]; // Menu name
+
+
+ v = favoritesButton->value();
+
+ if (!v) {
+ // Add current directory to favorites...
+ if (getenv("HOME")) v = favoritesButton->size() - 5;
+ else v = favoritesButton->size() - 4;
+
+ sprintf(menuname, "favorite%02d", v);
+
+ prefs_.set(menuname, directory_);
+ prefs_.flush();
+
+ quote_pathname(menuname, directory_, sizeof(menuname));
+ favoritesButton->add(menuname);
+
+ if (favoritesButton->size() > 104) {
+ ((Fl_Menu_Item *)favoritesButton->menu())[0].deactivate();
+ }
+ } else if (v == 1) {
+ // Manage favorites...
+ favoritesCB(0);
+ } else if (v == 2) {
+ // Filesystems/My Computer
+ directory("");
+ } else {
+ unquote_pathname(pathname, favoritesButton->text(v), sizeof(pathname));
+ directory(pathname);
+ }
+}
+
+
+//
+// 'Fl_File_Chooser::favoritesCB()' - Handle favorites dialog.
+//
+
+void
+Fl_File_Chooser::favoritesCB(Fl_Widget *w)
+ // I - Widget
+{
+ int i; // Looping var
+ char name[32], // Preference name
+ pathname[1024]; // Directory in list
+
+
+ if (!w) {
+ // Load the favorites list...
+ favList->clear();
+ favList->deselect();
+
+ for (i = 0; i < 100; i ++) {
+ // Get favorite directory 0 to 99...
+ sprintf(name, "favorite%02d", i);
+
+ prefs_.get(name, pathname, "", sizeof(pathname));
+
+ // Stop on the first empty favorite...
+ if (!pathname[0]) break;
+
+ // Add the favorite to the list...
+ favList->add(pathname,
+ Fl_File_Icon::find(pathname, Fl_File_Icon::DIRECTORY));
+ }
+
+ favUpButton->deactivate();
+ favDeleteButton->deactivate();
+ favDownButton->deactivate();
+ favOkButton->deactivate();
+
+ favWindow->hotspot(favList);
+ favWindow->show();
+ } else if (w == favList) {
+ i = favList->value();
+ if (i) {
+ if (i > 1) favUpButton->activate();
+ else favUpButton->deactivate();
+
+ favDeleteButton->activate();
+
+ if (i < favList->size()) favDownButton->activate();
+ else favDownButton->deactivate();
+ } else {
+ favUpButton->deactivate();
+ favDeleteButton->deactivate();
+ favDownButton->deactivate();
+ }
+ } else if (w == favUpButton) {
+ i = favList->value();
+
+ favList->insert(i - 1, favList->text(i), favList->data(i));
+ favList->remove(i + 1);
+ favList->select(i - 1);
+
+ if (i == 2) favUpButton->deactivate();
+
+ favDownButton->activate();
+
+ favOkButton->activate();
+ } else if (w == favDeleteButton) {
+ i = favList->value();
+
+ favList->remove(i);
+
+ if (i > favList->size()) i --;
+ favList->select(i);
+
+ if (i < favList->size()) favDownButton->activate();
+ else favDownButton->deactivate();
+
+ if (i > 1) favUpButton->activate();
+ else favUpButton->deactivate();
+
+ if (!i) favDeleteButton->deactivate();
+
+ favOkButton->activate();
+ } else if (w == favDownButton) {
+ i = favList->value();
+
+ favList->insert(i + 2, favList->text(i), favList->data(i));
+ favList->remove(i);
+ favList->select(i + 1);
+
+ if ((i + 1) == favList->size()) favDownButton->deactivate();
+
+ favUpButton->activate();
+
+ favOkButton->activate();
+ } else if (w == favOkButton) {
+ // Copy the new list over...
+ for (i = 0; i < favList->size(); i ++) {
+ // Set favorite directory 0 to 99...
+ sprintf(name, "favorite%02d", i);
+
+ prefs_.set(name, favList->text(i + 1));
+ }
+
+ // Clear old entries as necessary...
+ for (; i < 100; i ++) {
+ // Clear favorite directory 0 to 99...
+ sprintf(name, "favorite%02d", i);
+
+ prefs_.get(name, pathname, "", sizeof(pathname));
+
+ if (pathname[0]) prefs_.set(name, "");
+ else break;
+ }
+
+ update_favorites();
+ prefs_.flush();
+
+ favWindow->hide();
+ }
+}
+
+
+//
+// 'Fl_File_Chooser::fileListCB()' - Handle clicks (and double-clicks) in the
+// Fl_File_Browser.
+//
+
+void
+Fl_File_Chooser::fileListCB()
+{
+ char *filename, // New filename
+ pathname[1024]; // Full pathname to file
+
+
+ filename = (char *)fileList->text(fileList->value());
+ if (!filename)
+ return;
+
+ if (!directory_[0]) {
+ strlcpy(pathname, filename, sizeof(pathname));
+ } else if (strcmp(directory_, "/") == 0) {
+ snprintf(pathname, sizeof(pathname), "/%s", filename);
+ } else {
+ snprintf(pathname, sizeof(pathname), "%s/%s", directory_, filename);
+ }
+
+ if (Fl::event_clicks()) {
+#if (defined(WIN32) && ! defined(__CYGWIN__)) || defined(__EMX__)
+ if ((strlen(pathname) == 2 && pathname[1] == ':') ||
+ _fl_filename_isdir_quick(pathname))
+#else
+ if (_fl_filename_isdir_quick(pathname))
+#endif /* WIN32 || __EMX__ */
+ {
+ // Change directories...
+ directory(pathname);
+
+ // Reset the click count so that a click in the same spot won't
+ // be treated as a triple-click. We use a value of -1 because
+ // the next click will increment click count to 0, which is what
+ // we really want...
+ Fl::event_clicks(-1);
+ }
+ else
+ {
+ // Hide the window - picked the file...
+ window->hide();
+ }
+ }
+ else
+ {
+ // Check if the user clicks on a directory when picking files;
+ // if so, make sure only that item is selected...
+ filename = pathname + strlen(pathname) - 1;
+
+ if ((type_ & MULTI) && !(type_ & DIRECTORY)) {
+ if (*filename == '/') {
+ // Clicked on a directory, deselect everything else...
+ int i = fileList->value();
+ fileList->deselect();
+ fileList->select(i);
+ } else {
+ // Clicked on a file - see if there are other directories selected...
+ int i;
+ const char *temp;
+ for (i = 1; i <= fileList->size(); i ++) {
+ if (i != fileList->value() && fileList->selected(i)) {
+ temp = fileList->text(i);
+ temp += strlen(temp) - 1;
+ if (*temp == '/') break; // Yes, selected directory
+ }
+ }
+
+ if (i <= fileList->size()) {
+ i = fileList->value();
+ fileList->deselect();
+ fileList->select(i);
+ }
+ }
+ }
+ // Strip any trailing slash from the directory name...
+ if (*filename == '/') *filename = '\0';
+
+// puts("Setting fileName from fileListCB...");
+ fileName->value(pathname);
+
+ // Update the preview box...
+ Fl::remove_timeout((Fl_Timeout_Handler)previewCB, this);
+ Fl::add_timeout(1.0, (Fl_Timeout_Handler)previewCB, this);
+
+ // Do any callback that is registered...
+ if (callback_) (*callback_)(this, data_);
+
+ // Activate the OK button as needed...
+ if (!_fl_filename_isdir_quick(pathname) || (type_ & DIRECTORY))
+ okButton->activate();
+ else
+ okButton->deactivate();
+ }
+}
+
+
+//
+// 'Fl_File_Chooser::fileNameCB()' - Handle text entry in the FileBrowser.
+//
+
+void
+Fl_File_Chooser::fileNameCB()
+{
+ char *filename, // New filename
+ *slash, // Pointer to trailing slash
+ pathname[1024], // Full pathname to file
+ matchname[256]; // Matching filename
+ int i, // Looping var
+ min_match, // Minimum number of matching chars
+ max_match, // Maximum number of matching chars
+ num_files, // Number of files in directory
+ first_line; // First matching line
+ const char *file; // File from directory
+
+// puts("fileNameCB()");
+// printf("Event: %s\n", fl_eventnames[Fl::event()]);
+
+ // Get the filename from the text field...
+ filename = (char *)fileName->value();
+
+ if (!filename || !filename[0]) {
+ okButton->deactivate();
+ return;
+ }
+
+ // Expand ~ and $ variables as needed...
+ if (strchr(filename, '~') || strchr(filename, '$')) {
+ fl_filename_expand(pathname, sizeof(pathname), filename);
+ filename = pathname;
+ value(pathname);
+ }
+
+ // Make sure we have an absolute path...
+#if (defined(WIN32) && !defined(__CYGWIN__)) || defined(__EMX__)
+ if (directory_[0] != '\0' && filename[0] != '/' &&
+ filename[0] != '\\' &&
+ !(isalpha(filename[0] & 255) && (!filename[1] || filename[1] == ':'))) {
+#else
+ if (directory_[0] != '\0' && filename[0] != '/') {
+#endif /* WIN32 || __EMX__ */
+ fl_filename_absolute(pathname, sizeof(pathname), filename);
+ value(pathname);
+ fileName->mark(fileName->position()); // no selection after expansion
+ } else if (filename != pathname) {
+ // Finally, make sure that we have a writable copy...
+ strlcpy(pathname, filename, sizeof(pathname));
+ }
+
+ filename = pathname;
+
+ // Now process things according to the key pressed...
+ if (Fl::event_key() == FL_Enter || Fl::event_key() == FL_KP_Enter) {
+ // Enter pressed - select or change directory...
+#if (defined(WIN32) && ! defined(__CYGWIN__)) || defined(__EMX__)
+ if ((isalpha(pathname[0] & 255) && pathname[1] == ':' && !pathname[2]) ||
+ _fl_filename_isdir_quick(pathname) &&
+ compare_dirnames(pathname, directory_)) {
+#else
+ if (_fl_filename_isdir_quick(pathname) &&
+ compare_dirnames(pathname, directory_)) {
+#endif /* WIN32 || __EMX__ */
+ directory(pathname);
+ } else if ((type_ & CREATE) || access(pathname, 0) == 0) {
+ if (!_fl_filename_isdir_quick(pathname) || (type_ & DIRECTORY)) {
+ // Update the preview box...
+ update_preview();
+
+ // Do any callback that is registered...
+ if (callback_) (*callback_)(this, data_);
+
+ // Hide the window to signal things are done...
+ window->hide();
+ }
+ } else {
+ // File doesn't exist, so beep at and alert the user...
+ fl_alert(existing_file_label);
+ }
+ }
+ else if (Fl::event_key() != FL_Delete &&
+ Fl::event_key() != FL_BackSpace) {
+ // Check to see if the user has entered a directory...
+ if ((slash = strrchr(pathname, '/')) == NULL)
+ slash = strrchr(pathname, '\\');
+
+ if (!slash) return;
+
+ // Yes, change directories if necessary...
+ *slash++ = '\0';
+ filename = slash;
+
+#if defined(WIN32) || defined(__EMX__)
+ if (strcasecmp(pathname, directory_) &&
+ (pathname[0] || strcasecmp("/", directory_))) {
+#else
+ if (strcmp(pathname, directory_) &&
+ (pathname[0] || strcasecmp("/", directory_))) {
+#endif // WIN32 || __EMX__
+ int p = fileName->position();
+ int m = fileName->mark();
+
+ directory(pathname);
+
+ if (filename[0]) {
+ char tempname[1024];
+
+ snprintf(tempname, sizeof(tempname), "%s/%s", directory_, filename);
+ fileName->value(tempname);
+ strlcpy(pathname, tempname, sizeof(pathname));
+ }
+
+ fileName->position(p, m);
+ }
+
+ // Other key pressed - do filename completion as possible...
+ num_files = fileList->size();
+ min_match = strlen(filename);
+ max_match = min_match + 1;
+ first_line = 0;
+
+ for (i = 1; i <= num_files && max_match > min_match; i ++) {
+ file = fileList->text(i);
+
+#if (defined(WIN32) && ! defined(__CYGWIN__)) || defined(__EMX__)
+ if (strncasecmp(filename, file, min_match) == 0) {
+#else
+ if (strncmp(filename, file, min_match) == 0) {
+#endif // WIN32 || __EMX__
+ // OK, this one matches; check against the previous match
+ if (!first_line) {
+ // First match; copy stuff over...
+ strlcpy(matchname, file, sizeof(matchname));
+ max_match = strlen(matchname);
+
+ // Strip trailing /, if any...
+ if (matchname[max_match - 1] == '/') {
+ max_match --;
+ matchname[max_match] = '\0';
+ }
+
+ // And then make sure that the item is visible
+ fileList->topline(i);
+ first_line = i;
+ } else {
+ // Succeeding match; compare to find maximum string match...
+ while (max_match > min_match)
+#if (defined(WIN32) && ! defined(__CYGWIN__)) || defined(__EMX__)
+ if (strncasecmp(file, matchname, max_match) == 0)
+#else
+ if (strncmp(file, matchname, max_match) == 0)
+#endif // WIN32 || __EMX__
+ break;
+ else
+ max_match --;
+
+ // Truncate the string as needed...
+ matchname[max_match] = '\0';
+ }
+ }
+ }
+
+ // If we have any matches, add them to the input field...
+ if (first_line > 0 && min_match == max_match &&
+ max_match == (int)strlen(fileList->text(first_line))) {
+ // This is the only possible match...
+ fileList->deselect(0);
+ fileList->select(first_line);
+ fileList->redraw();
+ } else if (max_match > min_match && first_line) {
+ // Add the matching portion...
+ fileName->replace(filename - pathname, filename - pathname + min_match,
+ matchname);
+
+ // Highlight it with the cursor at the end of the selection so
+ // s/he can press the right arrow to accept the selection
+ // (Tab and End also do this for both cases.)
+ fileName->position(filename - pathname + max_match,
+ filename - pathname + min_match);
+ } else if (max_match == 0) {
+ fileList->deselect(0);
+ fileList->redraw();
+ }
+
+ // See if we need to enable the OK button...
+ if (((type_ & CREATE) || !access(fileName->value(), 0)) &&
+ (!fl_filename_isdir(fileName->value()) || (type_ & DIRECTORY))) {
+ okButton->activate();
+ } else {
+ okButton->deactivate();
+ }
+ } else {
+ // FL_Delete or FL_BackSpace
+ fileList->deselect(0);
+ fileList->redraw();
+ if (((type_ & CREATE) || !access(fileName->value(), 0)) &&
+ (!fl_filename_isdir(fileName->value()) || (type_ & DIRECTORY))) {
+ okButton->activate();
+ } else {
+ okButton->deactivate();
+ }
+ }
+}
+
+
+//
+// 'Fl_File_Chooser::filter()' - Set the filter(s) for the chooser.
+//
+
+void
+Fl_File_Chooser::filter(const char *p) // I - Pattern(s)
+{
+ char *copyp, // Copy of pattern
+ *start, // Start of pattern
+ *end; // End of pattern
+ int allfiles; // Do we have a "*" pattern?
+ char temp[1024]; // Temporary pattern string
+
+
+ // Make sure we have a pattern...
+ if (!p || !*p) p = "*";
+
+ // Copy the pattern string...
+ copyp = strdup(p);
+
+ // Separate the pattern string as necessary...
+ showChoice->clear();
+
+ for (start = copyp, allfiles = 0; start && *start; start = end) {
+ end = strchr(start, '\t');
+ if (end) *end++ = '\0';
+
+ if (strcmp(start, "*") == 0) {
+ showChoice->add(all_files_label);
+ allfiles = 1;
+ } else {
+ quote_pathname(temp, start, sizeof(temp));
+ showChoice->add(temp);
+ if (strstr(start, "(*)") != NULL) allfiles = 1;
+ }
+ }
+
+ free(copyp);
+
+ if (!allfiles) showChoice->add(all_files_label);
+
+ showChoice->add(custom_filter_label);
+
+ showChoice->value(0);
+ showChoiceCB();
+}
+
+
+//
+// 'Fl_File_Chooser::newdir()' - Make a new directory.
+//
+
+void
+Fl_File_Chooser::newdir()
+{
+ const char *dir; // New directory name
+ char pathname[1024]; // Full path of directory
+
+
+ // Get a directory name from the user
+ if ((dir = fl_input(new_directory_label, NULL)) == NULL)
+ return;
+
+ // Make it relative to the current directory as needed...
+#if (defined(WIN32) && ! defined (__CYGWIN__)) || defined(__EMX__)
+ if (dir[0] != '/' && dir[0] != '\\' && dir[1] != ':')
+#else
+ if (dir[0] != '/' && dir[0] != '\\')
+#endif /* WIN32 || __EMX__ */
+ snprintf(pathname, sizeof(pathname), "%s/%s", directory_, dir);
+ else
+ strlcpy(pathname, dir, sizeof(pathname));
+
+ // Create the directory; ignore EEXIST errors...
+#if defined(WIN32) && ! defined (__CYGWIN__)
+ if (mkdir(pathname))
+#else
+ if (mkdir(pathname, 0777))
+#endif /* WIN32 */
+ if (errno != EEXIST)
+ {
+ fl_alert("%s", strerror(errno));
+ return;
+ }
+
+ // Show the new directory...
+ directory(pathname);
+}
+
+
+//
+// 'Fl_File_Chooser::preview()' - Enable or disable the preview tile.
+//
+
+void
+Fl_File_Chooser::preview(int e)// I - 1 = enable preview, 0 = disable preview
+{
+ previewButton->value(e);
+ prefs_.set("preview", e);
+ prefs_.flush();
+
+ Fl_Group *p = previewBox->parent();
+ if (e) {
+ int w = p->w() * 2 / 3;
+ fileList->resize(fileList->x(), fileList->y(),
+ w, fileList->h());
+ previewBox->resize(fileList->x()+w, previewBox->y(),
+ p->w()-w, previewBox->h());
+ previewBox->show();
+ update_preview();
+ } else {
+ fileList->resize(fileList->x(), fileList->y(),
+ p->w(), fileList->h());
+ previewBox->resize(p->x()+p->w(), previewBox->y(),
+ 0, previewBox->h());
+ previewBox->hide();
+ }
+ p->init_sizes();
+
+ fileList->parent()->redraw();
+}
+
+
+//
+// 'Fl_File_Chooser::previewCB()' - Timeout handler for the preview box.
+//
+
+void
+Fl_File_Chooser::previewCB(Fl_File_Chooser *fc) { // I - File chooser
+ fc->update_preview();
+}
+
+
+//
+// 'Fl_File_Chooser::rescan()' - Rescan the current directory.
+//
+
+void
+Fl_File_Chooser::rescan()
+{
+ char pathname[1024]; // New pathname for filename field
+
+
+ // Clear the current filename
+ strlcpy(pathname, directory_, sizeof(pathname));
+ if (pathname[0] && pathname[strlen(pathname) - 1] != '/') {
+ strlcat(pathname, "/", sizeof(pathname));
+ }
+// puts("Setting fileName in rescan()");
+ fileName->value(pathname);
+
+ if (type_ & DIRECTORY)
+ okButton->activate();
+ else
+ okButton->deactivate();
+
+ // Build the file list...
+ fileList->load(directory_, sort);
+
+ // Update the preview box...
+ update_preview();
+}
+
+//
+// 'Fl_File_Chooser::rescan_keep_filename()' - Rescan the current directory
+// without clearing the filename, then select the file if it is in the list
+//
+
+void
+Fl_File_Chooser::rescan_keep_filename()
+{
+ // if no filename was set, this is likely a diretory browser
+ const char *fn = fileName->value();
+ if (!fn || !*fn || fn[strlen(fn) - 1]=='/') {
+ rescan();
+ return;
+ }
+
+ int i;
+ char pathname[1024]; // New pathname for filename field
+ strlcpy(pathname, fn, sizeof(pathname));
+
+ // Build the file list...
+ fileList->load(directory_, sort);
+
+ // Update the preview box...
+ update_preview();
+
+ // and select the chosen file
+ char found = 0;
+ char *slash = strrchr(pathname, '/');
+ if (slash)
+ slash++;
+ else
+ slash = pathname;
+ for (i = 1; i <= fileList->size(); i ++)
+#if defined(WIN32) || defined(__EMX__)
+ if (strcasecmp(fileList->text(i), slash) == 0) {
+#else
+ if (strcmp(fileList->text(i), slash) == 0) {
+#endif // WIN32 || __EMX__
+ fileList->topline(i);
+ fileList->select(i);
+ found = 1;
+ break;
+ }
+
+ // update OK button activity
+ if (found || type_ & CREATE)
+ okButton->activate();
+ else
+ okButton->deactivate();
+}
+
+
+//
+// 'Fl_File_Chooser::showChoiceCB()' - Handle show selections.
+//
+
+void
+Fl_File_Chooser::showChoiceCB()
+{
+ const char *item, // Selected item
+ *patstart; // Start of pattern
+ char *patend; // End of pattern
+ char temp[1024]; // Temporary string for pattern
+
+
+ item = showChoice->text(showChoice->value());
+
+ if (strcmp(item, custom_filter_label) == 0) {
+ if ((item = fl_input(custom_filter_label, pattern_)) != NULL) {
+ strlcpy(pattern_, item, sizeof(pattern_));
+
+ quote_pathname(temp, item, sizeof(temp));
+ showChoice->add(temp);
+ showChoice->value(showChoice->size() - 2);
+ }
+ } else if ((patstart = strchr(item, '(')) == NULL) {
+ strlcpy(pattern_, item, sizeof(pattern_));
+ } else {
+ strlcpy(pattern_, patstart + 1, sizeof(pattern_));
+ if ((patend = strrchr(pattern_, ')')) != NULL) *patend = '\0';
+ }
+
+ fileList->filter(pattern_);
+
+ if (shown()) {
+ // Rescan the directory...
+ rescan_keep_filename();
+ }
+}
+
+
+//
+// 'Fl_File_Chooser::update_favorites()' - Update the favorites menu.
+//
+
+void
+Fl_File_Chooser::update_favorites()
+{
+ int i; // Looping var
+ char pathname[1024], // Pathname
+ menuname[2048]; // Menu name
+ const char *home; // Home directory
+
+
+ favoritesButton->clear();
+ favoritesButton->add("bla");
+ favoritesButton->clear();
+ favoritesButton->add(add_favorites_label, FL_ALT + 'a', 0);
+ favoritesButton->add(manage_favorites_label, FL_ALT + 'm', 0, 0, FL_MENU_DIVIDER);
+ favoritesButton->add(filesystems_label, FL_ALT + 'f', 0);
+
+ if ((home = getenv("HOME")) != NULL) {
+ quote_pathname(menuname, home, sizeof(menuname));
+ favoritesButton->add(menuname, FL_ALT + 'h', 0);
+ }
+
+ for (i = 0; i < 100; i ++) {
+ sprintf(menuname, "favorite%02d", i);
+ prefs_.get(menuname, pathname, "", sizeof(pathname));
+ if (!pathname[0]) break;
+
+ quote_pathname(menuname, pathname, sizeof(menuname));
+
+ if (i < 10) favoritesButton->add(menuname, FL_ALT + '0' + i, 0);
+ else favoritesButton->add(menuname);
+ }
+
+ if (i == 100) ((Fl_Menu_Item *)favoritesButton->menu())[0].deactivate();
+}
+
+
+//
+// 'Fl_File_Chooser::update_preview()' - Update the preview box...
+//
+
+void
+Fl_File_Chooser::update_preview()
+{
+ const char *filename; // Current filename
+ Fl_Shared_Image *image, // New image
+ *oldimage; // Old image
+ int pbw, pbh; // Width and height of preview box
+ int w, h; // Width and height of preview image
+
+
+ if (!previewButton->value()) return;
+
+ if ((filename = value()) == NULL || fl_filename_isdir(filename)) image = NULL;
+ else {
+ window->cursor(FL_CURSOR_WAIT);
+ Fl::check();
+
+ image = Fl_Shared_Image::get(filename);
+
+ if (image) {
+ window->cursor(FL_CURSOR_DEFAULT);
+ Fl::check();
+ }
+ }
+
+ oldimage = (Fl_Shared_Image *)previewBox->image();
+
+ if (oldimage) oldimage->release();
+
+ previewBox->image(0);
+
+ if (!image) {
+ FILE *fp;
+ int bytes;
+ char *ptr;
+
+ if (filename) fp = fopen(filename, "rb");
+ else fp = NULL;
+
+ if (fp != NULL) {
+ // Try reading the first 1k of data for a label...
+ bytes = fread(preview_text_, 1, sizeof(preview_text_) - 1, fp);
+ preview_text_[bytes] = '\0';
+ fclose(fp);
+ } else {
+ // Assume we can't read any data...
+ preview_text_[0] = '\0';
+ }
+
+ window->cursor(FL_CURSOR_DEFAULT);
+ Fl::check();
+
+ // Scan the buffer for printable chars...
+ for (ptr = preview_text_;
+ *ptr && (isprint(*ptr & 255) || isspace(*ptr & 255));
+ ptr ++);
+
+ if (*ptr || ptr == preview_text_) {
+ // Non-printable file, just show a big ?...
+ previewBox->label(filename ? "?" : 0);
+ previewBox->align(FL_ALIGN_CLIP);
+ previewBox->labelsize(100);
+ previewBox->labelfont(FL_HELVETICA);
+ } else {
+ // Show the first 1k of text...
+ int size = previewBox->h() / 20;
+ if (size < 6) size = 6;
+ else if (size > 14) size = 14;
+
+ previewBox->label(preview_text_);
+ previewBox->align((Fl_Align)(FL_ALIGN_CLIP | FL_ALIGN_INSIDE |
+ FL_ALIGN_LEFT | FL_ALIGN_TOP));
+ previewBox->labelsize((uchar)size);
+ previewBox->labelfont(FL_COURIER);
+ }
+ } else {
+ pbw = previewBox->w() - 20;
+ pbh = previewBox->h() - 20;
+
+ if (image->w() > pbw || image->h() > pbh) {
+ w = pbw;
+ h = w * image->h() / image->w();
+
+ if (h > pbh) {
+ h = pbh;
+ w = h * image->w() / image->h();
+ }
+
+ oldimage = (Fl_Shared_Image *)image->copy(w, h);
+ previewBox->image((Fl_Image *)oldimage);
+
+ image->release();
+ } else {
+ previewBox->image((Fl_Image *)image);
+ }
+
+ previewBox->align(FL_ALIGN_CLIP);
+ previewBox->label(0);
+ }
+
+ previewBox->redraw();
+}
+
+
+//
+// 'Fl_File_Chooser::value()' - Return a selected filename.
+//
+
+const char * // O - Filename or NULL
+Fl_File_Chooser::value(int f) // I - File number
+{
+ int i; // Looping var
+ int fcount; // Number of selected files
+ const char *name; // Current filename
+ static char pathname[1024]; // Filename + directory
+
+
+ name = fileName->value();
+
+ if (!(type_ & MULTI)) {
+ // Return the filename in the filename field...
+ if (!name || !name[0]) return NULL;
+ else return name;
+ }
+
+ // Return a filename from the list...
+ for (i = 1, fcount = 0; i <= fileList->size(); i ++)
+ if (fileList->selected(i)) {
+ // See if this file is a selected file/directory...
+ name = fileList->text(i);
+
+ fcount ++;
+
+ if (fcount == f) {
+ if (directory_[0]) {
+ snprintf(pathname, sizeof(pathname), "%s/%s", directory_, name);
+ } else {
+ strlcpy(pathname, name, sizeof(pathname));
+ }
+
+ return pathname;
+ }
+ }
+
+ // If nothing is selected, use the filename field...
+ if (!name || !name[0]) return NULL;
+ else return name;
+}
+
+
+//
+// 'Fl_File_Chooser::value()' - Set the current filename.
+//
+
+void
+Fl_File_Chooser::value(const char *filename)
+ // I - Filename + directory
+{
+ int i, // Looping var
+ fcount; // Number of items in list
+ char *slash; // Directory separator
+ char pathname[1024]; // Local copy of filename
+
+
+// printf("Fl_File_Chooser::value(\"%s\")\n", filename == NULL ? "(null)" : filename);
+
+ // See if the filename is the "My System" directory...
+ if (filename == NULL || !filename[0]) {
+ // Yes, just change the current directory...
+ directory(filename);
+ fileName->value("");
+ okButton->deactivate();
+ return;
+ }
+
+#ifdef WIN32
+ // See if the filename contains backslashes...
+ char fixpath[1024]; // Path with slashes converted
+ if (strchr(filename, '\\')) {
+ // Convert backslashes to slashes...
+ strlcpy(fixpath, filename, sizeof(fixpath));
+
+ for (slash = strchr(fixpath, '\\'); slash; slash = strchr(slash + 1, '\\'))
+ *slash = '/';
+
+ filename = fixpath;
+ }
+#endif // WIN32
+
+ // See if there is a directory in there...
+ fl_filename_absolute(pathname, sizeof(pathname), filename);
+
+ if ((slash = strrchr(pathname, '/')) != NULL) {
+ // Yes, change the display to the directory...
+ if (!fl_filename_isdir(pathname)) *slash++ = '\0';
+
+ directory(pathname);
+ if (*slash == '/') slash = pathname;
+ } else {
+ directory(".");
+ slash = pathname;
+ }
+
+ // Set the input field to the absolute path...
+ if (slash > pathname) slash[-1] = '/';
+
+ fileName->value(pathname);
+ fileName->position(0, strlen(pathname));
+ okButton->activate();
+
+ // Then find the file in the file list and select it...
+ fcount = fileList->size();
+
+ fileList->deselect(0);
+ fileList->redraw();
+
+ for (i = 1; i <= fcount; i ++)
+#if defined(WIN32) || defined(__EMX__)
+ if (strcasecmp(fileList->text(i), slash) == 0) {
+#else
+ if (strcmp(fileList->text(i), slash) == 0) {
+#endif // WIN32 || __EMX__
+// printf("Selecting line %d...\n", i);
+ fileList->topline(i);
+ fileList->select(i);
+ break;
+ }
+}
+
+
+//
+// 'compare_dirnames()' - Compare two directory names.
+//
+
+static int
+compare_dirnames(const char *a, const char *b) {
+ int alen, blen;
+
+ // Get length of each string...
+ alen = strlen(a) - 1;
+ blen = strlen(b) - 1;
+
+ if (alen < 0 || blen < 0) return alen - blen;
+
+ // Check for trailing slashes...
+ if (a[alen] != '/') alen ++;
+ if (b[blen] != '/') blen ++;
+
+ // If the lengths aren't the same, then return the difference...
+ if (alen != blen) return alen - blen;
+
+ // Do a comparison of the first N chars (alen == blen at this point)...
+#ifdef WIN32
+ return strncasecmp(a, b, alen);
+#else
+ return strncmp(a, b, alen);
+#endif // WIN32
+}
+
+
+//
+// 'quote_pathname()' - Quote a pathname for a menu.
+//
+
+static void
+quote_pathname(char *dst, // O - Destination string
+ const char *src, // I - Source string
+ int dstsize) // I - Size of destination string
+{
+ dstsize --;
+
+ while (*src && dstsize > 1) {
+ if (*src == '\\') {
+ // Convert backslash to forward slash...
+ *dst++ = '\\';
+ *dst++ = '/';
+ src ++;
+ } else {
+ if (*src == '/') *dst++ = '\\';
+
+ *dst++ = *src++;
+ }
+ }
+
+ *dst = '\0';
+}
+
+
+//
+// 'unquote_pathname()' - Unquote a pathname from a menu.
+//
+
+static void
+unquote_pathname(char *dst, // O - Destination string
+ const char *src, // I - Source string
+ int dstsize) // I - Size of destination string
+{
+ dstsize --;
+
+ while (*src && dstsize > 1) {
+ if (*src == '\\') src ++;
+ *dst++ = *src++;
+ }
+
+ *dst = '\0';
+}
+
+
+//
+// End of "$Id: Fl_File_Chooser2.cxx 6092 2008-04-11 12:57:37Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_File_Icon.cxx b/third_party/windows/fltk-1.1.10/src/Fl_File_Icon.cxx new file mode 100644 index 0000000..853b22e --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_File_Icon.cxx @@ -0,0 +1,485 @@ +//
+// "$Id: Fl_File_Icon.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Fl_File_Icon routines.
+//
+// KDE icon code donated by Maarten De Boer.
+//
+// Copyright 1999-2005 by Michael Sweet.
+//
+// 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
+//
+// Contents:
+//
+// Fl_File_Icon::Fl_File_Icon() - Create a new file icon.
+// Fl_File_Icon::~Fl_File_Icon() - Remove a file icon.
+// Fl_File_Icon::add() - Add data to an icon.
+// Fl_File_Icon::find() - Find an icon based upon a given file.
+// Fl_File_Icon::draw() - Draw an icon.
+// Fl_File_Icon::label() - Set the widgets label to an icon.
+// Fl_File_Icon::labeltype() - Draw the icon label.
+//
+
+//
+// Include necessary header files...
+//
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "flstring.h"
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#if (defined(WIN32) && ! defined(__CYGWIN__)) || defined(__EMX__)
+# include <io.h>
+# define F_OK 0
+#else
+# include <unistd.h>
+#endif /* WIN32 || __EMX__ */
+
+#include <FL/Fl_File_Icon.H>
+#include <FL/Fl_Widget.H>
+#include <FL/fl_draw.H>
+#include <FL/filename.H>
+
+
+//
+// Define missing POSIX/XPG4 macros as needed...
+//
+
+#ifndef S_ISDIR
+# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
+# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+#endif /* !S_ISDIR */
+
+
+//
+// Icon cache...
+//
+
+Fl_File_Icon *Fl_File_Icon::first_ = (Fl_File_Icon *)0;
+
+
+//
+// 'Fl_File_Icon::Fl_File_Icon()' - Create a new file icon.
+//
+
+Fl_File_Icon::Fl_File_Icon(const char *p, /* I - Filename pattern */
+ int t, /* I - File type */
+ int nd, /* I - Number of data values */
+ short *d) /* I - Data values */
+{
+ // Initialize the pattern and type...
+ pattern_ = p;
+ type_ = t;
+
+ // Copy icon data as needed...
+ if (nd)
+ {
+ num_data_ = nd;
+ alloc_data_ = nd + 1;
+ data_ = (short *)calloc(sizeof(short), nd + 1);
+ memcpy(data_, d, nd * sizeof(short));
+ }
+ else
+ {
+ num_data_ = 0;
+ alloc_data_ = 0;
+ }
+
+ // And add the icon to the list of icons...
+ next_ = first_;
+ first_ = this;
+}
+
+
+//
+// 'Fl_File_Icon::~Fl_File_Icon()' - Remove a file icon.
+//
+
+Fl_File_Icon::~Fl_File_Icon()
+{
+ Fl_File_Icon *current, // Current icon in list
+ *prev; // Previous icon in list
+
+
+ // Find the icon in the list...
+ for (current = first_, prev = (Fl_File_Icon *)0;
+ current != this && current != (Fl_File_Icon *)0;
+ prev = current, current = current->next_);
+
+ // Remove the icon from the list as needed...
+ if (current)
+ {
+ if (prev)
+ prev->next_ = current->next_;
+ else
+ first_ = current->next_;
+ }
+
+ // Free any memory used...
+ if (alloc_data_)
+ free(data_);
+}
+
+
+//
+// 'Fl_File_Icon::add()' - Add data to an icon.
+//
+
+short * // O - Pointer to new data value
+Fl_File_Icon::add(short d) // I - Data to add
+{
+ short *dptr; // Pointer to new data value
+
+
+ // Allocate/reallocate memory as needed
+ if ((num_data_ + 1) >= alloc_data_)
+ {
+ alloc_data_ += 128;
+
+ if (alloc_data_ == 128)
+ dptr = (short *)malloc(sizeof(short) * alloc_data_);
+ else
+ dptr = (short *)realloc(data_, sizeof(short) * alloc_data_);
+
+ if (dptr == NULL)
+ return (NULL);
+
+ data_ = dptr;
+ }
+
+ // Store the new data value and return
+ data_[num_data_++] = d;
+ data_[num_data_] = END;
+
+ return (data_ + num_data_ - 1);
+}
+
+
+//
+// 'Fl_File_Icon::find()' - Find an icon based upon a given file.
+//
+
+Fl_File_Icon * // O - Matching file icon or NULL
+Fl_File_Icon::find(const char *filename,// I - Name of file */
+ int filetype) // I - Enumerated file type
+{
+ Fl_File_Icon *current; // Current file in list
+#ifndef WIN32
+ struct stat fileinfo; // Information on file
+#endif // !WIN32
+ const char *name; // Base name of filename
+
+
+ // Get file information if needed...
+ if (filetype == ANY)
+ {
+#ifdef WIN32
+ if (filename[strlen(filename) - 1] == '/')
+ filetype = DIRECTORY;
+ else if (fl_filename_isdir(filename))
+ filetype = DIRECTORY;
+ else
+ filetype = PLAIN;
+#else
+ if (!stat(filename, &fileinfo))
+ {
+ if (S_ISDIR(fileinfo.st_mode))
+ filetype = DIRECTORY;
+# ifdef S_IFIFO
+ else if (S_ISFIFO(fileinfo.st_mode))
+ filetype = FIFO;
+# endif // S_IFIFO
+# if defined(S_ICHR) && defined(S_IBLK)
+ else if (S_ISCHR(fileinfo.st_mode) || S_ISBLK(fileinfo.st_mode))
+ filetype = DEVICE;
+# endif // S_ICHR && S_IBLK
+# ifdef S_ILNK
+ else if (S_ISLNK(fileinfo.st_mode))
+ filetype = LINK;
+# endif // S_ILNK
+ else
+ filetype = PLAIN;
+ }
+ else
+ filetype = PLAIN;
+#endif // WIN32
+ }
+
+ // Look at the base name in the filename
+ name = fl_filename_name(filename);
+
+ // Loop through the available file types and return any match that
+ // is found...
+ for (current = first_; current != (Fl_File_Icon *)0; current = current->next_)
+ if ((current->type_ == filetype || current->type_ == ANY) &&
+ (fl_filename_match(filename, current->pattern_) ||
+ fl_filename_match(name, current->pattern_)))
+ break;
+
+ // Return the match (if any)...
+ return (current);
+}
+
+
+//
+// 'Fl_File_Icon::draw()' - Draw an icon.
+//
+
+void
+Fl_File_Icon::draw(int x, // I - Upper-lefthand X
+ int y, // I - Upper-lefthand Y
+ int w, // I - Width of bounding box
+ int h, // I - Height of bounding box
+ Fl_Color ic, // I - Icon color...
+ int active) // I - Active or inactive?
+{
+ Fl_Color c, // Current color
+ oc; // Outline color
+ short *d, // Pointer to data
+ *dend; // End of data...
+ short *prim; // Pointer to start of primitive...
+ double scale; // Scale of icon
+
+
+ // Don't try to draw a NULL array!
+ if (num_data_ == 0)
+ return;
+
+ // Setup the transform matrix as needed...
+ scale = w < h ? w : h;
+
+ fl_push_matrix();
+ fl_translate((float)x + 0.5 * ((float)w - scale),
+ (float)y + 0.5 * ((float)h + scale));
+ fl_scale(scale, -scale);
+
+ // Loop through the array until we see an unmatched END...
+ d = data_;
+ dend = data_ + num_data_;
+ prim = NULL;
+ c = ic;
+
+ if (active)
+ fl_color(c);
+ else
+ fl_color(fl_inactive(c));
+
+ while (d < dend)
+ switch (*d)
+ {
+ case END :
+ if (prim)
+ switch (*prim)
+ {
+ case LINE :
+ fl_end_line();
+ break;
+
+ case CLOSEDLINE :
+ fl_end_loop();
+ break;
+
+ case POLYGON :
+ fl_end_complex_polygon();
+ break;
+
+ case OUTLINEPOLYGON :
+ fl_end_complex_polygon();
+
+ oc = (Fl_Color)((((unsigned short *)prim)[1] << 16) |
+ ((unsigned short *)prim)[2]);
+ if (active)
+ {
+ if (oc == FL_ICON_COLOR)
+ fl_color(ic);
+ else
+ fl_color(oc);
+ }
+ else
+ {
+ if (oc == FL_ICON_COLOR)
+ fl_color(fl_inactive(ic));
+ else
+ fl_color(fl_inactive(oc));
+ }
+
+ fl_begin_loop();
+
+ prim += 3;
+ while (*prim == VERTEX)
+ {
+ fl_vertex(prim[1] * 0.0001, prim[2] * 0.0001);
+ prim += 3;
+ }
+
+ fl_end_loop();
+ fl_color(c);
+ break;
+ }
+
+ prim = NULL;
+ d ++;
+ break;
+
+ case COLOR :
+ c = (Fl_Color)((((unsigned short *)d)[1] << 16) |
+ ((unsigned short *)d)[2]);
+
+ if (c == FL_ICON_COLOR)
+ c = ic;
+
+ if (!active)
+ c = fl_inactive(c);
+
+ fl_color(c);
+ d += 3;
+ break;
+
+ case LINE :
+ prim = d;
+ d ++;
+ fl_begin_line();
+ break;
+
+ case CLOSEDLINE :
+ prim = d;
+ d ++;
+ fl_begin_loop();
+ break;
+
+ case POLYGON :
+ prim = d;
+ d ++;
+ fl_begin_complex_polygon();
+ break;
+
+ case OUTLINEPOLYGON :
+ prim = d;
+ d += 3;
+ fl_begin_complex_polygon();
+ break;
+
+ case VERTEX :
+ if (prim)
+ fl_vertex(d[1] * 0.0001, d[2] * 0.0001);
+ d += 3;
+ break;
+
+ default : // Ignore invalid data...
+ d ++;
+ }
+
+ // If we still have an open primitive, close it...
+ if (prim)
+ switch (*prim)
+ {
+ case LINE :
+ fl_end_line();
+ break;
+
+ case CLOSEDLINE :
+ fl_end_loop();
+ break;
+
+ case POLYGON :
+ fl_end_polygon();
+ break;
+
+ case OUTLINEPOLYGON :
+ fl_end_polygon();
+
+ oc = (Fl_Color)((((unsigned short *)prim)[1] << 16) |
+ ((unsigned short *)prim)[2]);
+ if (active)
+ {
+ if (oc == FL_ICON_COLOR)
+ fl_color(ic);
+ else
+ fl_color(oc);
+ }
+ else
+ {
+ if (oc == FL_ICON_COLOR)
+ fl_color(fl_inactive(ic));
+ else
+ fl_color(fl_inactive(oc));
+ }
+
+ fl_begin_loop();
+
+ prim += 3;
+ while (*prim == VERTEX)
+ {
+ fl_vertex(prim[1] * 0.0001, prim[2] * 0.0001);
+ prim += 3;
+ }
+
+ fl_end_loop();
+ fl_color(c);
+ break;
+ }
+
+ // Restore the transform matrix
+ fl_pop_matrix();
+}
+
+
+//
+// 'Fl_File_Icon::label()' - Set the widget's label to an icon.
+//
+
+void
+Fl_File_Icon::label(Fl_Widget *w) // I - Widget to label
+{
+ Fl::set_labeltype(_FL_ICON_LABEL, labeltype, 0);
+ w->label(_FL_ICON_LABEL, (const char*)this);
+}
+
+
+//
+// 'Fl_File_Icon::labeltype()' - Draw the icon label.
+//
+
+void
+Fl_File_Icon::labeltype(const Fl_Label *o, // I - Label data
+ int x, // I - X position of label
+ int y, // I - Y position of label
+ int w, // I - Width of label
+ int h, // I - Height of label
+ Fl_Align a) // I - Label alignment (not used)
+{
+ Fl_File_Icon *icon; // Pointer to icon data
+
+
+ (void)a;
+
+ icon = (Fl_File_Icon *)(o->value);
+ if (icon) icon->draw(x, y, w, h, (Fl_Color)(o->color));
+}
+
+
+//
+// End of "$Id: Fl_File_Icon.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_File_Icon2.cxx b/third_party/windows/fltk-1.1.10/src/Fl_File_Icon2.cxx new file mode 100644 index 0000000..d7b6eaf --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_File_Icon2.cxx @@ -0,0 +1,1015 @@ +//
+// "$Id: Fl_File_Icon2.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Fl_File_Icon system icon routines.
+//
+// KDE icon code donated by Maarten De Boer.
+//
+// Copyright 1999-2005 by Michael Sweet.
+//
+// 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
+//
+// Contents:
+//
+// Fl_File_Icon::load() - Load an icon file...
+// Fl_File_Icon::load_fti() - Load an SGI-format FTI file...
+// Fl_File_Icon::load_image() - Load an image icon file...
+// Fl_File_Icon::load_system_icons() - Load the standard system icons/filetypes.
+// load_kde_icons() - Load KDE icon files.
+// load_kde_mimelnk() - Load a KDE "mimelnk" file.
+// kde_to_fltk_pattern() - Convert a KDE pattern to a FLTK pattern.
+// get_kde_val() - Get a KDE value.
+//
+
+//
+// Include necessary header files...
+//
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "flstring.h"
+#include <ctype.h>
+#include <errno.h>
+#include <FL/math.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#if defined(WIN32) && !defined(__CYGWIN__)
+# include <io.h>
+# define F_OK 0
+// Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs
+// on Windows, which is supposed to be POSIX compliant...
+# define access _access
+#else
+# include <unistd.h>
+#endif // WIN32
+
+#include <FL/Fl_File_Icon.H>
+#include <FL/Fl_Shared_Image.H>
+#include <FL/Fl_Widget.H>
+#include <FL/fl_draw.H>
+#include <FL/filename.H>
+
+
+//
+// Define missing POSIX/XPG4 macros as needed...
+//
+
+#ifndef S_ISDIR
+# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
+# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+#endif /* !S_ISDIR */
+
+
+//
+// Local functions...
+//
+
+static void load_kde_icons(const char *directory, const char *icondir);
+static void load_kde_mimelnk(const char *filename, const char *icondir);
+static char *kde_to_fltk_pattern(const char *kdepattern);
+static char *get_kde_val(char *str, const char *key);
+
+
+//
+// Local globals...
+//
+
+static const char *kdedir = NULL;
+
+
+//
+// 'Fl_File_Icon::load()' - Load an icon file...
+//
+
+void
+Fl_File_Icon::load(const char *f) // I - File to read from
+{
+ int i; // Load status...
+ const char *ext; // File extension
+
+
+ ext = fl_filename_ext(f);
+
+ if (ext && strcmp(ext, ".fti") == 0)
+ i = load_fti(f);
+ else
+ i = load_image(f);
+
+ if (i)
+ {
+ Fl::warning("Fl_File_Icon::load(): Unable to load icon file \"%s\".", f);
+ return;
+ }
+}
+
+
+//
+// 'Fl_File_Icon::load_fti()' - Load an SGI-format FTI file...
+//
+
+int // O - 0 on success, non-zero on error
+Fl_File_Icon::load_fti(const char *fti) // I - File to read from
+{
+ FILE *fp; // File pointer
+ int ch; // Current character
+ char command[255], // Command string ("vertex", etc.)
+ params[255], // Parameter string ("10.0,20.0", etc.)
+ *ptr; // Pointer into strings
+ int outline; // Outline polygon
+
+
+ // Try to open the file...
+ if ((fp = fopen(fti, "rb")) == NULL)
+ {
+ Fl::error("Fl_File_Icon::load_fti(): Unable to open \"%s\" - %s",
+ fti, strerror(errno));
+ return -1;
+ }
+
+ // Read the entire file, adding data as needed...
+ outline = 0;
+
+ while ((ch = getc(fp)) != EOF)
+ {
+ // Skip whitespace
+ if (isspace(ch))
+ continue;
+
+ // Skip comments starting with "#"...
+ if (ch == '#')
+ {
+ while ((ch = getc(fp)) != EOF)
+ if (ch == '\n')
+ break;
+
+ if (ch == EOF)
+ break;
+ else
+ continue;
+ }
+
+ // OK, this character better be a letter...
+ if (!isalpha(ch))
+ {
+ Fl::error("Fl_File_Icon::load_fti(): Expected a letter at file position %ld (saw '%c')",
+ ftell(fp) - 1, ch);
+ break;
+ }
+
+ // Scan the command name...
+ ptr = command;
+ *ptr++ = ch;
+
+ while ((ch = getc(fp)) != EOF)
+ {
+ if (ch == '(')
+ break;
+ else if (ptr < (command + sizeof(command) - 1))
+ *ptr++ = ch;
+ }
+
+ *ptr++ = '\0';
+
+ // Make sure we stopped on a parenthesis...
+ if (ch != '(')
+ {
+ Fl::error("Fl_File_Icon::load_fti(): Expected a ( at file position %ld (saw '%c')",
+ ftell(fp) - 1, ch);
+ break;
+ }
+
+ // Scan the parameters...
+ ptr = params;
+
+ while ((ch = getc(fp)) != EOF)
+ {
+ if (ch == ')')
+ break;
+ else if (ptr < (params + sizeof(params) - 1))
+ *ptr++ = ch;
+ }
+
+ *ptr++ = '\0';
+
+ // Make sure we stopped on a parenthesis...
+ if (ch != ')')
+ {
+ Fl::error("Fl_File_Icon::load_fti(): Expected a ) at file position %ld (saw '%c')",
+ ftell(fp) - 1, ch);
+ break;
+ }
+
+ // Make sure the next character is a semicolon...
+ if ((ch = getc(fp)) != ';')
+ {
+ Fl::error("Fl_File_Icon::load_fti(): Expected a ; at file position %ld (saw '%c')",
+ ftell(fp) - 1, ch);
+ break;
+ }
+
+ // Now process the command...
+ if (strcmp(command, "color") == 0)
+ {
+ // Set the color; for negative colors blend the two primaries to
+ // produce a composite color. Also, the following symbolic color
+ // names are understood:
+ //
+ // name FLTK color
+ // ------------- ----------
+ // iconcolor FL_ICON_COLOR; mapped to the icon color in
+ // Fl_File_Icon::draw()
+ // shadowcolor FL_DARK3
+ // outlinecolor FL_BLACK
+ if (strcmp(params, "iconcolor") == 0)
+ add_color(FL_ICON_COLOR);
+ else if (strcmp(params, "shadowcolor") == 0)
+ add_color(FL_DARK3);
+ else if (strcmp(params, "outlinecolor") == 0)
+ add_color(FL_BLACK);
+ else
+ {
+ int c = atoi(params); // Color value
+
+
+ if (c < 0)
+ {
+ // Composite color; compute average...
+ c = -c;
+ add_color(fl_color_average((Fl_Color)(c >> 4),
+ (Fl_Color)(c & 15), 0.5f));
+ }
+ else
+ add_color((Fl_Color)c);
+ }
+ }
+ else if (strcmp(command, "bgnline") == 0)
+ add(LINE);
+ else if (strcmp(command, "bgnclosedline") == 0)
+ add(CLOSEDLINE);
+ else if (strcmp(command, "bgnpolygon") == 0)
+ add(POLYGON);
+ else if (strcmp(command, "bgnoutlinepolygon") == 0)
+ {
+ add(OUTLINEPOLYGON);
+ outline = add(0) - data_;
+ add(0);
+ }
+ else if (strcmp(command, "endoutlinepolygon") == 0 && outline)
+ {
+ unsigned cval; // Color value
+
+ // Set the outline color; see above for valid values...
+ if (strcmp(params, "iconcolor") == 0)
+ cval = FL_ICON_COLOR;
+ else if (strcmp(params, "shadowcolor") == 0)
+ cval = FL_DARK3;
+ else if (strcmp(params, "outlinecolor") == 0)
+ cval = FL_BLACK;
+ else
+ {
+ int c = atoi(params); // Color value
+
+
+ if (c < 0)
+ {
+ // Composite color; compute average...
+ c = -c;
+ cval = fl_color_average((Fl_Color)(c >> 4), (Fl_Color)(c & 15), 0.5f);
+ }
+ else
+ cval = c;
+ }
+
+ // Store outline color...
+ data_[outline] = cval >> 16;
+ data_[outline + 1] = cval;
+
+ outline = 0;
+ add(END);
+ }
+ else if (strncmp(command, "end", 3) == 0)
+ add(END);
+ else if (strcmp(command, "vertex") == 0)
+ {
+ float x, y; // Coordinates of vertex
+
+
+ if (sscanf(params, "%f,%f", &x, &y) != 2)
+ break;
+
+ add_vertex((short)(int)rint(x * 100.0), (short)(int)rint(y * 100.0));
+ }
+ else
+ {
+ Fl::error("Fl_File_Icon::load_fti(): Unknown command \"%s\" at file position %ld.",
+ command, ftell(fp) - 1);
+ break;
+ }
+ }
+
+ // Close the file and return...
+ fclose(fp);
+
+#ifdef DEBUG
+ printf("Icon File \"%s\":\n", fti);
+ for (int i = 0; i < num_data_; i ++)
+ printf(" %d,\n", data_[i]);
+#endif /* DEBUG */
+
+ return 0;
+}
+
+
+//
+// 'Fl_File_Icon::load_image()' - Load an image icon file...
+//
+
+int // O - 0 on success, non-0 on error
+Fl_File_Icon::load_image(const char *ifile) // I - File to read from
+{
+ Fl_Shared_Image *img; // Image file
+
+
+ img = Fl_Shared_Image::get(ifile);
+ if (!img || !img->count() || !img->w() || !img->h()) return -1;
+
+ if (img->count() == 1) {
+ int x, y; // X & Y in image
+ int startx; // Starting X coord
+ Fl_Color c, // Current color
+ temp; // Temporary color
+ const uchar *row; // Pointer into image
+
+
+ // Loop through grayscale or RGB image...
+ for (y = 0, row = (const uchar *)(*(img->data())); y < img->h(); y ++, row += img->ld())
+ {
+ for (x = 0, startx = 0, c = (Fl_Color)-1;
+ x < img->w();
+ x ++, row += img->d())
+ {
+ switch (img->d())
+ {
+ case 1 :
+ temp = fl_rgb_color(row[0], row[0], row[0]);
+ break;
+ case 2 :
+ if (row[1] > 127)
+ temp = fl_rgb_color(row[0], row[0], row[0]);
+ else
+ temp = (Fl_Color)-1;
+ break;
+ case 3 :
+ temp = fl_rgb_color(row[0], row[1], row[2]);
+ break;
+ default :
+ if (row[3] > 127)
+ temp = fl_rgb_color(row[0], row[1], row[2]);
+ else
+ temp = (Fl_Color)-1;
+ break;
+ }
+
+ if (temp != c)
+ {
+ if (x > startx && c != (Fl_Color)-1)
+ {
+ add_color(c);
+ add(POLYGON);
+ add_vertex(startx * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h());
+ add_vertex(x * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h());
+ add_vertex(x * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h());
+ add_vertex(startx * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h());
+ add(END);
+ }
+
+ c = temp;
+ startx = x;
+ }
+ }
+
+ if (x > startx && c != (Fl_Color)-1)
+ {
+ add_color(c);
+ add(POLYGON);
+ add_vertex(startx * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h());
+ add_vertex(x * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h());
+ add_vertex(x * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h());
+ add_vertex(startx * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h());
+ add(END);
+ }
+ }
+ } else {
+ int i, j; // Looping vars
+ int ch; // Current character
+ int newch; // New character
+ int bg; // Background color
+ char val[16]; // Color value
+ const char *lineptr, // Pointer into line
+ *const*ptr; // Pointer into data array
+ int ncolors, // Number of colors
+ chars_per_color; // Characters per color
+ Fl_Color *colors; // Colors
+ int red, green, blue; // Red, green, and blue values
+ int x, y; // X & Y in image
+ int startx; // Starting X coord
+
+
+ // Get the pixmap data...
+ ptr = img->data();
+ sscanf(*ptr, "%*d%*d%d%d", &ncolors, &chars_per_color);
+
+ colors = new Fl_Color[1 << (chars_per_color * 8)];
+
+ // Read the colormap...
+ memset(colors, 0, sizeof(Fl_Color) << (chars_per_color * 8));
+ bg = ' ';
+
+ ptr ++;
+
+ if (ncolors < 0) {
+ // Read compressed colormap...
+ const uchar *cmapptr;
+
+ ncolors = -ncolors;
+
+ for (i = 0, cmapptr = (const uchar *)*ptr; i < ncolors; i ++, cmapptr += 4)
+ colors[cmapptr[0]] = fl_rgb_color(cmapptr[1], cmapptr[2], cmapptr[3]);
+
+ ptr ++;
+ } else {
+ for (i = 0; i < ncolors; i ++, ptr ++) {
+ // Get the color's character
+ lineptr = *ptr;
+ ch = *lineptr++;
+
+ if (chars_per_color > 1) ch = (ch << 8) | *lineptr++;
+
+ // Get the color value...
+ if ((lineptr = strstr(lineptr, "c ")) == NULL) {
+ // No color; make this black...
+ colors[ch] = FL_BLACK;
+ } else if (lineptr[2] == '#') {
+ // Read the RGB triplet...
+ lineptr += 3;
+ for (j = 0; j < 12; j ++)
+ if (!isxdigit(lineptr[j]))
+ break;
+
+ switch (j) {
+ case 0 :
+ bg = ch;
+ default :
+ red = green = blue = 0;
+ break;
+
+ case 3 :
+ val[0] = lineptr[0];
+ val[1] = '\0';
+ red = 255 * strtol(val, NULL, 16) / 15;
+
+ val[0] = lineptr[1];
+ val[1] = '\0';
+ green = 255 * strtol(val, NULL, 16) / 15;
+
+ val[0] = lineptr[2];
+ val[1] = '\0';
+ blue = 255 * strtol(val, NULL, 16) / 15;
+ break;
+
+ case 6 :
+ case 9 :
+ case 12 :
+ j /= 3;
+
+ val[0] = lineptr[0];
+ val[1] = lineptr[1];
+ val[2] = '\0';
+ red = strtol(val, NULL, 16);
+
+ val[0] = lineptr[j + 0];
+ val[1] = lineptr[j + 1];
+ val[2] = '\0';
+ green = strtol(val, NULL, 16);
+
+ val[0] = lineptr[2 * j + 0];
+ val[1] = lineptr[2 * j + 1];
+ val[2] = '\0';
+ blue = strtol(val, NULL, 16);
+ break;
+ }
+
+ colors[ch] = fl_rgb_color((uchar)red, (uchar)green, (uchar)blue);
+ } else {
+ // Read a color name...
+ if (strncasecmp(lineptr + 2, "white", 5) == 0) colors[ch] = FL_WHITE;
+ else if (strncasecmp(lineptr + 2, "black", 5) == 0) colors[ch] = FL_BLACK;
+ else if (strncasecmp(lineptr + 2, "none", 4) == 0) {
+ colors[ch] = FL_BLACK;
+ bg = ch;
+ } else colors[ch] = FL_GRAY;
+ }
+ }
+ }
+
+ // Read the image data...
+ for (y = 0; y < img->h(); y ++, ptr ++) {
+ lineptr = *ptr;
+ startx = 0;
+ ch = bg;
+
+ for (x = 0; x < img->w(); x ++) {
+ newch = *lineptr++;
+
+ if (chars_per_color > 1) newch = (newch << 8) | *lineptr++;
+
+ if (newch != ch) {
+ if (ch != bg) {
+ add_color(colors[ch]);
+ add(POLYGON);
+ add_vertex(startx * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h());
+ add_vertex(x * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h());
+ add_vertex(x * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h());
+ add_vertex(startx * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h());
+ add(END);
+ }
+
+ ch = newch;
+ startx = x;
+ }
+ }
+
+ if (ch != bg) {
+ add_color(colors[ch]);
+ add(POLYGON);
+ add_vertex(startx * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h());
+ add_vertex(x * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h());
+ add_vertex(x * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h());
+ add_vertex(startx * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h());
+ add(END);
+ }
+ }
+
+ // Free the colormap...
+ delete[] colors;
+ }
+
+ img->release();
+
+#ifdef DEBUG
+ printf("Icon File \"%s\":\n", xpm);
+ for (i = 0; i < num_data_; i ++)
+ printf(" %d,\n", data_[i]);
+#endif // DEBUG
+
+ return 0;
+}
+
+
+//
+// 'Fl_File_Icon::load_system_icons()' - Load the standard system icons/filetypes.
+
+void
+Fl_File_Icon::load_system_icons(void) {
+ int i; // Looping var
+ Fl_File_Icon *icon; // New icons
+ char filename[1024]; // Filename
+ char icondir[1024]; // Icon directory
+ static int init = 0; // Have the icons been initialized?
+ const char * const icondirs[] = {
+ "Bluecurve", // Icon directories to look for, in order
+ "crystalsvg",
+ "default.kde",
+ "hicolor",
+ NULL
+ };
+ static short plain[] = { // Plain file icon
+ COLOR, -1, -1, OUTLINEPOLYGON, 0, FL_GRAY,
+ VERTEX, 2000, 1000, VERTEX, 2000, 9000,
+ VERTEX, 6000, 9000, VERTEX, 8000, 7000,
+ VERTEX, 8000, 1000, END, OUTLINEPOLYGON, 0, FL_GRAY,
+ VERTEX, 6000, 9000, VERTEX, 6000, 7000,
+ VERTEX, 8000, 7000, END,
+ COLOR, 0, FL_BLACK, LINE, VERTEX, 6000, 7000,
+ VERTEX, 8000, 7000, VERTEX, 8000, 1000,
+ VERTEX, 2000, 1000, END, LINE, VERTEX, 3000, 7000,
+ VERTEX, 5000, 7000, END, LINE, VERTEX, 3000, 6000,
+ VERTEX, 5000, 6000, END, LINE, VERTEX, 3000, 5000,
+ VERTEX, 7000, 5000, END, LINE, VERTEX, 3000, 4000,
+ VERTEX, 7000, 4000, END, LINE, VERTEX, 3000, 3000,
+ VERTEX, 7000, 3000, END, LINE, VERTEX, 3000, 2000,
+ VERTEX, 7000, 2000, END,
+ END
+ };
+ static short image[] = { // Image file icon
+ COLOR, -1, -1, OUTLINEPOLYGON, 0, FL_GRAY,
+ VERTEX, 2000, 1000, VERTEX, 2000, 9000,
+ VERTEX, 6000, 9000, VERTEX, 8000, 7000,
+ VERTEX, 8000, 1000, END, OUTLINEPOLYGON, 0, FL_GRAY,
+ VERTEX, 6000, 9000, VERTEX, 6000, 7000,
+ VERTEX, 8000, 7000, END,
+ COLOR, 0, FL_BLACK, LINE, VERTEX, 6000, 7000,
+ VERTEX, 8000, 7000, VERTEX, 8000, 1000,
+ VERTEX, 2000, 1000, END,
+ COLOR, 0, FL_RED, POLYGON, VERTEX, 3500, 2500,
+ VERTEX, 3000, 3000, VERTEX, 3000, 4000,
+ VERTEX, 3500, 4500, VERTEX, 4500, 4500,
+ VERTEX, 5000, 4000, VERTEX, 5000, 3000,
+ VERTEX, 4500, 2500, END,
+ COLOR, 0, FL_GREEN, POLYGON, VERTEX, 5500, 2500,
+ VERTEX, 5000, 3000, VERTEX, 5000, 4000,
+ VERTEX, 5500, 4500, VERTEX, 6500, 4500,
+ VERTEX, 7000, 4000, VERTEX, 7000, 3000,
+ VERTEX, 6500, 2500, END,
+ COLOR, 0, FL_BLUE, POLYGON, VERTEX, 4500, 3500,
+ VERTEX, 4000, 4000, VERTEX, 4000, 5000,
+ VERTEX, 4500, 5500, VERTEX, 5500, 5500,
+ VERTEX, 6000, 5000, VERTEX, 6000, 4000,
+ VERTEX, 5500, 3500, END,
+ END
+ };
+ static short dir[] = { // Directory icon
+ COLOR, -1, -1, POLYGON, VERTEX, 1000, 1000,
+ VERTEX, 1000, 7500, VERTEX, 9000, 7500,
+ VERTEX, 9000, 1000, END,
+ POLYGON, VERTEX, 1000, 7500, VERTEX, 2500, 9000,
+ VERTEX, 5000, 9000, VERTEX, 6500, 7500, END,
+ COLOR, 0, FL_WHITE, LINE, VERTEX, 1500, 1500,
+ VERTEX, 1500, 7000, VERTEX, 9000, 7000, END,
+ COLOR, 0, FL_BLACK, LINE, VERTEX, 9000, 7500,
+ VERTEX, 9000, 1000, VERTEX, 1000, 1000, END,
+ COLOR, 0, FL_GRAY, LINE, VERTEX, 1000, 1000,
+ VERTEX, 1000, 7500, VERTEX, 2500, 9000,
+ VERTEX, 5000, 9000, VERTEX, 6500, 7500,
+ VERTEX, 9000, 7500, END,
+ END
+ };
+
+
+ // Add symbols if they haven't been added already...
+ if (!init) {
+ // This method requires the images library...
+ fl_register_images();
+
+ if (!kdedir) {
+ // Figure out where KDE is installed...
+ if ((kdedir = getenv("KDEDIR")) == NULL) {
+ if (!access("/opt/kde", F_OK)) kdedir = "/opt/kde";
+ else if (!access("/usr/local/share/mimelnk", F_OK)) kdedir = "/usr/local";
+ else kdedir = "/usr";
+ }
+ }
+
+ snprintf(filename, sizeof(filename), "%s/share/mimelnk", kdedir);
+
+ if (!access(filename, F_OK)) {
+ // Load KDE icons...
+ icon = new Fl_File_Icon("*", Fl_File_Icon::PLAIN);
+
+ for (i = 0; icondirs[i]; i ++) {
+ snprintf(icondir, sizeof(icondir), "%s/share/icons/%s", kdedir,
+ icondirs[i]);
+
+ if (!access(icondir, F_OK)) break;
+ }
+
+ if (icondirs[i]) {
+ snprintf(filename, sizeof(filename), "%s/16x16/mimetypes/unknown.png",
+ icondir);
+ } else {
+ snprintf(filename, sizeof(filename), "%s/share/icons/unknown.xpm",
+ kdedir);
+ }
+
+ if (!access(filename, F_OK)) icon->load_image(filename);
+
+ icon = new Fl_File_Icon("*", Fl_File_Icon::LINK);
+
+ snprintf(filename, sizeof(filename), "%s/16x16/filesystems/link.png",
+ icondir);
+
+ if (!access(filename, F_OK)) icon->load_image(filename);
+
+ snprintf(filename, sizeof(filename), "%s/share/mimelnk", kdedir);
+ load_kde_icons(filename, icondir);
+ } else if (!access("/usr/share/icons/folder.xpm", F_OK)) {
+ // Load GNOME icons...
+ icon = new Fl_File_Icon("*", Fl_File_Icon::PLAIN);
+ icon->load_image("/usr/share/icons/page.xpm");
+
+ icon = new Fl_File_Icon("*", Fl_File_Icon::DIRECTORY);
+ icon->load_image("/usr/share/icons/folder.xpm");
+ } else if (!access("/usr/dt/appconfig/icons", F_OK)) {
+ // Load CDE icons...
+ icon = new Fl_File_Icon("*", Fl_File_Icon::PLAIN);
+ icon->load_image("/usr/dt/appconfig/icons/C/Dtdata.m.pm");
+
+ icon = new Fl_File_Icon("*", Fl_File_Icon::DIRECTORY);
+ icon->load_image("/usr/dt/appconfig/icons/C/DtdirB.m.pm");
+
+ icon = new Fl_File_Icon("core", Fl_File_Icon::PLAIN);
+ icon->load_image("/usr/dt/appconfig/icons/C/Dtcore.m.pm");
+
+ icon = new Fl_File_Icon("*.{bmp|bw|gif|jpg|pbm|pcd|pgm|ppm|png|ras|rgb|tif|xbm|xpm}", Fl_File_Icon::PLAIN);
+ icon->load_image("/usr/dt/appconfig/icons/C/Dtimage.m.pm");
+
+ icon = new Fl_File_Icon("*.{eps|pdf|ps}", Fl_File_Icon::PLAIN);
+ icon->load_image("/usr/dt/appconfig/icons/C/Dtps.m.pm");
+
+ icon = new Fl_File_Icon("*.ppd", Fl_File_Icon::PLAIN);
+ icon->load_image("/usr/dt/appconfig/icons/C/DtPrtpr.m.pm");
+ } else if (!access("/usr/lib/filetype", F_OK)) {
+ // Load SGI icons...
+ icon = new Fl_File_Icon("*", Fl_File_Icon::PLAIN);
+ icon->load_fti("/usr/lib/filetype/iconlib/generic.doc.fti");
+
+ icon = new Fl_File_Icon("*", Fl_File_Icon::DIRECTORY);
+ icon->load_fti("/usr/lib/filetype/iconlib/generic.folder.closed.fti");
+
+ icon = new Fl_File_Icon("core", Fl_File_Icon::PLAIN);
+ icon->load_fti("/usr/lib/filetype/default/iconlib/CoreFile.fti");
+
+ icon = new Fl_File_Icon("*.{bmp|bw|gif|jpg|pbm|pcd|pgm|ppm|png|ras|rgb|tif|xbm|xpm}", Fl_File_Icon::PLAIN);
+ icon->load_fti("/usr/lib/filetype/system/iconlib/ImageFile.fti");
+
+ if (!access("/usr/lib/filetype/install/iconlib/acroread.doc.fti", F_OK)) {
+ icon = new Fl_File_Icon("*.{eps|ps}", Fl_File_Icon::PLAIN);
+ icon->load_fti("/usr/lib/filetype/system/iconlib/PostScriptFile.closed.fti");
+
+ icon = new Fl_File_Icon("*.pdf", Fl_File_Icon::PLAIN);
+ icon->load_fti("/usr/lib/filetype/install/iconlib/acroread.doc.fti");
+ } else {
+ icon = new Fl_File_Icon("*.{eps|pdf|ps}", Fl_File_Icon::PLAIN);
+ icon->load_fti("/usr/lib/filetype/system/iconlib/PostScriptFile.closed.fti");
+ }
+
+ if (!access("/usr/lib/filetype/install/iconlib/html.fti", F_OK)) {
+ icon = new Fl_File_Icon("*.{htm|html|shtml}", Fl_File_Icon::PLAIN);
+ icon->load_fti("/usr/lib/filetype/iconlib/generic.doc.fti");
+ icon->load_fti("/usr/lib/filetype/install/iconlib/html.fti");
+ }
+
+ if (!access("/usr/lib/filetype/install/iconlib/color.ps.idle.fti", F_OK)) {
+ icon = new Fl_File_Icon("*.ppd", Fl_File_Icon::PLAIN);
+ icon->load_fti("/usr/lib/filetype/install/iconlib/color.ps.idle.fti");
+ }
+ } else {
+ // Create the default icons...
+ new Fl_File_Icon("*", Fl_File_Icon::PLAIN, sizeof(plain) / sizeof(plain[0]), plain);
+ new Fl_File_Icon("*.{bm|bmp|bw|gif|jpg|pbm|pcd|pgm|ppm|png|ras|rgb|tif|xbm|xpm}", Fl_File_Icon::PLAIN,
+ sizeof(image) / sizeof(image[0]), image);
+ new Fl_File_Icon("*", Fl_File_Icon::DIRECTORY, sizeof(dir) / sizeof(dir[0]), dir);
+ }
+
+ // Mark things as initialized...
+ init = 1;
+
+#ifdef DEBUG
+ int count;
+ Fl_File_Icon *temp;
+ for (count = 0, temp = first_; temp; temp = temp->next_, count ++);
+ printf("count of Fl_File_Icon's is %d...\n", count);
+#endif // DEBUG
+ }
+}
+
+
+//
+// 'load_kde_icons()' - Load KDE icon files.
+//
+
+static void
+load_kde_icons(const char *directory, // I - Directory to load
+ const char *icondir) { // I - Location of icons
+ int i; // Looping var
+ int n; // Number of entries in directory
+ dirent **entries; // Entries in directory
+ char full[1024]; // Full name of file
+
+
+ entries = (dirent **)0;
+ n = fl_filename_list(directory, &entries);
+
+ for (i = 0; i < n; i ++) {
+ if (entries[i]->d_name[0] != '.') {
+ snprintf(full, sizeof(full), "%s/%s", directory, entries[i]->d_name);
+
+ if (fl_filename_isdir(full)) load_kde_icons(full, icondir);
+ else load_kde_mimelnk(full, icondir);
+ }
+
+ free((void *)entries[i]);
+ }
+
+ free((void*)entries);
+}
+
+
+//
+// 'load_kde_mimelnk()' - Load a KDE "mimelnk" file.
+//
+
+static void
+load_kde_mimelnk(const char *filename, // I - mimelnk filename
+ const char *icondir) { // I - Location of icons
+ FILE *fp;
+ char tmp[1024];
+ char iconfilename[1024];
+ char pattern[1024];
+ char mimetype[1024];
+ char *val;
+ char full_iconfilename[1024];
+ Fl_File_Icon *icon;
+
+
+ mimetype[0] = '\0';
+ pattern[0] = '\0';
+ iconfilename[0] = '\0';
+
+ if ((fp = fopen(filename, "rb")) != NULL) {
+ while (fgets(tmp, sizeof(tmp), fp)) {
+ if ((val = get_kde_val(tmp, "Icon")) != NULL)
+ strlcpy(iconfilename, val, sizeof(iconfilename));
+ else if ((val = get_kde_val(tmp, "MimeType")) != NULL)
+ strlcpy(mimetype, val, sizeof(mimetype));
+ else if ((val = get_kde_val(tmp, "Patterns")) != NULL)
+ strlcpy(pattern, val, sizeof(pattern));
+ }
+
+ fclose(fp);
+
+#ifdef DEBUG
+ printf("%s: Icon=\"%s\", MimeType=\"%s\", Patterns=\"%s\"\n", filename,
+ iconfilename, mimetype, pattern);
+#endif // DEBUG
+
+ if (!pattern[0] && strncmp(mimetype, "inode/", 6)) return;
+
+ if (iconfilename[0]) {
+ if (iconfilename[0] == '/') {
+ strlcpy(full_iconfilename, iconfilename, sizeof(full_iconfilename));
+ } else if (!access(icondir, F_OK)) {
+ // KDE 3.x and 2.x icons
+ int i; // Looping var
+ static const char *paths[] = { // Subdirs to look in...
+ "16x16/actions",
+ "16x16/apps",
+ "16x16/devices",
+ "16x16/filesystems",
+ "16x16/mimetypes",
+/*
+ "20x20/actions",
+ "20x20/apps",
+ "20x20/devices",
+ "20x20/filesystems",
+ "20x20/mimetypes",
+
+ "22x22/actions",
+ "22x22/apps",
+ "22x22/devices",
+ "22x22/filesystems",
+ "22x22/mimetypes",
+
+ "24x24/actions",
+ "24x24/apps",
+ "24x24/devices",
+ "24x24/filesystems",
+ "24x24/mimetypes",
+*/
+ "32x32/actions",
+ "32x32/apps",
+ "32x32/devices",
+ "32x32/filesystems",
+ "32x32/mimetypes",
+/*
+ "36x36/actions",
+ "36x36/apps",
+ "36x36/devices",
+ "36x36/filesystems",
+ "36x36/mimetypes",
+
+ "48x48/actions",
+ "48x48/apps",
+ "48x48/devices",
+ "48x48/filesystems",
+ "48x48/mimetypes",
+
+ "64x64/actions",
+ "64x64/apps",
+ "64x64/devices",
+ "64x64/filesystems",
+ "64x64/mimetypes",
+
+ "96x96/actions",
+ "96x96/apps",
+ "96x96/devices",
+ "96x96/filesystems",
+ "96x96/mimetypes"
+*/ };
+
+ for (i = 0; i < (int)(sizeof(paths) / sizeof(paths[0])); i ++) {
+ snprintf(full_iconfilename, sizeof(full_iconfilename),
+ "%s/%s/%s.png", icondir, paths[i], iconfilename);
+
+ if (!access(full_iconfilename, F_OK)) break;
+ }
+
+ if (i >= (int)(sizeof(paths) / sizeof(paths[0]))) return;
+ } else {
+ // KDE 1.x icons
+ snprintf(full_iconfilename, sizeof(full_iconfilename),
+ "%s/%s", tmp, iconfilename);
+
+ if (access(full_iconfilename, F_OK)) return;
+ }
+
+ if (strncmp(mimetype, "inode/", 6) == 0) {
+ if (!strcmp(mimetype + 6, "directory"))
+ icon = new Fl_File_Icon("*", Fl_File_Icon::DIRECTORY);
+ else if (!strcmp(mimetype + 6, "blockdevice"))
+ icon = new Fl_File_Icon("*", Fl_File_Icon::DEVICE);
+ else if (!strcmp(mimetype + 6, "fifo"))
+ icon = new Fl_File_Icon("*", Fl_File_Icon::FIFO);
+ else return;
+ } else {
+ icon = new Fl_File_Icon(kde_to_fltk_pattern(pattern),
+ Fl_File_Icon::PLAIN);
+ }
+
+ icon->load(full_iconfilename);
+ }
+ }
+}
+
+
+//
+// 'kde_to_fltk_pattern()' - Convert a KDE pattern to a FLTK pattern.
+//
+
+static char *
+kde_to_fltk_pattern(const char *kdepattern) {
+ char *pattern,
+ *patptr;
+
+
+ pattern = (char *)malloc(strlen(kdepattern) + 3);
+ strcpy(pattern, "{");
+ strcpy(pattern + 1, kdepattern);
+
+ if (pattern[strlen(pattern) - 1] == ';') pattern[strlen(pattern) - 1] = '\0';
+
+ strcat(pattern, "}");
+
+ for (patptr = pattern; *patptr; patptr ++) {
+ if (*patptr == ';') *patptr = '|';
+ }
+
+ return (pattern);
+}
+
+
+//
+// 'get_kde_val()' - Get a KDE value.
+//
+
+static char *
+get_kde_val(char *str,
+ const char *key) {
+ while (*str == *key) {
+ str ++;
+ key ++;
+ }
+
+ if (*key == '\0' && *str == '=') {
+ if (str[strlen(str) - 1] == '\n') str[strlen(str) - 1] = '\0';
+
+ return (str + 1);
+ }
+
+ return ((char *)0);
+}
+
+
+//
+// End of "$Id: Fl_File_Icon2.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_File_Input.cxx b/third_party/windows/fltk-1.1.10/src/Fl_File_Input.cxx new file mode 100644 index 0000000..bfcc794 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_File_Input.cxx @@ -0,0 +1,288 @@ +//
+// "$Id: Fl_File_Input.cxx 6759 2009-04-13 07:32:03Z matt $"
+//
+// File_Input header file for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 by Bill Spitzak and others.
+// Original version Copyright 1998 by Curtis Edwards.
+//
+// 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_File_Input.H>
+#include <FL/Fl_Window.H>
+#include <FL/fl_draw.H>
+#include <stdio.h>
+#include "flstring.h"
+
+
+//
+// Height of directory buttons...
+//
+
+#define DIR_HEIGHT 10
+
+
+//
+// Redraw bit for directory bar...
+//
+
+#define FL_DAMAGE_BAR 0x10
+
+
+//
+// 'Fl_File_Input::Fl_File_Input()' - Create a Fl_File_Input widget.
+//
+
+Fl_File_Input::Fl_File_Input(int X, int Y, int W, int H, const char *l)
+ : Fl_Input(X, Y, W, H, l) {
+ buttons_[0] = 0;
+ errorcolor_ = FL_RED;
+ ok_entry_ = 1;
+ pressed_ = -1;
+
+ down_box(FL_UP_BOX);
+}
+
+//
+// 'Fl_File_Input::draw_buttons()' - Draw directory buttons.
+//
+
+void
+Fl_File_Input::draw_buttons() {
+ int i, // Looping var
+ X; // Current X position
+
+
+ if (damage() & (FL_DAMAGE_BAR | FL_DAMAGE_ALL)) {
+ update_buttons();
+ }
+
+ for (X = 0, i = 0; buttons_[i]; i ++)
+ {
+ if ((X + buttons_[i]) > xscroll()) {
+ if (X < xscroll()) {
+ draw_box(pressed_ == i ? fl_down(down_box()) : down_box(),
+ x(), y(), X + buttons_[i] - xscroll(), DIR_HEIGHT, FL_GRAY);
+ } else if ((X + buttons_[i] - xscroll()) > w()) {
+ draw_box(pressed_ == i ? fl_down(down_box()) : down_box(),
+ x() + X - xscroll(), y(), w() - X + xscroll(), DIR_HEIGHT,
+ FL_GRAY);
+ } else {
+ draw_box(pressed_ == i ? fl_down(down_box()) : down_box(),
+ x() + X - xscroll(), y(), buttons_[i], DIR_HEIGHT, FL_GRAY);
+ }
+ }
+
+ X += buttons_[i];
+ }
+
+ if (X < w()) {
+ draw_box(pressed_ == i ? fl_down(down_box()) : down_box(),
+ x() + X - xscroll(), y(), w() - X + xscroll(), DIR_HEIGHT, FL_GRAY);
+ }
+}
+
+//
+// 'Fl_File_Input::update_buttons()' - Update the sizes of the directory buttons.
+//
+
+void
+Fl_File_Input::update_buttons() {
+ int i; // Looping var
+ const char *start, // Start of path component
+ *end; // End of path component
+
+
+// puts("update_buttons()");
+
+ // Set the current font & size...
+ fl_font(textfont(), textsize());
+
+ // Loop through the value string, setting widths...
+ for (i = 0, start = value();
+ start && i < (int)(sizeof(buttons_) / sizeof(buttons_[0]) - 1);
+ start = end, i ++) {
+// printf(" start = \"%s\"\n", start);
+ if ((end = strchr(start, '/')) == NULL)
+#if defined(WIN32) || defined(__EMX__)
+ if ((end = strchr(start, '\\')) == NULL)
+#endif // WIN32 || __EMX__
+ break;
+
+ end ++;
+
+ buttons_[i] = (short)fl_width(start, end - start);
+ if (!i) buttons_[i] += Fl::box_dx(box()) + 6;
+ }
+
+// printf(" found %d components/buttons...\n", i);
+
+ buttons_[i] = 0;
+}
+
+
+//
+// 'Fl_File_Input::value()' - Set the value of the widget...
+//
+
+int // O - TRUE on success
+Fl_File_Input::value(const char *str, // I - New string value
+ int len) { // I - Length of value
+ damage(FL_DAMAGE_BAR);
+ return Fl_Input::value(str,len);
+}
+
+
+int // O - TRUE on success
+Fl_File_Input::value(const char *str) { // I - New string value
+ damage(FL_DAMAGE_BAR);
+ return Fl_Input::value(str);
+}
+
+
+//
+// 'Fl_File_Input::draw()' - Draw the file input widget...
+//
+
+void
+Fl_File_Input::draw() {
+ Fl_Boxtype b = box();
+ if (damage() & (FL_DAMAGE_BAR | FL_DAMAGE_ALL)) draw_buttons();
+ // this flag keeps Fl_Input_::drawtext from drawing a bogus box!
+ char must_trick_fl_input_ =
+ Fl::focus()!=this && !size() && !(damage()&FL_DAMAGE_ALL);
+ if ((damage() & FL_DAMAGE_ALL) || must_trick_fl_input_)
+ draw_box(b,x(),y()+DIR_HEIGHT,w(),h()-DIR_HEIGHT,color());
+ if (!must_trick_fl_input_)
+ Fl_Input_::drawtext(x()+Fl::box_dx(b)+3, y()+Fl::box_dy(b)+DIR_HEIGHT,
+ w()-Fl::box_dw(b)-6, h()-Fl::box_dh(b)-DIR_HEIGHT);
+}
+
+
+//
+// 'Fl_File_Input::handle()' - Handle events in the widget...
+//
+
+int // O - TRUE if we handled event
+Fl_File_Input::handle(int event) // I - Event
+{
+// printf("handle(event = %d)\n", event);
+ static char inButtonBar = 0;
+
+ switch (event) {
+ case FL_MOVE :
+ case FL_ENTER :
+ if (active_r()) {
+ if (Fl::event_y() < (y() + DIR_HEIGHT))
+ window()->cursor(FL_CURSOR_DEFAULT);
+ else
+ window()->cursor(FL_CURSOR_INSERT);
+ }
+
+ return 1;
+
+ case FL_PUSH :
+ inButtonBar = (Fl::event_y() < (y() + DIR_HEIGHT));
+ case FL_RELEASE :
+ case FL_DRAG :
+ if (inButtonBar)
+ return handle_button(event);
+ else
+ return Fl_Input::handle(event);
+
+ default :
+ if (Fl_Input::handle(event)) {
+ damage(FL_DAMAGE_BAR);
+ return 1;
+ }
+
+ return 0;
+ }
+}
+
+
+//
+// 'Fl_File_Input::handle_button()' - Handle button events in the widget...
+//
+
+int // O - TRUE if we handled event
+Fl_File_Input::handle_button(int event) // I - Event
+{
+ int i, // Looping var
+ X; // Current X position
+ char *start, // Start of path component
+ *end; // End of path component
+ char newvalue[1024]; // New value
+
+
+ // Figure out which button is being pressed...
+ for (X = 0, i = 0; buttons_[i]; i ++)
+ {
+ X += buttons_[i];
+
+ if (X > xscroll() && Fl::event_x() < (x() + X - xscroll())) break;
+ }
+
+// printf("handle_button(event = %d), button = %d\n", event, i);
+
+ // Redraw the directory bar...
+ if (event == FL_RELEASE) pressed_ = -1;
+ else pressed_ = (short)i;
+
+ window()->make_current();
+ draw_buttons();
+
+ // Return immediately if the user is clicking on the last button or
+ // has not released the mouse button...
+ if (!buttons_[i] || event != FL_RELEASE) return 1;
+
+ // Figure out where to truncate the path...
+ strlcpy(newvalue, value(), sizeof(newvalue));
+
+ for (start = newvalue, end = start; start && i >= 0; start = end, i --) {
+// printf(" start = \"%s\"\n", start);
+ if ((end = strchr(start, '/')) == NULL)
+#if defined(WIN32) || defined(__EMX__)
+ if ((end = strchr(start, '\\')) == NULL)
+#endif // WIN32 || __EMX__
+ break;
+
+ end ++;
+ }
+
+ if (i < 0) {
+ // Found the end; truncate the value and update the buttons...
+ *start = '\0';
+ value(newvalue, start - newvalue);
+
+ // Then do the callbacks, if necessary...
+ set_changed();
+ if (when() & FL_WHEN_CHANGED) do_callback();
+ }
+
+ return 1;
+}
+
+
+//
+// End of "$Id: Fl_File_Input.cxx 6759 2009-04-13 07:32:03Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Font.H b/third_party/windows/fltk-1.1.10/src/Fl_Font.H new file mode 100644 index 0000000..f28e0a6 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Font.H @@ -0,0 +1,111 @@ +//
+// "$Id: Fl_Font.H 5334 2006-08-19 15:24:55Z matt $"
+//
+// Font definitions for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Two internal fltk data structures:
+//
+// Fl_Fontdesc: an entry into the fl_font() table. There is one of these
+// for each fltk font number.
+//
+// Fl_FontSize: a structure for an actual system font, with junk to
+// help choose it and info on character sizes. Each Fl_Fontdesc has a
+// linked list of these. These are created the first time each system
+// font/size combination is used.
+
+#ifndef FL_FONT_
+#define FL_FONT_
+
+#include <config.h>
+
+# if USE_XFT
+typedef struct _XftFont XftFont;
+# endif // USE_XFT
+
+class Fl_FontSize {
+public:
+ Fl_FontSize *next; // linked list for this Fl_Fontdesc
+# ifdef WIN32
+ HFONT fid;
+ int width[256];
+ TEXTMETRIC metr;
+ FL_EXPORT Fl_FontSize(const char* fontname, int size);
+# elif defined(__APPLE_QD__)
+ FL_EXPORT Fl_FontSize(const char* fontname, int size);
+ short font, face, size;
+ short ascent, descent;
+ short width[256];
+ bool knowMetrics;
+# elif defined(__APPLE_QUARTZ__)
+ FL_EXPORT Fl_FontSize(const char* fontname, int size);
+ ATSUTextLayout layout;
+ ATSUStyle style;
+ short ascent, descent, q_width;
+ short width[256];
+ bool knowWidths;
+ char *q_name;
+ int size;
+# elif USE_XFT
+ XftFont* font;
+ const char* encoding;
+ int size;
+ FL_EXPORT Fl_FontSize(const char* xfontname);
+# else
+ XFontStruct* font; // X font information
+ FL_EXPORT Fl_FontSize(const char* xfontname);
+# endif
+ int minsize; // smallest point size that should use this
+ int maxsize; // largest point size that should use this
+# if HAVE_GL
+ unsigned int listbase;// base of display list, 0 = none
+# endif
+ FL_EXPORT ~Fl_FontSize();
+};
+
+extern FL_EXPORT Fl_FontSize *fl_fontsize; // the currently selected one
+
+struct Fl_Fontdesc {
+ const char *name;
+ char fontname[128]; // "Pretty" font name
+ Fl_FontSize *first; // linked list of sizes of this style
+# ifndef WIN32
+ char **xlist; // matched X font names
+ int n; // size of xlist, negative = don't free xlist!
+# endif
+};
+
+extern FL_EXPORT Fl_Fontdesc *fl_fonts; // the table
+
+# ifndef WIN32
+// functions for parsing X font names:
+FL_EXPORT const char* fl_font_word(const char *p, int n);
+FL_EXPORT char *fl_find_fontsize(char *name);
+# endif
+
+#endif
+
+//
+// End of "$Id: Fl_Font.H 5334 2006-08-19 15:24:55Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_GIF_Image.cxx b/third_party/windows/fltk-1.1.10/src/Fl_GIF_Image.cxx new file mode 100644 index 0000000..21ea9fd --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_GIF_Image.cxx @@ -0,0 +1,384 @@ +//
+// "$Id: Fl_GIF_Image.cxx 5845 2007-05-20 00:01:06Z mike $"
+//
+// Fl_GIF_Image routines.
+//
+// Copyright 1997-2005 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
+//
+// Contents:
+//
+//
+
+//
+// Include necessary header files...
+//
+
+#include <FL/Fl.H>
+#include <FL/Fl_GIF_Image.H>
+#include <stdio.h>
+#include <stdlib.h>
+#include "flstring.h"
+
+// Read a .gif file and convert it to a "xpm" format (actually my
+// modified one with compressed colormaps).
+
+// Extensively modified from original code for gif2ras by
+// Patrick J. Naughton of Sun Microsystems. The original
+// copyright notice follows:
+
+/* gif2ras.c - Converts from a Compuserve GIF (tm) image to a Sun Raster image.
+ *
+ * Copyright (c) 1988 by Patrick J. Naughton
+ *
+ * Author: Patrick J. Naughton
+ * naughton@wind.sun.com
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appear in all copies and that
+ * both that copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * This file is provided AS IS with no warranties of any kind. The author
+ * shall have no liability with respect to the infringement of copyrights,
+ * trade secrets or any patents by this file or any part thereof. In no
+ * event will the author be liable for any lost revenue or profits or
+ * other special, indirect and consequential damages.
+ *
+ * Comments and additions should be sent to the author:
+ *
+ * Patrick J. Naughton
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Ave, MS 14-40
+ * Mountain View, CA 94043
+ * (415) 336-1080
+ */
+
+typedef unsigned char uchar;
+
+#define NEXTBYTE (uchar)getc(GifFile)
+#define GETSHORT(var) var = NEXTBYTE; var += NEXTBYTE << 8
+
+Fl_GIF_Image::Fl_GIF_Image(const char *infname) : Fl_Pixmap((char *const*)0) {
+ FILE *GifFile; // File to read
+ char **new_data; // Data array
+
+ if ((GifFile = fopen(infname, "rb")) == NULL) {
+ Fl::error("Fl_GIF_Image: Unable to open %s!", infname);
+ return;
+ }
+
+ {char b[6];
+ if (fread(b,1,6,GifFile)<6) {
+ fclose(GifFile);
+ return; /* quit on eof */
+ }
+ if (b[0]!='G' || b[1]!='I' || b[2] != 'F') {
+ fclose(GifFile);
+ Fl::error("Fl_GIF_Image: %s is not a GIF file.\n", infname);
+ return;
+ }
+ if (b[3]!='8' || b[4]>'9' || b[5]!= 'a')
+ Fl::warning("%s is version %c%c%c.",infname,b[3],b[4],b[5]);
+ }
+
+ int Width; GETSHORT(Width);
+ int Height; GETSHORT(Height);
+
+ uchar ch = NEXTBYTE;
+ char HasColormap = ((ch & 0x80) != 0);
+ int BitsPerPixel = (ch & 7) + 1;
+ int ColorMapSize = 1 << BitsPerPixel;
+ // int OriginalResolution = ((ch>>4)&7)+1;
+ // int SortedTable = (ch&8)!=0;
+ ch = NEXTBYTE; // Background Color index
+ ch = NEXTBYTE; // Aspect ratio is N/64
+
+ // Read in global colormap:
+ uchar transparent_pixel = 0;
+ char has_transparent = 0;
+ uchar Red[256], Green[256], Blue[256]; /* color map */
+ if (HasColormap) {
+ for (int i=0; i < ColorMapSize; i++) {
+ Red[i] = NEXTBYTE;
+ Green[i] = NEXTBYTE;
+ Blue[i] = NEXTBYTE;
+ }
+ } else {
+ Fl::warning("%s does not have a colormap.", infname);
+ for (int i = 0; i < ColorMapSize; i++)
+ Red[i] = Green[i] = Blue[i] = (uchar)(255 * i / (ColorMapSize-1));
+ }
+
+ int CodeSize; /* Code size, init from GIF header, increases... */
+ char Interlace;
+
+ for (;;) {
+
+ int i = NEXTBYTE;
+ if (i<0) {
+ fclose(GifFile);
+ Fl::error("Fl_GIF_Image: %s - unexpected EOF",infname);
+ return;
+ }
+ int blocklen;
+
+ // if (i == 0x3B) return 0; eof code
+
+ if (i == 0x21) { // a "gif extension"
+
+ ch = NEXTBYTE;
+ blocklen = NEXTBYTE;
+
+ if (ch==0xF9 && blocklen==4) { // Netscape animation extension
+
+ char bits;
+ bits = NEXTBYTE;
+ getc(GifFile); getc(GifFile); // GETSHORT(delay);
+ transparent_pixel = NEXTBYTE;
+ if (bits & 1) has_transparent = 1;
+ blocklen = NEXTBYTE;
+
+ } else if (ch == 0xFF) { // Netscape repeat count
+ ;
+
+ } else if (ch != 0xFE) { //Gif Comment
+ Fl::warning("%s: unknown gif extension 0x%02x.", infname, ch);
+ }
+ } else if (i == 0x2c) { // an image
+
+ ch = NEXTBYTE; ch = NEXTBYTE; // GETSHORT(x_position);
+ ch = NEXTBYTE; ch = NEXTBYTE; // GETSHORT(y_position);
+ GETSHORT(Width);
+ GETSHORT(Height);
+ ch = NEXTBYTE;
+ Interlace = ((ch & 0x40) != 0);
+ if (ch&0x80) {
+ // read local color map
+ int n = 2<<(ch&7);
+ for (i=0; i < n; i++) {
+ Red[i] = NEXTBYTE;
+ Green[i] = NEXTBYTE;
+ Blue[i] = NEXTBYTE;
+ }
+ }
+ CodeSize = NEXTBYTE+1;
+ break; // okay, this is the image we want
+ } else {
+ Fl::warning("%s: unknown gif code 0x%02x", infname, i);
+ blocklen = 0;
+ }
+
+ // skip the data:
+ while (blocklen>0) {while (blocklen--) {ch = NEXTBYTE;} blocklen=NEXTBYTE;}
+ }
+
+ if (BitsPerPixel >= CodeSize)
+ {
+ // Workaround for broken GIF files...
+ BitsPerPixel = CodeSize - 1;
+ ColorMapSize = 1 << BitsPerPixel;
+ }
+
+ uchar *Image = new uchar[Width*Height];
+
+ int YC = 0, Pass = 0; /* Used to de-interlace the picture */
+ uchar *p = Image;
+ uchar *eol = p+Width;
+
+ int InitCodeSize = CodeSize;
+ int ClearCode = (1 << (CodeSize-1));
+ int EOFCode = ClearCode + 1;
+ int FirstFree = ClearCode + 2;
+ int FinChar = 0;
+ int ReadMask = (1<<CodeSize) - 1;
+ int FreeCode = FirstFree;
+ int OldCode = ClearCode;
+
+ // tables used by LZW decompresser:
+ short int Prefix[4096];
+ uchar Suffix[4096];
+
+ int blocklen = NEXTBYTE;
+ uchar thisbyte = NEXTBYTE; blocklen--;
+ int frombit = 0;
+
+ for (;;) {
+
+/* Fetch the next code from the raster data stream. The codes can be
+ * any length from 3 to 12 bits, packed into 8-bit bytes, so we have to
+ * maintain our location as a pointer and a bit offset.
+ * In addition, gif adds totally useless and annoying block counts
+ * that must be correctly skipped over. */
+ int CurCode = thisbyte;
+ if (frombit+CodeSize > 7) {
+ if (blocklen <= 0) {
+ blocklen = NEXTBYTE;
+ if (blocklen <= 0) break;
+ }
+ thisbyte = NEXTBYTE; blocklen--;
+ CurCode |= thisbyte<<8;
+ }
+ if (frombit+CodeSize > 15) {
+ if (blocklen <= 0) {
+ blocklen = NEXTBYTE;
+ if (blocklen <= 0) break;
+ }
+ thisbyte = NEXTBYTE; blocklen--;
+ CurCode |= thisbyte<<16;
+ }
+ CurCode = (CurCode>>frombit)&ReadMask;
+ frombit = (frombit+CodeSize)%8;
+
+ if (CurCode == ClearCode) {
+ CodeSize = InitCodeSize;
+ ReadMask = (1<<CodeSize) - 1;
+ FreeCode = FirstFree;
+ OldCode = ClearCode;
+ continue;
+ }
+
+ if (CurCode == EOFCode) break;
+
+ uchar OutCode[1025]; // temporary array for reversing codes
+ uchar *tp = OutCode;
+ int i;
+ if (CurCode < FreeCode) i = CurCode;
+ else if (CurCode == FreeCode) {*tp++ = (uchar)FinChar; i = OldCode;}
+ else {Fl::error("Fl_GIF_Image: %s - LZW Barf!", infname); break;}
+
+ while (i >= ColorMapSize) {*tp++ = Suffix[i]; i = Prefix[i];}
+ *tp++ = FinChar = i;
+ do {
+ *p++ = *--tp;
+ if (p >= eol) {
+ if (!Interlace) YC++;
+ else switch (Pass) {
+ case 0: YC += 8; if (YC >= Height) {Pass++; YC = 4;} break;
+ case 1: YC += 8; if (YC >= Height) {Pass++; YC = 2;} break;
+ case 2: YC += 4; if (YC >= Height) {Pass++; YC = 1;} break;
+ case 3: YC += 2; break;
+ }
+ if (YC>=Height) YC=0; /* cheap bug fix when excess data */
+ p = Image + YC*Width;
+ eol = p+Width;
+ }
+ } while (tp > OutCode);
+
+ if (OldCode != ClearCode) {
+ Prefix[FreeCode] = (short)OldCode;
+ Suffix[FreeCode] = FinChar;
+ FreeCode++;
+ if (FreeCode > ReadMask) {
+ if (CodeSize < 12) {
+ CodeSize++;
+ ReadMask = (1 << CodeSize) - 1;
+ }
+ else FreeCode--;
+ }
+ }
+ OldCode = CurCode;
+ }
+
+ // We are done reading the file, now convert to xpm:
+
+ // allocate line pointer arrays:
+ w(Width);
+ h(Height);
+ d(1);
+ new_data = new char*[Height+2];
+
+ // transparent pixel must be zero, swap if it isn't:
+ if (has_transparent && transparent_pixel != 0) {
+ // swap transparent pixel with zero
+ p = Image+Width*Height;
+ while (p-- > Image) {
+ if (*p==transparent_pixel) *p = 0;
+ else if (!*p) *p = transparent_pixel;
+ }
+ uchar t;
+ t = Red[0];
+ Red[0] = Red[transparent_pixel];
+ Red[transparent_pixel] = t;
+
+ t = Green[0];
+ Green[0] = Green[transparent_pixel];
+ Green[transparent_pixel] = t;
+
+ t = Blue[0];
+ Blue[0] = Blue[transparent_pixel];
+ Blue[transparent_pixel] = t;
+ }
+
+ // find out what colors are actually used:
+ uchar used[256]; uchar remap[256];
+ int i;
+ for (i = 0; i < ColorMapSize; i++) used[i] = 0;
+ p = Image+Width*Height;
+ while (p-- > Image) used[*p] = 1;
+
+ // remap them to start with printing characters:
+ int base = has_transparent && used[0] ? ' ' : ' '+1;
+ int numcolors = 0;
+ for (i = 0; i < ColorMapSize; i++) if (used[i]) {
+ remap[i] = (uchar)(base++);
+ numcolors++;
+ }
+
+ // write the first line of xpm data (use suffix as temp array):
+ int length = sprintf((char*)(Suffix),
+ "%d %d %d %d",Width,Height,-numcolors,1);
+ new_data[0] = new char[length+1];
+ strcpy(new_data[0], (char*)Suffix);
+
+ // write the colormap
+ new_data[1] = (char*)(p = new uchar[4*numcolors]);
+ for (i = 0; i < ColorMapSize; i++) if (used[i]) {
+ *p++ = remap[i];
+ *p++ = Red[i];
+ *p++ = Green[i];
+ *p++ = Blue[i];
+ }
+
+ // remap the image data:
+ p = Image+Width*Height;
+ while (p-- > Image) *p = remap[*p];
+
+ // split the image data into lines:
+ for (i=0; i<Height; i++) {
+ new_data[i+2] = new char[Width+1];
+ memcpy(new_data[i + 2], (char*)(Image + i*Width), Width);
+ new_data[i + 2][Width] = 0;
+ }
+
+ data((const char **)new_data, Height + 2);
+ alloc_data = 1;
+
+ delete[] Image;
+
+ fclose(GifFile);
+}
+
+
+//
+// End of "$Id: Fl_GIF_Image.cxx 5845 2007-05-20 00:01:06Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Gl_Choice.H b/third_party/windows/fltk-1.1.10/src/Fl_Gl_Choice.H new file mode 100644 index 0000000..a607d44 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Gl_Choice.H @@ -0,0 +1,132 @@ +//
+// "$Id: Fl_Gl_Choice.H 4052 2005-02-24 21:55:12Z mike $"
+//
+// OpenGL definitions for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2001 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 to "fltk-bugs@easysw.com".
+//
+
+// Internal interface to set up OpenGL.
+//
+// A "Fl_Gl_Choice" is created from an OpenGL mode and holds information
+// necessary to create a window (on X) and to create an OpenGL "context"
+// (on both X and Win32).
+//
+// fl_create_gl_context takes a window (necessary only on Win32) and an
+// Fl_Gl_Choice and returns a new OpenGL context. All contexts share
+// display lists with each other.
+//
+// On X another fl_create_gl_context is provided to create it for any
+// X visual.
+//
+// fl_set_gl_context makes the given OpenGL context current and makes
+// it draw into the passed window. It tracks the current one context
+// to avoid calling the context switching code when the same context
+// is used, though it is a mystery to me why the GLX/WGL libraries
+// don't do this themselves...
+//
+// fl_no_gl_context clears that cache so the next fl_set_gl_context is
+// guaranteed to work.
+//
+// fl_delete_gl_context destroys the context.
+//
+// This code is used by Fl_Gl_Window, gl_start(), and gl_visual()
+
+#ifndef Fl_Gl_Choice_H
+#define Fl_Gl_Choice_H
+
+// Warning: whatever GLContext is defined to must take exactly the same
+// space in a structure as a void*!!!
+#ifdef WIN32
+# include <FL/gl.h>
+# define GLContext HGLRC
+#elif defined(__APPLE_QD__)
+# include <OpenGL/gl.h>
+# include <AGL/agl.h>
+# define GLContext AGLContext
+#elif defined(__APPLE_QUARTZ__)
+// warning: the Quartz version should probably use Core GL (CGL) instead of AGL
+# include <OpenGL/gl.h>
+# include <AGL/agl.h>
+# define GLContext AGLContext
+#else
+# include <GL/glx.h>
+# define GLContext GLXContext
+#endif
+
+// Describes crap needed to create a GLContext.
+class Fl_Gl_Choice {
+ int mode;
+ const int *alist;
+ Fl_Gl_Choice *next;
+public:
+#ifdef WIN32
+ int pixelformat; // the visual to use
+ PIXELFORMATDESCRIPTOR pfd; // some wgl calls need this thing
+#elif defined(__APPLE_QD__)
+ AGLPixelFormat pixelformat;
+#elif defined(__APPLE_QUARTZ__)
+ // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
+ AGLPixelFormat pixelformat;
+#else
+ XVisualInfo *vis; // the visual to use
+ Colormap colormap; // a colormap for that visual
+#endif
+ // Return one of these structures for a given gl mode.
+ // The second argument is a glX attribute list, and is used if mode is
+ // zero. This is not supported on Win32:
+ static Fl_Gl_Choice *find(int mode, const int *);
+};
+
+class Fl_Window;
+
+#ifdef WIN32
+
+GLContext fl_create_gl_context(Fl_Window*, const Fl_Gl_Choice*, int layer=0);
+
+#elif defined(__APPLE_QD__)
+
+GLContext fl_create_gl_context(Fl_Window*, const Fl_Gl_Choice*, int layer=0);
+
+#elif defined(__APPLE_QUARTZ__)
+// warning: the Quartz version should probably use Core GL (CGL) instead of AGL
+
+GLContext fl_create_gl_context(Fl_Window*, const Fl_Gl_Choice*, int layer=0);
+
+#else
+
+GLContext fl_create_gl_context(XVisualInfo* vis);
+
+static inline
+GLContext fl_create_gl_context(Fl_Window*, const Fl_Gl_Choice* g) {
+ return fl_create_gl_context(g->vis);
+}
+
+#endif
+
+void fl_set_gl_context(Fl_Window*, GLContext);
+void fl_no_gl_context();
+void fl_delete_gl_context(GLContext);
+
+#endif
+
+//
+// End of "$Id: Fl_Gl_Choice.H 4052 2005-02-24 21:55:12Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Gl_Choice.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Gl_Choice.cxx new file mode 100644 index 0000000..124f1a0 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Gl_Choice.cxx @@ -0,0 +1,453 @@ +//
+// "$Id: Fl_Gl_Choice.cxx 6811 2009-06-30 19:05:09Z matt $"
+//
+// OpenGL visual selection code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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 <config.h>
+#if HAVE_GL
+
+# include <FL/Fl.H>
+# include <FL/x.H>
+# include <stdlib.h>
+# include "Fl_Gl_Choice.H"
+# include <FL/gl_draw.H>
+# include "flstring.h"
+
+# ifdef __APPLE__
+# include <FL/Fl_Window.H>
+# endif
+
+# ifdef WIN32
+void fl_save_dc(HWND, HDC);
+# endif
+
+static Fl_Gl_Choice *first;
+
+// this assummes one of the two arguments is zero:
+// We keep the list system in Win32 to stay compatible and interpret
+// the list later...
+Fl_Gl_Choice *Fl_Gl_Choice::find(int m, const int *alistp) {
+ Fl_Gl_Choice *g;
+
+ for (g = first; g; g = g->next)
+ if (g->mode == m && g->alist == alistp)
+ return g;
+
+# ifdef __APPLE_QD__
+ const int *blist;
+ int list[32];
+
+ if (alistp)
+ blist = alistp;
+ else {
+ int n = 0;
+ if (m & FL_INDEX) {
+ list[n++] = AGL_BUFFER_SIZE;
+ list[n++] = 8; // glut tries many sizes, but this should work...
+ } else {
+ list[n++] = AGL_RGBA;
+ list[n++] = AGL_GREEN_SIZE;
+ list[n++] = (m & FL_RGB8) ? 8 : 1;
+ if (m & FL_ALPHA) {
+ list[n++] = AGL_ALPHA_SIZE;
+ list[n++] = (m & FL_RGB8) ? 8 : 1;
+ }
+ if (m & FL_ACCUM) {
+ list[n++] = AGL_ACCUM_GREEN_SIZE;
+ list[n++] = 1;
+ if (m & FL_ALPHA) {
+ list[n++] = AGL_ACCUM_ALPHA_SIZE;
+ list[n++] = 1;
+ }
+ }
+ }
+ if (m & FL_DOUBLE) {
+ list[n++] = AGL_DOUBLEBUFFER;
+ }
+ if (m & FL_DEPTH) {
+ list[n++] = AGL_DEPTH_SIZE; list[n++] = 24;
+ }
+ if (m & FL_STENCIL) {
+ list[n++] = AGL_STENCIL_SIZE; list[n++] = 1;
+ }
+# ifdef AGL_STEREO
+ if (m & FL_STEREO) {
+ list[n++] = AGL_STEREO;
+ }
+# endif
+ list[n] = AGL_NONE;
+ blist = list;
+ }
+ fl_open_display();
+ AGLPixelFormat fmt = aglChoosePixelFormat(NULL, 0, (GLint*)blist);
+ if (!fmt) return 0;
+
+#elif defined(__APPLE_QUARTZ__)
+ // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
+ const int *blist;
+ int list[32];
+
+ if (alistp)
+ blist = alistp;
+ else {
+ int n = 0;
+ if (m & FL_INDEX) {
+ list[n++] = AGL_BUFFER_SIZE;
+ list[n++] = 8; // glut tries many sizes, but this should work...
+ } else {
+ list[n++] = AGL_RGBA;
+ list[n++] = AGL_GREEN_SIZE;
+ list[n++] = (m & FL_RGB8) ? 8 : 1;
+ if (m & FL_ALPHA) {
+ list[n++] = AGL_ALPHA_SIZE;
+ list[n++] = (m & FL_RGB8) ? 8 : 1;
+ }
+ if (m & FL_ACCUM) {
+ list[n++] = AGL_ACCUM_GREEN_SIZE;
+ list[n++] = 1;
+ if (m & FL_ALPHA) {
+ list[n++] = AGL_ACCUM_ALPHA_SIZE;
+ list[n++] = 1;
+ }
+ }
+ }
+ if (m & FL_DOUBLE) {
+ list[n++] = AGL_DOUBLEBUFFER;
+ }
+ if (m & FL_DEPTH) {
+ list[n++] = AGL_DEPTH_SIZE; list[n++] = 24;
+ }
+ if (m & FL_STENCIL) {
+ list[n++] = AGL_STENCIL_SIZE; list[n++] = 1;
+ }
+# ifdef AGL_STEREO
+ if (m & FL_STEREO) {
+ list[n++] = AGL_STEREO;
+ }
+# endif
+ list[n] = AGL_NONE;
+ blist = list;
+ }
+ fl_open_display();
+ AGLPixelFormat fmt = aglChoosePixelFormat(NULL, 0, (GLint*)blist);
+ if (!fmt) return 0;
+
+# elif !defined(WIN32)
+
+ const int *blist;
+ int list[32];
+
+ if (alistp)
+ blist = alistp;
+ else {
+ int n = 0;
+ if (m & FL_INDEX) {
+ list[n++] = GLX_BUFFER_SIZE;
+ list[n++] = 8; // glut tries many sizes, but this should work...
+ } else {
+ list[n++] = GLX_RGBA;
+ list[n++] = GLX_GREEN_SIZE;
+ list[n++] = (m & FL_RGB8) ? 8 : 1;
+ if (m & FL_ALPHA) {
+ list[n++] = GLX_ALPHA_SIZE;
+ list[n++] = (m & FL_RGB8) ? 8 : 1;
+ }
+ if (m & FL_ACCUM) {
+ list[n++] = GLX_ACCUM_GREEN_SIZE;
+ list[n++] = 1;
+ if (m & FL_ALPHA) {
+ list[n++] = GLX_ACCUM_ALPHA_SIZE;
+ list[n++] = 1;
+ }
+ }
+ }
+ if (m & FL_DOUBLE) {
+ list[n++] = GLX_DOUBLEBUFFER;
+ }
+ if (m & FL_DEPTH) {
+ list[n++] = GLX_DEPTH_SIZE; list[n++] = 1;
+ }
+ if (m & FL_STENCIL) {
+ list[n++] = GLX_STENCIL_SIZE; list[n++] = 1;
+ }
+ if (m & FL_STEREO) {
+ list[n++] = GLX_STEREO;
+ }
+# if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
+ if (m & FL_MULTISAMPLE) {
+ list[n++] = GLX_SAMPLES_SGIS;
+ list[n++] = 4; // value Glut uses
+ }
+# endif
+ list[n] = 0;
+ blist = list;
+ }
+
+ fl_open_display();
+ XVisualInfo *visp = glXChooseVisual(fl_display, fl_screen, (int *)blist);
+ if (!visp) {
+# if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
+ if (m&FL_MULTISAMPLE) return find(m&~FL_MULTISAMPLE,0);
+# endif
+ return 0;
+ }
+
+# else
+
+ // Replacement for ChoosePixelFormat() that finds one with an overlay
+ // if possible:
+ if (!fl_gc) fl_GetDC(0);
+ int pixelformat = 0;
+ PIXELFORMATDESCRIPTOR chosen_pfd;
+ for (int i = 1; ; i++) {
+ PIXELFORMATDESCRIPTOR pfd;
+ if (!DescribePixelFormat(fl_gc, i, sizeof(pfd), &pfd)) break;
+ // continue if it does not satisfy our requirements:
+ if (~pfd.dwFlags & (PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL)) continue;
+ if (pfd.iPixelType != ((m&FL_INDEX)?PFD_TYPE_COLORINDEX:PFD_TYPE_RGBA)) continue;
+ if ((m & FL_ALPHA) && !pfd.cAlphaBits) continue;
+ if ((m & FL_ACCUM) && !pfd.cAccumBits) continue;
+ if ((!(m & FL_DOUBLE)) != (!(pfd.dwFlags & PFD_DOUBLEBUFFER))) continue;
+ if ((!(m & FL_STEREO)) != (!(pfd.dwFlags & PFD_STEREO))) continue;
+ if ((m & FL_DEPTH) && !pfd.cDepthBits) continue;
+ if ((m & FL_STENCIL) && !pfd.cStencilBits) continue;
+ // see if better than the one we have already:
+ if (pixelformat) {
+ // offering non-generic rendering is better (read: hardware accelleration)
+ if (!(chosen_pfd.dwFlags & PFD_GENERIC_FORMAT) &&
+ (pfd.dwFlags & PFD_GENERIC_FORMAT)) continue;
+ // offering overlay is better:
+ else if (!(chosen_pfd.bReserved & 15) && (pfd.bReserved & 15)) {}
+ // otherwise more bit planes is better:
+ else if (chosen_pfd.cColorBits > pfd.cColorBits) continue;
+ else if (chosen_pfd.cDepthBits > pfd.cDepthBits) continue;
+ }
+ pixelformat = i;
+ chosen_pfd = pfd;
+ }
+ //printf("Chosen pixel format is %d\n", pixelformat);
+ if (!pixelformat) return 0;
+
+# endif
+
+ g = new Fl_Gl_Choice;
+ g->mode = m;
+ g->alist = alistp;
+ g->next = first;
+ first = g;
+
+# ifdef WIN32
+ g->pixelformat = pixelformat;
+ g->pfd = chosen_pfd;
+# elif defined(__APPLE_QD__)
+ g->pixelformat = fmt;
+# elif defined(__APPLE_QUARTZ__)
+ // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
+ g->pixelformat = fmt;
+# else
+ g->vis = visp;
+
+ if (/*MaxCmapsOfScreen(ScreenOfDisplay(fl_display,fl_screen))==1 && */
+ visp->visualid == fl_visual->visualid &&
+ !getenv("MESA_PRIVATE_CMAP"))
+ g->colormap = fl_colormap;
+ else
+ g->colormap = XCreateColormap(fl_display, RootWindow(fl_display,fl_screen),
+ visp->visual, AllocNone);
+# endif
+
+ return g;
+}
+
+static GLContext *context_list = 0;
+static int nContext = 0, NContext = 0;
+
+static void add_context(GLContext ctx) {
+ if (!ctx) return;
+ if (nContext==NContext) {
+ if (!NContext) NContext = 8;
+ NContext *= 2;
+ context_list = (GLContext*)realloc(
+ context_list, NContext*sizeof(GLContext));
+ }
+ context_list[nContext++] = ctx;
+}
+
+static void del_context(GLContext ctx) {
+ int i;
+ for (i=0; i<nContext; i++) {
+ if (context_list[i]==ctx) {
+ memmove(context_list+i, context_list+i+1,
+ (nContext-i-1) * sizeof(GLContext));
+ context_list[--nContext] = 0;
+ break;
+ }
+ }
+ if (!nContext) gl_remove_displaylist_fonts();
+}
+
+# ifdef WIN32
+
+GLContext fl_create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g, int layer) {
+ Fl_X* i = Fl_X::i(window);
+ HDC hdc = i->private_dc;
+ if (!hdc) {
+ hdc = i->private_dc = GetDCEx(i->xid, 0, DCX_CACHE);
+ fl_save_dc(i->xid, hdc);
+ SetPixelFormat(hdc, g->pixelformat, (PIXELFORMATDESCRIPTOR*)(&g->pfd));
+# if USE_COLORMAP
+ if (fl_palette) SelectPalette(hdc, fl_palette, FALSE);
+# endif
+ }
+ GLContext context =
+ layer ? wglCreateLayerContext(hdc, layer) : wglCreateContext(hdc);
+ if (context) {
+ if (context_list && nContext)
+ wglShareLists(context_list[0], context);
+ add_context(context);
+ }
+ return context;
+}
+
+# elif defined(__APPLE_QD__)
+GLContext fl_create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g, int layer) {
+ GLContext context, shared_ctx = 0;
+ if (context_list && nContext) shared_ctx = context_list[0];
+ context = aglCreateContext( g->pixelformat, shared_ctx);
+ if (!context) return 0;
+ add_context((GLContext)context);
+ if ( window->parent() ) {
+ Rect wrect; GetWindowPortBounds( fl_xid(window), &wrect );
+ GLint rect[] = { window->x(), wrect.bottom-window->h()-window->y(), window->w(), window->h() };
+ aglSetInteger( (GLContext)context, AGL_BUFFER_RECT, rect );
+ aglEnable( (GLContext)context, AGL_BUFFER_RECT );
+ }
+ aglSetDrawable( context, GetWindowPort( fl_xid(window) ) );
+ return (context);
+}
+# elif defined(__APPLE_QUARTZ__)
+ // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
+ GLContext fl_create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g, int layer) {
+ GLContext context, shared_ctx = 0;
+ if (context_list && nContext) shared_ctx = context_list[0];
+ context = aglCreateContext( g->pixelformat, shared_ctx);
+ if (!context) return 0;
+ add_context((GLContext)context);
+ if ( window->parent() ) {
+ Rect wrect; GetWindowPortBounds( fl_xid(window), &wrect );
+ GLint rect[] = { window->x(), wrect.bottom-window->h()-window->y(), window->w(), window->h() };
+ aglSetInteger( (GLContext)context, AGL_BUFFER_RECT, rect );
+ aglEnable( (GLContext)context, AGL_BUFFER_RECT );
+ }
+ aglSetDrawable( context, GetWindowPort( fl_xid(window) ) );
+ return (context);
+}
+# else
+
+GLContext fl_create_gl_context(XVisualInfo* vis) {
+ GLContext shared_ctx = 0;
+ if (context_list && nContext) shared_ctx = context_list[0];
+ GLContext context = glXCreateContext(fl_display, vis, shared_ctx, 1);
+ if (context)
+ add_context(context);
+ return context;
+}
+
+# endif
+
+static GLContext cached_context;
+static Fl_Window* cached_window;
+
+void fl_set_gl_context(Fl_Window* w, GLContext context) {
+ if (context != cached_context || w != cached_window) {
+ cached_context = context;
+ cached_window = w;
+# ifdef WIN32
+ wglMakeCurrent(Fl_X::i(w)->private_dc, context);
+# elif defined(__APPLE_QD__)
+ if ( w->parent() ) { //: resize our GL buffer rectangle
+ Rect wrect; GetWindowPortBounds( fl_xid(w), &wrect );
+ GLint rect[] = { w->x(), wrect.bottom-w->h()-w->y(), w->w(), w->h() };
+ aglSetInteger( context, AGL_BUFFER_RECT, rect );
+ aglEnable( context, AGL_BUFFER_RECT );
+ }
+ aglSetDrawable(context, GetWindowPort( fl_xid(w) ) );
+ aglSetCurrentContext(context);
+# elif defined(__APPLE_QUARTZ__)
+ // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
+ if ( w->parent() ) { //: resize our GL buffer rectangle
+ Rect wrect; GetWindowPortBounds( fl_xid(w), &wrect );
+ GLint rect[] = { w->x(), wrect.bottom-w->h()-w->y(), w->w(), w->h() };
+ aglSetInteger( context, AGL_BUFFER_RECT, rect );
+ aglEnable( context, AGL_BUFFER_RECT );
+ }
+ aglSetDrawable(context, GetWindowPort( fl_xid(w) ) );
+ aglSetCurrentContext(context);
+# else
+ glXMakeCurrent(fl_display, fl_xid(w), context);
+# endif
+ }
+}
+
+void fl_no_gl_context() {
+ cached_context = 0;
+ cached_window = 0;
+# ifdef WIN32
+ wglMakeCurrent(0, 0);
+# elif defined(__APPLE_QD__)
+ AGLContext ctx = aglGetCurrentContext();
+ if (ctx) aglSetDrawable(ctx, NULL);
+ aglSetCurrentContext(0);
+# elif defined(__APPLE_QUARTZ__)
+ // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
+ AGLContext ctx = aglGetCurrentContext();
+ if (ctx) aglSetDrawable(ctx, NULL);
+ aglSetCurrentContext(0);
+# else
+ glXMakeCurrent(fl_display, 0, 0);
+# endif
+}
+
+void fl_delete_gl_context(GLContext context) {
+ if (cached_context == context) fl_no_gl_context();
+# ifdef WIN32
+ wglDeleteContext(context);
+# elif defined(__APPLE_QD__)
+ aglDestroyContext( context );
+# elif defined(__APPLE_QUARTZ__)
+ // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
+ aglDestroyContext( context );
+# else
+ glXDestroyContext(fl_display, context);
+# endif
+ del_context(context);
+}
+
+#endif // HAVE_GL
+
+
+//
+// End of "$Id: Fl_Gl_Choice.cxx 6811 2009-06-30 19:05:09Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Gl_Overlay.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Gl_Overlay.cxx new file mode 100644 index 0000000..db95ab9 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Gl_Overlay.cxx @@ -0,0 +1,248 @@ +//
+// "$Id: Fl_Gl_Overlay.cxx 5350 2006-08-23 17:40:54Z mike $"
+//
+// OpenGL overlay code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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 <config.h>
+#if HAVE_GL
+
+#include <FL/Fl.H>
+#include <FL/x.H>
+#include "Fl_Gl_Choice.H"
+#include <FL/Fl_Gl_Window.H>
+#include <stdlib.h>
+
+#if !HAVE_GL_OVERLAY
+
+int Fl_Gl_Window::can_do_overlay() {return 0;}
+
+void Fl_Gl_Window::make_overlay() {overlay = this;}
+
+#else
+
+// Methods on Fl_Gl_Window that create an overlay window. Because
+// many programs don't need the overlay, this is seperated into this
+// source file so it is not linked in if not used.
+
+// Under X this is done by creating another window, of class _Fl_Gl_Overlay
+// which is a subclass of Fl_Gl_Window except it uses the overlay planes.
+// A pointer to this is stored in the "overlay" pointer of the Fl_Gl_Window.
+
+// Under win32 another GLX context is created to draw into the overlay
+// and it is stored in into the "overlay" pointer.
+
+// In both cases if overlay hardware is unavailable, the overlay is
+// "faked" by drawing into the main layers. This is indicated by
+// setting overlay == this.
+
+#ifndef WIN32
+////////////////////////////////////////////////////////////////
+// X version
+
+extern XVisualInfo *fl_find_overlay_visual();
+extern XVisualInfo *fl_overlay_visual;
+extern Colormap fl_overlay_colormap;
+extern unsigned long fl_transparent_pixel;
+extern uchar fl_overlay;
+
+class _Fl_Gl_Overlay : public Fl_Gl_Window {
+ void flush();
+ void draw();
+public:
+ void show();
+ _Fl_Gl_Overlay(int x, int y, int w, int h) :
+ Fl_Gl_Window(x,y,w,h) {
+ set_flag(INACTIVE);
+ }
+};
+
+void _Fl_Gl_Overlay::flush() {
+ make_current();
+#ifdef BOXX_BUGS
+ // The BoXX overlay is broken and you must not call swap-buffers. This
+ // code will make it work, but we lose because machines that do support
+ // double-buffered overlays will blink when they don't have to
+ glDrawBuffer(GL_FRONT);
+ draw();
+#else
+ draw();
+ swap_buffers();
+#endif
+ glFlush();
+ valid(1);
+}
+
+void _Fl_Gl_Overlay::draw() {
+ if (!valid()) glClearIndex((GLfloat)fl_transparent_pixel);
+ if (damage() != FL_DAMAGE_EXPOSE) glClear(GL_COLOR_BUFFER_BIT);
+ Fl_Gl_Window *w = (Fl_Gl_Window *)parent();
+ uchar save_valid = w->valid();
+ w->valid(valid());
+ fl_overlay = 1;
+ w->draw_overlay();
+ fl_overlay = 0;
+ valid(w->valid());
+ w->valid(save_valid);
+}
+
+void _Fl_Gl_Overlay::show() {
+ if (!shown()) {
+ fl_background_pixel = int(fl_transparent_pixel);
+ Fl_X::make_xid(this, fl_overlay_visual, fl_overlay_colormap);
+ fl_background_pixel = -1;
+ // find the outermost window to tell wm about the colormap:
+ Fl_Window *w = window();
+ for (;;) {Fl_Window *w1 = w->window(); if (!w1) break; w = w1;}
+ XSetWMColormapWindows(fl_display, fl_xid(w), &(Fl_X::i(this)->xid), 1);
+ context(fl_create_gl_context(fl_overlay_visual), 1);
+ valid(0);
+ }
+ Fl_Gl_Window::show();
+}
+
+int Fl_Gl_Window::can_do_overlay() {
+ return fl_find_overlay_visual() != 0;
+}
+
+void Fl_Gl_Window::make_overlay() {
+ if (overlay) return;
+ if (can_do_overlay()) {
+ _Fl_Gl_Overlay* o = new _Fl_Gl_Overlay(0,0,w(),h());
+ overlay = o;
+ add(*o);
+ o->show();
+ } else {
+ overlay = this; // fake the overlay
+ }
+}
+
+#else
+////////////////////////////////////////////////////////////////
+// WIN32 version:
+
+//static COLORREF *palette;
+extern int fl_overlay_depth;
+
+void Fl_Gl_Window::make_overlay() {
+ if (overlay) return;
+
+ GLContext context = fl_create_gl_context(this, g, 1);
+ if (!context) {overlay = this; return;} // fake the overlay
+
+ HDC hdc = Fl_X::i(this)->private_dc;
+ overlay = context;
+ LAYERPLANEDESCRIPTOR pfd;
+ wglDescribeLayerPlane(hdc, g->pixelformat, 1, sizeof(pfd), &pfd);
+ if (!pfd.iPixelType) {
+ ; // full-color overlay
+ } else {
+ fl_overlay_depth = pfd.cColorBits; // used by gl_color()
+ if (fl_overlay_depth > 8) fl_overlay_depth = 8;
+ COLORREF palette[256];
+ int n = (1<<fl_overlay_depth)-1;
+ // copy all colors except #0 into the overlay palette:
+ for (int i = 0; i <= n; i++) {
+ uchar r,g,b; Fl::get_color((Fl_Color)i,r,g,b);
+ palette[i] = RGB(r,g,b);
+ }
+ // always provide black & white in the last 2 pixels:
+ if (fl_overlay_depth < 8) {
+ palette[n-1] = RGB(0,0,0);
+ palette[n] = RGB(255,255,255);
+ }
+ // and use it:
+ wglSetLayerPaletteEntries(hdc, 1, 1, n, palette+1);
+ wglRealizeLayerPalette(hdc, 1, TRUE);
+ }
+ valid(0);
+ return;
+}
+
+int Fl_Gl_Window::can_do_overlay() {
+ if (!g) {
+ g = Fl_Gl_Choice::find(mode_,alist);
+ if (!g) return 0;
+ }
+ return (g->pfd.bReserved & 15) != 0;
+}
+
+////////////////////////////////////////////////////////////////
+#endif
+
+#endif
+
+void Fl_Gl_Window::redraw_overlay() {
+ if (!shown()) return;
+ make_overlay();
+#ifdef __APPLE__
+ redraw();
+#else
+#ifndef WIN32
+ if (overlay != this)
+ ((Fl_Gl_Window*)overlay)->redraw();
+ else
+#endif
+ damage(FL_DAMAGE_OVERLAY);
+#endif
+}
+
+void Fl_Gl_Window::make_overlay_current() {
+ make_overlay();
+#ifdef __APPLE__
+ // this is not very useful, but unfortunatly, Apple decided
+ // that front buffer drawing can no longer (OS X 10.4) be
+ // supported on their platforms.
+ make_current();
+#else
+#if HAVE_GL_OVERLAY
+ if (overlay != this) {
+#ifdef WIN32
+ fl_set_gl_context(this, (GLContext)overlay);
+// if (fl_overlay_depth)
+// wglRealizeLayerPalette(Fl_X::i(this)->private_dc, 1, TRUE);
+#else
+ ((Fl_Gl_Window*)overlay)->make_current();
+#endif
+ } else
+#endif
+ glDrawBuffer(GL_FRONT);
+#endif
+}
+
+void Fl_Gl_Window::hide_overlay() {
+#if HAVE_GL_OVERLAY
+#ifdef WIN32
+ // nothing needs to be done? Or should it be erased?
+#else
+ if (overlay && overlay!=this) ((Fl_Gl_Window*)overlay)->hide();
+#endif
+#endif
+}
+
+#endif
+
+//
+// End of "$Id: Fl_Gl_Overlay.cxx 5350 2006-08-23 17:40:54Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Gl_Window.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Gl_Window.cxx new file mode 100644 index 0000000..0deecca --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Gl_Window.cxx @@ -0,0 +1,440 @@ +//
+// "$Id: Fl_Gl_Window.cxx 6807 2009-06-30 13:38:52Z matt $"
+//
+// OpenGL window code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2006 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 "flstring.h"
+#if HAVE_GL
+
+#include <FL/Fl.H>
+#include <FL/x.H>
+#include "Fl_Gl_Choice.H"
+#include <FL/Fl_Gl_Window.H>
+#include <stdlib.h>
+
+////////////////////////////////////////////////////////////////
+
+// The symbol SWAP_TYPE defines what is in the back buffer after doing
+// a glXSwapBuffers().
+
+// The OpenGl documentation says that the contents of the backbuffer
+// are "undefined" after glXSwapBuffers(). However, if we know what
+// is in the backbuffers then we can save a good deal of time. For
+// this reason you can define some symbols to describe what is left in
+// the back buffer.
+
+// Having not found any way to determine this from glx (or wgl) I have
+// resorted to letting the user specify it with an environment variable,
+// GL_SWAP_TYPE, it should be equal to one of these symbols:
+
+// contents of back buffer after glXSwapBuffers():
+#define UNDEFINED 1 // anything
+#define SWAP 2 // former front buffer (same as unknown)
+#define COPY 3 // unchanged
+#define NODAMAGE 4 // unchanged even by X expose() events
+
+static char SWAP_TYPE = 0 ; // 0 = determine it from environment variable
+
+////////////////////////////////////////////////////////////////
+
+int Fl_Gl_Window::can_do(int a, const int *b) {
+ return Fl_Gl_Choice::find(a,b) != 0;
+}
+
+void Fl_Gl_Window::show() {
+ if (!shown()) {
+ if (!g) {
+ g = Fl_Gl_Choice::find(mode_,alist);
+
+ if (!g && (mode_ & FL_DOUBLE) == FL_SINGLE) {
+ g = Fl_Gl_Choice::find(mode_ | FL_DOUBLE,alist);
+ if (g) mode_ |= FL_FAKE_SINGLE;
+ }
+
+ if (!g) {
+ Fl::error("Insufficient GL support");
+ return;
+ }
+ }
+#if !defined(WIN32) && !defined(__APPLE__)
+ Fl_X::make_xid(this, g->vis, g->colormap);
+ if (overlay && overlay != this) ((Fl_Gl_Window*)overlay)->show();
+#endif
+ }
+ Fl_Window::show();
+
+#ifdef __APPLE__
+ set_visible();
+#endif /* __APPLE__ */
+}
+
+void Fl_Gl_Window::invalidate() {
+ valid(0);
+ context_valid(0);
+#ifndef WIN32
+ if (overlay) {
+ ((Fl_Gl_Window*)overlay)->valid(0);
+ ((Fl_Gl_Window*)overlay)->context_valid(0);
+ }
+#endif
+}
+
+int Fl_Gl_Window::mode(int m, const int *a) {
+ if (m == mode_ && a == alist) return 0;
+#ifndef __APPLE__
+ int oldmode = mode_;
+#endif // !__APPLE__
+#if !defined(WIN32) && !defined(__APPLE__)
+ Fl_Gl_Choice* oldg = g;
+#endif // !WIN32 && !__APPLE__
+ context(0);
+ mode_ = m; alist = a;
+ if (shown()) {
+ g = Fl_Gl_Choice::find(m, a);
+#if defined(WIN32)
+ if (!g || (oldmode^m)&(FL_DOUBLE|FL_STEREO)) {
+ hide();
+ show();
+ }
+#elif defined(__APPLE_QD__)
+ redraw();
+#elif defined(__APPLE_QUARTZ__)
+ // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
+ redraw();
+#else
+ // under X, if the visual changes we must make a new X window (yuck!):
+ if (!g || g->vis->visualid!=oldg->vis->visualid || (oldmode^m)&FL_DOUBLE) {
+ hide();
+ show();
+ }
+#endif
+ } else {
+ g = 0;
+ }
+ return 1;
+}
+
+#define NON_LOCAL_CONTEXT 0x80000000
+
+void Fl_Gl_Window::make_current() {
+// puts("Fl_Gl_Window::make_current()");
+// printf("make_current: context_=%p\n", context_);
+ if (!context_) {
+ mode_ &= ~NON_LOCAL_CONTEXT;
+ context_ = fl_create_gl_context(this, g);
+ valid(0);
+ context_valid(0);
+ }
+ fl_set_gl_context(this, context_);
+
+#ifdef __APPLE__
+ // Set the buffer rectangle here, since in resize() we won't have the
+ // correct parent window size to work with...
+ GLint xywh[4];
+
+ if (window()) {
+ xywh[0] = x();
+ xywh[1] = window()->h() - y() - h();
+ } else {
+ xywh[0] = 0;
+ xywh[1] = 0;
+ }
+
+ xywh[2] = w();
+ xywh[3] = h();
+
+ aglSetInteger(context_, AGL_BUFFER_RECT, xywh);
+ aglEnable(context_, AGL_BUFFER_RECT);
+// printf("make_current: xywh=[%d %d %d %d]\n", xywh[0], xywh[1], xywh[2], xywh[3]);
+#endif // __APPLE__
+
+#if defined(WIN32) && USE_COLORMAP
+ if (fl_palette) {
+ fl_GetDC(fl_xid(this));
+ SelectPalette(fl_gc, fl_palette, FALSE);
+ RealizePalette(fl_gc);
+ }
+#endif // USE_COLORMAP
+ if (mode_ & FL_FAKE_SINGLE) {
+ glDrawBuffer(GL_FRONT);
+ glReadBuffer(GL_FRONT);
+ }
+ current_ = this;
+}
+
+void Fl_Gl_Window::ortho() {
+// Alpha NT seems to have a broken OpenGL that does not like negative coords:
+#ifdef _M_ALPHA
+ glLoadIdentity();
+ glViewport(0, 0, w(), h());
+ glOrtho(0, w(), 0, h(), -1, 1);
+#else
+ GLint v[2];
+ glGetIntegerv(GL_MAX_VIEWPORT_DIMS, v);
+ glLoadIdentity();
+ glViewport(w()-v[0], h()-v[1], v[0], v[1]);
+ glOrtho(w()-v[0], w(), h()-v[1], h(), -1, 1);
+#endif
+}
+
+void Fl_Gl_Window::swap_buffers() {
+#ifdef WIN32
+# if HAVE_GL_OVERLAY
+ // Do not swap the overlay, to match GLX:
+ BOOL ret = wglSwapLayerBuffers(Fl_X::i(this)->private_dc, WGL_SWAP_MAIN_PLANE);
+ DWORD err = GetLastError();;
+# else
+ SwapBuffers(Fl_X::i(this)->private_dc);
+# endif
+#elif defined(__APPLE_QD__)
+ aglSwapBuffers((AGLContext)context_);
+#elif defined(__APPLE_QUARTZ__)
+ // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
+ aglSwapBuffers((AGLContext)context_);
+#else
+ glXSwapBuffers(fl_display, fl_xid(this));
+#endif
+}
+
+#if HAVE_GL_OVERLAY && defined(WIN32)
+uchar fl_overlay; // changes how fl_color() works
+int fl_overlay_depth = 0;
+#endif
+
+void Fl_Gl_Window::flush() {
+ uchar save_valid = valid_f_ & 1;
+#if HAVE_GL_OVERLAY && defined(WIN32)
+ uchar save_valid_f = valid_f_;
+#endif
+
+#ifdef __APPLE_QD__
+ //: clear previous clipping in this shared port
+ GrafPtr port = GetWindowPort( fl_xid(this) );
+ Rect rect; SetRect( &rect, 0, 0, 0x7fff, 0x7fff );
+ GrafPtr old; GetPort( &old );
+ SetPort( port );
+ ClipRect( &rect );
+ SetPort( old );
+#elif defined(__APPLE_QUARTZ__)
+ // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
+ //: clear previous clipping in this shared port
+ GrafPtr port = GetWindowPort( fl_xid(this) );
+ Rect rect; SetRect( &rect, 0, 0, 0x7fff, 0x7fff );
+ GrafPtr old; GetPort( &old );
+ SetPort( port );
+ ClipRect( &rect );
+ SetPort( old );
+#endif
+
+#if HAVE_GL_OVERLAY && defined(WIN32)
+
+ bool fixcursor = false; // for fixing the SGI 320 bug
+
+ // Draw into hardware overlay planes if they are damaged:
+ if (overlay && overlay != this
+ && (damage()&(FL_DAMAGE_OVERLAY|FL_DAMAGE_EXPOSE) || !save_valid)) {
+ // SGI 320 messes up overlay with user-defined cursors:
+ if (Fl_X::i(this)->cursor && Fl_X::i(this)->cursor != fl_default_cursor) {
+ fixcursor = true; // make it restore cursor later
+ SetCursor(0);
+ }
+ fl_set_gl_context(this, (GLContext)overlay);
+ if (fl_overlay_depth)
+ wglRealizeLayerPalette(Fl_X::i(this)->private_dc, 1, TRUE);
+ glDisable(GL_SCISSOR_TEST);
+ glClear(GL_COLOR_BUFFER_BIT);
+ fl_overlay = 1;
+ draw_overlay();
+ fl_overlay = 0;
+ valid_f_ = save_valid_f;
+ wglSwapLayerBuffers(Fl_X::i(this)->private_dc, WGL_SWAP_OVERLAY1);
+ // if only the overlay was damaged we are done, leave main layer alone:
+ if (damage() == FL_DAMAGE_OVERLAY) {
+ if (fixcursor) SetCursor(Fl_X::i(this)->cursor);
+ return;
+ }
+ }
+#endif
+
+ make_current();
+
+ if (mode_ & FL_DOUBLE) {
+
+ glDrawBuffer(GL_BACK);
+
+ if (!SWAP_TYPE) {
+#ifdef __APPLE_QD__
+ SWAP_TYPE = COPY;
+#elif defined __APPLE_QUARTZ__
+ // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
+ SWAP_TYPE = COPY;
+#else
+ SWAP_TYPE = UNDEFINED;
+#endif
+ const char* c = getenv("GL_SWAP_TYPE");
+ if (c) {
+ if (!strcmp(c,"COPY")) SWAP_TYPE = COPY;
+ else if (!strcmp(c, "NODAMAGE")) SWAP_TYPE = NODAMAGE;
+ else if (!strcmp(c, "SWAP")) SWAP_TYPE = SWAP;
+ }
+ }
+
+ if (SWAP_TYPE == NODAMAGE) {
+
+ // don't draw if only overlay damage or expose events:
+ if ((damage()&~(FL_DAMAGE_OVERLAY|FL_DAMAGE_EXPOSE)) || !save_valid)
+ draw();
+ swap_buffers();
+
+ } else if (SWAP_TYPE == COPY) {
+
+ // don't draw if only the overlay is damaged:
+ if (damage() != FL_DAMAGE_OVERLAY || !save_valid) draw();
+ swap_buffers();
+
+ } else { // SWAP_TYPE == UNDEFINED
+
+ // If we are faking the overlay, use CopyPixels to act like
+ // SWAP_TYPE == COPY. Otherwise overlay redraw is way too slow.
+ if (overlay == this) {
+ // don't draw if only the overlay is damaged:
+ if (damage1_ || damage() != FL_DAMAGE_OVERLAY || !save_valid) draw();
+ // we use a seperate context for the copy because rasterpos must be 0
+ // and depth test needs to be off:
+ static GLContext ortho_context = 0;
+ static Fl_Gl_Window* ortho_window = 0;
+ int orthoinit = !ortho_context;
+ if (orthoinit) ortho_context = fl_create_gl_context(this, g);
+ fl_set_gl_context(this, ortho_context);
+ if (orthoinit || !save_valid || ortho_window != this) {
+ glDisable(GL_DEPTH_TEST);
+ glReadBuffer(GL_BACK);
+ glDrawBuffer(GL_FRONT);
+ glLoadIdentity();
+ glViewport(0, 0, w(), h());
+ glOrtho(0, w(), 0, h(), -1, 1);
+ glRasterPos2i(0,0);
+ ortho_window = this;
+ }
+ glCopyPixels(0,0,w(),h(),GL_COLOR);
+ make_current(); // set current context back to draw overlay
+ damage1_ = 0;
+
+ } else {
+ damage1_ = damage();
+ clear_damage(0xff); draw();
+ swap_buffers();
+ }
+
+ }
+
+ if (overlay==this) { // fake overlay in front buffer
+ glDrawBuffer(GL_FRONT);
+ draw_overlay();
+ glDrawBuffer(GL_BACK);
+ glFlush();
+ }
+
+ } else { // single-buffered context is simpler:
+
+ draw();
+ if (overlay == this) draw_overlay();
+ glFlush();
+
+ }
+
+#if HAVE_GL_OVERLAY && defined(WIN32)
+ if (fixcursor) SetCursor(Fl_X::i(this)->cursor);
+#endif
+ valid(1);
+ context_valid(1);
+}
+
+void Fl_Gl_Window::resize(int X,int Y,int W,int H) {
+// printf("Fl_Gl_Window::resize(X=%d, Y=%d, W=%d, H=%d)\n", X, Y, W, H);
+// printf("current: x()=%d, y()=%d, w()=%d, h()=%d\n", x(), y(), w(), h());
+
+ if (W != w() || H != h()) valid(0);
+
+#ifdef __APPLE__
+ if (X != x() || Y != y() || W != w() || H != h()) aglUpdateContext(context_);
+#elif !defined(WIN32)
+ if ((W != w() || H != h()) && !resizable() && overlay && overlay != this) {
+ ((Fl_Gl_Window*)overlay)->resize(0,0,W,H);
+ }
+#endif
+
+ Fl_Window::resize(X,Y,W,H);
+}
+
+void Fl_Gl_Window::context(void* v, int destroy_flag) {
+ if (context_ && !(mode_&NON_LOCAL_CONTEXT)) fl_delete_gl_context(context_);
+ context_ = (GLContext)v;
+ if (destroy_flag) mode_ &= ~NON_LOCAL_CONTEXT;
+ else mode_ |= NON_LOCAL_CONTEXT;
+}
+
+void Fl_Gl_Window::hide() {
+ context(0);
+#if HAVE_GL_OVERLAY && defined(WIN32)
+ if (overlay && overlay != this) {
+ fl_delete_gl_context((GLContext)overlay);
+ overlay = 0;
+ }
+#endif
+ Fl_Window::hide();
+}
+
+Fl_Gl_Window::~Fl_Gl_Window() {
+ hide();
+// delete overlay; this is done by ~Fl_Group
+}
+
+void Fl_Gl_Window::init() {
+ end(); // we probably don't want any children
+ box(FL_NO_BOX);
+
+ mode_ = FL_RGB | FL_DEPTH | FL_DOUBLE;
+ alist = 0;
+ context_ = 0;
+ g = 0;
+ overlay = 0;
+ valid_f_ = 0;
+ damage1_ = 0;
+
+#if 0 // This breaks resizing on Linux/X11
+ int H = h();
+ h(1); // Make sure we actually do something in resize()...
+ resize(x(), y(), w(), H);
+#endif // 0
+}
+
+void Fl_Gl_Window::draw_overlay() {}
+
+#endif
+
+//
+// End of "$Id: Fl_Gl_Window.cxx 6807 2009-06-30 13:38:52Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Group.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Group.cxx new file mode 100644 index 0000000..b3ab928 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Group.cxx @@ -0,0 +1,623 @@ +//
+// "$Id: Fl_Group.cxx 6463 2008-10-19 06:40:02Z AlbrechtS $"
+//
+// Group widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// The Fl_Group is the only defined container type in FLTK.
+
+// Fl_Window itself is a subclass of this, and most of the event
+// handling is designed so windows themselves work correctly.
+
+#include <stdio.h>
+#include <FL/Fl.H>
+#include <FL/Fl_Group.H>
+#include <FL/Fl_Window.H>
+#include <FL/fl_draw.H>
+#include <stdlib.h>
+
+Fl_Group* Fl_Group::current_;
+
+// Hack: A single child is stored in the pointer to the array, while
+// multiple children are stored in an allocated array:
+Fl_Widget*const* Fl_Group::array() const {
+ return children_ <= 1 ? (Fl_Widget**)(&array_) : array_;
+}
+
+int Fl_Group::find(const Fl_Widget* o) const {
+ Fl_Widget*const* a = array();
+ int i; for (i=0; i < children_; i++) if (*a++ == o) break;
+ return i;
+}
+
+// Metrowerks CodeWarrior and others can't export the static
+// class member: current_, so these methods can't be inlined...
+void Fl_Group::begin() {current_ = this;}
+void Fl_Group::end() {current_ = (Fl_Group*)parent();}
+Fl_Group *Fl_Group::current() {return current_;}
+void Fl_Group::current(Fl_Group *g) {current_ = g;}
+
+extern Fl_Widget* fl_oldfocus; // set by Fl::focus
+
+// For back-compatability, we must adjust all events sent to child
+// windows so they are relative to that window.
+
+static int send(Fl_Widget* o, int event) {
+ if (o->type() < FL_WINDOW) return o->handle(event);
+ switch ( event )
+ {
+ case FL_DND_ENTER:
+ case FL_DND_DRAG:
+ // figure out correct type of event:
+ event = (o->contains(Fl::belowmouse())) ? FL_DND_DRAG : FL_DND_ENTER;
+ }
+ int save_x = Fl::e_x; Fl::e_x -= o->x();
+ int save_y = Fl::e_y; Fl::e_y -= o->y();
+ int ret = o->handle(event);
+ Fl::e_y = save_y;
+ Fl::e_x = save_x;
+ switch ( event )
+ {
+ case FL_ENTER:
+ case FL_DND_ENTER:
+ // Successful completion of FL_ENTER means the widget is now the
+ // belowmouse widget, but only call Fl::belowmouse if the child
+ // widget did not do so:
+ if (!o->contains(Fl::belowmouse())) Fl::belowmouse(o);
+ break;
+ }
+ return ret;
+}
+
+// translate the current keystroke into up/down/left/right for navigation:
+#define ctrl(x) (x^0x40)
+static int navkey() {
+ switch (Fl::event_key()) {
+ case 0: // not an FL_KEYBOARD/FL_SHORTCUT event
+ break;
+ case FL_Tab:
+ if (!Fl::event_state(FL_SHIFT)) return FL_Right;
+ case 0xfe20: // XK_ISO_Left_Tab
+ return FL_Left;
+ case FL_Right:
+ return FL_Right;
+ case FL_Left:
+ return FL_Left;
+ case FL_Up:
+ return FL_Up;
+ case FL_Down:
+ return FL_Down;
+ }
+ return 0;
+}
+
+int Fl_Group::handle(int event) {
+
+ Fl_Widget*const* a = array();
+ int i;
+ Fl_Widget* o;
+
+ switch (event) {
+
+ case FL_FOCUS:
+ switch (navkey()) {
+ default:
+ if (savedfocus_ && savedfocus_->take_focus()) return 1;
+ case FL_Right:
+ case FL_Down:
+ for (i = children(); i--;) if ((*a++)->take_focus()) return 1;
+ break;
+ case FL_Left:
+ case FL_Up:
+ for (i = children(); i--;) if (a[i]->take_focus()) return 1;
+ break;
+ }
+ return 0;
+
+ case FL_UNFOCUS:
+ savedfocus_ = fl_oldfocus;
+ return 0;
+
+ case FL_KEYBOARD:
+ return navigation(navkey());
+
+ case FL_SHORTCUT:
+ for (i = children(); i--;) {
+ o = a[i];
+ if (o->takesevents() && Fl::event_inside(o) && send(o,FL_SHORTCUT))
+ return 1;
+ }
+ for (i = children(); i--;) {
+ o = a[i];
+ if (o->takesevents() && !Fl::event_inside(o) && send(o,FL_SHORTCUT))
+ return 1;
+ }
+ if ((Fl::event_key() == FL_Enter || Fl::event_key() == FL_KP_Enter)) return navigation(FL_Down);
+ return 0;
+
+ case FL_ENTER:
+ case FL_MOVE:
+ for (i = children(); i--;) {
+ o = a[i];
+ if (o->visible() && Fl::event_inside(o)) {
+ if (o->contains(Fl::belowmouse())) {
+ return send(o,FL_MOVE);
+ } else {
+ Fl::belowmouse(o);
+ if (send(o,FL_ENTER)) return 1;
+ }
+ }
+ }
+ Fl::belowmouse(this);
+ return 1;
+
+ case FL_DND_ENTER:
+ case FL_DND_DRAG:
+ for (i = children(); i--;) {
+ o = a[i];
+ if (o->takesevents() && Fl::event_inside(o)) {
+ if (o->contains(Fl::belowmouse())) {
+ return send(o,FL_DND_DRAG);
+ } else if (send(o,FL_DND_ENTER)) {
+ if (!o->contains(Fl::belowmouse())) Fl::belowmouse(o);
+ return 1;
+ }
+ }
+ }
+ Fl::belowmouse(this);
+ return 0;
+
+ case FL_PUSH:
+ for (i = children(); i--;) {
+ o = a[i];
+ if (o->takesevents() && Fl::event_inside(o)) {
+ if (send(o,FL_PUSH)) {
+ if (Fl::pushed() && !o->contains(Fl::pushed())) Fl::pushed(o);
+ return 1;
+ }
+ }
+ }
+ return 0;
+
+ case FL_RELEASE:
+ case FL_DRAG:
+ o = Fl::pushed();
+ if (o == this) return 0;
+ else if (o) send(o,event);
+ else {
+ for (i = children(); i--;) {
+ o = a[i];
+ if (o->takesevents() && Fl::event_inside(o)) {
+ if (send(o,event)) return 1;
+ }
+ }
+ }
+ return 0;
+
+ case FL_MOUSEWHEEL:
+ for (i = children(); i--;) {
+ o = a[i];
+ if (o->takesevents() && Fl::event_inside(o) && send(o,FL_MOUSEWHEEL))
+ return 1;
+ }
+ for (i = children(); i--;) {
+ o = a[i];
+ if (o->takesevents() && !Fl::event_inside(o) && send(o,FL_MOUSEWHEEL))
+ return 1;
+ }
+ return 0;
+
+ case FL_DEACTIVATE:
+ case FL_ACTIVATE:
+ for (i = children(); i--;) {
+ o = *a++;
+ if (o->active()) o->handle(event);
+ }
+ return 1;
+
+ case FL_SHOW:
+ case FL_HIDE:
+ for (i = children(); i--;) {
+ o = *a++;
+ if (event == FL_HIDE && o == Fl::focus()) {
+ // Give up input focus...
+ int old_event = Fl::e_number;
+ o->handle(Fl::e_number = FL_UNFOCUS);
+ Fl::e_number = old_event;
+ Fl::focus(0);
+ }
+ if (o->visible()) o->handle(event);
+ }
+ return 1;
+
+ default:
+ // For all other events, try to give to each child, starting at focus:
+ for (i = 0; i < children(); i ++)
+ if (Fl::focus_ == a[i]) break;
+
+ if (i >= children()) i = 0;
+
+ if (children()) {
+ for (int j = i;;) {
+ if (a[j]->takesevents()) if (send(a[j], event)) return 1;
+ j++;
+ if (j >= children()) j = 0;
+ if (j == i) break;
+ }
+ }
+
+ return 0;
+ }
+}
+
+//void Fl_Group::focus(Fl_Widget *o) {Fl::focus(o); o->handle(FL_FOCUS);}
+
+#if 0
+const char *nameof(Fl_Widget *o) {
+ if (!o) return "NULL";
+ if (!o->label()) return "<no label>";
+ return o->label();
+}
+#endif
+
+// try to move the focus in response to a keystroke:
+int Fl_Group::navigation(int key) {
+ if (children() <= 1) return 0;
+ int i;
+ for (i = 0; ; i++) {
+ if (i >= children_) return 0;
+ if (array_[i]->contains(Fl::focus())) break;
+ }
+ Fl_Widget *previous = array_[i];
+
+ for (;;) {
+ switch (key) {
+ case FL_Right:
+ case FL_Down:
+ i++;
+ if (i >= children_) {
+ if (parent()) return 0;
+ i = 0;
+ }
+ break;
+ case FL_Left:
+ case FL_Up:
+ if (i) i--;
+ else {
+ if (parent()) return 0;
+ i = children_-1;
+ }
+ break;
+ default:
+ return 0;
+ }
+ Fl_Widget* o = array_[i];
+ if (o == previous) return 0;
+ switch (key) {
+ case FL_Down:
+ case FL_Up:
+ // for up/down, the widgets have to overlap horizontally:
+ if (o->x() >= previous->x()+previous->w() ||
+ o->x()+o->w() <= previous->x()) continue;
+ }
+ if (o->take_focus()) return 1;
+ }
+}
+
+////////////////////////////////////////////////////////////////
+
+Fl_Group::Fl_Group(int X,int Y,int W,int H,const char *l)
+: Fl_Widget(X,Y,W,H,l) {
+ align(FL_ALIGN_TOP);
+ children_ = 0;
+ array_ = 0;
+ savedfocus_ = 0;
+ resizable_ = this;
+ sizes_ = 0; // this is allocated when first resize() is done
+ // Subclasses may want to construct child objects as part of their
+ // constructor, so make sure they are add()'d to this object.
+ // But you must end() the object!
+ begin();
+}
+
+void Fl_Group::clear() {
+ Fl_Widget*const* old_array = array();
+ int old_children = children();
+ // clear everything now, in case fl_fix_focus recursively calls us:
+ children_ = 0;
+ //array_ = 0; //dont do this, it will clobber old_array if only one child
+ savedfocus_ = 0;
+ resizable_ = this;
+ init_sizes();
+ // okay, now it is safe to destroy the children:
+ Fl_Widget*const* a = old_array;
+ for (int i=old_children; i--;) {
+ Fl_Widget* o = *a++;
+ if (o->parent() == this) delete o;
+ }
+ if (old_children > 1) free((void*)old_array);
+}
+
+Fl_Group::~Fl_Group() {
+ clear();
+}
+
+void Fl_Group::insert(Fl_Widget &o, int index) {
+ if (o.parent()) {
+ Fl_Group* g = (Fl_Group*)(o.parent());
+ int n = g->find(o);
+ if (g == this) {
+ if (index > n) index--;
+ if (index == n) return;
+ }
+ g->remove(o);
+ }
+ o.parent_ = this;
+ if (children_ == 0) { // use array pointer to point at single child
+ array_ = (Fl_Widget**)&o;
+ } else if (children_ == 1) { // go from 1 to 2 children
+ Fl_Widget* t = (Fl_Widget*)array_;
+ array_ = (Fl_Widget**)malloc(2*sizeof(Fl_Widget*));
+ if (index) {array_[0] = t; array_[1] = &o;}
+ else {array_[0] = &o; array_[1] = t;}
+ } else {
+ if (!(children_ & (children_-1))) // double number of children
+ array_ = (Fl_Widget**)realloc((void*)array_,
+ 2*children_*sizeof(Fl_Widget*));
+ int j; for (j = children_; j > index; j--) array_[j] = array_[j-1];
+ array_[j] = &o;
+ }
+ children_++;
+ init_sizes();
+}
+
+void Fl_Group::add(Fl_Widget &o) {insert(o, children_);}
+
+void Fl_Group::remove(Fl_Widget &o) {
+ if (!children_) return;
+ int i = find(o);
+ if (i >= children_) return;
+ if (&o == savedfocus_) savedfocus_ = 0;
+ o.parent_ = 0;
+ children_--;
+ if (children_ == 1) { // go from 2 to 1 child
+ Fl_Widget *t = array_[!i];
+ free((void*)array_);
+ array_ = (Fl_Widget**)t;
+ } else if (children_ > 1) { // delete from array
+ for (; i < children_; i++) array_[i] = array_[i+1];
+ }
+ init_sizes();
+}
+
+////////////////////////////////////////////////////////////////
+
+// Rather lame kludge here, I need to detect windows and ignore the
+// changes to X,Y, since all children are relative to X,Y. That
+// is why I check type():
+
+// sizes array stores the initial positions of widgets as
+// left,right,top,bottom quads. The first quad is the group, the
+// second is the resizable (clipped to the group), and the
+// rest are the children. This is a convienent order for the
+// algorithim. If you change this be sure to fix Fl_Tile which
+// also uses this array!
+
+void Fl_Group::init_sizes() {
+ delete[] sizes_; sizes_ = 0;
+}
+
+short* Fl_Group::sizes() {
+ if (!sizes_) {
+ short* p = sizes_ = new short[4*(children_+2)];
+ // first thing in sizes array is the group's size:
+ if (type() < FL_WINDOW) {p[0] = x(); p[2] = y();} else {p[0] = p[2] = 0;}
+ p[1] = p[0]+w(); p[3] = p[2]+h();
+ // next is the resizable's size:
+ p[4] = p[0]; // init to the group's size
+ p[5] = p[1];
+ p[6] = p[2];
+ p[7] = p[3];
+ Fl_Widget* r = resizable();
+ if (r && r != this) { // then clip the resizable to it
+ int t;
+ t = r->x(); if (t > p[0]) p[4] = t;
+ t +=r->w(); if (t < p[1]) p[5] = t;
+ t = r->y(); if (t > p[2]) p[6] = t;
+ t +=r->h(); if (t < p[3]) p[7] = t;
+ }
+ // next is all the children's sizes:
+ p += 8;
+ Fl_Widget*const* a = array();
+ for (int i=children_; i--;) {
+ Fl_Widget* o = *a++;
+ *p++ = o->x();
+ *p++ = o->x()+o->w();
+ *p++ = o->y();
+ *p++ = o->y()+o->h();
+ }
+ }
+ return sizes_;
+}
+
+void Fl_Group::resize(int X, int Y, int W, int H) {
+
+ int dx = X-x();
+ int dy = Y-y();
+ int dw = W-w();
+ int dh = H-h();
+
+ short *p = sizes(); // save initial sizes and positions
+
+ Fl_Widget::resize(X,Y,W,H); // make new xywh values visible for children
+
+ if (!resizable() || dw==0 && dh==0 ) {
+
+ if (type() < FL_WINDOW) {
+ Fl_Widget*const* a = array();
+ for (int i=children_; i--;) {
+ Fl_Widget* o = *a++;
+ o->resize(o->x()+dx, o->y()+dy, o->w(), o->h());
+ }
+ }
+
+ } else if (children_) {
+
+ // get changes in size/position from the initial size:
+ dx = X - p[0];
+ dw = W - (p[1]-p[0]);
+ dy = Y - p[2];
+ dh = H - (p[3]-p[2]);
+ if (type() >= FL_WINDOW) dx = dy = 0;
+ p += 4;
+
+ // get initial size of resizable():
+ int IX = *p++;
+ int IR = *p++;
+ int IY = *p++;
+ int IB = *p++;
+
+ Fl_Widget*const* a = array();
+ for (int i=children_; i--;) {
+ Fl_Widget* o = *a++;
+#if 1
+ int XX = *p++;
+ if (XX >= IR) XX += dw;
+ else if (XX > IX) XX = IX+((XX-IX)*(IR+dw-IX)+(IR-IX)/2)/(IR-IX);
+ int R = *p++;
+ if (R >= IR) R += dw;
+ else if (R > IX) R = IX+((R-IX)*(IR+dw-IX)+(IR-IX)/2)/(IR-IX);
+
+ int YY = *p++;
+ if (YY >= IB) YY += dh;
+ else if (YY > IY) YY = IY+((YY-IY)*(IB+dh-IY)+(IB-IY)/2)/(IB-IY);
+ int B = *p++;
+ if (B >= IB) B += dh;
+ else if (B > IY) B = IY+((B-IY)*(IB+dh-IY)+(IB-IY)/2)/(IB-IY);
+#else // much simpler code from Francois Ostiguy:
+ int XX = *p++;
+ if (XX >= IR) XX += dw;
+ else if (XX > IX) XX += dw * (XX-IX)/(IR-IX);
+ int R = *p++;
+ if (R >= IR) R += dw;
+ else if (R > IX) R = R + dw * (R-IX)/(IR-IX);
+
+ int YY = *p++;
+ if (YY >= IB) YY += dh;
+ else if (YY > IY) YY = YY + dh*(YY-IY)/(IB-IY);
+ int B = *p++;
+ if (B >= IB) B += dh;
+ else if (B > IY) B = B + dh*(B-IY)/(IB-IY);
+#endif
+ o->resize(XX+dx, YY+dy, R-XX, B-YY);
+ }
+ }
+}
+
+void Fl_Group::draw_children() {
+ Fl_Widget*const* a = array();
+
+ if (clip_children()) {
+ fl_push_clip(x() + Fl::box_dx(box()),
+ y() + Fl::box_dy(box()),
+ w() - Fl::box_dw(box()),
+ h() - Fl::box_dh(box()));
+ }
+
+ if (damage() & ~FL_DAMAGE_CHILD) { // redraw the entire thing:
+ for (int i=children_; i--;) {
+ Fl_Widget& o = **a++;
+ draw_child(o);
+ draw_outside_label(o);
+ }
+ } else { // only redraw the children that need it:
+ for (int i=children_; i--;) update_child(**a++);
+ }
+
+ if (clip_children()) fl_pop_clip();
+}
+
+void Fl_Group::draw() {
+ if (damage() & ~FL_DAMAGE_CHILD) { // redraw the entire thing:
+ draw_box();
+ draw_label();
+ }
+ draw_children();
+}
+
+// Draw a child only if it needs it:
+void Fl_Group::update_child(Fl_Widget& widget) const {
+ if (widget.damage() && widget.visible() && widget.type() < FL_WINDOW &&
+ fl_not_clipped(widget.x(), widget.y(), widget.w(), widget.h())) {
+ widget.draw();
+ widget.clear_damage();
+ }
+}
+
+// Force a child to redraw:
+void Fl_Group::draw_child(Fl_Widget& widget) const {
+ if (widget.visible() && widget.type() < FL_WINDOW &&
+ fl_not_clipped(widget.x(), widget.y(), widget.w(), widget.h())) {
+ widget.clear_damage(FL_DAMAGE_ALL);
+ widget.draw();
+ widget.clear_damage();
+ }
+}
+
+extern char fl_draw_shortcut;
+
+// Parents normally call this to draw outside labels:
+void Fl_Group::draw_outside_label(const Fl_Widget& widget) const {
+ if (!widget.visible()) return;
+ // skip any labels that are inside the widget:
+ if (!(widget.align()&15) || (widget.align() & FL_ALIGN_INSIDE)) return;
+ // invent a box that is outside the widget:
+ int a = widget.align();
+ int X = widget.x();
+ int Y = widget.y();
+ int W = widget.w();
+ int H = widget.h();
+ if (a & FL_ALIGN_TOP) {
+ a ^= (FL_ALIGN_BOTTOM|FL_ALIGN_TOP);
+ Y = y();
+ H = widget.y()-Y;
+ } else if (a & FL_ALIGN_BOTTOM) {
+ a ^= (FL_ALIGN_BOTTOM|FL_ALIGN_TOP);
+ Y = Y+H;
+ H = y()+h()-Y;
+ } else if (a & FL_ALIGN_LEFT) {
+ a ^= (FL_ALIGN_LEFT|FL_ALIGN_RIGHT);
+ X = x();
+ W = widget.x()-X-3;
+ } else if (a & FL_ALIGN_RIGHT) {
+ a ^= (FL_ALIGN_LEFT|FL_ALIGN_RIGHT);
+ X = X+W+3;
+ W = x()+this->w()-X;
+ }
+ widget.draw_label(X,Y,W,H,(Fl_Align)a);
+}
+
+//
+// End of "$Id: Fl_Group.cxx 6463 2008-10-19 06:40:02Z AlbrechtS $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Help_Dialog.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Help_Dialog.cxx new file mode 100644 index 0000000..0488f91 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Help_Dialog.cxx @@ -0,0 +1,301 @@ +//
+// "$Id: Fl_Help_Dialog.cxx 5643 2007-01-28 19:36:51Z mike $"
+//
+// Fl_Help_Dialog dialog for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// generated by Fast Light User Interface Designer (fluid) version 1.0108
+
+#include "../FL/Fl_Help_Dialog.H"
+#include "flstring.h"
+#include <FL/fl_ask.H>
+
+void Fl_Help_Dialog::cb_back__i(Fl_Button*, void*) {
+ if (index_ > 0)
+ index_ --;
+
+if (index_ == 0)
+ back_->deactivate();
+
+forward_->activate();
+
+int l = line_[index_];
+
+if (strcmp(view_->filename(), file_[index_]) != 0)
+ view_->load(file_[index_]);
+
+view_->topline(l);
+}
+void Fl_Help_Dialog::cb_back_(Fl_Button* o, void* v) {
+ ((Fl_Help_Dialog*)(o->parent()->parent()->user_data()))->cb_back__i(o,v);
+}
+
+void Fl_Help_Dialog::cb_forward__i(Fl_Button*, void*) {
+ if (index_ < max_)
+ index_ ++;
+
+if (index_ >= max_)
+ forward_->deactivate();
+
+back_->activate();
+
+int l = view_->topline();
+
+if (strcmp(view_->filename(), file_[index_]) != 0)
+ view_->load(file_[index_]);
+
+view_->topline(l);
+}
+void Fl_Help_Dialog::cb_forward_(Fl_Button* o, void* v) {
+ ((Fl_Help_Dialog*)(o->parent()->parent()->user_data()))->cb_forward__i(o,v);
+}
+
+void Fl_Help_Dialog::cb_smaller__i(Fl_Button*, void*) {
+ if (view_->textsize() > 8)
+ view_->textsize(view_->textsize() - 2);
+
+if (view_->textsize() <= 8)
+ smaller_->deactivate();
+larger_->activate();
+}
+void Fl_Help_Dialog::cb_smaller_(Fl_Button* o, void* v) {
+ ((Fl_Help_Dialog*)(o->parent()->parent()->user_data()))->cb_smaller__i(o,v);
+}
+
+void Fl_Help_Dialog::cb_larger__i(Fl_Button*, void*) {
+ if (view_->textsize() < 18)
+ view_->textsize(view_->textsize() + 2);
+
+if (view_->textsize() >= 18)
+ larger_->deactivate();
+smaller_->activate();
+}
+void Fl_Help_Dialog::cb_larger_(Fl_Button* o, void* v) {
+ ((Fl_Help_Dialog*)(o->parent()->parent()->user_data()))->cb_larger__i(o,v);
+}
+
+void Fl_Help_Dialog::cb_find__i(Fl_Input*, void*) {
+ find_pos_ = view_->find(find_->value(), find_pos_);
+}
+void Fl_Help_Dialog::cb_find_(Fl_Input* o, void* v) {
+ ((Fl_Help_Dialog*)(o->parent()->parent()->parent()->user_data()))->cb_find__i(o,v);
+}
+
+void Fl_Help_Dialog::cb_view__i(Fl_Help_View*, void*) {
+ if (view_->filename())
+{
+ if (view_->changed())
+ {
+ index_ ++;
+
+ if (index_ >= 100)
+ {
+ memmove(line_, line_ + 10, sizeof(line_[0]) * 90);
+ memmove(file_, file_ + 10, sizeof(file_[0]) * 90);
+ index_ -= 10;
+ }
+
+ max_ = index_;
+
+ strlcpy(file_[index_], view_->filename(),sizeof(file_[0]));
+ line_[index_] = view_->topline();
+
+ if (index_ > 0)
+ back_->activate();
+ else
+ back_->deactivate();
+
+ forward_->deactivate();
+ window_->label(view_->title());
+ }
+ else // if ! view_->changed()
+ {
+ strlcpy(file_[index_], view_->filename(), sizeof(file_[0]));
+ line_[index_] = view_->topline();
+ }
+} else { // if ! view_->filename()
+ index_ = 0; // hitting an internal page will disable the back/fwd buffer
+ file_[index_][0] = 0; // unnamed internal page
+ line_[index_] = view_->topline();
+ back_->deactivate();
+ forward_->deactivate();
+};
+}
+void Fl_Help_Dialog::cb_view_(Fl_Help_View* o, void* v) {
+ ((Fl_Help_Dialog*)(o->parent()->user_data()))->cb_view__i(o,v);
+}
+
+Fl_Help_Dialog::Fl_Help_Dialog() {
+ { window_ = new Fl_Double_Window(530, 385, "Help Dialog");
+ window_->user_data((void*)(this));
+ { Fl_Group* o = new Fl_Group(10, 10, 511, 25);
+ { back_ = new Fl_Button(10, 10, 25, 25, "@<-");
+ back_->tooltip("Show the previous help page.");
+ back_->shortcut(0xff51);
+ back_->labelcolor((Fl_Color)2);
+ back_->callback((Fl_Callback*)cb_back_);
+ } // Fl_Button* back_
+ { forward_ = new Fl_Button(45, 10, 25, 25, "@->");
+ forward_->tooltip("Show the next help page.");
+ forward_->shortcut(0xff53);
+ forward_->labelcolor((Fl_Color)2);
+ forward_->callback((Fl_Callback*)cb_forward_);
+ } // Fl_Button* forward_
+ { smaller_ = new Fl_Button(80, 10, 25, 25, "F");
+ smaller_->tooltip("Make the help text smaller.");
+ smaller_->labelfont(1);
+ smaller_->labelsize(10);
+ smaller_->callback((Fl_Callback*)cb_smaller_);
+ } // Fl_Button* smaller_
+ { larger_ = new Fl_Button(115, 10, 25, 25, "F");
+ larger_->tooltip("Make the help text larger.");
+ larger_->labelfont(1);
+ larger_->labelsize(16);
+ larger_->callback((Fl_Callback*)cb_larger_);
+ } // Fl_Button* larger_
+ { Fl_Group* o = new Fl_Group(350, 10, 171, 25);
+ o->box(FL_DOWN_BOX);
+ o->color(FL_BACKGROUND2_COLOR);
+ { find_ = new Fl_Input(375, 12, 143, 21, "@search");
+ find_->tooltip("find text in document");
+ find_->box(FL_FLAT_BOX);
+ find_->labelsize(13);
+ find_->textfont(4);
+ find_->callback((Fl_Callback*)cb_find_);
+ find_->when(FL_WHEN_ENTER_KEY_ALWAYS);
+ } // Fl_Input* find_
+ o->end();
+ } // Fl_Group* o
+ { Fl_Box* o = new Fl_Box(150, 10, 190, 25);
+ Fl_Group::current()->resizable(o);
+ } // Fl_Box* o
+ o->end();
+ } // Fl_Group* o
+ { view_ = new Fl_Help_View(10, 45, 510, 330);
+ view_->box(FL_DOWN_BOX);
+ view_->callback((Fl_Callback*)cb_view_);
+ Fl_Group::current()->resizable(view_);
+ } // Fl_Help_View* view_
+ window_->size_range(260, 150);
+ window_->end();
+ } // Fl_Double_Window* window_
+ back_->deactivate();
+forward_->deactivate();
+
+index_ = -1;
+max_ = 0;
+find_pos_ = 0;
+
+fl_register_images();
+}
+
+Fl_Help_Dialog::~Fl_Help_Dialog() {
+ delete window_;
+}
+
+int Fl_Help_Dialog::h() {
+ return (window_->h());
+}
+
+void Fl_Help_Dialog::hide() {
+ window_->hide();
+}
+
+void Fl_Help_Dialog::load(const char *f) {
+ view_->set_changed();
+view_->load(f);
+window_->label(view_->title());
+}
+
+void Fl_Help_Dialog::position(int xx, int yy) {
+ window_->position(xx, yy);
+}
+
+void Fl_Help_Dialog::resize(int xx, int yy, int ww, int hh) {
+ window_->resize(xx, yy, ww, hh);
+}
+
+void Fl_Help_Dialog::show() {
+ window_->show();
+}
+
+void Fl_Help_Dialog::show(int argc, char **argv) {
+ window_->show(argc, argv);
+}
+
+void Fl_Help_Dialog::textsize(uchar s) {
+ view_->textsize(s);
+
+if (s <= 8)
+ smaller_->deactivate();
+else
+ smaller_->activate();
+
+if (s >= 18)
+ larger_->deactivate();
+else
+ larger_->activate();
+}
+
+uchar Fl_Help_Dialog::textsize() {
+ return (view_->textsize());
+}
+
+void Fl_Help_Dialog::topline(const char *n) {
+ view_->topline(n);
+}
+
+void Fl_Help_Dialog::topline(int n) {
+ view_->topline(n);
+}
+
+void Fl_Help_Dialog::value(const char *f) {
+ view_->set_changed();
+view_->value(f);
+window_->label(view_->title());
+}
+
+const char * Fl_Help_Dialog::value() const {
+ return view_->value();
+}
+
+int Fl_Help_Dialog::visible() {
+ return (window_->visible());
+}
+
+int Fl_Help_Dialog::w() {
+ return (window_->w());
+}
+
+int Fl_Help_Dialog::x() {
+ return (window_->x());
+}
+
+int Fl_Help_Dialog::y() {
+ return (window_->y());
+}
+
+//
+// End of "$Id: Fl_Help_Dialog.cxx 5643 2007-01-28 19:36:51Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Help_Dialog.fl b/third_party/windows/fltk-1.1.10/src/Fl_Help_Dialog.fl new file mode 100644 index 0000000..78f23a5 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Help_Dialog.fl @@ -0,0 +1,265 @@ +# data file for the Fltk User Interface Designer (fluid)
+version 1.0108
+header_name {../FL/Fl_Help_Dialog.H}
+code_name {.cxx}
+comment {//
+// "$Id: Fl_Help_Dialog.fl 5643 2007-01-28 19:36:51Z mike $"
+//
+// Fl_Help_Dialog dialog for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+} {in_source in_header
+}
+
+decl {\#include "flstring.h"} {}
+
+decl {\#include <FL/fl_ask.H>} {}
+
+class FL_EXPORT Fl_Help_Dialog {open
+} {
+ decl {int index_;} {}
+ decl {int max_;} {}
+ decl {int line_[100];} {}
+ decl {char file_[100][256];} {}
+ decl {int find_pos_;} {}
+ Function {Fl_Help_Dialog()} {open
+ } {
+ Fl_Window window_ {
+ label {Help Dialog} open
+ private xywh {398 64 530 385} type Double resizable size_range {260 150 0 0} visible
+ } {
+ Fl_Group {} {open selected
+ xywh {10 10 511 25}
+ } {
+ Fl_Button back_ {
+ label {@<-}
+ callback {if (index_ > 0)
+ index_ --;
+
+if (index_ == 0)
+ back_->deactivate();
+
+forward_->activate();
+
+int l = line_[index_];
+
+if (strcmp(view_->filename(), file_[index_]) != 0)
+ view_->load(file_[index_]);
+
+view_->topline(l);}
+ private tooltip {Show the previous help page.} xywh {10 10 25 25} shortcut 0xff51 labelcolor 2
+ }
+ Fl_Button forward_ {
+ label {@->}
+ callback {if (index_ < max_)
+ index_ ++;
+
+if (index_ >= max_)
+ forward_->deactivate();
+
+back_->activate();
+
+int l = view_->topline();
+
+if (strcmp(view_->filename(), file_[index_]) != 0)
+ view_->load(file_[index_]);
+
+view_->topline(l);}
+ private tooltip {Show the next help page.} xywh {45 10 25 25} shortcut 0xff53 labelcolor 2
+ }
+ Fl_Button smaller_ {
+ label F
+ callback {if (view_->textsize() > 8)
+ view_->textsize(view_->textsize() - 2);
+
+if (view_->textsize() <= 8)
+ smaller_->deactivate();
+larger_->activate();}
+ private tooltip {Make the help text smaller.} xywh {80 10 25 25} labelfont 1 labelsize 10
+ }
+ Fl_Button larger_ {
+ label F
+ callback {if (view_->textsize() < 18)
+ view_->textsize(view_->textsize() + 2);
+
+if (view_->textsize() >= 18)
+ larger_->deactivate();
+smaller_->activate();}
+ private tooltip {Make the help text larger.} xywh {115 10 25 25} labelfont 1 labelsize 16
+ }
+ Fl_Group {} {open
+ xywh {350 10 171 25} box DOWN_BOX color 7
+ } {
+ Fl_Input find_ {
+ label {@search}
+ callback {find_pos_ = view_->find(find_->value(), find_pos_);}
+ private tooltip {find text in document} xywh {375 12 143 21} box FLAT_BOX labelsize 13 when 10 textfont 4
+ }
+ }
+ Fl_Box {} {
+ xywh {150 10 190 25} resizable
+ }
+ }
+ Fl_Help_View view_ {
+ callback {if (view_->filename())
+{
+ if (view_->changed())
+ {
+ index_ ++;
+
+ if (index_ >= 100)
+ {
+ memmove(line_, line_ + 10, sizeof(line_[0]) * 90);
+ memmove(file_, file_ + 10, sizeof(file_[0]) * 90);
+ index_ -= 10;
+ }
+
+ max_ = index_;
+
+ strlcpy(file_[index_], view_->filename(),sizeof(file_[0]));
+ line_[index_] = view_->topline();
+
+ if (index_ > 0)
+ back_->activate();
+ else
+ back_->deactivate();
+
+ forward_->deactivate();
+ window_->label(view_->title());
+ }
+ else // if ! view_->changed()
+ {
+ strlcpy(file_[index_], view_->filename(), sizeof(file_[0]));
+ line_[index_] = view_->topline();
+ }
+} else { // if ! view_->filename()
+ index_ = 0; // hitting an internal page will disable the back/fwd buffer
+ file_[index_][0] = 0; // unnamed internal page
+ line_[index_] = view_->topline();
+ back_->deactivate();
+ forward_->deactivate();
+}}
+ private xywh {10 45 510 330} box DOWN_BOX resizable
+ }
+ }
+ code {back_->deactivate();
+forward_->deactivate();
+
+index_ = -1;
+max_ = 0;
+find_pos_ = 0;
+
+fl_register_images();} {}
+ }
+ Function {~Fl_Help_Dialog()} {} {
+ code {delete window_;} {}
+ }
+ Function {h()} {return_type int
+ } {
+ code {return (window_->h());} {}
+ }
+ Function {hide()} {return_type void
+ } {
+ code {window_->hide();} {}
+ }
+ Function {load(const char *f)} {return_type void
+ } {
+ code {view_->set_changed();
+view_->load(f);
+window_->label(view_->title());} {}
+ }
+ Function {position(int xx, int yy)} {return_type void
+ } {
+ code {window_->position(xx, yy);} {}
+ }
+ Function {resize(int xx, int yy, int ww, int hh)} {return_type void
+ } {
+ code {window_->resize(xx, yy, ww, hh);} {}
+ }
+ Function {show()} {return_type void
+ } {
+ code {window_->show();} {}
+ }
+ Function {show(int argc, char **argv)} {return_type void
+ } {
+ code {window_->show(argc, argv);} {}
+ }
+ Function {textsize(uchar s)} {return_type void
+ } {
+ code {view_->textsize(s);
+
+if (s <= 8)
+ smaller_->deactivate();
+else
+ smaller_->activate();
+
+if (s >= 18)
+ larger_->deactivate();
+else
+ larger_->activate();} {}
+ }
+ Function {textsize()} {return_type uchar
+ } {
+ code {return (view_->textsize());} {}
+ }
+ Function {topline(const char *n)} {return_type void
+ } {
+ code {view_->topline(n);} {}
+ }
+ Function {topline(int n)} {return_type void
+ } {
+ code {view_->topline(n);} {}
+ }
+ Function {value(const char *f)} {return_type void
+ } {
+ code {view_->set_changed();
+view_->value(f);
+window_->label(view_->title());} {}
+ }
+ Function {value() const} {return_type {const char *}
+ } {
+ code {return view_->value();} {}
+ }
+ Function {visible()} {return_type int
+ } {
+ code {return (window_->visible());} {}
+ }
+ Function {w()} {return_type int
+ } {
+ code {return (window_->w());} {}
+ }
+ Function {x()} {return_type int
+ } {
+ code {return (window_->x());} {}
+ }
+ Function {y()} {return_type int
+ } {
+ code {return (window_->y());} {}
+ }
+}
+
+comment {
+//
+// End of "$Id: Fl_Help_Dialog.fl 5643 2007-01-28 19:36:51Z mike $".
+//} {in_source in_header
+}
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Help_View.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Help_View.cxx new file mode 100644 index 0000000..c7bd073 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Help_View.cxx @@ -0,0 +1,3507 @@ +//
+// "$Id: Fl_Help_View.cxx 6745 2009-04-07 18:37:25Z AlbrechtS $"
+//
+// Fl_Help_View widget routines.
+//
+// Copyright 1997-2007 by Easy Software Products.
+// Image support donated by Matthias Melcher, Copyright 2000.
+//
+// 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
+//
+// Contents:
+//
+// Fl_Help_View::add_block() - Add a text block to the list.
+// Fl_Help_View::add_link() - Add a new link to the list.
+// Fl_Help_View::add_target() - Add a new target to the list.
+// Fl_Help_View::compare_targets() - Compare two targets.
+// Fl_Help_View::do_align() - Compute the alignment for a line in
+// a block.
+// Fl_Help_View::draw() - Draw the Fl_Help_View widget.
+// Fl_Help_View::format() - Format the help text.
+// Fl_Help_View::format_table() - Format a table...
+// Fl_Help_View::free_data() - Free memory used for the document.
+// Fl_Help_View::get_align() - Get an alignment attribute.
+// Fl_Help_View::get_attr() - Get an attribute value from the string.
+// Fl_Help_View::get_color() - Get an alignment attribute.
+// Fl_Help_View::handle() - Handle events in the widget.
+// Fl_Help_View::Fl_Help_View() - Build a Fl_Help_View widget.
+// Fl_Help_View::~Fl_Help_View() - Destroy a Fl_Help_View widget.
+// Fl_Help_View::load() - Load the specified file.
+// Fl_Help_View::resize() - Resize the help widget.
+// Fl_Help_View::topline() - Set the top line to the named target.
+// Fl_Help_View::topline() - Set the top line by number.
+// Fl_Help_View::value() - Set the help text directly.
+// scrollbar_callback() - A callback for the scrollbar.
+//
+
+//
+// Include necessary header files...
+//
+
+#include <FL/Fl_Help_View.H>
+#include <FL/Fl_Window.H>
+#include <FL/Fl_Pixmap.H>
+#include <FL/x.H>
+#include <stdio.h>
+#include <stdlib.h>
+#include "flstring.h"
+#include <ctype.h>
+#include <errno.h>
+#include <math.h>
+
+#if defined(WIN32) && ! defined(__CYGWIN__)
+# include <io.h>
+# include <direct.h>
+// Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs
+// on Windows, which is supposed to be POSIX compliant...
+# define getcwd _getcwd
+#else
+# include <unistd.h>
+#endif // WIN32
+
+#define MAX_COLUMNS 200
+
+
+//
+// Typedef the C API sort function type the only way I know how...
+//
+
+extern "C"
+{
+ typedef int (*compare_func_t)(const void *, const void *);
+}
+
+
+//
+// Local functions...
+//
+
+static int quote_char(const char *);
+static void scrollbar_callback(Fl_Widget *s, void *);
+static void hscrollbar_callback(Fl_Widget *s, void *);
+
+//
+// global flag for image loading (see get_image).
+//
+
+static char initial_load = 0;
+
+//
+// Broken image...
+//
+
+static const char *broken_xpm[] =
+ {
+ "16 24 4 1",
+ "@ c #000000",
+ " c #ffffff",
+ "+ c none",
+ "x c #ff0000",
+ // pixels
+ "@@@@@@@+++++++++",
+ "@ @++++++++++",
+ "@ @+++++++++++",
+ "@ @++@++++++++",
+ "@ @@+++++++++",
+ "@ @+++@+++++",
+ "@ @++@@++++@",
+ "@ xxx @@ @++@@",
+ "@ xxx xx@@ @",
+ "@ xxx xxx @",
+ "@ xxxxxx @",
+ "@ xxxx @",
+ "@ xxxxxx @",
+ "@ xxx xxx @",
+ "@ xxx xxx @",
+ "@ xxx xxx @",
+ "@ @",
+ "@ @",
+ "@ @",
+ "@ @",
+ "@ @",
+ "@ @",
+ "@ @",
+ "@@@@@@@@@@@@@@@@",
+ NULL
+ };
+
+static Fl_Pixmap broken_image(broken_xpm);
+
+//
+// Simple margin stack for Fl_Help_View::format()...
+//
+
+struct fl_margins {
+ int depth_;
+ int margins_[100];
+
+ fl_margins() { clear(); }
+
+ int clear() {
+// puts("fl_margins::clear()");
+
+ depth_ = 0;
+ return margins_[0] = 4;
+ }
+
+ int current() { return margins_[depth_]; }
+
+ int pop() {
+// printf("fl_margins::pop(): depth_=%d, xx=%d\n", depth_,
+// depth_ > 0 ? margins_[depth_ - 1] : 4);
+
+ if (depth_ > 0) {
+ depth_ --;
+ return margins_[depth_];
+ } else return 4;
+ }
+
+ int push(int indent) {
+ int xx;
+
+ xx = margins_[depth_] + indent;
+
+// printf("fl_margins::push(indent=%d): depth_=%d, xx=%d\n", indent,
+// depth_ + 1, xx);
+
+ if (depth_ < 99) {
+ depth_ ++;
+ margins_[depth_] = xx;
+ }
+
+ return xx;
+ }
+};
+
+//
+// All the stuff needed to implement text selection in Fl_Help_View
+//
+
+/* matt:
+ * We are trying to keep binary compatibility with previous versions
+ * of FLTK. This means that we are limited to adding static variables
+ * only to not enlarge the Fl_Help_View class. Lucky for us, only one
+ * text can be selected system wide, so we can remember the selection
+ * in a single set of variables.
+ *
+ * Still to do:
+ * - &word; style characters mess up our count inside a word boundary
+ * - we can only select words, no individual characters
+ * - no dragging of the selection into another widget
+ * - selection must be cleared if another widget get focus!
+ * - write a comment for every new function
+ */
+
+/*
+The following functions are also used to draw stuff and should be replaced with
+local copies that are much faster when merely counting:
+
+fl_color(Fl_Color);
+fl_rectf(int, int, int, int);
+fl_push_clip(int, int, int, int);
+fl_xyline(int, int, int);
+fl_rect()
+fl_line()
+img->draw()
+*/
+
+// We don't put the offscreen buffer in the help view class because
+// we'd need to include x.H in the header...
+static Fl_Offscreen fl_help_view_buffer;
+int Fl_Help_View::selection_first = 0;
+int Fl_Help_View::selection_last = 0;
+int Fl_Help_View::selection_push_first = 0;
+int Fl_Help_View::selection_push_last = 0;
+int Fl_Help_View::selection_drag_first = 0;
+int Fl_Help_View::selection_drag_last = 0;
+int Fl_Help_View::selected = 0;
+int Fl_Help_View::draw_mode = 0;
+int Fl_Help_View::mouse_x = 0;
+int Fl_Help_View::mouse_y = 0;
+int Fl_Help_View::current_pos = 0;
+Fl_Help_View *Fl_Help_View::current_view = 0L;
+Fl_Color Fl_Help_View::hv_selection_color;
+Fl_Color Fl_Help_View::hv_selection_text_color;
+
+/*
+ * Limitation: if a word contains &code; notations, we will calculate a wrong length.
+ *
+ * This function must be optimized for speed!
+ */
+void Fl_Help_View::hv_draw(const char *t, int x, int y)
+{
+ if (selected && current_view==this && current_pos<selection_last && current_pos>=selection_first) {
+ Fl_Color c = fl_color();
+ fl_color(hv_selection_color);
+ int w = (int)fl_width(t);
+ if (current_pos+(int)strlen(t)<selection_last)
+ w += (int)fl_width(' ');
+ fl_rectf(x, y+fl_descent()-fl_height(), w, fl_height());
+ fl_color(hv_selection_text_color);
+ fl_draw(t, x, y);
+ fl_color(c);
+ } else {
+ fl_draw(t, x, y);
+ }
+ if (draw_mode) {
+ int w = (int)fl_width(t);
+ if (mouse_x>=x && mouse_x<x+w) {
+ if (mouse_y>=y-fl_height()+fl_descent()&&mouse_y<=y+fl_descent()) {
+ int f = current_pos;
+ int l = f+strlen(t); // use 'quote_char' to calculate the true length of the HTML string
+ if (draw_mode==1) {
+ selection_push_first = f;
+ selection_push_last = l;
+ } else {
+ selection_drag_first = f;
+ selection_drag_last = l;
+ }
+ }
+ }
+ }
+}
+
+
+//
+// 'Fl_Help_View::add_block()' - Add a text block to the list.
+//
+
+Fl_Help_Block * // O - Pointer to new block
+Fl_Help_View::add_block(const char *s, // I - Pointer to start of block text
+ int xx, // I - X position of block
+ int yy, // I - Y position of block
+ int ww, // I - Right margin of block
+ int hh, // I - Height of block
+ unsigned char border) // I - Draw border?
+{
+ Fl_Help_Block *temp; // New block
+
+
+// printf("add_block(s = %p, xx = %d, yy = %d, ww = %d, hh = %d, border = %d)\n",
+// s, xx, yy, ww, hh, border);
+
+ if (nblocks_ >= ablocks_)
+ {
+ ablocks_ += 16;
+
+ if (ablocks_ == 16)
+ blocks_ = (Fl_Help_Block *)malloc(sizeof(Fl_Help_Block) * ablocks_);
+ else
+ blocks_ = (Fl_Help_Block *)realloc(blocks_, sizeof(Fl_Help_Block) * ablocks_);
+ }
+
+ temp = blocks_ + nblocks_;
+ memset(temp, 0, sizeof(Fl_Help_Block));
+ temp->start = s;
+ temp->end = s;
+ temp->x = xx;
+ temp->y = yy;
+ temp->w = ww;
+ temp->h = hh;
+ temp->border = border;
+ temp->bgcolor = bgcolor_;
+ nblocks_ ++;
+
+ return (temp);
+}
+
+
+//
+// 'Fl_Help_View::add_link()' - Add a new link to the list.
+//
+
+void
+Fl_Help_View::add_link(const char *n, // I - Name of link
+ int xx, // I - X position of link
+ int yy, // I - Y position of link
+ int ww, // I - Width of link text
+ int hh) // I - Height of link text
+{
+ Fl_Help_Link *temp; // New link
+ char *target; // Pointer to target name
+
+
+ if (nlinks_ >= alinks_)
+ {
+ alinks_ += 16;
+
+ if (alinks_ == 16)
+ links_ = (Fl_Help_Link *)malloc(sizeof(Fl_Help_Link) * alinks_);
+ else
+ links_ = (Fl_Help_Link *)realloc(links_, sizeof(Fl_Help_Link) * alinks_);
+ }
+
+ temp = links_ + nlinks_;
+
+ temp->x = xx;
+ temp->y = yy;
+ temp->w = xx + ww;
+ temp->h = yy + hh;
+
+ strlcpy(temp->filename, n, sizeof(temp->filename));
+
+ if ((target = strrchr(temp->filename, '#')) != NULL)
+ {
+ *target++ = '\0';
+ strlcpy(temp->name, target, sizeof(temp->name));
+ }
+ else
+ temp->name[0] = '\0';
+
+ nlinks_ ++;
+}
+
+
+//
+// 'Fl_Help_View::add_target()' - Add a new target to the list.
+//
+
+void
+Fl_Help_View::add_target(const char *n, // I - Name of target
+ int yy) // I - Y position of target
+{
+ Fl_Help_Target *temp; // New target
+
+
+ if (ntargets_ >= atargets_)
+ {
+ atargets_ += 16;
+
+ if (atargets_ == 16)
+ targets_ = (Fl_Help_Target *)malloc(sizeof(Fl_Help_Target) * atargets_);
+ else
+ targets_ = (Fl_Help_Target *)realloc(targets_, sizeof(Fl_Help_Target) * atargets_);
+ }
+
+ temp = targets_ + ntargets_;
+
+ temp->y = yy;
+ strlcpy(temp->name, n, sizeof(temp->name));
+
+ ntargets_ ++;
+}
+
+
+//
+// 'Fl_Help_View::compare_targets()' - Compare two targets.
+//
+
+int // O - Result of comparison
+Fl_Help_View::compare_targets(const Fl_Help_Target *t0, // I - First target
+ const Fl_Help_Target *t1) // I - Second target
+{
+ return (strcasecmp(t0->name, t1->name));
+}
+
+
+//
+// 'Fl_Help_View::do_align()' - Compute the alignment for a line in a block.
+//
+
+int // O - New line
+Fl_Help_View::do_align(Fl_Help_Block *block, // I - Block to add to
+ int line, // I - Current line
+ int xx, // I - Current X position
+ int a, // I - Current alignment
+ int &l) // IO - Starting link
+{
+ int offset; // Alignment offset
+
+
+ switch (a)
+ {
+ case RIGHT : // Right align
+ offset = block->w - xx;
+ break;
+ case CENTER : // Center
+ offset = (block->w - xx) / 2;
+ break;
+ default : // Left align
+ offset = 0;
+ break;
+ }
+
+ block->line[line] = block->x + offset;
+
+ if (line < 31)
+ line ++;
+
+ while (l < nlinks_)
+ {
+ links_[l].x += offset;
+ links_[l].w += offset;
+ l ++;
+ }
+
+ return (line);
+}
+
+
+//
+// 'Fl_Help_View::draw()' - Draw the Fl_Help_View widget.
+//
+
+void
+Fl_Help_View::draw()
+{
+ int i; // Looping var
+ const Fl_Help_Block *block; // Pointer to current block
+ const char *ptr, // Pointer to text in block
+ *attrs; // Pointer to start of element attributes
+ char *s, // Pointer into buffer
+ buf[1024], // Text buffer
+ attr[1024]; // Attribute buffer
+ int xx, yy, ww, hh; // Current positions and sizes
+ int line; // Current line
+ unsigned char font, fsize; // Current font and size
+ int head, pre, // Flags for text
+ needspace; // Do we need whitespace?
+ Fl_Boxtype b = box() ? box() : FL_DOWN_BOX;
+ // Box to draw...
+ int underline, // Underline text?
+ xtra_ww; // Extra width for underlined space between words
+
+
+ // Draw the scrollbar(s) and box first...
+ ww = w() ;
+ hh = h();
+ i = 0;
+
+ draw_box(b, x(), y(), ww, hh, bgcolor_);
+
+ int ss = Fl::scrollbar_size();
+ if (hscrollbar_.visible()) {
+ draw_child(hscrollbar_);
+ hh -= ss;
+ i ++;
+ }
+ if (scrollbar_.visible()) {
+ draw_child(scrollbar_);
+ ww -= ss;
+ i ++;
+ }
+ if (i == 2) {
+ fl_color(FL_GRAY);
+ fl_rectf(x() + ww - Fl::box_dw(b) + Fl::box_dx(b),
+ y() + hh - Fl::box_dh(b) + Fl::box_dy(b), ss, ss);
+ }
+
+ if (!value_)
+ return;
+
+ if (current_view == this && selected) {
+ hv_selection_color = FL_SELECTION_COLOR;
+ hv_selection_text_color = fl_contrast(textcolor_, FL_SELECTION_COLOR);
+ }
+ current_pos = 0;
+
+ // Clip the drawing to the inside of the box...
+ fl_push_clip(x() + Fl::box_dx(b), y() + Fl::box_dy(b),
+ ww - Fl::box_dw(b), hh - Fl::box_dh(b));
+ fl_color(textcolor_);
+
+ // Draw all visible blocks...
+ for (i = 0, block = blocks_; i < nblocks_; i ++, block ++)
+ if ((block->y + block->h) >= topline_ && block->y < (topline_ + h()))
+ {
+ line = 0;
+ xx = block->line[line];
+ yy = block->y - topline_;
+ hh = 0;
+ pre = 0;
+ head = 0;
+ needspace = 0;
+ underline = 0;
+
+ initfont(font, fsize);
+
+ for (ptr = block->start, s = buf; ptr < block->end;)
+ {
+ if ((*ptr == '<' || isspace((*ptr)&255)) && s > buf)
+ {
+ if (!head && !pre)
+ {
+ // Check width...
+ *s = '\0';
+ s = buf;
+ ww = (int)fl_width(buf);
+
+ if (needspace && xx > block->x)
+ xx += (int)fl_width(' ');
+
+ if ((xx + ww) > block->w)
+ {
+ if (line < 31)
+ line ++;
+ xx = block->line[line];
+ yy += hh;
+ hh = 0;
+ }
+
+ hv_draw(buf, xx + x() - leftline_, yy + y());
+ if (underline) {
+ xtra_ww = isspace((*ptr)&255)?(int)fl_width(' '):0;
+ fl_xyline(xx + x() - leftline_, yy + y() + 1,
+ xx + x() - leftline_ + ww + xtra_ww);
+ }
+ current_pos = ptr-value_;
+
+ xx += ww;
+ if ((fsize + 2) > hh)
+ hh = fsize + 2;
+
+ needspace = 0;
+ }
+ else if (pre)
+ {
+ while (isspace((*ptr)&255))
+ {
+ if (*ptr == '\n')
+ {
+ *s = '\0';
+ s = buf;
+
+ hv_draw(buf, xx + x() - leftline_, yy + y());
+ if (underline) fl_xyline(xx + x() - leftline_, yy + y() + 1,
+ xx + x() - leftline_ +
+ (int)fl_width(buf));
+
+ current_pos = ptr-value_;
+ if (line < 31)
+ line ++;
+ xx = block->line[line];
+ yy += hh;
+ hh = fsize + 2;
+ }
+ else if (*ptr == '\t')
+ {
+ // Do tabs every 8 columns...
+ while (((s - buf) & 7))
+ *s++ = ' ';
+ }
+ else
+ *s++ = ' ';
+
+ if ((fsize + 2) > hh)
+ hh = fsize + 2;
+
+ ptr ++;
+ }
+
+ if (s > buf)
+ {
+ *s = '\0';
+ s = buf;
+
+ hv_draw(buf, xx + x() - leftline_, yy + y());
+ ww = (int)fl_width(buf);
+ if (underline) fl_xyline(xx + x() - leftline_, yy + y() + 1,
+ xx + x() - leftline_ + ww);
+ xx += ww;
+ current_pos = ptr-value_;
+ }
+
+ needspace = 0;
+ }
+ else
+ {
+ s = buf;
+
+ while (isspace((*ptr)&255))
+ ptr ++;
+ current_pos = ptr-value_;
+ }
+ }
+
+ if (*ptr == '<')
+ {
+ ptr ++;
+
+ if (strncmp(ptr, "!--", 3) == 0)
+ {
+ // Comment...
+ ptr += 3;
+ if ((ptr = strstr(ptr, "-->")) != NULL)
+ {
+ ptr += 3;
+ continue;
+ }
+ else
+ break;
+ }
+
+ while (*ptr && *ptr != '>' && !isspace((*ptr)&255))
+ if (s < (buf + sizeof(buf) - 1))
+ *s++ = *ptr++;
+ else
+ ptr ++;
+
+ *s = '\0';
+ s = buf;
+
+ attrs = ptr;
+ while (*ptr && *ptr != '>')
+ ptr ++;
+
+ if (*ptr == '>')
+ ptr ++;
+
+ // end of command reached, set the supposed start of printed eord here
+ current_pos = ptr-value_;
+ if (strcasecmp(buf, "HEAD") == 0)
+ head = 1;
+ else if (strcasecmp(buf, "BR") == 0)
+ {
+ if (line < 31)
+ line ++;
+ xx = block->line[line];
+ yy += hh;
+ hh = 0;
+ }
+ else if (strcasecmp(buf, "HR") == 0)
+ {
+ fl_line(block->x + x(), yy + y(), block->w + x(),
+ yy + y());
+
+ if (line < 31)
+ line ++;
+ xx = block->line[line];
+ yy += 2 * hh;
+ hh = 0;
+ }
+ else if (strcasecmp(buf, "CENTER") == 0 ||
+ strcasecmp(buf, "P") == 0 ||
+ strcasecmp(buf, "H1") == 0 ||
+ strcasecmp(buf, "H2") == 0 ||
+ strcasecmp(buf, "H3") == 0 ||
+ strcasecmp(buf, "H4") == 0 ||
+ strcasecmp(buf, "H5") == 0 ||
+ strcasecmp(buf, "H6") == 0 ||
+ strcasecmp(buf, "UL") == 0 ||
+ strcasecmp(buf, "OL") == 0 ||
+ strcasecmp(buf, "DL") == 0 ||
+ strcasecmp(buf, "LI") == 0 ||
+ strcasecmp(buf, "DD") == 0 ||
+ strcasecmp(buf, "DT") == 0 ||
+ strcasecmp(buf, "PRE") == 0)
+ {
+ if (tolower(buf[0]) == 'h')
+ {
+ font = FL_HELVETICA_BOLD;
+ fsize = (uchar)(textsize_ + '7' - buf[1]);
+ }
+ else if (strcasecmp(buf, "DT") == 0)
+ {
+ font = (uchar)(textfont_ | FL_ITALIC);
+ fsize = textsize_;
+ }
+ else if (strcasecmp(buf, "PRE") == 0)
+ {
+ font = FL_COURIER;
+ fsize = textsize_;
+ pre = 1;
+ }
+
+ if (strcasecmp(buf, "LI") == 0)
+ {
+#ifdef __APPLE_QUARTZ__
+ fl_font(FL_SYMBOL, fsize);
+ hv_draw("\245", xx - fsize + x() - leftline_, yy + y());
+#else
+ fl_font(FL_SYMBOL, fsize);
+ hv_draw("\267", xx - fsize + x() - leftline_, yy + y());
+#endif
+ }
+
+ pushfont(font, fsize);
+ }
+ else if (strcasecmp(buf, "A") == 0 &&
+ get_attr(attrs, "HREF", attr, sizeof(attr)) != NULL)
+ {
+ fl_color(linkcolor_);
+ underline = 1;
+ }
+ else if (strcasecmp(buf, "/A") == 0)
+ {
+ fl_color(textcolor_);
+ underline = 0;
+ }
+ else if (strcasecmp(buf, "FONT") == 0)
+ {
+ if (get_attr(attrs, "COLOR", attr, sizeof(attr)) != NULL) {
+ fl_color(get_color(attr, textcolor_));
+ }
+
+ if (get_attr(attrs, "FACE", attr, sizeof(attr)) != NULL) {
+ if (!strncasecmp(attr, "helvetica", 9) ||
+ !strncasecmp(attr, "arial", 5) ||
+ !strncasecmp(attr, "sans", 4)) font = FL_HELVETICA;
+ else if (!strncasecmp(attr, "times", 5) ||
+ !strncasecmp(attr, "serif", 5)) font = FL_TIMES;
+ else if (!strncasecmp(attr, "symbol", 6)) font = FL_SYMBOL;
+ else font = FL_COURIER;
+ }
+
+ if (get_attr(attrs, "SIZE", attr, sizeof(attr)) != NULL) {
+ if (isdigit(attr[0] & 255)) {
+ // Absolute size
+ fsize = (int)(textsize_ * pow(1.2, atof(attr) - 3.0));
+ } else {
+ // Relative size
+ fsize = (int)(fsize * pow(1.2, atof(attr) - 3.0));
+ }
+ }
+
+ pushfont(font, fsize);
+ }
+ else if (strcasecmp(buf, "/FONT") == 0)
+ {
+ fl_color(textcolor_);
+ popfont(font, fsize);
+ }
+ else if (strcasecmp(buf, "U") == 0)
+ underline = 1;
+ else if (strcasecmp(buf, "/U") == 0)
+ underline = 0;
+ else if (strcasecmp(buf, "B") == 0 ||
+ strcasecmp(buf, "STRONG") == 0)
+ pushfont(font |= FL_BOLD, fsize);
+ else if (strcasecmp(buf, "TD") == 0 ||
+ strcasecmp(buf, "TH") == 0)
+ {
+ int tx, ty, tw, th;
+
+ if (tolower(buf[1]) == 'h')
+ pushfont(font |= FL_BOLD, fsize);
+ else
+ pushfont(font = textfont_, fsize);
+
+ tx = block->x - 4 - leftline_;
+ ty = block->y - topline_ - fsize - 3;
+ tw = block->w - block->x + 7;
+ th = block->h + fsize - 5;
+
+ if (tx < 0)
+ {
+ tw += tx;
+ tx = 0;
+ }
+
+ if (ty < 0)
+ {
+ th += ty;
+ ty = 0;
+ }
+
+ tx += x();
+ ty += y();
+
+ if (block->bgcolor != bgcolor_)
+ {
+ fl_color(block->bgcolor);
+ fl_rectf(tx, ty, tw, th);
+ fl_color(textcolor_);
+ }
+
+ if (block->border)
+ fl_rect(tx, ty, tw, th);
+ }
+ else if (strcasecmp(buf, "I") == 0 ||
+ strcasecmp(buf, "EM") == 0)
+ pushfont(font |= FL_ITALIC, fsize);
+ else if (strcasecmp(buf, "CODE") == 0 ||
+ strcasecmp(buf, "TT") == 0)
+ pushfont(font = FL_COURIER, fsize);
+ else if (strcasecmp(buf, "KBD") == 0)
+ pushfont(font = FL_COURIER_BOLD, fsize);
+ else if (strcasecmp(buf, "VAR") == 0)
+ pushfont(font = FL_COURIER_ITALIC, fsize);
+ else if (strcasecmp(buf, "/HEAD") == 0)
+ head = 0;
+ else if (strcasecmp(buf, "/H1") == 0 ||
+ strcasecmp(buf, "/H2") == 0 ||
+ strcasecmp(buf, "/H3") == 0 ||
+ strcasecmp(buf, "/H4") == 0 ||
+ strcasecmp(buf, "/H5") == 0 ||
+ strcasecmp(buf, "/H6") == 0 ||
+ strcasecmp(buf, "/B") == 0 ||
+ strcasecmp(buf, "/STRONG") == 0 ||
+ strcasecmp(buf, "/I") == 0 ||
+ strcasecmp(buf, "/EM") == 0 ||
+ strcasecmp(buf, "/CODE") == 0 ||
+ strcasecmp(buf, "/TT") == 0 ||
+ strcasecmp(buf, "/KBD") == 0 ||
+ strcasecmp(buf, "/VAR") == 0)
+ popfont(font, fsize);
+ else if (strcasecmp(buf, "/PRE") == 0)
+ {
+ popfont(font, fsize);
+ pre = 0;
+ }
+ else if (strcasecmp(buf, "IMG") == 0)
+ {
+ Fl_Shared_Image *img = 0;
+ int width, height;
+ char wattr[8], hattr[8];
+
+
+ get_attr(attrs, "WIDTH", wattr, sizeof(wattr));
+ get_attr(attrs, "HEIGHT", hattr, sizeof(hattr));
+ width = get_length(wattr);
+ height = get_length(hattr);
+
+ if (get_attr(attrs, "SRC", attr, sizeof(attr))) {
+ img = get_image(attr, width, height);
+ if (!width) width = img->w();
+ if (!height) height = img->h();
+ }
+
+ if (!width || !height) {
+ if (get_attr(attrs, "ALT", attr, sizeof(attr)) == NULL) {
+ strcpy(attr, "IMG");
+ }
+ }
+
+ ww = width;
+
+ if (needspace && xx > block->x)
+ xx += (int)fl_width(' ');
+
+ if ((xx + ww) > block->w)
+ {
+ if (line < 31)
+ line ++;
+
+ xx = block->line[line];
+ yy += hh;
+ hh = 0;
+ }
+
+ if (img) {
+ img->draw(xx + x() - leftline_,
+ yy + y() - fl_height() + fl_descent() + 2);
+ }
+
+ xx += ww;
+ if ((height + 2) > hh)
+ hh = height + 2;
+
+ needspace = 0;
+ }
+ }
+ else if (*ptr == '\n' && pre)
+ {
+ *s = '\0';
+ s = buf;
+
+ hv_draw(buf, xx + x() - leftline_, yy + y());
+
+ if (line < 31)
+ line ++;
+ xx = block->line[line];
+ yy += hh;
+ hh = fsize + 2;
+ needspace = 0;
+
+ ptr ++;
+ current_pos = ptr-value_;
+ }
+ else if (isspace((*ptr)&255))
+ {
+ if (pre)
+ {
+ if (*ptr == ' ')
+ *s++ = ' ';
+ else
+ {
+ // Do tabs every 8 columns...
+ while (((s - buf) & 7))
+ *s++ = ' ';
+ }
+ }
+
+ ptr ++;
+ if (!pre) current_pos = ptr-value_;
+ needspace = 1;
+ }
+ else if (*ptr == '&')
+ {
+ ptr ++;
+
+ int qch = quote_char(ptr);
+
+ if (qch < 0)
+ *s++ = '&';
+ else {
+ *s++ = qch;
+ ptr = strchr(ptr, ';') + 1;
+ }
+
+ if ((fsize + 2) > hh)
+ hh = fsize + 2;
+ }
+ else
+ {
+ *s++ = *ptr++;
+
+ if ((fsize + 2) > hh)
+ hh = fsize + 2;
+ }
+ }
+
+ *s = '\0';
+
+ if (s > buf && !pre && !head)
+ {
+ ww = (int)fl_width(buf);
+
+ if (needspace && xx > block->x)
+ xx += (int)fl_width(' ');
+
+ if ((xx + ww) > block->w)
+ {
+ if (line < 31)
+ line ++;
+ xx = block->line[line];
+ yy += hh;
+ hh = 0;
+ }
+ }
+
+ if (s > buf && !head)
+ {
+ hv_draw(buf, xx + x() - leftline_, yy + y());
+ if (underline) fl_xyline(xx + x() - leftline_, yy + y() + 1,
+ xx + x() - leftline_ + ww);
+ current_pos = ptr-value_;
+ }
+ }
+
+ fl_pop_clip();
+}
+
+
+//
+// 'Fl_Help_View::find()' - Find the specified string...
+//
+
+int // O - Matching position or -1 if not found
+Fl_Help_View::find(const char *s, // I - String to find
+ int p) // I - Starting position
+{
+ int i, // Looping var
+ c; // Current character
+ Fl_Help_Block *b; // Current block
+ const char *bp, // Block matching pointer
+ *bs, // Start of current comparison
+ *sp; // Search string pointer
+
+
+ // Range check input and value...
+ if (!s || !value_) return -1;
+
+ if (p < 0 || p >= (int)strlen(value_)) p = 0;
+ else if (p > 0) p ++;
+
+ // Look for the string...
+ for (i = nblocks_, b = blocks_; i > 0; i --, b ++) {
+ if (b->end < (value_ + p))
+ continue;
+
+ if (b->start < (value_ + p)) bp = value_ + p;
+ else bp = b->start;
+
+ for (sp = s, bs = bp; *sp && *bp && bp < b->end; bp ++) {
+ if (*bp == '<') {
+ // skip to end of element...
+ while (*bp && bp < b->end && *bp != '>') bp ++;
+ continue;
+ } else if (*bp == '&') {
+ // decode HTML entity...
+ if ((c = quote_char(bp + 1)) < 0) c = '&';
+ else bp = strchr(bp + 1, ';') + 1;
+ } else c = *bp;
+
+ if (tolower(*sp) == tolower(c)) sp ++;
+ else {
+ // No match, so reset to start of search...
+ sp = s;
+ bs ++;
+ bp = bs;
+ }
+ }
+
+ if (!*sp) {
+ // Found a match!
+ topline(b->y - b->h);
+ return (b->end - value_);
+ }
+ }
+
+ // No match!
+ return (-1);
+}
+
+
+//
+// 'Fl_Help_View::format()' - Format the help text.
+//
+
+void
+Fl_Help_View::format()
+{
+ int i; // Looping var
+ int done; // Are we done yet?
+ Fl_Help_Block *block, // Current block
+ *cell; // Current table cell
+ int cells[MAX_COLUMNS],
+ // Cells in the current row...
+ row; // Current table row (block number)
+ const char *ptr, // Pointer into block
+ *start, // Pointer to start of element
+ *attrs; // Pointer to start of element attributes
+ char *s, // Pointer into buffer
+ buf[1024], // Text buffer
+ attr[1024], // Attribute buffer
+ wattr[1024], // Width attribute buffer
+ hattr[1024], // Height attribute buffer
+ linkdest[1024]; // Link destination
+ int xx, yy, ww, hh; // Size of current text fragment
+ int line; // Current line in block
+ int links; // Links for current line
+ unsigned char font, fsize; // Current font and size
+ unsigned char border; // Draw border?
+ int talign, // Current alignment
+ newalign, // New alignment
+ head, // In the <HEAD> section?
+ pre, // <PRE> text?
+ needspace; // Do we need whitespace?
+ int table_width, // Width of table
+ table_offset; // Offset of table
+ int column, // Current table column number
+ columns[MAX_COLUMNS];
+ // Column widths
+ Fl_Color tc, rc; // Table/row background color
+ Fl_Boxtype b = box() ? box() : FL_DOWN_BOX;
+ // Box to draw...
+ fl_margins margins; // Left margin stack...
+
+
+ // Reset document width...
+ hsize_ = w() - Fl::scrollbar_size() - Fl::box_dw(b);
+
+ done = 0;
+ while (!done)
+ {
+ // Reset state variables...
+ done = 1;
+ nblocks_ = 0;
+ nlinks_ = 0;
+ ntargets_ = 0;
+ size_ = 0;
+ bgcolor_ = color();
+ textcolor_ = textcolor();
+ linkcolor_ = fl_contrast(FL_BLUE, color());
+
+ tc = rc = bgcolor_;
+
+ strcpy(title_, "Untitled");
+
+ if (!value_)
+ return;
+
+ // Setup for formatting...
+ initfont(font, fsize);
+
+ line = 0;
+ links = 0;
+ xx = margins.clear();
+ yy = fsize + 2;
+ ww = 0;
+ column = 0;
+ border = 0;
+ hh = 0;
+ block = add_block(value_, xx, yy, hsize_, 0);
+ row = 0;
+ head = 0;
+ pre = 0;
+ talign = LEFT;
+ newalign = LEFT;
+ needspace = 0;
+ linkdest[0] = '\0';
+ table_offset = 0;
+
+ for (ptr = value_, s = buf; *ptr;)
+ {
+ if ((*ptr == '<' || isspace((*ptr)&255)) && s > buf)
+ {
+ // Get width...
+ *s = '\0';
+ ww = (int)fl_width(buf);
+
+ if (!head && !pre)
+ {
+ // Check width...
+ if (ww > hsize_) {
+ hsize_ = ww;
+ done = 0;
+ break;
+ }
+
+ if (needspace && xx > block->x)
+ ww += (int)fl_width(' ');
+
+ // printf("line = %d, xx = %d, ww = %d, block->x = %d, block->w = %d\n",
+ // line, xx, ww, block->x, block->w);
+
+ if ((xx + ww) > block->w)
+ {
+ line = do_align(block, line, xx, newalign, links);
+ xx = block->x;
+ yy += hh;
+ block->h += hh;
+ hh = 0;
+ }
+
+ if (linkdest[0])
+ add_link(linkdest, xx, yy - fsize, ww, fsize);
+
+ xx += ww;
+ if ((fsize + 2) > hh)
+ hh = fsize + 2;
+
+ needspace = 0;
+ }
+ else if (pre)
+ {
+ // Add a link as needed...
+ if (linkdest[0])
+ add_link(linkdest, xx, yy - hh, ww, hh);
+
+ xx += ww;
+ if ((fsize + 2) > hh)
+ hh = fsize + 2;
+
+ // Handle preformatted text...
+ while (isspace((*ptr)&255))
+ {
+ if (*ptr == '\n')
+ {
+ if (xx > hsize_) break;
+
+ line = do_align(block, line, xx, newalign, links);
+ xx = block->x;
+ yy += hh;
+ block->h += hh;
+ hh = fsize + 2;
+ }
+ else
+ xx += (int)fl_width(' ');
+
+ if ((fsize + 2) > hh)
+ hh = fsize + 2;
+
+ ptr ++;
+ }
+
+ if (xx > hsize_) {
+ hsize_ = xx;
+ done = 0;
+ break;
+ }
+
+ needspace = 0;
+ }
+ else
+ {
+ // Handle normal text or stuff in the <HEAD> section...
+ while (isspace((*ptr)&255))
+ ptr ++;
+ }
+
+ s = buf;
+ }
+
+ if (*ptr == '<')
+ {
+ start = ptr;
+ ptr ++;
+
+ if (strncmp(ptr, "!--", 3) == 0)
+ {
+ // Comment...
+ ptr += 3;
+ if ((ptr = strstr(ptr, "-->")) != NULL)
+ {
+ ptr += 3;
+ continue;
+ }
+ else
+ break;
+ }
+
+ while (*ptr && *ptr != '>' && !isspace((*ptr)&255))
+ if (s < (buf + sizeof(buf) - 1))
+ *s++ = *ptr++;
+ else
+ ptr ++;
+
+ *s = '\0';
+ s = buf;
+
+// puts(buf);
+
+ attrs = ptr;
+ while (*ptr && *ptr != '>')
+ ptr ++;
+
+ if (*ptr == '>')
+ ptr ++;
+
+ if (strcasecmp(buf, "HEAD") == 0)
+ head = 1;
+ else if (strcasecmp(buf, "/HEAD") == 0)
+ head = 0;
+ else if (strcasecmp(buf, "TITLE") == 0)
+ {
+ // Copy the title in the document...
+ for (s = title_;
+ *ptr != '<' && *ptr && s < (title_ + sizeof(title_) - 1);
+ *s++ = *ptr++);
+
+ *s = '\0';
+ s = buf;
+ }
+ else if (strcasecmp(buf, "A") == 0)
+ {
+ if (get_attr(attrs, "NAME", attr, sizeof(attr)) != NULL)
+ add_target(attr, yy - fsize - 2);
+
+ if (get_attr(attrs, "HREF", attr, sizeof(attr)) != NULL)
+ strlcpy(linkdest, attr, sizeof(linkdest));
+ }
+ else if (strcasecmp(buf, "/A") == 0)
+ linkdest[0] = '\0';
+ else if (strcasecmp(buf, "BODY") == 0)
+ {
+ bgcolor_ = get_color(get_attr(attrs, "BGCOLOR", attr, sizeof(attr)),
+ color());
+ textcolor_ = get_color(get_attr(attrs, "TEXT", attr, sizeof(attr)),
+ textcolor());
+ linkcolor_ = get_color(get_attr(attrs, "LINK", attr, sizeof(attr)),
+ fl_contrast(FL_BLUE, color()));
+ }
+ else if (strcasecmp(buf, "BR") == 0)
+ {
+ line = do_align(block, line, xx, newalign, links);
+ xx = block->x;
+ block->h += hh;
+ yy += hh;
+ hh = 0;
+ }
+ else if (strcasecmp(buf, "CENTER") == 0 ||
+ strcasecmp(buf, "P") == 0 ||
+ strcasecmp(buf, "H1") == 0 ||
+ strcasecmp(buf, "H2") == 0 ||
+ strcasecmp(buf, "H3") == 0 ||
+ strcasecmp(buf, "H4") == 0 ||
+ strcasecmp(buf, "H5") == 0 ||
+ strcasecmp(buf, "H6") == 0 ||
+ strcasecmp(buf, "UL") == 0 ||
+ strcasecmp(buf, "OL") == 0 ||
+ strcasecmp(buf, "DL") == 0 ||
+ strcasecmp(buf, "LI") == 0 ||
+ strcasecmp(buf, "DD") == 0 ||
+ strcasecmp(buf, "DT") == 0 ||
+ strcasecmp(buf, "HR") == 0 ||
+ strcasecmp(buf, "PRE") == 0 ||
+ strcasecmp(buf, "TABLE") == 0)
+ {
+ block->end = start;
+ line = do_align(block, line, xx, newalign, links);
+ newalign = strcasecmp(buf, "CENTER") ? LEFT : CENTER;
+ xx = block->x;
+ block->h += hh;
+
+ if (strcasecmp(buf, "UL") == 0 ||
+ strcasecmp(buf, "OL") == 0 ||
+ strcasecmp(buf, "DL") == 0)
+ {
+ block->h += fsize + 2;
+ xx = margins.push(4 * fsize);
+ }
+ else if (strcasecmp(buf, "TABLE") == 0)
+ {
+ if (get_attr(attrs, "BORDER", attr, sizeof(attr)))
+ border = (uchar)atoi(attr);
+ else
+ border = 0;
+
+ tc = rc = get_color(get_attr(attrs, "BGCOLOR", attr, sizeof(attr)), bgcolor_);
+
+ block->h += fsize + 2;
+
+ format_table(&table_width, columns, start);
+
+ if ((xx + table_width) > hsize_) {
+#ifdef DEBUG
+ printf("xx=%d, table_width=%d, hsize_=%d\n", xx, table_width,
+ hsize_);
+#endif // DEBUG
+ hsize_ = xx + table_width;
+ done = 0;
+ break;
+ }
+
+ switch (get_align(attrs, talign))
+ {
+ default :
+ table_offset = 0;
+ break;
+
+ case CENTER :
+ table_offset = (hsize_ - table_width) / 2 - textsize_;
+ break;
+
+ case RIGHT :
+ table_offset = hsize_ - table_width - textsize_;
+ break;
+ }
+
+ column = 0;
+ }
+
+ if (tolower(buf[0]) == 'h' && isdigit(buf[1]))
+ {
+ font = FL_HELVETICA_BOLD;
+ fsize = (uchar)(textsize_ + '7' - buf[1]);
+ }
+ else if (strcasecmp(buf, "DT") == 0)
+ {
+ font = (uchar)(textfont_ | FL_ITALIC);
+ fsize = textsize_;
+ }
+ else if (strcasecmp(buf, "PRE") == 0)
+ {
+ font = FL_COURIER;
+ fsize = textsize_;
+ pre = 1;
+ }
+ else
+ {
+ font = textfont_;
+ fsize = textsize_;
+ }
+
+ pushfont(font, fsize);
+
+ yy = block->y + block->h;
+ hh = 0;
+
+ if ((tolower(buf[0]) == 'h' && isdigit(buf[1])) ||
+ strcasecmp(buf, "DD") == 0 ||
+ strcasecmp(buf, "DT") == 0 ||
+ strcasecmp(buf, "P") == 0)
+ yy += fsize + 2;
+ else if (strcasecmp(buf, "HR") == 0)
+ {
+ hh += 2 * fsize;
+ yy += fsize;
+ }
+
+ if (row)
+ block = add_block(start, xx, yy, block->w, 0);
+ else
+ block = add_block(start, xx, yy, hsize_, 0);
+
+ needspace = 0;
+ line = 0;
+
+ if (strcasecmp(buf, "CENTER") == 0)
+ newalign = talign = CENTER;
+ else
+ newalign = get_align(attrs, talign);
+ }
+ else if (strcasecmp(buf, "/CENTER") == 0 ||
+ strcasecmp(buf, "/P") == 0 ||
+ strcasecmp(buf, "/H1") == 0 ||
+ strcasecmp(buf, "/H2") == 0 ||
+ strcasecmp(buf, "/H3") == 0 ||
+ strcasecmp(buf, "/H4") == 0 ||
+ strcasecmp(buf, "/H5") == 0 ||
+ strcasecmp(buf, "/H6") == 0 ||
+ strcasecmp(buf, "/PRE") == 0 ||
+ strcasecmp(buf, "/UL") == 0 ||
+ strcasecmp(buf, "/OL") == 0 ||
+ strcasecmp(buf, "/DL") == 0 ||
+ strcasecmp(buf, "/TABLE") == 0)
+ {
+ line = do_align(block, line, xx, newalign, links);
+ xx = block->x;
+ block->end = ptr;
+
+ if (strcasecmp(buf, "/UL") == 0 ||
+ strcasecmp(buf, "/OL") == 0 ||
+ strcasecmp(buf, "/DL") == 0)
+ {
+ xx = margins.pop();
+ block->h += fsize + 2;
+ }
+ else if (strcasecmp(buf, "/TABLE") == 0)
+ {
+ block->h += fsize + 2;
+ xx = margins.current();
+ }
+ else if (strcasecmp(buf, "/PRE") == 0)
+ {
+ pre = 0;
+ hh = 0;
+ }
+ else if (strcasecmp(buf, "/CENTER") == 0)
+ talign = LEFT;
+
+ popfont(font, fsize);
+
+ while (isspace((*ptr)&255))
+ ptr ++;
+
+ block->h += hh;
+ yy += hh;
+
+ if (tolower(buf[2]) == 'l')
+ yy += fsize + 2;
+
+ if (row)
+ block = add_block(ptr, xx, yy, block->w, 0);
+ else
+ block = add_block(ptr, xx, yy, hsize_, 0);
+
+ needspace = 0;
+ hh = 0;
+ line = 0;
+ newalign = talign;
+ }
+ else if (strcasecmp(buf, "TR") == 0)
+ {
+ block->end = start;
+ line = do_align(block, line, xx, newalign, links);
+ xx = block->x;
+ block->h += hh;
+
+ if (row)
+ {
+ yy = blocks_[row].y + blocks_[row].h;
+
+ for (cell = blocks_ + row + 1; cell <= block; cell ++)
+ if ((cell->y + cell->h) > yy)
+ yy = cell->y + cell->h;
+
+ block = blocks_ + row;
+
+ block->h = yy - block->y + 2;
+
+ for (i = 0; i < column; i ++)
+ if (cells[i])
+ {
+ cell = blocks_ + cells[i];
+ cell->h = block->h;
+ }
+ }
+
+ memset(cells, 0, sizeof(cells));
+
+ yy = block->y + block->h - 4;
+ hh = 0;
+ block = add_block(start, xx, yy, hsize_, 0);
+ row = block - blocks_;
+ needspace = 0;
+ column = 0;
+ line = 0;
+
+ rc = get_color(get_attr(attrs, "BGCOLOR", attr, sizeof(attr)), tc);
+ }
+ else if (strcasecmp(buf, "/TR") == 0 && row)
+ {
+ line = do_align(block, line, xx, newalign, links);
+ block->end = start;
+ block->h += hh;
+ talign = LEFT;
+
+ xx = blocks_[row].x;
+ yy = blocks_[row].y + blocks_[row].h;
+
+ for (cell = blocks_ + row + 1; cell <= block; cell ++)
+ if ((cell->y + cell->h) > yy)
+ yy = cell->y + cell->h;
+
+ block = blocks_ + row;
+
+ block->h = yy - block->y + 2;
+
+ for (i = 0; i < column; i ++)
+ if (cells[i])
+ {
+ cell = blocks_ + cells[i];
+ cell->h = block->h;
+ }
+
+ yy = block->y + block->h /*- 4*/;
+ block = add_block(start, xx, yy, hsize_, 0);
+ needspace = 0;
+ row = 0;
+ line = 0;
+ }
+ else if ((strcasecmp(buf, "TD") == 0 ||
+ strcasecmp(buf, "TH") == 0) && row)
+ {
+ int colspan; // COLSPAN attribute
+
+
+ line = do_align(block, line, xx, newalign, links);
+ block->end = start;
+ block->h += hh;
+
+ if (strcasecmp(buf, "TH") == 0)
+ font = (uchar)(textfont_ | FL_BOLD);
+ else
+ font = textfont_;
+
+ fsize = textsize_;
+
+ xx = blocks_[row].x + fsize + 3 + table_offset;
+ for (i = 0; i < column; i ++)
+ xx += columns[i] + 6;
+
+ margins.push(xx - margins.current());
+
+ if (get_attr(attrs, "COLSPAN", attr, sizeof(attr)) != NULL)
+ colspan = atoi(attr);
+ else
+ colspan = 1;
+
+ for (i = 0, ww = -6; i < colspan; i ++)
+ ww += columns[column + i] + 6;
+
+ if (block->end == block->start && nblocks_ > 1)
+ {
+ nblocks_ --;
+ block --;
+ }
+
+ pushfont(font, fsize);
+
+ yy = blocks_[row].y;
+ hh = 0;
+ block = add_block(start, xx, yy, xx + ww, 0, border);
+ needspace = 0;
+ line = 0;
+ newalign = get_align(attrs, tolower(buf[1]) == 'h' ? CENTER : LEFT);
+ talign = newalign;
+
+ cells[column] = block - blocks_;
+
+ column += colspan;
+
+ block->bgcolor = get_color(get_attr(attrs, "BGCOLOR", attr,
+ sizeof(attr)), rc);
+ }
+ else if ((strcasecmp(buf, "/TD") == 0 ||
+ strcasecmp(buf, "/TH") == 0) && row)
+ {
+ line = do_align(block, line, xx, newalign, links);
+ popfont(font, fsize);
+ xx = margins.pop();
+ talign = LEFT;
+ }
+ else if (strcasecmp(buf, "FONT") == 0)
+ {
+ if (get_attr(attrs, "FACE", attr, sizeof(attr)) != NULL) {
+ if (!strncasecmp(attr, "helvetica", 9) ||
+ !strncasecmp(attr, "arial", 5) ||
+ !strncasecmp(attr, "sans", 4)) font = FL_HELVETICA;
+ else if (!strncasecmp(attr, "times", 5) ||
+ !strncasecmp(attr, "serif", 5)) font = FL_TIMES;
+ else if (!strncasecmp(attr, "symbol", 6)) font = FL_SYMBOL;
+ else font = FL_COURIER;
+ }
+
+ if (get_attr(attrs, "SIZE", attr, sizeof(attr)) != NULL) {
+ if (isdigit(attr[0] & 255)) {
+ // Absolute size
+ fsize = (int)(textsize_ * pow(1.2, atoi(attr) - 3.0));
+ } else {
+ // Relative size
+ fsize = (int)(fsize * pow(1.2, atoi(attr)));
+ }
+ }
+
+ pushfont(font, fsize);
+ }
+ else if (strcasecmp(buf, "/FONT") == 0)
+ popfont(font, fsize);
+ else if (strcasecmp(buf, "B") == 0 ||
+ strcasecmp(buf, "STRONG") == 0)
+ pushfont(font |= FL_BOLD, fsize);
+ else if (strcasecmp(buf, "I") == 0 ||
+ strcasecmp(buf, "EM") == 0)
+ pushfont(font |= FL_ITALIC, fsize);
+ else if (strcasecmp(buf, "CODE") == 0 ||
+ strcasecmp(buf, "TT") == 0)
+ pushfont(font = FL_COURIER, fsize);
+ else if (strcasecmp(buf, "KBD") == 0)
+ pushfont(font = FL_COURIER_BOLD, fsize);
+ else if (strcasecmp(buf, "VAR") == 0)
+ pushfont(font = FL_COURIER_ITALIC, fsize);
+ else if (strcasecmp(buf, "/B") == 0 ||
+ strcasecmp(buf, "/STRONG") == 0 ||
+ strcasecmp(buf, "/I") == 0 ||
+ strcasecmp(buf, "/EM") == 0 ||
+ strcasecmp(buf, "/CODE") == 0 ||
+ strcasecmp(buf, "/TT") == 0 ||
+ strcasecmp(buf, "/KBD") == 0 ||
+ strcasecmp(buf, "/VAR") == 0)
+ popfont(font, fsize);
+ else if (strcasecmp(buf, "IMG") == 0)
+ {
+ Fl_Shared_Image *img = 0;
+ int width;
+ int height;
+
+
+ get_attr(attrs, "WIDTH", wattr, sizeof(wattr));
+ get_attr(attrs, "HEIGHT", hattr, sizeof(hattr));
+ width = get_length(wattr);
+ height = get_length(hattr);
+
+ if (get_attr(attrs, "SRC", attr, sizeof(attr))) {
+ img = get_image(attr, width, height);
+ width = img->w();
+ height = img->h();
+ }
+
+ ww = width;
+
+ if (ww > hsize_) {
+ hsize_ = ww;
+ done = 0;
+ break;
+ }
+
+ if (needspace && xx > block->x)
+ ww += (int)fl_width(' ');
+
+ if ((xx + ww) > block->w)
+ {
+ line = do_align(block, line, xx, newalign, links);
+ xx = block->x;
+ yy += hh;
+ block->h += hh;
+ hh = 0;
+ }
+
+ if (linkdest[0])
+ add_link(linkdest, xx, yy - height, ww, height);
+
+ xx += ww;
+ if ((height + 2) > hh)
+ hh = height + 2;
+
+ needspace = 0;
+ }
+ }
+ else if (*ptr == '\n' && pre)
+ {
+ if (linkdest[0])
+ add_link(linkdest, xx, yy - hh, ww, hh);
+
+ if (xx > hsize_) {
+ hsize_ = xx;
+ done = 0;
+ break;
+ }
+
+ line = do_align(block, line, xx, newalign, links);
+ xx = block->x;
+ yy += hh;
+ block->h += hh;
+ needspace = 0;
+ ptr ++;
+ }
+ else if (isspace((*ptr)&255))
+ {
+ needspace = 1;
+
+ ptr ++;
+ }
+ else if (*ptr == '&' && s < (buf + sizeof(buf) - 1))
+ {
+ ptr ++;
+
+ int qch = quote_char(ptr);
+
+ if (qch < 0)
+ *s++ = '&';
+ else {
+ *s++ = qch;
+ ptr = strchr(ptr, ';') + 1;
+ }
+
+ if ((fsize + 2) > hh)
+ hh = fsize + 2;
+ }
+ else
+ {
+ if (s < (buf + sizeof(buf) - 1))
+ *s++ = *ptr++;
+ else
+ ptr ++;
+
+ if ((fsize + 2) > hh)
+ hh = fsize + 2;
+ }
+ }
+
+ if (s > buf && !head)
+ {
+ *s = '\0';
+ ww = (int)fl_width(buf);
+
+ // printf("line = %d, xx = %d, ww = %d, block->x = %d, block->w = %d\n",
+ // line, xx, ww, block->x, block->w);
+
+ if (ww > hsize_) {
+ hsize_ = ww;
+ done = 0;
+ break;
+ }
+
+ if (needspace && xx > block->x)
+ ww += (int)fl_width(' ');
+
+ if ((xx + ww) > block->w)
+ {
+ line = do_align(block, line, xx, newalign, links);
+ xx = block->x;
+ yy += hh;
+ block->h += hh;
+ hh = 0;
+ }
+
+ if (linkdest[0])
+ add_link(linkdest, xx, yy - fsize, ww, fsize);
+
+ xx += ww;
+ }
+
+ do_align(block, line, xx, newalign, links);
+
+ block->end = ptr;
+ size_ = yy + hh;
+ }
+
+// printf("margins.depth_=%d\n", margins.depth_);
+
+ if (ntargets_ > 1)
+ qsort(targets_, ntargets_, sizeof(Fl_Help_Target),
+ (compare_func_t)compare_targets);
+
+ int dx = Fl::box_dw(b) - Fl::box_dx(b);
+ int dy = Fl::box_dh(b) - Fl::box_dy(b);
+ int ss = Fl::scrollbar_size();
+ int dw = Fl::box_dw(b) + ss;
+ int dh = Fl::box_dh(b);
+
+ if (hsize_ > (w() - dw)) {
+ hscrollbar_.show();
+
+ dh += ss;
+
+ if (size_ < (h() - dh)) {
+ scrollbar_.hide();
+ hscrollbar_.resize(x() + Fl::box_dx(b), y() + h() - ss - dy,
+ w() - Fl::box_dw(b), ss);
+ } else {
+ scrollbar_.show();
+ scrollbar_.resize(x() + w() - ss - dx, y() + Fl::box_dy(b),
+ ss, h() - ss - Fl::box_dh(b));
+ hscrollbar_.resize(x() + Fl::box_dx(b), y() + h() - ss - dy,
+ w() - ss - Fl::box_dw(b), ss);
+ }
+ } else {
+ hscrollbar_.hide();
+
+ if (size_ < (h() - dh)) scrollbar_.hide();
+ else {
+ scrollbar_.resize(x() + w() - ss - dx, y() + Fl::box_dy(b),
+ ss, h() - Fl::box_dh(b));
+ scrollbar_.show();
+ }
+ }
+
+ // Reset scrolling if it needs to be...
+ if (scrollbar_.visible()) {
+ int temph = h() - Fl::box_dh(b);
+ if (hscrollbar_.visible()) temph -= ss;
+ if ((topline_ + temph) > size_) topline(size_ - temph);
+ else topline(topline_);
+ } else topline(0);
+
+ if (hscrollbar_.visible()) {
+ int tempw = w() - ss - Fl::box_dw(b);
+ if ((leftline_ + tempw) > hsize_) leftline(hsize_ - tempw);
+ else leftline(leftline_);
+ } else leftline(0);
+}
+
+
+//
+// 'Fl_Help_View::format_table()' - Format a table...
+//
+
+void
+Fl_Help_View::format_table(int *table_width, // O - Total table width
+ int *columns, // O - Column widths
+ const char *table) // I - Pointer to start of table
+{
+ int column, // Current column
+ num_columns, // Number of columns
+ colspan, // COLSPAN attribute
+ width, // Current width
+ temp_width, // Temporary width
+ max_width, // Maximum width
+ incell, // In a table cell?
+ pre, // <PRE> text?
+ needspace; // Need whitespace?
+ char *s, // Pointer into buffer
+ buf[1024], // Text buffer
+ attr[1024], // Other attribute
+ wattr[1024], // WIDTH attribute
+ hattr[1024]; // HEIGHT attribute
+ const char *ptr, // Pointer into table
+ *attrs, // Pointer to attributes
+ *start; // Start of element
+ int minwidths[MAX_COLUMNS]; // Minimum widths for each column
+ unsigned char font, fsize; // Current font and size
+
+
+ // Clear widths...
+ *table_width = 0;
+ for (column = 0; column < MAX_COLUMNS; column ++)
+ {
+ columns[column] = 0;
+ minwidths[column] = 0;
+ }
+
+ num_columns = 0;
+ colspan = 0;
+ max_width = 0;
+ pre = 0;
+ needspace = 0;
+ font = fonts_[nfonts_][0];
+ fsize = fonts_[nfonts_][1];
+
+ // Scan the table...
+ for (ptr = table, column = -1, width = 0, s = buf, incell = 0; *ptr;)
+ {
+ if ((*ptr == '<' || isspace((*ptr)&255)) && s > buf && incell)
+ {
+ // Check width...
+ if (needspace)
+ {
+ *s++ = ' ';
+ needspace = 0;
+ }
+
+ *s = '\0';
+ temp_width = (int)fl_width(buf);
+ s = buf;
+
+ if (temp_width > minwidths[column])
+ minwidths[column] = temp_width;
+
+ width += temp_width;
+
+ if (width > max_width)
+ max_width = width;
+ }
+
+ if (*ptr == '<')
+ {
+ start = ptr;
+
+ for (s = buf, ptr ++; *ptr && *ptr != '>' && !isspace((*ptr)&255);)
+ if (s < (buf + sizeof(buf) - 1))
+ *s++ = *ptr++;
+ else
+ ptr ++;
+
+ *s = '\0';
+ s = buf;
+
+ attrs = ptr;
+ while (*ptr && *ptr != '>')
+ ptr ++;
+
+ if (*ptr == '>')
+ ptr ++;
+
+ if (strcasecmp(buf, "BR") == 0 ||
+ strcasecmp(buf, "HR") == 0)
+ {
+ width = 0;
+ needspace = 0;
+ }
+ else if (strcasecmp(buf, "TABLE") == 0 && start > table)
+ break;
+ else if (strcasecmp(buf, "CENTER") == 0 ||
+ strcasecmp(buf, "P") == 0 ||
+ strcasecmp(buf, "H1") == 0 ||
+ strcasecmp(buf, "H2") == 0 ||
+ strcasecmp(buf, "H3") == 0 ||
+ strcasecmp(buf, "H4") == 0 ||
+ strcasecmp(buf, "H5") == 0 ||
+ strcasecmp(buf, "H6") == 0 ||
+ strcasecmp(buf, "UL") == 0 ||
+ strcasecmp(buf, "OL") == 0 ||
+ strcasecmp(buf, "DL") == 0 ||
+ strcasecmp(buf, "LI") == 0 ||
+ strcasecmp(buf, "DD") == 0 ||
+ strcasecmp(buf, "DT") == 0 ||
+ strcasecmp(buf, "PRE") == 0)
+ {
+ width = 0;
+ needspace = 0;
+
+ if (tolower(buf[0]) == 'h' && isdigit(buf[1]))
+ {
+ font = FL_HELVETICA_BOLD;
+ fsize = (uchar)(textsize_ + '7' - buf[1]);
+ }
+ else if (strcasecmp(buf, "DT") == 0)
+ {
+ font = (uchar)(textfont_ | FL_ITALIC);
+ fsize = textsize_;
+ }
+ else if (strcasecmp(buf, "PRE") == 0)
+ {
+ font = FL_COURIER;
+ fsize = textsize_;
+ pre = 1;
+ }
+ else if (strcasecmp(buf, "LI") == 0)
+ {
+ width += 4 * fsize;
+ font = textfont_;
+ fsize = textsize_;
+ }
+ else
+ {
+ font = textfont_;
+ fsize = textsize_;
+ }
+
+ pushfont(font, fsize);
+ }
+ else if (strcasecmp(buf, "/CENTER") == 0 ||
+ strcasecmp(buf, "/P") == 0 ||
+ strcasecmp(buf, "/H1") == 0 ||
+ strcasecmp(buf, "/H2") == 0 ||
+ strcasecmp(buf, "/H3") == 0 ||
+ strcasecmp(buf, "/H4") == 0 ||
+ strcasecmp(buf, "/H5") == 0 ||
+ strcasecmp(buf, "/H6") == 0 ||
+ strcasecmp(buf, "/PRE") == 0 ||
+ strcasecmp(buf, "/UL") == 0 ||
+ strcasecmp(buf, "/OL") == 0 ||
+ strcasecmp(buf, "/DL") == 0)
+ {
+ width = 0;
+ needspace = 0;
+
+ popfont(font, fsize);
+ }
+ else if (strcasecmp(buf, "TR") == 0 || strcasecmp(buf, "/TR") == 0 ||
+ strcasecmp(buf, "/TABLE") == 0)
+ {
+// printf("%s column = %d, colspan = %d, num_columns = %d\n",
+// buf, column, colspan, num_columns);
+
+ if (column >= 0)
+ {
+ // This is a hack to support COLSPAN...
+ max_width /= colspan;
+
+ while (colspan > 0)
+ {
+ if (max_width > columns[column])
+ columns[column] = max_width;
+
+ column ++;
+ colspan --;
+ }
+ }
+
+ if (strcasecmp(buf, "/TABLE") == 0)
+ break;
+
+ needspace = 0;
+ column = -1;
+ width = 0;
+ max_width = 0;
+ incell = 0;
+ }
+ else if (strcasecmp(buf, "TD") == 0 ||
+ strcasecmp(buf, "TH") == 0)
+ {
+// printf("BEFORE column = %d, colspan = %d, num_columns = %d\n",
+// column, colspan, num_columns);
+
+ if (column >= 0)
+ {
+ // This is a hack to support COLSPAN...
+ max_width /= colspan;
+
+ while (colspan > 0)
+ {
+ if (max_width > columns[column])
+ columns[column] = max_width;
+
+ column ++;
+ colspan --;
+ }
+ }
+ else
+ column ++;
+
+ if (get_attr(attrs, "COLSPAN", attr, sizeof(attr)) != NULL)
+ colspan = atoi(attr);
+ else
+ colspan = 1;
+
+// printf("AFTER column = %d, colspan = %d, num_columns = %d\n",
+// column, colspan, num_columns);
+
+ if ((column + colspan) >= num_columns)
+ num_columns = column + colspan;
+
+ needspace = 0;
+ width = 0;
+ incell = 1;
+
+ if (strcasecmp(buf, "TH") == 0)
+ font = (uchar)(textfont_ | FL_BOLD);
+ else
+ font = textfont_;
+
+ fsize = textsize_;
+
+ pushfont(font, fsize);
+
+ if (get_attr(attrs, "WIDTH", attr, sizeof(attr)) != NULL)
+ max_width = get_length(attr);
+ else
+ max_width = 0;
+
+// printf("max_width = %d\n", max_width);
+ }
+ else if (strcasecmp(buf, "/TD") == 0 ||
+ strcasecmp(buf, "/TH") == 0)
+ {
+ incell = 0;
+ popfont(font, fsize);
+ }
+ else if (strcasecmp(buf, "B") == 0 ||
+ strcasecmp(buf, "STRONG") == 0)
+ pushfont(font |= FL_BOLD, fsize);
+ else if (strcasecmp(buf, "I") == 0 ||
+ strcasecmp(buf, "EM") == 0)
+ pushfont(font |= FL_ITALIC, fsize);
+ else if (strcasecmp(buf, "CODE") == 0 ||
+ strcasecmp(buf, "TT") == 0)
+ pushfont(font = FL_COURIER, fsize);
+ else if (strcasecmp(buf, "KBD") == 0)
+ pushfont(font = FL_COURIER_BOLD, fsize);
+ else if (strcasecmp(buf, "VAR") == 0)
+ pushfont(font = FL_COURIER_ITALIC, fsize);
+ else if (strcasecmp(buf, "/B") == 0 ||
+ strcasecmp(buf, "/STRONG") == 0 ||
+ strcasecmp(buf, "/I") == 0 ||
+ strcasecmp(buf, "/EM") == 0 ||
+ strcasecmp(buf, "/CODE") == 0 ||
+ strcasecmp(buf, "/TT") == 0 ||
+ strcasecmp(buf, "/KBD") == 0 ||
+ strcasecmp(buf, "/VAR") == 0)
+ popfont(font, fsize);
+ else if (strcasecmp(buf, "IMG") == 0 && incell)
+ {
+ Fl_Shared_Image *img = 0;
+ int iwidth, iheight;
+
+
+ get_attr(attrs, "WIDTH", wattr, sizeof(wattr));
+ get_attr(attrs, "HEIGHT", hattr, sizeof(hattr));
+ iwidth = get_length(wattr);
+ iheight = get_length(hattr);
+
+ if (get_attr(attrs, "SRC", attr, sizeof(attr))) {
+ img = get_image(attr, iwidth, iheight);
+ iwidth = img->w();
+ iheight = img->h();
+ }
+
+ if (iwidth > minwidths[column])
+ minwidths[column] = iwidth;
+
+ width += iwidth;
+ if (needspace)
+ width += (int)fl_width(' ');
+
+ if (width > max_width)
+ max_width = width;
+
+ needspace = 0;
+ }
+ }
+ else if (*ptr == '\n' && pre)
+ {
+ width = 0;
+ needspace = 0;
+ ptr ++;
+ }
+ else if (isspace((*ptr)&255))
+ {
+ needspace = 1;
+
+ ptr ++;
+ }
+ else if (*ptr == '&' && s < (buf + sizeof(buf) - 1))
+ {
+ ptr ++;
+
+ int qch = quote_char(ptr);
+
+ if (qch < 0)
+ *s++ = '&';
+ else {
+ *s++ = qch;
+ ptr = strchr(ptr, ';') + 1;
+ }
+ }
+ else
+ {
+ if (s < (buf + sizeof(buf) - 1))
+ *s++ = *ptr++;
+ else
+ ptr ++;
+ }
+ }
+
+ // Now that we have scanned the entire table, adjust the table and
+ // cell widths to fit on the screen...
+ if (get_attr(table + 6, "WIDTH", attr, sizeof(attr)))
+ *table_width = get_length(attr);
+ else
+ *table_width = 0;
+
+#ifdef DEBUG
+ printf("num_columns = %d, table_width = %d\n", num_columns, *table_width);
+#endif // DEBUG
+
+ if (num_columns == 0)
+ return;
+
+ // Add up the widths...
+ for (column = 0, width = 0; column < num_columns; column ++)
+ width += columns[column];
+
+#ifdef DEBUG
+ printf("width = %d, w() = %d\n", width, w());
+ for (column = 0; column < num_columns; column ++)
+ printf(" columns[%d] = %d, minwidths[%d] = %d\n", column, columns[column],
+ column, minwidths[column]);
+#endif // DEBUG
+
+ // Adjust the width if needed...
+ int scale_width = *table_width;
+
+ if (scale_width == 0) {
+ if (width > (hsize_ - Fl::scrollbar_size())) scale_width = hsize_ - Fl::scrollbar_size();
+ else scale_width = width;
+ }
+
+ if (width < scale_width) {
+#ifdef DEBUG
+ printf("Scaling table up to %d from %d...\n", scale_width, width);
+#endif // DEBUG
+
+ *table_width = 0;
+
+ scale_width = (scale_width - width) / num_columns;
+
+#ifdef DEBUG
+ printf("adjusted scale_width = %d\n", scale_width);
+#endif // DEBUG
+
+ for (column = 0; column < num_columns; column ++) {
+ columns[column] += scale_width;
+
+ (*table_width) += columns[column];
+ }
+ }
+ else if (width > scale_width) {
+#ifdef DEBUG
+ printf("Scaling table down to %d from %d...\n", scale_width, width);
+#endif // DEBUG
+
+ for (column = 0; column < num_columns; column ++) {
+ width -= minwidths[column];
+ scale_width -= minwidths[column];
+ }
+
+#ifdef DEBUG
+ printf("adjusted width = %d, scale_width = %d\n", width, scale_width);
+#endif // DEBUG
+
+ if (width > 0) {
+ for (column = 0; column < num_columns; column ++) {
+ columns[column] -= minwidths[column];
+ columns[column] = scale_width * columns[column] / width;
+ columns[column] += minwidths[column];
+ }
+ }
+
+ *table_width = 0;
+ for (column = 0; column < num_columns; column ++) {
+ (*table_width) += columns[column];
+ }
+ }
+ else if (*table_width == 0)
+ *table_width = width;
+
+#ifdef DEBUG
+ printf("FINAL table_width = %d\n", *table_width);
+ for (column = 0; column < num_columns; column ++)
+ printf(" columns[%d] = %d\n", column, columns[column]);
+#endif // DEBUG
+}
+
+
+//
+// 'Fl_Help_View::free_data()' - Free memory used for the document.
+//
+
+void
+Fl_Help_View::free_data() {
+ // Release all images...
+ if (value_) {
+ const char *ptr, // Pointer into block
+ *attrs; // Pointer to start of element attributes
+ char *s, // Pointer into buffer
+ buf[1024], // Text buffer
+ attr[1024], // Attribute buffer
+ wattr[1024], // Width attribute buffer
+ hattr[1024]; // Height attribute buffer
+
+ for (ptr = value_; *ptr;)
+ {
+ if (*ptr == '<')
+ {
+ ptr ++;
+
+ if (strncmp(ptr, "!--", 3) == 0)
+ {
+ // Comment...
+ ptr += 3;
+ if ((ptr = strstr(ptr, "-->")) != NULL)
+ {
+ ptr += 3;
+ continue;
+ }
+ else
+ break;
+ }
+
+ s = buf;
+
+ while (*ptr && *ptr != '>' && !isspace((*ptr)&255))
+ if (s < (buf + sizeof(buf) - 1))
+ *s++ = *ptr++;
+ else
+ ptr ++;
+
+ *s = '\0';
+
+ attrs = ptr;
+ while (*ptr && *ptr != '>')
+ ptr ++;
+
+ if (*ptr == '>')
+ ptr ++;
+
+ if (strcasecmp(buf, "IMG") == 0)
+ {
+ Fl_Shared_Image *img;
+ int width;
+ int height;
+
+ get_attr(attrs, "WIDTH", wattr, sizeof(wattr));
+ get_attr(attrs, "HEIGHT", hattr, sizeof(hattr));
+ width = get_length(wattr);
+ height = get_length(hattr);
+
+ if (get_attr(attrs, "SRC", attr, sizeof(attr))) {
+ // Get and release the image to free it from memory...
+ img = get_image(attr, width, height);
+ if ((void*)img != &broken_image) {
+ img->release();
+ }
+ }
+ }
+ }
+ else
+ ptr ++;
+ }
+
+ free((void *)value_);
+ value_ = 0;
+ }
+
+ // Free all of the arrays...
+ if (nblocks_) {
+ free(blocks_);
+
+ ablocks_ = 0;
+ nblocks_ = 0;
+ blocks_ = 0;
+ }
+
+ if (nlinks_) {
+ free(links_);
+
+ alinks_ = 0;
+ nlinks_ = 0;
+ links_ = 0;
+ }
+
+ if (ntargets_) {
+ free(targets_);
+
+ atargets_ = 0;
+ ntargets_ = 0;
+ targets_ = 0;
+ }
+}
+
+//
+// 'Fl_Help_View::get_align()' - Get an alignment attribute.
+//
+
+int // O - Alignment
+Fl_Help_View::get_align(const char *p, // I - Pointer to start of attrs
+ int a) // I - Default alignment
+{
+ char buf[255]; // Alignment value
+
+
+ if (get_attr(p, "ALIGN", buf, sizeof(buf)) == NULL)
+ return (a);
+
+ if (strcasecmp(buf, "CENTER") == 0)
+ return (CENTER);
+ else if (strcasecmp(buf, "RIGHT") == 0)
+ return (RIGHT);
+ else
+ return (LEFT);
+}
+
+
+//
+// 'Fl_Help_View::get_attr()' - Get an attribute value from the string.
+//
+
+const char * // O - Pointer to buf or NULL
+Fl_Help_View::get_attr(const char *p, // I - Pointer to start of attributes
+ const char *n, // I - Name of attribute
+ char *buf, // O - Buffer for attribute value
+ int bufsize) // I - Size of buffer
+{
+ char name[255], // Name from string
+ *ptr, // Pointer into name or value
+ quote; // Quote
+
+
+ buf[0] = '\0';
+
+ while (*p && *p != '>')
+ {
+ while (isspace((*p)&255))
+ p ++;
+
+ if (*p == '>' || !*p)
+ return (NULL);
+
+ for (ptr = name; *p && !isspace((*p)&255) && *p != '=' && *p != '>';)
+ if (ptr < (name + sizeof(name) - 1))
+ *ptr++ = *p++;
+ else
+ p ++;
+
+ *ptr = '\0';
+
+ if (isspace((*p)&255) || !*p || *p == '>')
+ buf[0] = '\0';
+ else
+ {
+ if (*p == '=')
+ p ++;
+
+ for (ptr = buf; *p && !isspace((*p)&255) && *p != '>';)
+ if (*p == '\'' || *p == '\"')
+ {
+ quote = *p++;
+
+ while (*p && *p != quote)
+ if ((ptr - buf + 1) < bufsize)
+ *ptr++ = *p++;
+ else
+ p ++;
+
+ if (*p == quote)
+ p ++;
+ }
+ else if ((ptr - buf + 1) < bufsize)
+ *ptr++ = *p++;
+ else
+ p ++;
+
+ *ptr = '\0';
+ }
+
+ if (strcasecmp(n, name) == 0)
+ return (buf);
+ else
+ buf[0] = '\0';
+
+ if (*p == '>')
+ return (NULL);
+ }
+
+ return (NULL);
+}
+
+
+//
+// 'Fl_Help_View::get_color()' - Get a color attribute.
+//
+
+Fl_Color // O - Color value
+Fl_Help_View::get_color(const char *n, // I - Color name
+ Fl_Color c) // I - Default color value
+{
+ int i; // Looping var
+ int rgb, r, g, b; // RGB values
+ static const struct { // Color name table
+ const char *name;
+ int r, g, b;
+ } colors[] = {
+ { "black", 0x00, 0x00, 0x00 },
+ { "red", 0xff, 0x00, 0x00 },
+ { "green", 0x00, 0x80, 0x00 },
+ { "yellow", 0xff, 0xff, 0x00 },
+ { "blue", 0x00, 0x00, 0xff },
+ { "magenta", 0xff, 0x00, 0xff },
+ { "fuchsia", 0xff, 0x00, 0xff },
+ { "cyan", 0x00, 0xff, 0xff },
+ { "aqua", 0x00, 0xff, 0xff },
+ { "white", 0xff, 0xff, 0xff },
+ { "gray", 0x80, 0x80, 0x80 },
+ { "grey", 0x80, 0x80, 0x80 },
+ { "lime", 0x00, 0xff, 0x00 },
+ { "maroon", 0x80, 0x00, 0x00 },
+ { "navy", 0x00, 0x00, 0x80 },
+ { "olive", 0x80, 0x80, 0x00 },
+ { "purple", 0x80, 0x00, 0x80 },
+ { "silver", 0xc0, 0xc0, 0xc0 },
+ { "teal", 0x00, 0x80, 0x80 }
+ };
+
+
+ if (!n || !n[0]) return c;
+
+ if (n[0] == '#') {
+ // Do hex color lookup
+ rgb = strtol(n + 1, NULL, 16);
+
+ if (strlen(n) > 4) {
+ r = rgb >> 16;
+ g = (rgb >> 8) & 255;
+ b = rgb & 255;
+ } else {
+ r = (rgb >> 8) * 17;
+ g = ((rgb >> 4) & 15) * 17;
+ b = (rgb & 15) * 17;
+ }
+ return (fl_rgb_color((uchar)r, (uchar)g, (uchar)b));
+ } else {
+ for (i = 0; i < (int)(sizeof(colors) / sizeof(colors[0])); i ++)
+ if (!strcasecmp(n, colors[i].name)) {
+ return fl_rgb_color(colors[i].r, colors[i].g, colors[i].b);
+ }
+ return c;
+ }
+}
+
+
+//
+// 'Fl_Help_View::get_image()' - Get an inline image.
+//
+
+/** Gets an inline image.
+
+ The image reference count is maintained accordingly, such that
+ the image can be released exactly once when the document is closed.
+
+ \return a pointer to a cached Fl_Shared_Image, if the image can be loaded,
+ otherwise a pointer to an internal Fl_Pixmap (broken_image).
+
+ \todo Fl_Help_View::get_image() returns a pointer to the internal
+ Fl_Pixmap broken_image, but this is _not_ compatible with the
+ return type Fl_Shared_Image (release() must not be called).
+*/
+
+/* Implementation note: (A.S. Apr 05, 2009)
+
+ Fl_Help_View::get_image() uses a static global flag (initial_load)
+ to determine, if it is called from the initial loading of a document
+ (load() or value()), or from resize() or draw().
+
+ A better solution would be to manage all loaded images in an own
+ structure like Fl_Help_Target (Fl_Help_Image ?) to avoid using this
+ global flag, but this would break the ABI !
+
+ This should be fixed in FLTK 1.3 !
+
+
+ If initial_load is true, then Fl_Shared_Image::get() is called to
+ load the image, and the reference count of the shared image is
+ increased by one.
+
+ If initial_load is false, then Fl_Shared_Image::find() is called to
+ load the image, and the image is released immediately. This avoids
+ increasing the reference count when calling get_image() from draw()
+ or resize().
+
+ Calling Fl_Shared_Image::find() instead of Fl_Shared_Image::get() avoids
+ doing unnecessary i/o for "broken images" within each resize/redraw.
+
+ Each image must be released exactly once in the destructor or before
+ a new document is loaded: see free_data().
+*/
+
+Fl_Shared_Image *
+Fl_Help_View::get_image(const char *name, int W, int H) {
+ const char *localname; // Local filename
+ char dir[1024]; // Current directory
+ char temp[1024], // Temporary filename
+ *tempptr; // Pointer into temporary name
+ Fl_Shared_Image *ip; // Image pointer...
+
+ // See if the image can be found...
+ if (strchr(directory_, ':') != NULL && strchr(name, ':') == NULL) {
+ if (name[0] == '/') {
+ strlcpy(temp, directory_, sizeof(temp));
+
+ if ((tempptr = strrchr(strchr(directory_, ':') + 3, '/')) != NULL) {
+ strlcpy(tempptr, name, sizeof(temp) - (tempptr - temp));
+ } else {
+ strlcat(temp, name, sizeof(temp));
+ }
+ } else {
+ snprintf(temp, sizeof(temp), "%s/%s", directory_, name);
+ }
+
+ if (link_) localname = (*link_)(this, temp);
+ else localname = temp;
+ } else if (name[0] != '/' && strchr(name, ':') == NULL) {
+ if (directory_[0]) snprintf(temp, sizeof(temp), "%s/%s", directory_, name);
+ else {
+ getcwd(dir, sizeof(dir));
+ snprintf(temp, sizeof(temp), "file:%s/%s", dir, name);
+ }
+
+ if (link_) localname = (*link_)(this, temp);
+ else localname = temp;
+ } else if (link_) localname = (*link_)(this, name);
+ else localname = name;
+
+ if (!localname) return 0;
+
+ if (strncmp(localname, "file:", 5) == 0) localname += 5;
+
+ if (initial_load) {
+ if ((ip = Fl_Shared_Image::get(localname, W, H)) == NULL) {
+ ip = (Fl_Shared_Image *)&broken_image;
+ }
+ } else { // draw or resize
+ if ((ip = Fl_Shared_Image::find(localname, W, H)) == NULL) {
+ ip = (Fl_Shared_Image *)&broken_image;
+ } else {
+ ip->release();
+ }
+ }
+
+ return ip;
+}
+
+
+//
+// 'Fl_Help_View::get_length()' - Get a length value, either absolute or %.
+//
+
+int
+Fl_Help_View::get_length(const char *l) { // I - Value
+ int val; // Integer value
+
+ if (!l[0]) return 0;
+
+ val = atoi(l);
+ if (l[strlen(l) - 1] == '%') {
+ if (val > 100) val = 100;
+ else if (val < 0) val = 0;
+
+ val = val * (hsize_ - Fl::scrollbar_size()) / 100;
+ }
+
+ return val;
+}
+
+
+Fl_Help_Link *Fl_Help_View::find_link(int xx, int yy)
+{
+ int i;
+ Fl_Help_Link *linkp;
+ for (i = nlinks_, linkp = links_; i > 0; i --, linkp ++) {
+ if (xx >= linkp->x && xx < linkp->w &&
+ yy >= linkp->y && yy < linkp->h)
+ break;
+ }
+ return i ? linkp : 0L;
+}
+
+void Fl_Help_View::follow_link(Fl_Help_Link *linkp)
+{
+ char target[32]; // Current target
+
+ clear_selection();
+
+ strlcpy(target, linkp->name, sizeof(target));
+
+ set_changed();
+
+ if (strcmp(linkp->filename, filename_) != 0 && linkp->filename[0])
+ {
+ char dir[1024]; // Current directory
+ char temp[1024], // Temporary filename
+ *tempptr; // Pointer into temporary filename
+
+
+ if (strchr(directory_, ':') != NULL &&
+ strchr(linkp->filename, ':') == NULL)
+ {
+ if (linkp->filename[0] == '/')
+ {
+ strlcpy(temp, directory_, sizeof(temp));
+ if ((tempptr = strrchr(strchr(directory_, ':') + 3, '/')) != NULL)
+ strlcpy(tempptr, linkp->filename, sizeof(temp));
+ else
+ strlcat(temp, linkp->filename, sizeof(temp));
+ }
+ else
+ snprintf(temp, sizeof(temp), "%s/%s", directory_, linkp->filename);
+ }
+ else if (linkp->filename[0] != '/' && strchr(linkp->filename, ':') == NULL)
+ {
+ if (directory_[0])
+ snprintf(temp, sizeof(temp), "%s/%s", directory_, linkp->filename);
+ else
+ {
+ getcwd(dir, sizeof(dir));
+ snprintf(temp, sizeof(temp), "file:%s/%s", dir, linkp->filename);
+ }
+ }
+ else
+ strlcpy(temp, linkp->filename, sizeof(temp));
+
+ if (linkp->name[0])
+ snprintf(temp + strlen(temp), sizeof(temp) - strlen(temp), "#%s",
+ linkp->name);
+
+ load(temp);
+ }
+ else if (target[0])
+ topline(target);
+ else
+ topline(0);
+
+ leftline(0);
+}
+
+void Fl_Help_View::clear_selection()
+{
+ if (current_view==this)
+ clear_global_selection();
+}
+
+void Fl_Help_View::select_all()
+{
+ clear_global_selection();
+ if (!value_) return;
+ current_view = this;
+ selection_drag_last = selection_last = strlen(value_);
+ selected = 1;
+}
+
+void Fl_Help_View::clear_global_selection()
+{
+ if (selected) redraw();
+ selection_push_first = selection_push_last = 0;
+ selection_drag_first = selection_drag_last = 0;
+ selection_first = selection_last = 0;
+ selected = 0;
+}
+
+char Fl_Help_View::begin_selection()
+{
+ clear_global_selection();
+
+ if (!fl_help_view_buffer) fl_help_view_buffer = fl_create_offscreen(1, 1);
+
+ mouse_x = Fl::event_x();
+ mouse_y = Fl::event_y();
+ draw_mode = 1;
+
+ current_view = this;
+ fl_begin_offscreen(fl_help_view_buffer);
+ draw();
+ fl_end_offscreen();
+
+ draw_mode = 0;
+
+ if (selection_push_last) return 1;
+ else return 0;
+}
+
+char Fl_Help_View::extend_selection()
+{
+ if (Fl::event_is_click())
+ return 0;
+
+// printf("old selection_first=%d, selection_last=%d\n",
+// selection_first, selection_last);
+
+ int sf = selection_first, sl = selection_last;
+
+ selected = 1;
+ mouse_x = Fl::event_x();
+ mouse_y = Fl::event_y();
+ draw_mode = 2;
+
+ fl_begin_offscreen(fl_help_view_buffer);
+ draw();
+ fl_end_offscreen();
+
+ draw_mode = 0;
+
+ if (selection_push_first < selection_drag_first) {
+ selection_first = selection_push_first;
+ } else {
+ selection_first = selection_drag_first;
+ }
+
+ if (selection_push_last > selection_drag_last) {
+ selection_last = selection_push_last;
+ } else {
+ selection_last = selection_drag_last;
+ }
+
+// printf("new selection_first=%d, selection_last=%d\n",
+// selection_first, selection_last);
+
+ if (sf!=selection_first || sl!=selection_last) {
+// puts("REDRAW!!!\n");
+ return 1;
+ } else {
+// puts("");
+ return 0;
+ }
+}
+
+// convert a command with up to four letters into an unsigned int
+static unsigned int command(const char *cmd)
+{
+ unsigned int ret = (tolower(cmd[0])<<24);
+ char c = cmd[1];
+ if (c=='>' || c==' ' || c==0) return ret;
+ ret |= (tolower(c)<<16);
+ c = cmd[2];
+ if (c=='>' || c==' ' || c==0) return ret;
+ ret |= (tolower(c)<<8);
+ c = cmd[3];
+ if (c=='>' || c==' ' || c==0) return ret;
+ ret |= tolower(c);
+ c = cmd[4];
+ if (c=='>' || c==' ' || c==0) return ret;
+ return 0;
+}
+
+#define CMD(a, b, c, d) ((a<<24)|(b<<16)|(c<<8)|d)
+
+void Fl_Help_View::end_selection(int clipboard)
+{
+ if (!selected || current_view!=this)
+ return;
+ // convert the select part of our html text into some kind of somewhat readable ASCII
+ // and store it in the selection buffer
+ char p = 0, pre = 0;;
+ int len = strlen(value_);
+ char *txt = (char*)malloc(len+1), *d = txt;
+ const char *s = value_, *cmd, *src;
+ for (;;) {
+ char c = *s++;
+ if (c==0) break;
+ if (c=='<') { // begin of some html command. Skip until we find a '>'
+ cmd = s;
+ for (;;) {
+ c = *s++;
+ if (c==0 || c=='>') break;
+ }
+ if (c==0) break;
+ // do something with this command... .
+ // the replacement string must not be longer that the command itself plus '<' and '>'
+ src = 0;
+ switch (command(cmd)) {
+ case CMD('p','r','e', 0 ): pre = 1; break;
+ case CMD('/','p','r','e'): pre = 0; break;
+ case CMD('t','d', 0 , 0 ):
+ case CMD('p', 0 , 0 , 0 ):
+ case CMD('/','p', 0 , 0 ):
+ case CMD('b','r', 0 , 0 ): src = "\n"; break;
+ case CMD('l','i', 0 , 0 ): src = "\n * "; break;
+ case CMD('/','h','1', 0 ):
+ case CMD('/','h','2', 0 ):
+ case CMD('/','h','3', 0 ):
+ case CMD('/','h','4', 0 ):
+ case CMD('/','h','5', 0 ):
+ case CMD('/','h','6', 0 ): src = "\n\n"; break;
+ case CMD('t','r', 0 , 0 ):
+ case CMD('h','1', 0 , 0 ):
+ case CMD('h','2', 0 , 0 ):
+ case CMD('h','3', 0 , 0 ):
+ case CMD('h','4', 0 , 0 ):
+ case CMD('h','5', 0 , 0 ):
+ case CMD('h','6', 0 , 0 ): src = "\n\n"; break;
+ case CMD('d','t', 0 , 0 ): src = "\n "; break;
+ case CMD('d','d', 0 , 0 ): src = "\n - "; break;
+ }
+ int n = s-value_;
+ if (src && n>selection_first && n<=selection_last) {
+ while (*src) {
+ *d++ = *src++;
+ }
+ c = src[-1];
+ p = isspace(c&255) ? ' ' : c;
+ }
+ continue;
+ }
+ if (c=='&') { // special characters
+ int xx = quote_char(s);
+ if (xx>=0) {
+ c = (char)xx;
+ for (;;) {
+ char cc = *s++;
+ if (!cc || cc==';') break;
+ }
+ }
+ }
+ int n = s-value_;
+ if (n>selection_first && n<=selection_last) {
+ if (!pre && isspace(c&255)) c = ' ';
+ if (p!=' '||c!=' ')
+ *d++ = c;
+ p = c;
+ }
+ }
+ *d = 0;
+ Fl::copy(txt, strlen(txt), clipboard);
+ free(txt);
+}
+
+#define ctrl(x) ((x)&0x1f)
+
+//
+// 'Fl_Help_View::handle()' - Handle events in the widget.
+//
+
+int // O - 1 if we handled it, 0 otherwise
+Fl_Help_View::handle(int event) // I - Event to handle
+{
+ static Fl_Help_Link *linkp; // currently clicked link
+
+ int xx = Fl::event_x() - x() + leftline_;
+ int yy = Fl::event_y() - y() + topline_;
+
+ switch (event)
+ {
+ case FL_FOCUS:
+ redraw();
+ return 1;
+ case FL_UNFOCUS:
+ clear_selection();
+ redraw();
+ return 1;
+ case FL_ENTER :
+ Fl_Group::handle(event);
+ return 1;
+ case FL_LEAVE :
+ fl_cursor(FL_CURSOR_DEFAULT);
+ break;
+ case FL_MOVE:
+ if (find_link(xx, yy)) fl_cursor(FL_CURSOR_HAND);
+ else fl_cursor(FL_CURSOR_DEFAULT);
+ return 1;
+ case FL_PUSH:
+ if (Fl_Group::handle(event)) return 1;
+ linkp = find_link(xx, yy);
+ if (linkp) {
+ fl_cursor(FL_CURSOR_HAND);
+ return 1;
+ }
+ if (begin_selection()) {
+ fl_cursor(FL_CURSOR_INSERT);
+ return 1;
+ }
+ fl_cursor(FL_CURSOR_DEFAULT);
+ return 1;
+ case FL_DRAG:
+ if (linkp) {
+ if (Fl::event_is_click()) {
+ fl_cursor(FL_CURSOR_HAND);
+ } else {
+ fl_cursor(FL_CURSOR_DEFAULT); // should be "FL_CURSOR_CANCEL" if we had it
+ }
+ return 1;
+ }
+ if (current_view==this && selection_push_last) {
+ if (extend_selection()) redraw();
+ fl_cursor(FL_CURSOR_INSERT);
+ return 1;
+ }
+ fl_cursor(FL_CURSOR_DEFAULT);
+ return 1;
+ case FL_RELEASE:
+ if (linkp) {
+ if (Fl::event_is_click()) {
+ follow_link(linkp);
+ }
+ fl_cursor(FL_CURSOR_DEFAULT);
+ linkp = 0;
+ return 1;
+ }
+ if (current_view==this && selection_push_last) {
+ end_selection();
+ return 1;
+ }
+ return 1;
+ case FL_SHORTCUT: {
+ char ascii = Fl::event_text()[0];
+ switch (ascii) {
+ case ctrl('A'): select_all(); redraw(); return 1;
+ case ctrl('C'):
+ case ctrl('X'): end_selection(1); return 1;
+ }
+ break; }
+ }
+ return (Fl_Group::handle(event));
+}
+
+//
+// 'Fl_Help_View::Fl_Help_View()' - Build a Fl_Help_View widget.
+//
+
+Fl_Help_View::Fl_Help_View(int xx, // I - Left position
+ int yy, // I - Top position
+ int ww, // I - Width in pixels
+ int hh, // I - Height in pixels
+ const char *l)
+ : Fl_Group(xx, yy, ww, hh, l),
+ scrollbar_(xx + ww - Fl::scrollbar_size(), yy,
+ Fl::scrollbar_size(), hh - Fl::scrollbar_size()),
+ hscrollbar_(xx, yy + hh - Fl::scrollbar_size(),
+ ww - Fl::scrollbar_size(), Fl::scrollbar_size())
+{
+ color(FL_BACKGROUND2_COLOR, FL_SELECTION_COLOR);
+
+ title_[0] = '\0';
+ defcolor_ = FL_FOREGROUND_COLOR;
+ bgcolor_ = FL_BACKGROUND_COLOR;
+ textcolor_ = FL_FOREGROUND_COLOR;
+ linkcolor_ = FL_SELECTION_COLOR;
+ textfont_ = FL_TIMES;
+ textsize_ = 12;
+ value_ = NULL;
+
+ ablocks_ = 0;
+ nblocks_ = 0;
+ blocks_ = (Fl_Help_Block *)0;
+
+ nfonts_ = 0;
+
+ link_ = (Fl_Help_Func *)0;
+
+ alinks_ = 0;
+ nlinks_ = 0;
+ links_ = (Fl_Help_Link *)0;
+
+ atargets_ = 0;
+ ntargets_ = 0;
+ targets_ = (Fl_Help_Target *)0;
+
+ directory_[0] = '\0';
+ filename_[0] = '\0';
+
+ topline_ = 0;
+ leftline_ = 0;
+ size_ = 0;
+ hsize_ = 0;
+
+ scrollbar_.value(0, hh, 0, 1);
+ scrollbar_.step(8.0);
+ scrollbar_.show();
+ scrollbar_.callback(scrollbar_callback);
+
+ hscrollbar_.value(0, ww, 0, 1);
+ hscrollbar_.step(8.0);
+ hscrollbar_.show();
+ hscrollbar_.callback(hscrollbar_callback);
+ hscrollbar_.type(FL_HORIZONTAL);
+ end();
+
+ resize(xx, yy, ww, hh);
+}
+
+
+//
+// 'Fl_Help_View::~Fl_Help_View()' - Destroy a Fl_Help_View widget.
+//
+
+Fl_Help_View::~Fl_Help_View()
+{
+ clear_selection();
+ free_data();
+}
+
+
+//
+// 'Fl_Help_View::load()' - Load the specified file.
+//
+
+int // O - 0 on success, -1 on error
+Fl_Help_View::load(const char *f)// I - Filename to load (may also have target)
+{
+ FILE *fp; // File to read from
+ long len; // Length of file
+ char *target; // Target in file
+ char *slash; // Directory separator
+ const char *localname; // Local filename
+ char error[1024]; // Error buffer
+ char newname[1024]; // New filename buffer
+
+ clear_selection();
+
+ strlcpy(newname, f, sizeof(newname));
+ if ((target = strrchr(newname, '#')) != NULL)
+ *target++ = '\0';
+
+ if (link_)
+ localname = (*link_)(this, newname);
+ else
+ localname = filename_;
+
+ if (!localname)
+ return (0);
+
+ free_data();
+
+ strlcpy(filename_, newname, sizeof(filename_));
+ strlcpy(directory_, newname, sizeof(directory_));
+
+ // Note: We do not support Windows backslashes, since they are illegal
+ // in URLs...
+ if ((slash = strrchr(directory_, '/')) == NULL)
+ directory_[0] = '\0';
+ else if (slash > directory_ && slash[-1] != '/')
+ *slash = '\0';
+
+ if (strncmp(localname, "ftp:", 4) == 0 ||
+ strncmp(localname, "http:", 5) == 0 ||
+ strncmp(localname, "https:", 6) == 0 ||
+ strncmp(localname, "ipp:", 4) == 0 ||
+ strncmp(localname, "mailto:", 7) == 0 ||
+ strncmp(localname, "news:", 5) == 0)
+ {
+ // Remote link wasn't resolved...
+ snprintf(error, sizeof(error),
+ "<HTML><HEAD><TITLE>Error</TITLE></HEAD>"
+ "<BODY><H1>Error</H1>"
+ "<P>Unable to follow the link \"%s\" - "
+ "no handler exists for this URI scheme.</P></BODY>",
+ localname);
+ value_ = strdup(error);
+ }
+ else
+ {
+ if (strncmp(localname, "file:", 5) == 0)
+ localname += 5; // Adjust for local filename...
+
+ if ((fp = fopen(localname, "rb")) != NULL)
+ {
+ fseek(fp, 0, SEEK_END);
+ len = ftell(fp);
+ rewind(fp);
+
+ value_ = (const char *)calloc(len + 1, 1);
+ fread((void *)value_, 1, len, fp);
+ fclose(fp);
+ }
+ else
+ {
+ snprintf(error, sizeof(error),
+ "<HTML><HEAD><TITLE>Error</TITLE></HEAD>"
+ "<BODY><H1>Error</H1>"
+ "<P>Unable to follow the link \"%s\" - "
+ "%s.</P></BODY>",
+ localname, strerror(errno));
+ value_ = strdup(error);
+ }
+ }
+
+ initial_load = 1;
+ format();
+ initial_load = 0;
+
+ if (target)
+ topline(target);
+ else
+ topline(0);
+
+ return (0);
+}
+
+
+//
+// 'Fl_Help_View::resize()' - Resize the help widget.
+//
+
+void
+Fl_Help_View::resize(int xx, // I - New left position
+ int yy, // I - New top position
+ int ww, // I - New width
+ int hh) // I - New height
+{
+ Fl_Boxtype b = box() ? box() : FL_DOWN_BOX;
+ // Box to draw...
+
+
+ Fl_Widget::resize(xx, yy, ww, hh);
+
+ int ss = Fl::scrollbar_size();
+ scrollbar_.resize(x() + w() - ss - Fl::box_dw(b) + Fl::box_dx(b),
+ y() + Fl::box_dy(b), ss, h() - ss - Fl::box_dh(b));
+ hscrollbar_.resize(x() + Fl::box_dx(b),
+ y() + h() - ss - Fl::box_dh(b) + Fl::box_dy(b),
+ w() - ss - Fl::box_dw(b), ss);
+
+ format();
+}
+
+
+//
+// 'Fl_Help_View::topline()' - Set the top line to the named target.
+//
+
+void
+Fl_Help_View::topline(const char *n) // I - Target name
+{
+ Fl_Help_Target key, // Target name key
+ *target; // Pointer to matching target
+
+
+ if (ntargets_ == 0)
+ return;
+
+ strlcpy(key.name, n, sizeof(key.name));
+
+ target = (Fl_Help_Target *)bsearch(&key, targets_, ntargets_, sizeof(Fl_Help_Target),
+ (compare_func_t)compare_targets);
+
+ if (target != NULL)
+ topline(target->y);
+}
+
+
+//
+// 'Fl_Help_View::topline()' - Set the top line by number.
+//
+
+void
+Fl_Help_View::topline(int t) // I - Top line number
+{
+ if (!value_)
+ return;
+
+ if (size_ < (h() - Fl::scrollbar_size()) || t < 0)
+ t = 0;
+ else if (t > size_)
+ t = size_;
+
+ topline_ = t;
+
+ scrollbar_.value(topline_, h() - Fl::scrollbar_size(), 0, size_);
+
+ do_callback();
+
+ redraw();
+}
+
+
+//
+// 'Fl_Help_View::leftline()' - Set the left position.
+//
+
+void
+Fl_Help_View::leftline(int l) // I - Left position
+{
+ if (!value_)
+ return;
+
+ if (hsize_ < (w() - Fl::scrollbar_size()) || l < 0)
+ l = 0;
+ else if (l > hsize_)
+ l = hsize_;
+
+ leftline_ = l;
+
+ hscrollbar_.value(leftline_, w() - Fl::scrollbar_size(), 0, hsize_);
+
+ redraw();
+}
+
+
+//
+// 'Fl_Help_View::value()' - Set the help text directly.
+//
+
+void
+Fl_Help_View::value(const char *v) // I - Text to view
+{
+ clear_selection();
+ free_data();
+ set_changed();
+
+ if (!v)
+ return;
+
+ value_ = strdup(v);
+
+ initial_load = 1;
+ format();
+ initial_load = 0;
+
+ topline(0);
+ leftline(0);
+}
+
+#ifdef ENC
+# undef ENC
+#endif
+#ifdef __APPLE__
+# define ENC(a, b) b
+#else
+# define ENC(a, b) a
+#endif
+
+//
+// 'quote_char()' - Return the character code associated with a quoted char.
+//
+
+static int // O - Code or -1 on error
+quote_char(const char *p) { // I - Quoted string
+ int i; // Looping var
+ static struct {
+ const char *name;
+ int namelen;
+ int code;
+ } *nameptr, // Pointer into name array
+ names[] = { // Quoting names
+ { "Aacute;", 7, ENC(193,231) },
+ { "aacute;", 7, ENC(225,135) },
+ { "Acirc;", 6, ENC(194,229) },
+ { "acirc;", 6, ENC(226,137) },
+ { "acute;", 6, ENC(180,171) },
+ { "AElig;", 6, ENC(198,174) },
+ { "aelig;", 6, ENC(230,190) },
+ { "Agrave;", 7, ENC(192,203) },
+ { "agrave;", 7, ENC(224,136) },
+ { "amp;", 4, ENC('&','&') },
+ { "Aring;", 6, ENC(197,129) },
+ { "aring;", 6, ENC(229,140) },
+ { "Atilde;", 7, ENC(195,204) },
+ { "atilde;", 7, ENC(227,139) },
+ { "Auml;", 5, ENC(196,128) },
+ { "auml;", 5, ENC(228,138) },
+ { "brvbar;", 7, ENC(166, -1) },
+ { "bull;", 5, ENC(149,165) },
+ { "Ccedil;", 7, ENC(199,199) },
+ { "ccedil;", 7, ENC(231,141) },
+ { "cedil;", 6, ENC(184,252) },
+ { "cent;", 5, ENC(162,162) },
+ { "copy;", 5, ENC(169,169) },
+ { "curren;", 7, ENC(164, -1) },
+ { "deg;", 4, ENC(176,161) },
+ { "divide;", 7, ENC(247,214) },
+ { "Eacute;", 7, ENC(201,131) },
+ { "eacute;", 7, ENC(233,142) },
+ { "Ecirc;", 6, ENC(202,230) },
+ { "ecirc;", 6, ENC(234,144) },
+ { "Egrave;", 7, ENC(200,233) },
+ { "egrave;", 7, ENC(232,143) },
+ { "ETH;", 4, ENC(208, -1) },
+ { "eth;", 4, ENC(240, -1) },
+ { "Euml;", 5, ENC(203,232) },
+ { "euml;", 5, ENC(235,145) },
+ { "euro;", 5, ENC(128,219) },
+ { "frac12;", 7, ENC(189, -1) },
+ { "frac14;", 7, ENC(188, -1) },
+ { "frac34;", 7, ENC(190, -1) },
+ { "gt;", 3, ENC('>','>') },
+ { "Iacute;", 7, ENC(205,234) },
+ { "iacute;", 7, ENC(237,146) },
+ { "Icirc;", 6, ENC(206,235) },
+ { "icirc;", 6, ENC(238,148) },
+ { "iexcl;", 6, ENC(161,193) },
+ { "Igrave;", 7, ENC(204,237) },
+ { "igrave;", 7, ENC(236,147) },
+ { "iquest;", 7, ENC(191,192) },
+ { "Iuml;", 5, ENC(207,236) },
+ { "iuml;", 5, ENC(239,149) },
+ { "laquo;", 6, ENC(171,199) },
+ { "lt;", 3, ENC('<','<') },
+ { "macr;", 5, ENC(175,248) },
+ { "micro;", 6, ENC(181,181) },
+ { "middot;", 7, ENC(183,225) },
+ { "nbsp;", 5, ENC(' ',' ') },
+ { "not;", 4, ENC(172,194) },
+ { "Ntilde;", 7, ENC(209,132) },
+ { "ntilde;", 7, ENC(241,150) },
+ { "Oacute;", 7, ENC(211,238) },
+ { "oacute;", 7, ENC(243,151) },
+ { "Ocirc;", 6, ENC(212,239) },
+ { "ocirc;", 6, ENC(244,153) },
+ { "Ograve;", 7, ENC(210,241) },
+ { "ograve;", 7, ENC(242,152) },
+ { "ordf;", 5, ENC(170,187) },
+ { "ordm;", 5, ENC(186,188) },
+ { "Oslash;", 7, ENC(216,175) },
+ { "oslash;", 7, ENC(248,191) },
+ { "Otilde;", 7, ENC(213,205) },
+ { "otilde;", 7, ENC(245,155) },
+ { "Ouml;", 5, ENC(214,133) },
+ { "ouml;", 5, ENC(246,154) },
+ { "para;", 5, ENC(182,166) },
+ { "premil;", 7, ENC(137,228) },
+ { "plusmn;", 7, ENC(177,177) },
+ { "pound;", 6, ENC(163,163) },
+ { "quot;", 5, ENC('\"','\"') },
+ { "raquo;", 6, ENC(187,200) },
+ { "reg;", 4, ENC(174,168) },
+ { "sect;", 5, ENC(167,164) },
+ { "shy;", 4, ENC(173,'-') },
+ { "sup1;", 5, ENC(185, -1) },
+ { "sup2;", 5, ENC(178, -1) },
+ { "sup3;", 5, ENC(179, -1) },
+ { "szlig;", 6, ENC(223,167) },
+ { "THORN;", 6, ENC(222, -1) },
+ { "thorn;", 6, ENC(254, -1) },
+ { "times;", 6, ENC(215,'x') },
+ { "trade;", 6, ENC(153,170) },
+ { "Uacute;", 7, ENC(218,242) },
+ { "uacute;", 7, ENC(250,156) },
+ { "Ucirc;", 6, ENC(219,243) },
+ { "ucirc;", 6, ENC(251,158) },
+ { "Ugrave;", 7, ENC(217,244) },
+ { "ugrave;", 7, ENC(249,157) },
+ { "uml;", 4, ENC(168,172) },
+ { "Uuml;", 5, ENC(220,134) },
+ { "uuml;", 5, ENC(252,159) },
+ { "Yacute;", 7, ENC(221, -1) },
+ { "yacute;", 7, ENC(253, -1) },
+ { "yen;", 4, ENC(165,180) },
+ { "Yuml;", 5, ENC(159,217) },
+ { "yuml;", 5, ENC(255,216) }
+ };
+
+ if (!strchr(p, ';')) return -1;
+ if (*p == '#') {
+ if (*(p+1) == 'x' || *(p+1) == 'X') return strtol(p+2, NULL, 16);
+ else return atoi(p+1);
+ }
+ for (i = (int)(sizeof(names) / sizeof(names[0])), nameptr = names; i > 0; i --, nameptr ++)
+ if (strncmp(p, nameptr->name, nameptr->namelen) == 0)
+ return nameptr->code;
+
+ return -1;
+}
+
+
+//
+// 'scrollbar_callback()' - A callback for the scrollbar.
+//
+
+static void
+scrollbar_callback(Fl_Widget *s, void *)
+{
+ ((Fl_Help_View *)(s->parent()))->topline(int(((Fl_Scrollbar*)s)->value()));
+}
+
+
+//
+// 'hscrollbar_callback()' - A callback for the horizontal scrollbar.
+//
+
+static void
+hscrollbar_callback(Fl_Widget *s, void *)
+{
+ ((Fl_Help_View *)(s->parent()))->leftline(int(((Fl_Scrollbar*)s)->value()));
+}
+
+
+//
+// End of "$Id: Fl_Help_View.cxx 6745 2009-04-07 18:37:25Z AlbrechtS $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Image.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Image.cxx new file mode 100644 index 0000000..56cf83d --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Image.cxx @@ -0,0 +1,525 @@ +//
+// "$Id: Fl_Image.cxx 6805 2009-06-29 07:45:48Z AlbrechtS $"
+//
+// Image drawing code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2006 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_draw.H>
+#include <FL/x.H>
+#include <FL/Fl_Widget.H>
+#include <FL/Fl_Menu_Item.H>
+#include <FL/Fl_Image.H>
+#include "flstring.h"
+
+#ifdef WIN32
+void fl_release_dc(HWND, HDC); // from Fl_win32.cxx
+#endif
+
+void fl_restore_clip(); // from fl_rect.cxx
+
+//
+// Base image class...
+//
+
+Fl_Image::~Fl_Image() {
+}
+
+void Fl_Image::uncache() {
+}
+
+void Fl_Image::draw(int XP, int YP, int, int, int, int) {
+ draw_empty(XP, YP);
+}
+
+void Fl_Image::draw_empty(int X, int Y) {
+ if (w() > 0 && h() > 0) {
+ fl_color(FL_FOREGROUND_COLOR);
+ fl_rect(X, Y, w(), h());
+ fl_line(X, Y, X + w() - 1, Y + h() - 1);
+ fl_line(X, Y + h() - 1, X + w() - 1, Y);
+ }
+}
+
+Fl_Image *Fl_Image::copy(int W, int H) {
+ return new Fl_Image(W, H, d());
+}
+
+void Fl_Image::color_average(Fl_Color, float) {
+}
+
+void Fl_Image::desaturate() {
+}
+
+void Fl_Image::label(Fl_Widget* widget) {
+ widget->image(this);
+}
+
+void Fl_Image::label(Fl_Menu_Item* m) {
+ Fl::set_labeltype(_FL_IMAGE_LABEL, labeltype, measure);
+ m->label(_FL_IMAGE_LABEL, (const char*)this);
+}
+
+void
+Fl_Image::labeltype(const Fl_Label *lo, // I - Label
+ int lx, // I - X position
+ int ly, // I - Y position
+ int lw, // I - Width of label
+ int lh, // I - Height of label
+ Fl_Align la) { // I - Alignment
+ Fl_Image *img; // Image pointer
+ int cx, cy; // Image position
+
+ img = (Fl_Image *)(lo->value);
+
+ if (la & FL_ALIGN_LEFT) cx = 0;
+ else if (la & FL_ALIGN_RIGHT) cx = img->w() - lw;
+ else cx = (img->w() - lw) / 2;
+
+ if (la & FL_ALIGN_TOP) cy = 0;
+ else if (la & FL_ALIGN_BOTTOM) cy = img->h() - lh;
+ else cy = (img->h() - lh) / 2;
+
+ fl_color((Fl_Color)lo->color);
+
+ img->draw(lx, ly, lw, lh, cx, cy);
+}
+
+void
+Fl_Image::measure(const Fl_Label *lo, // I - Label
+ int &lw, // O - Width of image
+ int &lh) { // O - Height of image
+ Fl_Image *img; // Image pointer
+
+ img = (Fl_Image *)(lo->value);
+
+ lw = img->w();
+ lh = img->h();
+}
+
+
+//
+// RGB image class...
+//
+
+Fl_RGB_Image::~Fl_RGB_Image() {
+ uncache();
+ if (alloc_array) delete[] (uchar *)array;
+}
+
+void Fl_RGB_Image::uncache() {
+#ifdef __APPLE_QUARTZ__
+ if (id) {
+ CGImageRelease((CGImageRef)id);
+ id = 0;
+ }
+#else
+ if (id) {
+ fl_delete_offscreen((Fl_Offscreen)id);
+ id = 0;
+ }
+
+ if (mask) {
+ fl_delete_bitmask((Fl_Bitmask)mask);
+ mask = 0;
+ }
+#endif
+}
+
+Fl_Image *Fl_RGB_Image::copy(int W, int H) {
+ Fl_RGB_Image *new_image; // New RGB image
+ uchar *new_array; // New array for image data
+
+ // Optimize the simple copy where the width and height are the same,
+ // or when we are copying an empty image...
+ if ((W == w() && H == h()) ||
+ !w() || !h() || !d() || !array) {
+ if (array) {
+ // Make a copy of the image data and return a new Fl_RGB_Image...
+ new_array = new uchar[w() * h() * d()];
+ if (ld() && ld()!=w()*d()) {
+ const uchar *src = array;
+ uchar *dst = new_array;
+ int dy, dh = h(), wd = w()*d(), wld = ld();
+ for (dy=0; dy<dh; dy++) {
+ memcpy(dst, src, wd);
+ src += wld;
+ dst += wd;
+ }
+ } else {
+ memcpy(new_array, array, w() * h() * d());
+ }
+ new_image = new Fl_RGB_Image(new_array, w(), h(), d());
+ new_image->alloc_array = 1;
+
+ return new_image;
+ } else return new Fl_RGB_Image(array, w(), h(), d(), ld());
+ }
+ if (W <= 0 || H <= 0) return 0;
+
+ // OK, need to resize the image data; allocate memory and
+ uchar *new_ptr; // Pointer into new array
+ const uchar *old_ptr; // Pointer into old array
+ int c, // Channel number
+ sy, // Source coordinate
+ dx, dy, // Destination coordinates
+ xerr, yerr, // X & Y errors
+ xmod, ymod, // X & Y moduli
+ xstep, ystep, // X & Y step increments
+ line_d; // stride from line to line
+
+
+ // Figure out Bresenheim step/modulus values...
+ xmod = w() % W;
+ xstep = (w() / W) * d();
+ ymod = h() % H;
+ ystep = h() / H;
+ line_d = ld() ? ld() : w() * d();
+
+ // Allocate memory for the new image...
+ new_array = new uchar [W * H * d()];
+ new_image = new Fl_RGB_Image(new_array, W, H, d());
+ new_image->alloc_array = 1;
+
+ // Scale the image using a nearest-neighbor algorithm...
+ for (dy = H, sy = 0, yerr = H, new_ptr = new_array; dy > 0; dy --) {
+ for (dx = W, xerr = W, old_ptr = array + sy * line_d; dx > 0; dx --) {
+ for (c = 0; c < d(); c ++) *new_ptr++ = old_ptr[c];
+
+ old_ptr += xstep;
+ xerr -= xmod;
+
+ if (xerr <= 0) {
+ xerr += W;
+ old_ptr += d();
+ }
+ }
+
+ sy += ystep;
+ yerr -= ymod;
+ if (yerr <= 0) {
+ yerr += H;
+ sy ++;
+ }
+ }
+
+ return new_image;
+}
+
+void Fl_RGB_Image::color_average(Fl_Color c, float i) {
+ // Don't average an empty image...
+ if (!w() || !h() || !d() || !array) return;
+
+ // Delete any existing pixmap/mask objects...
+ uncache();
+
+ // Allocate memory as needed...
+ uchar *new_array,
+ *new_ptr;
+
+ if (!alloc_array) new_array = new uchar[h() * w() * d()];
+ else new_array = (uchar *)array;
+
+ // Get the color to blend with...
+ uchar r, g, b;
+ unsigned ia, ir, ig, ib;
+
+ Fl::get_color(c, r, g, b);
+ if (i < 0.0f) i = 0.0f;
+ else if (i > 1.0f) i = 1.0f;
+
+ ia = (unsigned)(256 * i);
+ ir = r * (256 - ia);
+ ig = g * (256 - ia);
+ ib = b * (256 - ia);
+
+ // Update the image data to do the blend...
+ const uchar *old_ptr;
+ int x, y;
+ int line_i = ld() ? ld() - (w()*d()) : 0; // increment from line end to beginning of next line
+
+ if (d() < 3) {
+ ig = (r * 31 + g * 61 + b * 8) / 100 * (256 - ia);
+
+ for (new_ptr = new_array, old_ptr = array, y = 0; y < h(); y ++, old_ptr += line_i)
+ for (x = 0; x < w(); x ++) {
+ *new_ptr++ = (*old_ptr++ * ia + ig) >> 8;
+ if (d() > 1) *new_ptr++ = *old_ptr++;
+ }
+ } else {
+ for (new_ptr = new_array, old_ptr = array, y = 0; y < h(); y ++, old_ptr += line_i)
+ for (x = 0; x < w(); x ++) {
+ *new_ptr++ = (*old_ptr++ * ia + ir) >> 8;
+ *new_ptr++ = (*old_ptr++ * ia + ig) >> 8;
+ *new_ptr++ = (*old_ptr++ * ia + ib) >> 8;
+ if (d() > 3) *new_ptr++ = *old_ptr++;
+ }
+ }
+
+ // Set the new pointers/values as needed...
+ if (!alloc_array) {
+ array = new_array;
+ alloc_array = 1;
+
+ ld(0);
+ }
+}
+
+void Fl_RGB_Image::desaturate() {
+ // Don't desaturate an empty image...
+ if (!w() || !h() || !d() || !array) return;
+
+ // Can only desaturate color images...
+ if (d() < 3) return;
+
+ // Delete any existing pixmap/mask objects...
+ uncache();
+
+ // Allocate memory for a grayscale image...
+ uchar *new_array,
+ *new_ptr;
+ int new_d;
+
+ new_d = d() - 2;
+ new_array = new uchar[h() * w() * new_d];
+
+ // Copy the image data, converting to grayscale...
+ const uchar *old_ptr;
+ int x, y;
+ int line_i = ld() ? ld() - (w()*d()) : 0; // increment from line end to beginning of next line
+
+ for (new_ptr = new_array, old_ptr = array, y = 0; y < h(); y ++, old_ptr += line_i)
+ for (x = 0; x < w(); x ++, old_ptr += d()) {
+ *new_ptr++ = (uchar)((31 * old_ptr[0] + 61 * old_ptr[1] + 8 * old_ptr[2]) / 100);
+ if (d() > 3) *new_ptr++ = old_ptr[3];
+ }
+
+ // Free the old array as needed, and then set the new pointers/values...
+ if (alloc_array) delete[] (uchar *)array;
+
+ array = new_array;
+ alloc_array = 1;
+
+ ld(0);
+ d(new_d);
+}
+
+#if !defined(WIN32) && !USE_QUARTZ
+// Composite an image with alpha on systems that don't have accelerated
+// alpha compositing...
+static void alpha_blend(Fl_RGB_Image *img, int X, int Y, int W, int H, int cx, int cy) {
+ uchar *srcptr = (uchar*)img->array + img->d() * (img->w() * cy + cx);
+ int srcskip = img->d() * (img->w() - W);
+
+ uchar *dst = new uchar[W * H * 3];
+ uchar *dstptr = dst;
+
+ fl_read_image(dst, X, Y, W, H, 0);
+
+ uchar srcr, srcg, srcb, srca;
+ uchar dstr, dstg, dstb, dsta;
+
+ if (img->d() == 2) {
+ // Composite grayscale + alpha over RGB...
+ // Composite RGBA over RGB...
+ for (int y = H; y > 0; y--, srcptr+=srcskip)
+ for (int x = W; x > 0; x--) {
+ srcg = *srcptr++;
+ srca = *srcptr++;
+
+ dstr = dstptr[0];
+ dstg = dstptr[1];
+ dstb = dstptr[2];
+ dsta = 255 - srca;
+
+ *dstptr++ = (srcg * srca + dstr * dsta) >> 8;
+ *dstptr++ = (srcg * srca + dstg * dsta) >> 8;
+ *dstptr++ = (srcg * srca + dstb * dsta) >> 8;
+ }
+ } else {
+ // Composite RGBA over RGB...
+ for (int y = H; y > 0; y--, srcptr+=srcskip)
+ for (int x = W; x > 0; x--) {
+ srcr = *srcptr++;
+ srcg = *srcptr++;
+ srcb = *srcptr++;
+ srca = *srcptr++;
+
+ dstr = dstptr[0];
+ dstg = dstptr[1];
+ dstb = dstptr[2];
+ dsta = 255 - srca;
+
+ *dstptr++ = (srcr * srca + dstr * dsta) >> 8;
+ *dstptr++ = (srcg * srca + dstg * dsta) >> 8;
+ *dstptr++ = (srcb * srca + dstb * dsta) >> 8;
+ }
+ }
+
+ fl_draw_image(dst, X, Y, W, H, 3, 0);
+
+ delete[] dst;
+}
+#endif // !WIN32 && !USE_QUARTZ
+
+void Fl_RGB_Image::draw(int XP, int YP, int WP, int HP, int cx, int cy) {
+ // Don't draw an empty image...
+ if (!d() || !array) {
+ draw_empty(XP, YP);
+ return;
+ }
+
+ // account for current clip region (faster on Irix):
+ int X,Y,W,H; fl_clip_box(XP,YP,WP,HP,X,Y,W,H);
+ cx += X-XP; cy += Y-YP;
+ // clip the box down to the size of image, quit if empty:
+ if (cx < 0) {W += cx; X -= cx; cx = 0;}
+ if (cx+W > w()) W = w()-cx;
+ if (W <= 0) return;
+ if (cy < 0) {H += cy; Y -= cy; cy = 0;}
+ if (cy+H > h()) H = h()-cy;
+ if (H <= 0) return;
+ if (!id) {
+#ifdef __APPLE_QUARTZ__
+ CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB();
+ CGDataProviderRef src = CGDataProviderCreateWithData( 0L, array, w()*h()*d(), 0L);
+ id = CGImageCreate( w(), h(), 8, d()*8, ld()?ld():w()*d(),
+ lut, (d()&1)?kCGImageAlphaNone:kCGImageAlphaLast,
+ src, 0L, false, kCGRenderingIntentDefault);
+ CGColorSpaceRelease(lut);
+ CGDataProviderRelease(src);
+#elif defined(WIN32)
+ id = fl_create_offscreen(w(), h());
+ if ((d() == 2 || d() == 4) && fl_can_do_alpha_blending()) {
+ fl_begin_offscreen((Fl_Offscreen)id);
+ fl_draw_image(array, 0, 0, w(), h(), d()|FL_IMAGE_WITH_ALPHA, ld());
+ fl_end_offscreen();
+ } else {
+ fl_begin_offscreen((Fl_Offscreen)id);
+ fl_draw_image(array, 0, 0, w(), h(), d(), ld());
+ fl_end_offscreen();
+ if (d() == 2 || d() == 4) {
+ mask = fl_create_alphamask(w(), h(), d(), ld(), array);
+ }
+ }
+#else
+ if (d() == 1 || d() == 3) {
+ id = fl_create_offscreen(w(), h());
+ fl_begin_offscreen((Fl_Offscreen)id);
+ fl_draw_image(array, 0, 0, w(), h(), d(), ld());
+ fl_end_offscreen();
+ }
+#endif
+ }
+#ifdef WIN32
+ if (mask) {
+ HDC new_gc = CreateCompatibleDC(fl_gc);
+ int save = SaveDC(new_gc);
+ SelectObject(new_gc, (void*)mask);
+ BitBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, SRCAND);
+ SelectObject(new_gc, (void*)id);
+ BitBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, SRCPAINT);
+ RestoreDC(new_gc,save);
+ DeleteDC(new_gc);
+ } else if (d()==2 || d()==4) {
+ fl_copy_offscreen_with_alpha(X, Y, W, H, (Fl_Offscreen)id, cx, cy);
+ } else {
+ fl_copy_offscreen(X, Y, W, H, (Fl_Offscreen)id, cx, cy);
+ }
+#elif defined(__APPLE_QD__)
+ if (mask) {
+ Rect src, dst;
+ // MRS: STR #114 says we should be using cx, cy, W, and H...
+// src.left = 0; src.right = w();
+// src.top = 0; src.bottom = h();
+// dst.left = X; dst.right = X+w();
+// dst.top = Y; dst.bottom = Y+h();
+ src.left = cx; src.right = cx+W;
+ src.top = cy; src.bottom = cy+H;
+ dst.left = X; dst.right = X+W;
+ dst.top = Y; dst.bottom = Y+H;
+ RGBColor rgb;
+ rgb.red = 0xffff; rgb.green = 0xffff; rgb.blue = 0xffff;
+ RGBBackColor(&rgb);
+ rgb.red = 0x0000; rgb.green = 0x0000; rgb.blue = 0x0000;
+ RGBForeColor(&rgb);
+
+ CopyMask(GetPortBitMapForCopyBits((GrafPtr)id),
+ GetPortBitMapForCopyBits((GrafPtr)mask),
+ GetPortBitMapForCopyBits(GetWindowPort(fl_window)),
+ &src, &src, &dst);
+ } else if (id) fl_copy_offscreen(X, Y, W, H, (Fl_Offscreen)id, cx, cy);
+ else {
+ // Composite image with alpha manually each time...
+ alpha_blend(this, X, Y, W, H, cx, cy);
+ }
+#elif defined(__APPLE_QUARTZ__)
+ if (id && fl_gc) {
+ CGRect rect = { { X, Y }, { W, H } };
+ Fl_X::q_begin_image(rect, cx, cy, w(), h());
+ CGContextDrawImage(fl_gc, rect, (CGImageRef)id);
+ Fl_X::q_end_image();
+ }
+#else
+ if (id) {
+ if (mask) {
+ // I can't figure out how to combine a mask with existing region,
+ // so cut the image down to a clipped rectangle:
+ int nx, ny; fl_clip_box(X,Y,W,H,nx,ny,W,H);
+ cx += nx-X; X = nx;
+ cy += ny-Y; Y = ny;
+ // make X use the bitmap as a mask:
+ XSetClipMask(fl_display, fl_gc, mask);
+ int ox = X-cx; if (ox < 0) ox += w();
+ int oy = Y-cy; if (oy < 0) oy += h();
+ XSetClipOrigin(fl_display, fl_gc, X-cx, Y-cy);
+ }
+
+ fl_copy_offscreen(X, Y, W, H, id, cx, cy);
+
+ if (mask) {
+ // put the old clip region back
+ XSetClipOrigin(fl_display, fl_gc, 0, 0);
+ fl_restore_clip();
+ }
+ } else {
+ // Composite image with alpha manually each time...
+ alpha_blend(this, X, Y, W, H, cx, cy);
+ }
+#endif
+}
+
+void Fl_RGB_Image::label(Fl_Widget* widget) {
+ widget->image(this);
+}
+
+void Fl_RGB_Image::label(Fl_Menu_Item* m) {
+ Fl::set_labeltype(_FL_IMAGE_LABEL, labeltype, measure);
+ m->label(_FL_IMAGE_LABEL, (const char*)this);
+}
+
+
+//
+// End of "$Id: Fl_Image.cxx 6805 2009-06-29 07:45:48Z AlbrechtS $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Input.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Input.cxx new file mode 100644 index 0000000..c32da2c --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Input.cxx @@ -0,0 +1,477 @@ +//
+// "$Id: Fl_Input.cxx 6940 2009-11-17 19:39:01Z matt $"
+//
+// Input widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2006 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
+//
+
+// This is the "user interface", it decodes user actions into what to
+// do to the text. See also Fl_Input_.cxx, where the text is actually
+// manipulated (and some ui, in particular the mouse, is done...).
+// In theory you can replace this code with another subclass to change
+// the keybindings.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <FL/Fl.H>
+#include <FL/Fl_Window.H>
+#include <FL/Fl_Input.H>
+#include <FL/fl_draw.H>
+#include <FL/fl_ask.H>
+#include "flstring.h"
+
+#ifdef HAVE_LOCALE_H
+# include <locale.h>
+#endif
+
+
+void Fl_Input::draw() {
+ if (input_type() == FL_HIDDEN_INPUT) return;
+ Fl_Boxtype b = box();
+ if (damage() & FL_DAMAGE_ALL) draw_box(b, color());
+ Fl_Input_::drawtext(x()+Fl::box_dx(b), y()+Fl::box_dy(b),
+ w()-Fl::box_dw(b), h()-Fl::box_dh(b));
+}
+
+// kludge so shift causes selection to extend:
+int Fl_Input::shift_position(int p) {
+ return position(p, Fl::event_state(FL_SHIFT) ? mark() : p);
+}
+int Fl_Input::shift_up_down_position(int p) {
+ return up_down_position(p, Fl::event_state(FL_SHIFT));
+}
+
+// If you define this symbol as zero you will get the peculiar fltk
+// behavior where moving off the end of an input field will move the
+// cursor into the next field:
+// define it as 1 to prevent cursor movement from going to next field:
+#define NORMAL_INPUT_MOVE 0
+
+#define ctrl(x) ((x)^0x40)
+
+// List of characters that are legal in a floating point input field.
+// This text string is created at run-time to take the current locale
+// into account (for example, continental Europe uses a comma instead
+// of a decimal point). For back compatibility reasons, we always
+// allow the decimal point.
+#ifdef HAVE_LOCALECONV
+static const char *standard_fp_chars = ".eE+-";
+static const char *legal_fp_chars = 0L;
+#else
+static const char *legal_fp_chars = ".eE+-";
+#endif
+
+int Fl_Input::handle_key() {
+
+ char ascii = Fl::event_text()[0];
+
+ int repeat_num=1;
+
+ int del;
+ if (Fl::compose(del)) {
+
+ // Insert characters into numeric fields after checking for legality:
+ if (input_type() == FL_FLOAT_INPUT || input_type() == FL_INT_INPUT) {
+ Fl::compose_reset(); // ignore any foreign letters...
+
+ // initialize the list of legal characters inside a floating point number
+#ifdef HAVE_LOCALECONV
+ if (!legal_fp_chars) {
+ int len = strlen(standard_fp_chars);
+ struct lconv *lc = localeconv();
+ if (lc) {
+ if (lc->decimal_point) len += strlen(lc->decimal_point);
+ if (lc->mon_decimal_point) len += strlen(lc->mon_decimal_point);
+ if (lc->positive_sign) len += strlen(lc->positive_sign);
+ if (lc->negative_sign) len += strlen(lc->negative_sign);
+ }
+ // the following line is not a true memory leak because the array is only
+ // allocated once if required, and automatically freed when the program quits
+ char *chars = (char*)malloc(len+1);
+ legal_fp_chars = chars;
+ strcpy(chars, standard_fp_chars);
+ if (lc) {
+ if (lc->decimal_point) strcat(chars, lc->decimal_point);
+ if (lc->mon_decimal_point) strcat(chars, lc->mon_decimal_point);
+ if (lc->positive_sign) strcat(chars, lc->positive_sign);
+ if (lc->negative_sign) strcat(chars, lc->negative_sign);
+ }
+ }
+#endif // HAVE_LOCALECONV
+
+ // find the insert position
+ int ip = position()<mark() ? position() : mark();
+ // This is complex to allow "0xff12" hex to be typed:
+ if (!ip && (ascii == '+' || ascii == '-')
+ || (ascii >= '0' && ascii <= '9')
+ || (ip==1 && index(0)=='0' && (ascii=='x' || ascii == 'X'))
+ || (ip>1 && index(0)=='0' && (index(1)=='x'||index(1)=='X')
+ && (ascii>='A'&& ascii<='F' || ascii>='a'&& ascii<='f'))
+ || input_type()==FL_FLOAT_INPUT && ascii && strchr(legal_fp_chars, ascii))
+ {
+ if (readonly()) fl_beep();
+ else replace(position(), mark(), &ascii, 1);
+ }
+ return 1;
+ }
+
+ if (del || Fl::event_length()) {
+ if (readonly()) fl_beep();
+ else replace(position(), del ? position()-del : mark(),
+ Fl::event_text(), Fl::event_length());
+ }
+ return 1;
+ }
+
+ switch (Fl::event_key()) {
+ case FL_Insert:
+ if (Fl::event_state() & FL_CTRL) ascii = ctrl('C');
+ else if (Fl::event_state() & FL_SHIFT) ascii = ctrl('V');
+ break;
+ case FL_Delete:
+ if (Fl::event_state() & FL_SHIFT) ascii = ctrl('X');
+ else ascii = ctrl('D');
+ break;
+ case FL_Left:
+ ascii = ctrl('B'); break;
+ case FL_Right:
+ ascii = ctrl('F'); break;
+ case FL_Page_Up:
+ fl_font(textfont(),textsize()); //ensure current font is set to ours
+ repeat_num=h()/fl_height(); // number of lines to scroll
+ if (!repeat_num) repeat_num=1;
+ case FL_Up:
+ ascii = ctrl('P'); break;
+ case FL_Page_Down:
+ fl_font(textfont(),textsize());
+ repeat_num=h()/fl_height();
+ if (!repeat_num) repeat_num=1;
+ case FL_Down:
+ ascii = ctrl('N'); break;
+ case FL_Home:
+ if (Fl::event_state() & FL_CTRL) {
+ shift_position(0);
+ return 1;
+ }
+ ascii = ctrl('A');
+ break;
+ case FL_End:
+ if (Fl::event_state() & FL_CTRL) {
+ shift_position(size());
+ return 1;
+ }
+ ascii = ctrl('E'); break;
+
+ case FL_BackSpace:
+ ascii = ctrl('H'); break;
+ case FL_Enter:
+ case FL_KP_Enter:
+ if (when() & FL_WHEN_ENTER_KEY) {
+ position(size(), 0);
+ maybe_do_callback();
+ return 1;
+ } else if (input_type() == FL_MULTILINE_INPUT && !readonly())
+ return replace(position(), mark(), "\n", 1);
+ else
+ return 0; // reserved for shortcuts
+ case FL_Tab:
+ if (Fl::event_state(FL_CTRL|FL_SHIFT) || input_type()!=FL_MULTILINE_INPUT || readonly()) return 0;
+ return replace(position(), mark(), &ascii, 1);
+#ifdef __APPLE__
+ case 'c' :
+ case 'v' :
+ case 'x' :
+ case 'z' :
+// printf("'%c' (0x%02x) pressed with%s%s%s%s\n", ascii, ascii,
+// Fl::event_state(FL_SHIFT) ? " FL_SHIFT" : "",
+// Fl::event_state(FL_CTRL) ? " FL_CTRL" : "",
+// Fl::event_state(FL_ALT) ? " FL_ALT" : "",
+// Fl::event_state(FL_META) ? " FL_META" : "");
+ if (Fl::event_state(FL_META)) ascii -= 0x60;
+// printf("using '%c' (0x%02x)...\n", ascii, ascii);
+ break;
+#endif // __APPLE__
+ }
+
+ int i;
+ switch (ascii) {
+ case ctrl('A'):
+ return shift_position(line_start(position())) + NORMAL_INPUT_MOVE;
+ case ctrl('B'):
+ return shift_position(position()-1) + NORMAL_INPUT_MOVE;
+ case ctrl('C'): // copy
+ return copy(1);
+ case ctrl('D'):
+ case ctrl('?'):
+ if (readonly()) {
+ fl_beep();
+ return 1;
+ }
+ if (mark() != position()) return cut();
+ else return cut(1);
+ case ctrl('E'):
+ return shift_position(line_end(position())) + NORMAL_INPUT_MOVE;
+ case ctrl('F'):
+ return shift_position(position()+1) + NORMAL_INPUT_MOVE;
+ case ctrl('H'):
+ if (readonly()) {
+ fl_beep();
+ return 1;
+ }
+ if (mark() != position()) cut();
+ else cut(-1);
+ return 1;
+ case ctrl('K'):
+ if (readonly()) {
+ fl_beep();
+ return 1;
+ }
+ if (position()>=size()) return 0;
+ i = line_end(position());
+ if (i == position() && i < size()) i++;
+ cut(position(), i);
+ return copy_cuts();
+ case ctrl('N'):
+ i = position();
+ if (line_end(i) >= size()) return NORMAL_INPUT_MOVE;
+ while (repeat_num--) {
+ i = line_end(i);
+ if (i >= size()) break;
+ i++;
+ }
+ shift_up_down_position(i);
+ return 1;
+ case ctrl('P'):
+ i = position();
+ if (!line_start(i)) return NORMAL_INPUT_MOVE;
+ while(repeat_num--) {
+ i = line_start(i);
+ if (!i) break;
+ i--;
+ }
+ shift_up_down_position(line_start(i));
+ return 1;
+ case ctrl('U'):
+ if (readonly()) {
+ fl_beep();
+ return 1;
+ }
+ return cut(0, size());
+ case ctrl('V'):
+ case ctrl('Y'):
+ if (readonly()) {
+ fl_beep();
+ return 1;
+ }
+ Fl::paste(*this, 1);
+ return 1;
+ case ctrl('X'):
+ case ctrl('W'):
+ if (readonly()) {
+ fl_beep();
+ return 1;
+ }
+ copy(1);
+ return cut();
+ case ctrl('Z'):
+ case ctrl('_'):
+ if (readonly()) {
+ fl_beep();
+ return 1;
+ }
+ return undo();
+ case ctrl('I'):
+ case ctrl('J'):
+ case ctrl('L'):
+ case ctrl('M'):
+ if (readonly()) {
+ fl_beep();
+ return 1;
+ }
+ // insert a few selected control characters literally:
+ if (input_type() != FL_FLOAT_INPUT && input_type() != FL_INT_INPUT)
+ return replace(position(), mark(), &ascii, 1);
+ }
+
+ return 0;
+}
+
+int Fl_Input::handle(int event) {
+ static int dnd_save_position, dnd_save_mark, drag_start = -1, newpos;
+ static Fl_Widget *dnd_save_focus;
+ switch (event) {
+ case FL_FOCUS:
+ switch (Fl::event_key()) {
+ case FL_Right:
+ position(0);
+ break;
+ case FL_Left:
+ position(size());
+ break;
+ case FL_Down:
+ up_down_position(0);
+ break;
+ case FL_Up:
+ up_down_position(line_start(size()));
+ break;
+ case FL_Tab:
+ case 0xfe20: // XK_ISO_Left_Tab
+ position(size(),0);
+ break;
+ default:
+ position(position(),mark());// turns off the saved up/down arrow position
+ break;
+ }
+ break;
+
+ case FL_KEYBOARD:
+ if (Fl::event_key() == FL_Tab && mark() != position()) {
+ // Set the current cursor position to the end of the selection...
+ if (mark() > position())
+ position(mark());
+ else
+ position(position());
+ return (1);
+ } else {
+ if (active_r() && window() && this == Fl::belowmouse())
+ window()->cursor(FL_CURSOR_NONE);
+ return handle_key();
+ }
+
+ case FL_PUSH:
+ if (Fl::dnd_text_ops()) {
+ int oldpos = position(), oldmark = mark();
+ Fl_Boxtype b = box();
+ Fl_Input_::handle_mouse(
+ x()+Fl::box_dx(b), y()+Fl::box_dy(b),
+ w()-Fl::box_dw(b), h()-Fl::box_dh(b), 0);
+ newpos = position();
+ position( oldpos, oldmark );
+ if (Fl::focus()==this && !Fl::event_state(FL_SHIFT) && input_type()!=FL_SECRET_INPUT &&
+ (newpos >= mark() && newpos < position() ||
+ newpos >= position() && newpos < mark())) {
+ // user clicked in the selection, may be trying to drag
+ drag_start = newpos;
+ return 1;
+ }
+ drag_start = -1;
+ }
+
+ if (Fl::focus() != this) {
+ Fl::focus(this);
+ handle(FL_FOCUS);
+ }
+ break;
+
+ case FL_DRAG:
+ if (Fl::dnd_text_ops()) {
+ if (drag_start >= 0) {
+ if (Fl::event_is_click()) return 1; // debounce the mouse
+ // save the position because sometimes we don't get DND_ENTER:
+ dnd_save_position = position();
+ dnd_save_mark = mark();
+ // drag the data:
+ copy(0); Fl::dnd();
+ return 1;
+ }
+ }
+ break;
+
+ case FL_RELEASE:
+ if (Fl::event_button() == 2) {
+ Fl::event_is_click(0); // stop double click from picking a word
+ Fl::paste(*this, 0);
+ } else if (!Fl::event_is_click()) {
+ // copy drag-selected text to the clipboard.
+ copy(0);
+ } else if (Fl::event_is_click() && drag_start >= 0) {
+ // user clicked in the field and wants to reset the cursor position...
+ position(drag_start, drag_start);
+ drag_start = -1;
+ } else if (Fl::event_clicks()) {
+ // user double or triple clicked to select word or whole text
+ copy(0);
+ }
+
+ // For output widgets, do the callback so the app knows the user
+ // did something with the mouse...
+ if (readonly()) do_callback();
+
+ return 1;
+
+ case FL_DND_ENTER:
+ Fl::belowmouse(this); // send the leave events first
+ dnd_save_position = position();
+ dnd_save_mark = mark();
+ dnd_save_focus = Fl::focus();
+ if (dnd_save_focus != this) {
+ Fl::focus(this);
+ handle(FL_FOCUS);
+ }
+ // fall through:
+ case FL_DND_DRAG:
+ //int p = mouse_position(X, Y, W, H);
+#if DND_OUT_XXXX
+ if (Fl::focus()==this && (p>=dnd_save_position && p<=dnd_save_mark ||
+ p>=dnd_save_mark && p<=dnd_save_position)) {
+ position(dnd_save_position, dnd_save_mark);
+ return 0;
+ }
+#endif
+ {
+ Fl_Boxtype b = box();
+ Fl_Input_::handle_mouse(
+ x()+Fl::box_dx(b), y()+Fl::box_dy(b),
+ w()-Fl::box_dw(b), h()-Fl::box_dh(b), 0);
+ }
+ return 1;
+
+ case FL_DND_LEAVE:
+ position(dnd_save_position, dnd_save_mark);
+#if DND_OUT_XXXX
+ if (!focused())
+#endif
+ if (dnd_save_focus != this) {
+ Fl::focus(dnd_save_focus);
+ handle(FL_UNFOCUS);
+ }
+ return 1;
+
+ case FL_DND_RELEASE:
+ take_focus();
+ return 1;
+
+ }
+ Fl_Boxtype b = box();
+ return Fl_Input_::handletext(event,
+ x()+Fl::box_dx(b), y()+Fl::box_dy(b),
+ w()-Fl::box_dw(b), h()-Fl::box_dh(b));
+}
+
+Fl_Input::Fl_Input(int X, int Y, int W, int H, const char *l)
+: Fl_Input_(X, Y, W, H, l) {
+}
+
+//
+// End of "$Id: Fl_Input.cxx 6940 2009-11-17 19:39:01Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Input_.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Input_.cxx new file mode 100644 index 0000000..7642653 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Input_.cxx @@ -0,0 +1,907 @@ +//
+// "$Id: Fl_Input_.cxx 6104 2008-04-21 20:54:37Z matt $"
+//
+// Common input widget routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2006 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
+//
+
+// This is the base class for Fl_Input. You can use it directly
+// if you are one of those people who like to define their own
+// set of editing keys. It may also be useful for adding scrollbars
+// to the input field.
+
+#include <FL/Fl.H>
+#include <FL/Fl_Input_.H>
+#include <FL/Fl_Window.H>
+#include <FL/fl_draw.H>
+#include <FL/fl_ask.H>
+#include <math.h>
+#include "flstring.h"
+#include <stdlib.h>
+#include <ctype.h>
+
+#define MAXBUF 1024
+
+extern void fl_draw(const char*, int, float, float);
+
+////////////////////////////////////////////////////////////////
+
+// Copy string p..e to the buffer, replacing characters with ^X and \nnn
+// as necessary. Truncate if necessary so the resulting string and
+// null terminator fits in a buffer of size n. Return new end pointer.
+const char* Fl_Input_::expand(const char* p, char* buf) const {
+ char* o = buf;
+ char* e = buf+(MAXBUF-4);
+ const char* lastspace = p;
+ char* lastspace_out = o;
+ int width_to_lastspace = 0;
+ int word_count = 0;
+ int word_wrap;
+
+ if (input_type()==FL_SECRET_INPUT) {
+ while (o<e && p < value_+size_) {*o++ = '*'; p++;}
+ } else while (o<e) {
+ if (wrap() && (p >= value_+size_ || isspace(*p & 255))) {
+ word_wrap = w() - Fl::box_dw(box()) - 2;
+ width_to_lastspace += (int)fl_width(lastspace_out, o-lastspace_out);
+ if (p > lastspace+1) {
+ if (word_count && width_to_lastspace > word_wrap) {
+ p = lastspace; o = lastspace_out; break;
+ }
+ word_count++;
+ }
+ lastspace = p;
+ lastspace_out = o;
+ }
+
+ if (p >= value_+size_) break;
+ int c = *p++ & 255;
+ if (c < ' ' || c == 127) {
+ if (c=='\n' && input_type()==FL_MULTILINE_INPUT) {p--; break;}
+ if (c == '\t' && input_type()==FL_MULTILINE_INPUT) {
+ for (c = (o-buf)%8; c<8 && o<e; c++) *o++ = ' ';
+ } else {
+ *o++ = '^';
+ *o++ = c ^ 0x40;
+ }
+#ifdef __APPLE__
+ // In MacRoman, all characters are defined, and non-break-space is 0xca
+ } else if (c == 0xCA) { // nbsp
+ *o++ = ' ';
+#else
+ // in ISO 8859-1, undefined characters are rendered as octal
+ // this is commented out since most X11 seems to use MSWindows Latin-1
+ //} else if (c >= 128 && c < 0xA0) {
+ // these codes are not defined in ISO code, so we output the octal code instead
+ // *o++ = '\\';
+ // *o++ = ((c>>6)&0x03) + '0';
+ // *o++ = ((c>>3)&0x07) + '0';
+ // *o++ = (c&0x07) + '0';
+ } else if (c == 0xA0) { // nbsp
+ *o++ = ' ';
+#endif
+ } else {
+ *o++ = c;
+ }
+ }
+ *o = 0;
+ return p;
+}
+
+// After filling in such a buffer, find the width to e
+double Fl_Input_::expandpos(
+ const char* p, // real string
+ const char* e, // pointer into real string
+ const char* buf, // conversion of real string by expand()
+ int* returnn // return offset into buf here
+) const {
+ int n = 0;
+ if (input_type()==FL_SECRET_INPUT) n = e-p;
+ else while (p<e) {
+ int c = *p++ & 255;
+ if (c < ' ' || c == 127) {
+ if (c == '\t' && input_type()==FL_MULTILINE_INPUT) n += 8-(n%8);
+ else n += 2;
+#ifdef __APPLE__
+ // in MacRoman, all characters are defined
+#else
+ // in Windows Latin-1 all characters are defined
+ //} else if (c >= 128 && c < 0xA0) {
+ // these codes are not defined in ISO code, so we output the octal code instead
+ // n += 4;
+#endif
+ } else {
+ n++;
+ }
+ }
+ if (returnn) *returnn = n;
+ return fl_width(buf, n);
+}
+
+////////////////////////////////////////////////////////////////
+
+// minimal update:
+// Characters from mu_p to end of widget are redrawn.
+// If erase_cursor_only, small part at mu_p is redrawn.
+// Right now minimal update just keeps unchanged characters from
+// being erased, so they don't blink.
+
+void Fl_Input_::minimal_update(int p) {
+ if (damage() & FL_DAMAGE_ALL) return; // don't waste time if it won't be done
+ if (damage() & FL_DAMAGE_EXPOSE) {
+ if (p < mu_p) mu_p = p;
+ } else {
+ mu_p = p;
+ }
+
+ damage(FL_DAMAGE_EXPOSE);
+ erase_cursor_only = 0;
+}
+
+void Fl_Input_::minimal_update(int p, int q) {
+ if (q < p) p = q;
+ minimal_update(p);
+}
+
+////////////////////////////////////////////////////////////////
+
+static double up_down_pos;
+static int was_up_down;
+
+void Fl_Input_::setfont() const {
+ fl_font(textfont(), textsize());
+}
+
+void Fl_Input_::drawtext(int X, int Y, int W, int H) {
+ int do_mu = !(damage()&FL_DAMAGE_ALL);
+
+ if (Fl::focus()!=this && !size()) {
+ if (do_mu) { // we have to erase it if cursor was there
+ draw_box(box(), X-Fl::box_dx(box()), Y-Fl::box_dy(box()),
+ W+Fl::box_dw(box()), H+Fl::box_dh(box()), color());
+ }
+ return;
+ }
+
+ int selstart, selend;
+ if (Fl::focus()!=this && /*Fl::selection_owner()!=this &&*/ Fl::pushed()!=this)
+ selstart = selend = 0;
+ else if (position() <= mark()) {
+ selstart = position(); selend = mark();
+ } else {
+ selend = position(); selstart = mark();
+ }
+
+ setfont();
+ const char *p, *e;
+ char buf[MAXBUF];
+
+ // count how many lines and put the last one into the buffer:
+ // And figure out where the cursor is:
+ int height = fl_height();
+ int lines;
+ int curx, cury;
+ for (p=value(), curx=cury=lines=0; ;) {
+ e = expand(p, buf);
+ if (position() >= p-value() && position() <= e-value()) {
+ curx = int(expandpos(p, value()+position(), buf, 0)+.5);
+ if (Fl::focus()==this && !was_up_down) up_down_pos = curx;
+ cury = lines*height;
+ int newscroll = xscroll_;
+ if (curx > newscroll+W-20) {
+ // figure out scrolling so there is space after the cursor:
+ newscroll = curx+20-W;
+ // figure out the furthest left we ever want to scroll:
+ int ex = int(expandpos(p, e, buf, 0))+2-W;
+ // use minimum of both amounts:
+ if (ex < newscroll) newscroll = ex;
+ } else if (curx < newscroll+20) {
+ newscroll = curx-20;
+ }
+ if (newscroll < 0) newscroll = 0;
+ if (newscroll != xscroll_) {
+ xscroll_ = newscroll;
+ mu_p = 0; erase_cursor_only = 0;
+ }
+ }
+ lines++;
+ if (e >= value_+size_) break;
+ p = e+1;
+ }
+
+ // adjust the scrolling:
+ if (input_type()==FL_MULTILINE_INPUT) {
+ int newy = yscroll_;
+ if (cury < newy) newy = cury;
+ if (cury > newy+H-height) newy = cury-H+height;
+ if (newy < -1) newy = -1;
+ if (newy != yscroll_) {yscroll_ = newy; mu_p = 0; erase_cursor_only = 0;}
+ } else {
+ yscroll_ = -(H-height)/2;
+ }
+
+ fl_clip(X, Y, W, H);
+ Fl_Color tc = active_r() ? textcolor() : fl_inactive(textcolor());
+
+ p = value();
+ // visit each line and draw it:
+ int desc = height-fl_descent();
+ float xpos = (float)(X - xscroll_ + 1);
+ int ypos = -yscroll_;
+ for (; ypos < H;) {
+
+ // re-expand line unless it is the last one calculated above:
+ if (lines>1) e = expand(p, buf);
+
+ if (ypos <= -height) goto CONTINUE; // clipped off top
+
+ if (do_mu) { // for minimal update:
+ const char* pp = value()+mu_p; // pointer to where minimal update starts
+ if (e < pp) goto CONTINUE2; // this line is before the changes
+ if (readonly()) erase_cursor_only = 0; // this isn't the most efficient way
+ if (erase_cursor_only && p > pp) goto CONTINUE2; // this line is after
+ // calculate area to erase:
+ float r = (float)(X+W);
+ float xx;
+ if (p >= pp) {
+ xx = (float)X;
+ if (erase_cursor_only) r = xpos+2;
+ else if (readonly()) xx -= 3;
+ } else {
+ xx = xpos + (float)expandpos(p, pp, buf, 0);
+ if (erase_cursor_only) r = xx+2;
+ else if (readonly()) xx -= 3;
+ }
+ // clip to and erase it:
+ fl_push_clip((int)xx-1-height/8, Y+ypos, (int)(r-xx+2+height/4), height);
+ draw_box(box(), X-Fl::box_dx(box()), Y-Fl::box_dy(box()),
+ W+Fl::box_dw(box()), H+Fl::box_dh(box()), color());
+ // it now draws entire line over it
+ // this should not draw letters to left of erased area, but
+ // that is nyi.
+ }
+
+ // Draw selection area if required:
+ if (selstart < selend && selstart <= e-value() && selend > p-value()) {
+ const char* pp = value()+selstart;
+ float x1 = xpos;
+ int offset1 = 0;
+ if (pp > p) {
+ fl_color(tc);
+ x1 += (float)expandpos(p, pp, buf, &offset1);
+ fl_draw(buf, offset1, xpos, (float)(Y+ypos+desc));
+ }
+ pp = value()+selend;
+ float x2 = (float)(X+W);
+ int offset2;
+ if (pp <= e) x2 = xpos + (float)expandpos(p, pp, buf, &offset2);
+ else offset2 = strlen(buf);
+ fl_color(selection_color());
+ fl_rectf((int)(x1+0.5), Y+ypos, (int)(x2-x1+0.5), height);
+ fl_color(fl_contrast(textcolor(), selection_color()));
+ fl_draw(buf+offset1, offset2-offset1, x1, (float)(Y+ypos+desc));
+ if (pp < e) {
+ fl_color(tc);
+ fl_draw(buf+offset2, strlen(buf+offset2), x2, (float)(Y+ypos+desc));
+ }
+ } else {
+ // draw unselected text
+ fl_color(tc);
+ fl_draw(buf, strlen(buf), xpos, (float)(Y+ypos+desc));
+ }
+
+ if (do_mu) fl_pop_clip();
+
+ CONTINUE2:
+ // draw the cursor:
+ if (Fl::focus() == this && selstart == selend &&
+ position() >= p-value() && position() <= e-value()) {
+ fl_color(cursor_color());
+ if (readonly()) {
+ fl_line((int)(xpos+curx-2.5f), Y+ypos+height-1,
+ (int)(xpos+curx+0.5f), Y+ypos+height-4,
+ (int)(xpos+curx+3.5f), Y+ypos+height-1);
+ } else {
+ fl_rectf((int)(xpos+curx+0.5), Y+ypos, 2, height);
+ }
+ }
+
+ CONTINUE:
+ ypos += height;
+ if (e >= value_+size_) break;
+ if (*e == '\n' || *e == ' ') e++;
+ p = e;
+ }
+
+ // for minimal update, erase all lines below last one if necessary:
+ if (input_type()==FL_MULTILINE_INPUT && do_mu && ypos<H
+ && (!erase_cursor_only || p <= value()+mu_p)) {
+ if (ypos < 0) ypos = 0;
+ fl_push_clip(X, Y+ypos, W, H-ypos);
+ draw_box(box(), X-Fl::box_dx(box()), Y-Fl::box_dy(box()),
+ W+Fl::box_dw(box()), H+Fl::box_dh(box()), color());
+ fl_pop_clip();
+ }
+
+ fl_pop_clip();
+}
+
+static int isword(char c) {
+ return (c&128 || isalnum(c) || strchr("#%&-/@\\_~", c));
+}
+
+int Fl_Input_::word_end(int i) const {
+ if (input_type() == FL_SECRET_INPUT) return size();
+ //while (i < size() && !isword(index(i))) i++;
+ while (i < size() && isword(index(i))) i++;
+ return i;
+}
+
+int Fl_Input_::word_start(int i) const {
+ if (input_type() == FL_SECRET_INPUT) return 0;
+// if (i >= size() || !isword(index(i)))
+// while (i > 0 && !isword(index(i-1))) i--;
+ while (i > 0 && isword(index(i-1))) i--;
+ return i;
+}
+
+int Fl_Input_::line_end(int i) const {
+ if (input_type() != FL_MULTILINE_INPUT) return size();
+
+ if (wrap()) {
+ // go to the start of the paragraph:
+ int j = i;
+ while (j > 0 && index(j-1) != '\n') j--;
+ // now measure lines until we get past i, end of that line is real eol:
+ setfont();
+ for (const char* p=value()+j; ;) {
+ char buf[MAXBUF];
+ p = expand(p, buf);
+ if (p-value() >= i) return p-value();
+ p++;
+ }
+ } else {
+ while (i < size() && index(i) != '\n') i++;
+ return i;
+ }
+}
+
+int Fl_Input_::line_start(int i) const {
+ if (input_type() != FL_MULTILINE_INPUT) return 0;
+ int j = i;
+ while (j > 0 && index(j-1) != '\n') j--;
+ if (wrap()) {
+ // now measure lines until we get past i, start of that line is real eol:
+ setfont();
+ for (const char* p=value()+j; ;) {
+ char buf[MAXBUF];
+ const char* e = expand(p, buf);
+ if (e-value() >= i) return p-value();
+ p = e+1;
+ }
+ } else return j;
+}
+
+void Fl_Input_::handle_mouse(int X, int Y, int /*W*/, int /*H*/, int drag) {
+ was_up_down = 0;
+ if (!size()) return;
+ setfont();
+
+ const char *p, *e;
+ char buf[MAXBUF];
+
+ int theline = (input_type()==FL_MULTILINE_INPUT) ?
+ (Fl::event_y()-Y+yscroll_)/fl_height() : 0;
+
+ int newpos = 0;
+ for (p=value();; ) {
+ e = expand(p, buf);
+ theline--; if (theline < 0) break;
+ if (e >= value_+size_) break;
+ p = e+1;
+ }
+ const char *l, *r, *t; double f0 = Fl::event_x()-X+xscroll_;
+ for (l = p, r = e; l<r; ) {
+ double f;
+ t = l+(r-l+1)/2;
+ f = X-xscroll_+expandpos(p, t, buf, 0);
+ if (f <= Fl::event_x()) {l = t; f0 = Fl::event_x()-f;}
+ else r = t-1;
+ }
+ if (l < e) { // see if closer to character on right:
+ double f1 = X-xscroll_+expandpos(p, l+1, buf, 0)-Fl::event_x();
+ if (f1 < f0) l = l+1;
+ }
+ newpos = l-value();
+
+ int newmark = drag ? mark() : newpos;
+ if (Fl::event_clicks()) {
+ if (newpos >= newmark) {
+ if (newpos == newmark) {
+ if (newpos < size()) newpos++;
+ else newmark--;
+ }
+ if (Fl::event_clicks() > 1) {
+ newpos = line_end(newpos);
+ newmark = line_start(newmark);
+ } else {
+ newpos = word_end(newpos);
+ newmark = word_start(newmark);
+ }
+ } else {
+ if (Fl::event_clicks() > 1) {
+ newpos = line_start(newpos);
+ newmark = line_end(newmark);
+ } else {
+ newpos = word_start(newpos);
+ newmark = word_end(newmark);
+ }
+ }
+ // if the multiple click does not increase the selection, revert
+ // to single-click behavior:
+ if (!drag && (mark() > position() ?
+ (newmark >= position() && newpos <= mark()) :
+ (newmark >= mark() && newpos <= position()))) {
+ Fl::event_clicks(0);
+ newmark = newpos = l-value();
+ }
+ }
+ position(newpos, newmark);
+}
+
+int Fl_Input_::position(int p, int m) {
+ was_up_down = 0;
+ if (p<0) p = 0;
+ if (p>size()) p = size();
+ if (m<0) m = 0;
+ if (m>size()) m = size();
+ if (p == position_ && m == mark_) return 0;
+ //if (Fl::selection_owner() == this) Fl::selection_owner(0);
+ if (p != m) {
+ if (p != position_) minimal_update(position_, p);
+ if (m != mark_) minimal_update(mark_, m);
+ } else {
+ // new position is a cursor
+ if (position_ == mark_) {
+ // old position was just a cursor
+ if (Fl::focus() == this && !(damage()&FL_DAMAGE_EXPOSE)) {
+ minimal_update(position_); erase_cursor_only = 1;
+ }
+ } else { // old position was a selection
+ minimal_update(position_, mark_);
+ }
+ }
+ position_ = p;
+ mark_ = m;
+ return 1;
+}
+
+int Fl_Input_::up_down_position(int i, int keepmark) {
+ // unlike before, i must be at the start of the line already!
+
+ setfont();
+ char buf[MAXBUF];
+ const char* p = value()+i;
+ const char* e = expand(p, buf);
+ const char *l, *r, *t;
+ for (l = p, r = e; l<r; ) {
+ t = l+(r-l+1)/2;
+ int f = (int)expandpos(p, t, buf, 0);
+ if (f <= up_down_pos) l = t; else r = t-1;
+ }
+ int j = l-value();
+ j = position(j, keepmark ? mark_ : j);
+ was_up_down = 1;
+ return j;
+}
+
+int Fl_Input_::copy(int clipboard) {
+ int b = position();
+ int e = mark();
+ if (b != e) {
+ if (b > e) {b = mark(); e = position();}
+ if (input_type() == FL_SECRET_INPUT) e = b;
+ Fl::copy(value()+b, e-b, clipboard);
+ return 1;
+ }
+ return 0;
+}
+
+#define MAXFLOATSIZE 40
+
+static char* undobuffer;
+static int undobufferlength;
+static Fl_Input_* undowidget;
+static int undoat; // points after insertion
+static int undocut; // number of characters deleted there
+static int undoinsert; // number of characters inserted
+static int yankcut; // length of valid contents of buffer, even if undocut=0
+
+static void undobuffersize(int n) {
+ if (n > undobufferlength) {
+ if (undobuffer) {
+ do {undobufferlength *= 2;} while (undobufferlength < n);
+ undobuffer = (char*)realloc(undobuffer, undobufferlength);
+ } else {
+ undobufferlength = n+9;
+ undobuffer = (char*)malloc(undobufferlength);
+ }
+ }
+}
+
+// all changes go through here, delete characters b-e and insert text:
+int Fl_Input_::replace(int b, int e, const char* text, int ilen) {
+
+ was_up_down = 0;
+
+ if (b<0) b = 0;
+ if (e<0) e = 0;
+ if (b>size_) b = size_;
+ if (e>size_) e = size_;
+ if (e<b) {int t=b; b=e; e=t;}
+ if (text && !ilen) ilen = strlen(text);
+ if (e<=b && !ilen) return 0; // don't clobber undo for a null operation
+ if (size_+ilen-(e-b) > maximum_size_) {
+ ilen = maximum_size_-size_+(e-b);
+ if (ilen < 0) ilen = 0;
+ }
+
+ put_in_buffer(size_+ilen);
+
+ if (e>b) {
+ if (undowidget == this && b == undoat) {
+ undobuffersize(undocut+(e-b));
+ memcpy(undobuffer+undocut, value_+b, e-b);
+ undocut += e-b;
+ } else if (undowidget == this && e == undoat && !undoinsert) {
+ undobuffersize(undocut+(e-b));
+ memmove(undobuffer+(e-b), undobuffer, undocut);
+ memcpy(undobuffer, value_+b, e-b);
+ undocut += e-b;
+ } else if (undowidget == this && e == undoat && (e-b)<undoinsert) {
+ undoinsert -= e-b;
+ } else {
+ undobuffersize(e-b);
+ memcpy(undobuffer, value_+b, e-b);
+ undocut = e-b;
+ undoinsert = 0;
+ }
+ memmove(buffer+b, buffer+e, size_-e+1);
+ size_ -= e-b;
+ undowidget = this;
+ undoat = b;
+ if (input_type() == FL_SECRET_INPUT) yankcut = 0; else yankcut = undocut;
+ }
+
+ if (ilen) {
+ if (undowidget == this && b == undoat)
+ undoinsert += ilen;
+ else {
+ undocut = 0;
+ undoinsert = ilen;
+ }
+ memmove(buffer+b+ilen, buffer+b, size_-b+1);
+ memcpy(buffer+b, text, ilen);
+ size_ += ilen;
+ }
+ undowidget = this;
+ undoat = b+ilen;
+
+ // Insertions into the word at the end of the line will cause it to
+ // wrap to the next line, so we must indicate that the changes may start
+ // right after the whitespace before the current word. This will
+ // result in sub-optimal update when such wrapping does not happen
+ // but it is too hard to figure out for now...
+ if (wrap()) {
+ // if there is a space in the pasted text, the whole line may have rewrapped
+ int i;
+ for (i=0; i<ilen; i++)
+ if (text[i]==' ') break;
+ if (i==ilen)
+ while (b > 0 && !isspace(index(b) & 255) && index(b)!='\n') b--;
+ else
+ while (b > 0 && index(b)!='\n') b--;
+ }
+
+ // make sure we redraw the old selection or cursor:
+ if (mark_ < b) b = mark_;
+ if (position_ < b) b = position_;
+
+ minimal_update(b);
+
+ mark_ = position_ = undoat;
+
+ set_changed();
+ if (when()&FL_WHEN_CHANGED) do_callback();
+ return 1;
+}
+
+int Fl_Input_::undo() {
+ was_up_down = 0;
+ if (undowidget != this || !undocut && !undoinsert) return 0;
+
+ int ilen = undocut;
+ int xlen = undoinsert;
+ int b = undoat-xlen;
+ int b1 = b;
+
+ put_in_buffer(size_+ilen);
+
+ if (ilen) {
+ memmove(buffer+b+ilen, buffer+b, size_-b+1);
+ memcpy(buffer+b, undobuffer, ilen);
+ size_ += ilen;
+ b += ilen;
+ }
+
+ if (xlen) {
+ undobuffersize(xlen);
+ memcpy(undobuffer, buffer+b, xlen);
+ memmove(buffer+b, buffer+b+xlen, size_-xlen-b+1);
+ size_ -= xlen;
+ }
+
+ undocut = xlen;
+ if (xlen) yankcut = xlen;
+ undoinsert = ilen;
+ undoat = b;
+ mark_ = b /* -ilen */;
+ position_ = b;
+
+ if (wrap())
+ while (b1 > 0 && index(b1)!='\n') b1--;
+ minimal_update(b1);
+ set_changed();
+ if (when()&FL_WHEN_CHANGED) do_callback();
+ return 1;
+}
+
+int Fl_Input_::copy_cuts() {
+ // put the yank buffer into the X clipboard
+ if (!yankcut || input_type()==FL_SECRET_INPUT) return 0;
+ Fl::copy(undobuffer, yankcut, 1);
+ return 1;
+}
+
+void Fl_Input_::maybe_do_callback() {
+ if (changed() || (when()&FL_WHEN_NOT_CHANGED)) {
+ do_callback();
+ }
+}
+
+int Fl_Input_::handletext(int event, int X, int Y, int W, int H) {
+ switch (event) {
+
+ case FL_ENTER:
+ case FL_MOVE:
+ if (active_r() && window()) window()->cursor(FL_CURSOR_INSERT);
+ return 1;
+
+ case FL_LEAVE:
+ if (active_r() && window()) window()->cursor(FL_CURSOR_DEFAULT);
+ return 1;
+
+ case FL_FOCUS:
+ if (mark_ == position_) {
+ minimal_update(size()+1);
+ } else //if (Fl::selection_owner() != this)
+ minimal_update(mark_, position_);
+ return 1;
+
+ case FL_UNFOCUS:
+ if (active_r() && window()) window()->cursor(FL_CURSOR_DEFAULT);
+ if (mark_ == position_) {
+ if (!(damage()&FL_DAMAGE_EXPOSE)) {minimal_update(position_); erase_cursor_only = 1;}
+ } else //if (Fl::selection_owner() != this)
+ minimal_update(mark_, position_);
+ case FL_HIDE:
+ if (!readonly() && (when() & FL_WHEN_RELEASE))
+ maybe_do_callback();
+ return 1;
+
+ case FL_PUSH:
+ if (active_r() && window()) window()->cursor(FL_CURSOR_INSERT);
+
+ handle_mouse(X, Y, W, H, Fl::event_state(FL_SHIFT));
+
+ if (Fl::focus() != this) {
+ Fl::focus(this);
+ handle(FL_FOCUS);
+ }
+ return 1;
+
+ case FL_DRAG:
+ handle_mouse(X, Y, W, H, 1);
+ return 1;
+
+ case FL_RELEASE:
+ copy(0);
+ return 1;
+
+ case FL_PASTE: {
+ // Don't allow pastes into readonly widgets...
+ if (readonly()) {
+ fl_beep(FL_BEEP_ERROR);
+ return 1;
+ }
+
+ // See if we have anything to paste...
+ if (!Fl::event_text() || !Fl::event_length()) return 1;
+
+ // strip trailing control characters and spaces before pasting:
+ const char* t = Fl::event_text();
+ const char* e = t+Fl::event_length();
+ if (input_type() != FL_MULTILINE_INPUT) while (e > t && isspace(*(e-1) & 255)) e--;
+ if (!t || e <= t) return 1; // Int/float stuff will crash without this test
+ if (input_type() == FL_INT_INPUT) {
+ while (isspace(*t & 255) && t < e) t ++;
+ const char *p = t;
+ if (*p == '+' || *p == '-') p ++;
+ if (strncmp(p, "0x", 2) == 0) {
+ p += 2;
+ while (isxdigit(*p & 255) && p < e) p ++;
+ } else {
+ while (isdigit(*p & 255) && p < e) p ++;
+ }
+ if (p < e) {
+ fl_beep(FL_BEEP_ERROR);
+ return 1;
+ } else return replace(0, size(), t, e - t);
+ } else if (input_type() == FL_FLOAT_INPUT) {
+ while (isspace(*t & 255) && t < e) t ++;
+ const char *p = t;
+ if (*p == '+' || *p == '-') p ++;
+ while (isdigit(*p & 255) && p < e) p ++;
+ if (*p == '.') {
+ p ++;
+ while (isdigit(*p & 255) && p < e) p ++;
+ if (*p == 'e' || *p == 'E') {
+ p ++;
+ if (*p == '+' || *p == '-') p ++;
+ while (isdigit(*p & 255) && p < e) p ++;
+ }
+ }
+ if (p < e) {
+ fl_beep(FL_BEEP_ERROR);
+ return 1;
+ } else return replace(0, size(), t, e - t);
+ }
+ return replace(position(), mark(), t, e-t);}
+
+ default:
+ return 0;
+ }
+}
+
+/*------------------------------*/
+
+Fl_Input_::Fl_Input_(int X, int Y, int W, int H, const char* l)
+: Fl_Widget(X, Y, W, H, l) {
+ box(FL_DOWN_BOX);
+ color(FL_BACKGROUND2_COLOR, FL_SELECTION_COLOR);
+ align(FL_ALIGN_LEFT);
+ textsize_ = (uchar)FL_NORMAL_SIZE;
+ textfont_ = FL_HELVETICA;
+ textcolor_ = FL_FOREGROUND_COLOR;
+ cursor_color_ = FL_FOREGROUND_COLOR; // was FL_BLUE
+ mark_ = position_ = size_ = 0;
+ bufsize = 0;
+ buffer = 0;
+ value_ = "";
+ xscroll_ = yscroll_ = 0;
+ maximum_size_ = 32767;
+}
+
+void Fl_Input_::put_in_buffer(int len) {
+ if (value_ == buffer && bufsize > len) {
+ buffer[size_] = 0;
+ return;
+ }
+ if (!bufsize) {
+ if (len > size_) len += 9; // let a few characters insert before realloc
+ bufsize = len+1;
+ buffer = (char*)malloc(bufsize);
+ } else if (bufsize <= len) {
+ // we may need to move old value in case it points into buffer:
+ int moveit = (value_ >= buffer && value_ < buffer+bufsize);
+ // enlarge current buffer
+ if (len > size_) {
+ do {bufsize *= 2;} while (bufsize <= len);
+ } else {
+ bufsize = len+1;
+ }
+ // Note: the following code is equivalent to:
+ //
+ // if (moveit) value_ = value_ - buffer;
+ // char* nbuffer = (char*)realloc(buffer, bufsize);
+ // if (moveit) value_ = value_ + nbuffer;
+ // buffer = nbuffer;
+ //
+ // We just optimized the pointer arithmetic for value_...
+ //
+ char* nbuffer = (char*)realloc(buffer, bufsize);
+ if (moveit) value_ += (nbuffer-buffer);
+ buffer = nbuffer;
+ }
+ memmove(buffer, value_, size_); buffer[size_] = 0;
+ value_ = buffer;
+}
+
+int Fl_Input_::static_value(const char* str, int len) {
+ clear_changed();
+ if (undowidget == this) undowidget = 0;
+ if (str == value_ && len == size_) return 0;
+ if (len) { // non-empty new value:
+ if (xscroll_ || yscroll_) {
+ xscroll_ = yscroll_ = 0;
+ minimal_update(0);
+ } else {
+ int i = 0;
+ // find first different character:
+ if (value_) {
+ for (; i<size_ && i<len && str[i]==value_[i]; i++);
+ if (i==size_ && i==len) return 0;
+ }
+ minimal_update(i);
+ }
+ value_ = str;
+ size_ = len;
+ } else { // empty new value:
+ if (!size_) return 0; // both old and new are empty.
+ size_ = 0;
+ value_ = "";
+ xscroll_ = yscroll_ = 0;
+ minimal_update(0);
+ }
+ position(readonly() ? 0 : size());
+ return 1;
+}
+
+int Fl_Input_::static_value(const char* str) {
+ return static_value(str, str ? strlen(str) : 0);
+}
+
+int Fl_Input_::value(const char* str, int len) {
+ int r = static_value(str, len);
+ if (len) put_in_buffer(len);
+ return r;
+}
+
+int Fl_Input_::value(const char* str) {
+ return value(str, str ? strlen(str) : 0);
+}
+
+void Fl_Input_::resize(int X, int Y, int W, int H) {
+ if (W != w()) xscroll_ = 0;
+ if (H != h()) yscroll_ = 0;
+ Fl_Widget::resize(X, Y, W, H);
+}
+
+Fl_Input_::~Fl_Input_() {
+ if (undowidget == this) undowidget = 0;
+ if (bufsize) free((void*)buffer);
+}
+
+//
+// End of "$Id: Fl_Input_.cxx 6104 2008-04-21 20:54:37Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_JPEG_Image.cxx b/third_party/windows/fltk-1.1.10/src/Fl_JPEG_Image.cxx new file mode 100644 index 0000000..0ab1324 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_JPEG_Image.cxx @@ -0,0 +1,193 @@ +//
+// "$Id: Fl_JPEG_Image.cxx 5845 2007-05-20 00:01:06Z mike $"
+//
+// Fl_JPEG_Image routines.
+//
+// Copyright 1997-2005 by Easy Software Products.
+// Image support donated by Matthias Melcher, Copyright 2000.
+//
+// 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
+//
+// Contents:
+//
+// Fl_JPEG_Image::Fl_JPEG_Image() - Load a JPEG image file.
+//
+
+//
+// Include necessary header files...
+//
+
+#include <FL/Fl_JPEG_Image.H>
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <setjmp.h>
+
+
+// Some releases of the Cygwin JPEG libraries don't have a correctly
+// updated header file for the INT32 data type; the following define
+// from Shane Hill seems to be a usable workaround...
+
+#if defined(WIN32) && defined(__CYGWIN__)
+# define XMD_H
+#endif // WIN32 && __CYGWIN__
+
+
+extern "C"
+{
+#ifdef HAVE_LIBJPEG
+# include <jpeglib.h>
+#endif // HAVE_LIBJPEG
+}
+
+
+//
+// Custom JPEG error handling structure...
+//
+
+#ifdef HAVE_LIBJPEG
+struct fl_jpeg_error_mgr {
+ jpeg_error_mgr pub_; // Destination manager...
+ jmp_buf errhand_; // Error handler
+};
+#endif // HAVE_LIBJPEG
+
+
+//
+// Error handler for JPEG files...
+//
+
+#ifdef HAVE_LIBJPEG
+extern "C" {
+ static void
+ fl_jpeg_error_handler(j_common_ptr dinfo) { // I - Decompressor info
+ longjmp(((fl_jpeg_error_mgr *)(dinfo->err))->errhand_, 1);
+ }
+
+ static void
+ fl_jpeg_output_handler(j_common_ptr) { // I - Decompressor info (not used)
+ }
+}
+#endif // HAVE_LIBJPEG
+
+
+//
+// 'Fl_JPEG_Image::Fl_JPEG_Image()' - Load a JPEG image file.
+//
+
+Fl_JPEG_Image::Fl_JPEG_Image(const char *jpeg) // I - File to load
+ : Fl_RGB_Image(0,0,0) {
+#ifdef HAVE_LIBJPEG
+ FILE *fp; // File pointer
+ jpeg_decompress_struct dinfo; // Decompressor info
+ fl_jpeg_error_mgr jerr; // Error handler info
+ JSAMPROW row; // Sample row pointer
+
+ // the following variables are pointers allocating some private space that
+ // is not reset by 'setjmp()'
+ char* max_finish_decompress_err; // count errors and give up afer a while
+ char* max_destroy_decompress_err; // to avoid recusion and deadlock
+
+ // Clear data...
+ alloc_array = 0;
+ array = (uchar *)0;
+
+ // Open the image file...
+ if ((fp = fopen(jpeg, "rb")) == NULL) return;
+
+ // Setup the decompressor info and read the header...
+ dinfo.err = jpeg_std_error((jpeg_error_mgr *)&jerr);
+ jerr.pub_.error_exit = fl_jpeg_error_handler;
+ jerr.pub_.output_message = fl_jpeg_output_handler;
+
+ // Setup error loop variables
+ max_finish_decompress_err = (char*)malloc(1); // allocate space on the frame for error counters
+ max_destroy_decompress_err = (char*)malloc(1); // otherwise, the variables are reset on the longjmp
+ *max_finish_decompress_err=10;
+ *max_destroy_decompress_err=10;
+
+ if (setjmp(jerr.errhand_))
+ {
+ // JPEG error handling...
+ // if any of the cleanup routines hits another error, we would end up
+ // in a loop. So instead, we decrement max_err for some upper cleanup limit.
+ if ( ((*max_finish_decompress_err)-- > 0) && array)
+ jpeg_finish_decompress(&dinfo);
+ if ( (*max_destroy_decompress_err)-- > 0)
+ jpeg_destroy_decompress(&dinfo);
+
+ fclose(fp);
+
+ w(0);
+ h(0);
+ d(0);
+
+ if (array) {
+ delete[] (uchar *)array;
+ array = 0;
+ alloc_array = 0;
+ }
+
+ free(max_destroy_decompress_err);
+ free(max_finish_decompress_err);
+
+ return;
+ }
+
+ jpeg_create_decompress(&dinfo);
+ jpeg_stdio_src(&dinfo, fp);
+ jpeg_read_header(&dinfo, 1);
+
+ dinfo.quantize_colors = (boolean)FALSE;
+ dinfo.out_color_space = JCS_RGB;
+ dinfo.out_color_components = 3;
+ dinfo.output_components = 3;
+
+ jpeg_calc_output_dimensions(&dinfo);
+
+ w(dinfo.output_width);
+ h(dinfo.output_height);
+ d(dinfo.output_components);
+
+ array = new uchar[w() * h() * d()];
+ alloc_array = 1;
+
+ jpeg_start_decompress(&dinfo);
+
+ while (dinfo.output_scanline < dinfo.output_height) {
+ row = (JSAMPROW)(array +
+ dinfo.output_scanline * dinfo.output_width *
+ dinfo.output_components);
+ jpeg_read_scanlines(&dinfo, &row, (JDIMENSION)1);
+ }
+
+ jpeg_finish_decompress(&dinfo);
+ jpeg_destroy_decompress(&dinfo);
+
+ free(max_destroy_decompress_err);
+ free(max_finish_decompress_err);
+
+ fclose(fp);
+#endif // HAVE_LIBJPEG
+}
+
+//
+// End of "$Id: Fl_JPEG_Image.cxx 5845 2007-05-20 00:01:06Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Light_Button.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Light_Button.cxx new file mode 100644 index 0000000..76d865a --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Light_Button.cxx @@ -0,0 +1,169 @@ +//
+// "$Id: Fl_Light_Button.cxx 5721 2007-02-27 19:23:24Z matt $"
+//
+// Lighted button widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2006 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
+//
+
+// Subclass of Fl_Button where the "box" indicates whether it is
+// pushed or not, and the "down box" is drawn small and square on
+// the left to indicate the current state.
+
+// The default down_box of zero draws a rectangle designed to look
+// just like Flame's buttons.
+
+#include <FL/Fl.H>
+#include <FL/Fl_Light_Button.H>
+#include <FL/fl_draw.H>
+#include "flstring.h"
+
+void Fl_Light_Button::draw() {
+ if (box()) draw_box(this==Fl::pushed() ? fl_down(box()) : box(), color());
+ Fl_Color col = value() ? (active_r() ? selection_color() :
+ fl_inactive(selection_color())) : color();
+ int W;
+ int dx, dy;
+
+ W = labelsize();
+ dx = Fl::box_dx(box()) + 2;
+ dy = (h() - W) / 2;
+ // if (dy < 0) dy = 0; // neg. offset o.k. for vertical centering
+
+ if (down_box()) {
+ // draw other down_box() styles:
+ switch (down_box()) {
+ case FL_DOWN_BOX :
+ case FL_UP_BOX :
+ case _FL_PLASTIC_DOWN_BOX :
+ case _FL_PLASTIC_UP_BOX :
+ // Check box...
+ draw_box(down_box(), x()+dx, y()+dy, W, W, FL_BACKGROUND2_COLOR);
+ if (value()) {
+ if (Fl::scheme() && !strcmp(Fl::scheme(), "gtk+")) {
+ fl_color(FL_SELECTION_COLOR);
+ } else {
+ fl_color(col);
+ }
+ int tx = x() + dx + 3;
+ int tw = W - 6;
+ int d1 = tw/3;
+ int d2 = tw-d1;
+ int ty = y() + dy + (W+d2)/2-d1-2;
+ for (int n = 0; n < 3; n++, ty++) {
+ fl_line(tx, ty, tx+d1, ty+d1);
+ fl_line(tx+d1, ty+d1, tx+tw-1, ty+d1-d2+1);
+ }
+ }
+ break;
+ case _FL_ROUND_DOWN_BOX :
+ case _FL_ROUND_UP_BOX :
+ // Radio button...
+ draw_box(down_box(), x()+dx, y()+dy, W, W, FL_BACKGROUND2_COLOR);
+ if (value()) {
+ int tW = (W - Fl::box_dw(down_box())) / 2 + 1;
+ if ((W - tW) & 1) tW++; // Make sure difference is even to center
+ int tdx = dx + (W - tW) / 2;
+ int tdy = dy + (W - tW) / 2;
+
+ if (Fl::scheme() && !strcmp(Fl::scheme(), "gtk+")) {
+ fl_color(FL_SELECTION_COLOR);
+ tW --;
+ fl_pie(x() + tdx - 1, y() + tdy - 1, tW + 3, tW + 3, 0.0, 360.0);
+ fl_arc(x() + tdx - 1, y() + tdy - 1, tW + 3, tW + 3, 0.0, 360.0);
+ fl_color(fl_color_average(FL_WHITE, FL_SELECTION_COLOR, 0.2f));
+ } else fl_color(col);
+
+ switch (tW) {
+ // Larger circles draw fine...
+ default :
+ fl_pie(x() + tdx, y() + tdy, tW, tW, 0.0, 360.0);
+ break;
+
+ // Small circles don't draw well on many systems...
+ case 6 :
+ fl_rectf(x() + tdx + 2, y() + tdy, tW - 4, tW);
+ fl_rectf(x() + tdx + 1, y() + tdy + 1, tW - 2, tW - 2);
+ fl_rectf(x() + tdx, y() + tdy + 2, tW, tW - 4);
+ break;
+
+ case 5 :
+ case 4 :
+ case 3 :
+ fl_rectf(x() + tdx + 1, y() + tdy, tW - 2, tW);
+ fl_rectf(x() + tdx, y() + tdy + 1, tW, tW - 2);
+ break;
+
+ case 2 :
+ case 1 :
+ fl_rectf(x() + tdx, y() + tdy, tW, tW);
+ break;
+ }
+
+ if (Fl::scheme() && !strcmp(Fl::scheme(), "gtk+")) {
+ fl_color(fl_color_average(FL_WHITE, FL_SELECTION_COLOR, 0.5));
+ fl_arc(x() + tdx, y() + tdy, tW + 1, tW + 1, 60.0, 180.0);
+ }
+ }
+ break;
+ default :
+ draw_box(down_box(), x()+dx, y()+dy, W, W, col);
+ break;
+ }
+ } else {
+ // if down_box() is zero, draw light button style:
+ int hh = h()-2*dy - 2;
+ int ww = W/2+1;
+ int xx = dx;
+ if (w()<ww+2*xx) xx = (w()-ww)/2;
+ if (Fl::scheme() && !strcmp(Fl::scheme(), "plastic")) {
+ col = active_r() ? selection_color() : fl_inactive(selection_color());
+ fl_color(value() ? col : fl_color_average(col, FL_BLACK, 0.5f));
+ fl_pie(x()+xx, y()+dy+1, ww, hh, 0, 360);
+ } else {
+ draw_box(FL_THIN_DOWN_BOX, x()+xx, y()+dy+1, ww, hh, col);
+ }
+ dx = (ww + 2 * dx - W) / 2;
+ }
+ draw_label(x()+W+2*dx, y(), w()-W-2*dx, h());
+ if (Fl::focus() == this) draw_focus();
+}
+
+int Fl_Light_Button::handle(int event) {
+ switch (event) {
+ case FL_RELEASE:
+ if (box()) redraw();
+ default:
+ return Fl_Button::handle(event);
+ }
+}
+
+Fl_Light_Button::Fl_Light_Button(int X, int Y, int W, int H, const char* l)
+: Fl_Button(X, Y, W, H, l) {
+ type(FL_TOGGLE_BUTTON);
+ selection_color(FL_YELLOW);
+ align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
+}
+
+//
+// End of "$Id: Fl_Light_Button.cxx 5721 2007-02-27 19:23:24Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Menu.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Menu.cxx new file mode 100644 index 0000000..4a7533b --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Menu.cxx @@ -0,0 +1,949 @@ +//
+// "$Id: Fl_Menu.cxx 6478 2008-10-19 21:28:06Z matt $"
+//
+// Menu code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2006 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
+//
+
+// Warning: this menu code is quite a mess!
+
+// This file contains code for implementing Fl_Menu_Item, and for
+// methods for bringing up popup menu hierarchies without using the
+// Fl_Menu_ widget.
+
+#include <FL/Fl.H>
+#include <FL/Fl_Menu_Window.H>
+#include <FL/Fl_Menu_.H>
+#include <FL/fl_draw.H>
+#include <stdio.h>
+#include "flstring.h"
+
+#ifdef __APPLE__
+# include <Carbon/Carbon.h>
+#endif
+
+int Fl_Menu_Item::size() const {
+ const Fl_Menu_Item* m = this;
+ int nest = 0;
+ for (;;) {
+ if (!m->text) {
+ if (!nest) return (m-this+1);
+ nest--;
+ } else if (m->flags & FL_SUBMENU) {
+ nest++;
+ }
+ m++;
+ }
+}
+
+const Fl_Menu_Item* Fl_Menu_Item::next(int n) const {
+ if (n < 0) return 0; // this is so selected==-1 returns NULL
+ const Fl_Menu_Item* m = this;
+ int nest = 0;
+ if (!m->visible()) n++;
+ while (n>0) {
+ if (!m->text) {
+ if (!nest) return m;
+ nest--;
+ } else if (m->flags&FL_SUBMENU) {
+ nest++;
+ }
+ m++;
+ if (!nest && m->visible()) n--;
+ }
+ return m;
+}
+
+// appearance of current menus are pulled from this parent widget:
+static const Fl_Menu_* button;
+
+////////////////////////////////////////////////////////////////
+
+// tiny window for title of menu:
+class menutitle : public Fl_Menu_Window {
+ void draw();
+public:
+ const Fl_Menu_Item* menu;
+ menutitle(int X, int Y, int W, int H, const Fl_Menu_Item*);
+};
+
+// each vertical menu has one of these:
+class menuwindow : public Fl_Menu_Window {
+ void draw();
+ void drawentry(const Fl_Menu_Item*, int i, int erase);
+public:
+ menutitle* title;
+ int handle(int);
+#ifdef __APPLE__
+ int early_hide_handle(int);
+#endif
+ int itemheight; // zero == menubar
+ int numitems;
+ int selected;
+ int drawn_selected; // last redraw has this selected
+ const Fl_Menu_Item* menu;
+ menuwindow(const Fl_Menu_Item* m, int X, int Y, int W, int H,
+ const Fl_Menu_Item* picked, const Fl_Menu_Item* title,
+ int menubar = 0, int menubar_title = 0, int right_edge = 0);
+ ~menuwindow();
+ void set_selected(int);
+ int find_selected(int mx, int my);
+ int titlex(int);
+ void autoscroll(int);
+ void position(int x, int y);
+ int is_inside(int x, int y);
+};
+
+#define LEADING 4 // extra vertical leading
+
+extern char fl_draw_shortcut;
+
+// width of label, including effect of & characters:
+int Fl_Menu_Item::measure(int* hp, const Fl_Menu_* m) const {
+ Fl_Label l;
+ l.value = text;
+ l.image = 0;
+ l.deimage = 0;
+ l.type = labeltype_;
+ l.font = labelsize_ || labelfont_ ? labelfont_ : uchar(m ? m->textfont() : FL_HELVETICA);
+ l.size = labelsize_ ? labelsize_ : m ? m->textsize() : (uchar)FL_NORMAL_SIZE;
+ l.color = FL_FOREGROUND_COLOR; // this makes no difference?
+ fl_draw_shortcut = 1;
+ int w = 0; int h = 0;
+ l.measure(w, hp ? *hp : h);
+ fl_draw_shortcut = 0;
+ if (flags & (FL_MENU_TOGGLE|FL_MENU_RADIO)) w += 14;
+ return w;
+}
+
+void Fl_Menu_Item::draw(int x, int y, int w, int h, const Fl_Menu_* m,
+ int selected) const {
+ Fl_Label l;
+ l.value = text;
+ l.image = 0;
+ l.deimage = 0;
+ l.type = labeltype_;
+ l.font = labelsize_ || labelfont_ ? labelfont_ : uchar(m ? m->textfont() : FL_HELVETICA);
+ l.size = labelsize_ ? labelsize_ : m ? m->textsize() : (uchar)FL_NORMAL_SIZE;
+ l.color = labelcolor_ ? labelcolor_ : m ? m->textcolor() : int(FL_FOREGROUND_COLOR);
+ if (!active()) l.color = fl_inactive((Fl_Color)l.color);
+ Fl_Color color = m ? m->color() : FL_GRAY;
+ if (selected) {
+ Fl_Color r = m ? m->selection_color() : FL_SELECTION_COLOR;
+ Fl_Boxtype b = m && m->down_box() ? m->down_box() : FL_FLAT_BOX;
+ if (fl_contrast(r,color)!=r) { // back compatability boxtypes
+ if (selected == 2) { // menu title
+ r = color;
+ b = m ? m->box() : FL_UP_BOX;
+ } else {
+ r = (Fl_Color)(FL_COLOR_CUBE-1); // white
+ l.color = fl_contrast((Fl_Color)labelcolor_, r);
+ }
+ } else {
+ l.color = fl_contrast((Fl_Color)labelcolor_, r);
+ }
+ if (selected == 2) { // menu title
+ fl_draw_box(b, x, y, w, h, r);
+ x += 3;
+ w -= 8;
+ } else {
+ fl_draw_box(b, x+1, y-(LEADING-2)/2, w-2, h+(LEADING-2), r);
+ }
+ }
+
+ if (flags & (FL_MENU_TOGGLE|FL_MENU_RADIO)) {
+ int d = (h - FL_NORMAL_SIZE + 1) / 2;
+ int W = h - 2 * d;
+
+ if (flags & FL_MENU_RADIO) {
+ fl_draw_box(FL_ROUND_DOWN_BOX, x+2, y+d, W, W, FL_BACKGROUND2_COLOR);
+ if (value()) {
+ int tW = (W - Fl::box_dw(FL_ROUND_DOWN_BOX)) / 2 + 1;
+ if ((W - tW) & 1) tW++; // Make sure difference is even to center
+ int td = Fl::box_dx(FL_ROUND_DOWN_BOX) + 1;
+ if (Fl::scheme()) {
+ // Offset the radio circle...
+ td ++;
+
+ if (!strcmp(Fl::scheme(), "gtk+")) {
+ fl_color(FL_SELECTION_COLOR);
+ tW --;
+ fl_pie(x + td + 1, y + d + td - 1, tW + 3, tW + 3, 0.0, 360.0);
+ fl_arc(x + td + 1, y + d + td - 1, tW + 3, tW + 3, 0.0, 360.0);
+ fl_color(fl_color_average(FL_WHITE, FL_SELECTION_COLOR, 0.2f));
+ } else fl_color(labelcolor_);
+ } else fl_color(labelcolor_);
+
+ switch (tW) {
+ // Larger circles draw fine...
+ default :
+ fl_pie(x + td + 2, y + d + td, tW, tW, 0.0, 360.0);
+ break;
+
+ // Small circles don't draw well on many systems...
+ case 6 :
+ fl_rectf(x + td + 4, y + d + td, tW - 4, tW);
+ fl_rectf(x + td + 3, y + d + td + 1, tW - 2, tW - 2);
+ fl_rectf(x + td + 2, y + d + td + 2, tW, tW - 4);
+ break;
+
+ case 5 :
+ case 4 :
+ case 3 :
+ fl_rectf(x + td + 3, y + d + td, tW - 2, tW);
+ fl_rectf(x + td + 2, y + d + td + 1, tW, tW - 2);
+ break;
+
+ case 2 :
+ case 1 :
+ fl_rectf(x + td + 2, y + d + td, tW, tW);
+ break;
+ }
+
+ if (Fl::scheme() && !strcmp(Fl::scheme(), "gtk+")) {
+ fl_color(fl_color_average(FL_WHITE, FL_SELECTION_COLOR, 0.5));
+ fl_arc(x + td + 2, y + d + td, tW + 1, tW + 1, 60.0, 180.0);
+ }
+ }
+ } else {
+ fl_draw_box(FL_DOWN_BOX, x+2, y+d, W, W, FL_BACKGROUND2_COLOR);
+ if (value()) {
+ if (Fl::scheme() && !strcmp(Fl::scheme(), "gtk+")) {
+ fl_color(FL_SELECTION_COLOR);
+ } else {
+ fl_color(labelcolor_);
+ }
+ int tx = x + 5;
+ int tw = W - 6;
+ int d1 = tw/3;
+ int d2 = tw-d1;
+ int ty = y + d + (W+d2)/2-d1-2;
+ for (int n = 0; n < 3; n++, ty++) {
+ fl_line(tx, ty, tx+d1, ty+d1);
+ fl_line(tx+d1, ty+d1, tx+tw-1, ty+d1-d2+1);
+ }
+ }
+ }
+ x += W + 3;
+ w -= W + 3;
+ }
+
+ if (!fl_draw_shortcut) fl_draw_shortcut = 1;
+ l.draw(x+3, y, w>6 ? w-6 : 0, h, FL_ALIGN_LEFT);
+ fl_draw_shortcut = 0;
+}
+
+menutitle::menutitle(int X, int Y, int W, int H, const Fl_Menu_Item* L) :
+ Fl_Menu_Window(X, Y, W, H, 0) {
+ end();
+ set_modal();
+ clear_border();
+ menu = L;
+ if (L->labelcolor_ || Fl::scheme() || L->labeltype_ > FL_NO_LABEL) clear_overlay();
+}
+
+menuwindow::menuwindow(const Fl_Menu_Item* m, int X, int Y, int Wp, int Hp,
+ const Fl_Menu_Item* picked, const Fl_Menu_Item* t,
+ int menubar, int menubar_title, int right_edge)
+ : Fl_Menu_Window(X, Y, Wp, Hp, 0)
+{
+ int scr_x, scr_y, scr_w, scr_h;
+ int tx = X, ty = Y;
+
+ Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h);
+ if (!right_edge || right_edge > scr_x+scr_w) right_edge = scr_x+scr_w;
+
+ end();
+ set_modal();
+ clear_border();
+ menu = m;
+ if (m) m = m->first(); // find the first item that needs to be rendered
+ drawn_selected = -1;
+ if (button) {
+ box(button->box());
+ if (box() == FL_NO_BOX || box() == FL_FLAT_BOX) box(FL_UP_BOX);
+ } else {
+ box(FL_UP_BOX);
+ }
+ color(button && !Fl::scheme() ? button->color() : FL_GRAY);
+ selected = -1;
+ {int j = 0;
+ if (m) for (const Fl_Menu_Item* m1=m; ; m1 = m1->next(), j++) {
+ if (picked) {
+ if (m1 == picked) {selected = j; picked = 0;}
+ else if (m1 > picked) {selected = j-1; picked = 0; Wp = Hp = 0;}
+ }
+ if (!m1->text) break;
+ }
+ numitems = j;}
+
+ if (menubar) {
+ itemheight = 0;
+ title = 0;
+ return;
+ }
+
+ itemheight = 1;
+
+ int hotKeysw = 0;
+ int Wtitle = 0;
+ int Htitle = 0;
+ if (t) Wtitle = t->measure(&Htitle, button) + 12;
+ int W = 0;
+ if (m) for (; m->text; m = m->next()) {
+ int hh; int w1 = m->measure(&hh, button);
+ if (hh+LEADING>itemheight) itemheight = hh+LEADING;
+ if (m->flags&(FL_SUBMENU|FL_SUBMENU_POINTER)) w1 += 14;
+ if (w1 > W) W = w1;
+ if (m->shortcut_) {
+ w1 = int(fl_width(fl_shortcut_label(m->shortcut_))) + 8;
+ if (w1 > hotKeysw) hotKeysw = w1;
+ }
+ if (m->labelcolor_ || Fl::scheme() || m->labeltype_ > FL_NO_LABEL) clear_overlay();
+ }
+ if (selected >= 0 && !Wp) X -= W/2;
+ int BW = Fl::box_dx(box());
+ W += hotKeysw+2*BW+7;
+ if (Wp > W) W = Wp;
+ if (Wtitle > W) W = Wtitle;
+
+ if (X < scr_x) X = scr_x; if (X > scr_x+scr_w-W) X = right_edge-W; // X= scr_x+scr_w-W;
+ x(X); w(W);
+ h((numitems ? itemheight*numitems-LEADING : 0)+2*BW+3);
+ if (selected >= 0)
+ Y = Y+(Hp-itemheight)/2-selected*itemheight-BW;
+ else {
+ Y = Y+Hp;
+ // if the menu hits the bottom of the screen, we try to draw
+ // it above the menubar instead. We will not adjust any menu
+ // that has a selected item.
+ if (Y+h()>scr_y+scr_h && Y-h()>=scr_y) {
+ if (Hp>1)
+ // if we know the height of the Fl_Menu_, use it
+ Y = Y-Hp-h();
+ else if (t)
+ // assume that the menubar item height relates to the first
+ // menuitem as well
+ Y = Y-itemheight-h()-Fl::box_dh(box());
+ else
+ // draw the menu to the right
+ Y = Y-h()+itemheight+Fl::box_dy(box());
+ }
+ }
+ if (m) y(Y); else {y(Y-2); w(1); h(1);}
+
+ if (t) {
+ if (menubar_title) {
+ int dy = Fl::box_dy(button->box())+1;
+ int ht = button->h()-dy*2;
+ title = new menutitle(tx, ty-ht-dy, Wtitle, ht, t);
+ } else {
+ int dy = 2;
+ int ht = Htitle+2*BW+3;
+ title = new menutitle(X, Y-ht-dy, Wtitle, ht, t);
+ }
+ } else
+ title = 0;
+}
+
+menuwindow::~menuwindow() {
+ hide();
+ delete title;
+}
+
+void menuwindow::position(int X, int Y) {
+ if (title) {title->position(X, title->y()+Y-y());}
+ Fl_Menu_Window::position(X, Y);
+ // x(X); y(Y); // don't wait for response from X
+}
+
+// scroll so item i is visible on screen
+void menuwindow::autoscroll(int n) {
+ int scr_x, scr_y, scr_w, scr_h;
+ int Y = y()+Fl::box_dx(box())+2+n*itemheight;
+
+ Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h);
+ if (Y <= scr_y) Y = scr_y-Y+10;
+ else {
+ Y = Y+itemheight-scr_h-scr_y;
+ if (Y < 0) return;
+ Y = -Y-10;
+ }
+ Fl_Menu_Window::position(x(), y()+Y);
+ // y(y()+Y); // don't wait for response from X
+}
+
+////////////////////////////////////////////////////////////////
+
+void menuwindow::drawentry(const Fl_Menu_Item* m, int n, int eraseit) {
+ if (!m) return; // this happens if -1 is selected item and redrawn
+
+ int BW = Fl::box_dx(box());
+ int xx = BW;
+ int W = w();
+ int ww = W-2*BW-1;
+ int yy = BW+1+n*itemheight;
+ int hh = itemheight - LEADING;
+
+ if (eraseit && n != selected) {
+ fl_push_clip(xx+1, yy-(LEADING-2)/2, ww-2, hh+(LEADING-2));
+ draw_box(box(), 0, 0, w(), h(), button ? button->color() : color());
+ fl_pop_clip();
+ }
+
+ m->draw(xx, yy, ww, hh, button, n==selected);
+
+ // the shortcuts and arrows assumme fl_color() was left set by draw():
+ if (m->submenu()) {
+ int sz = (hh-7)&-2;
+ int y1 = yy+(hh-sz)/2;
+ int x1 = xx+ww-sz-3;
+ fl_polygon(x1+2, y1, x1+2, y1+sz, x1+sz/2+2, y1+sz/2);
+ } else if (m->shortcut_) {
+ Fl_Font f = m->labelsize_ || m->labelfont_ ? (Fl_Font)m->labelfont_ :
+ button ? button->textfont() : FL_HELVETICA;
+ fl_font(f, m->labelsize_ ? m->labelsize_ :
+ button ? button->textsize() : FL_NORMAL_SIZE);
+ fl_draw(fl_shortcut_label(m->shortcut_), xx, yy, ww-3, hh, FL_ALIGN_RIGHT);
+ }
+
+ if (m->flags & FL_MENU_DIVIDER) {
+ fl_color(FL_DARK3);
+ fl_xyline(BW-1, yy+hh+(LEADING-2)/2, W-2*BW+2);
+ fl_color(FL_LIGHT3);
+ fl_xyline(BW-1, yy+hh+((LEADING-2)/2+1), W-2*BW+2);
+ }
+}
+
+void menutitle::draw() {
+ menu->draw(0, 0, w(), h(), button, 2);
+}
+
+void menuwindow::draw() {
+ if (damage() != FL_DAMAGE_CHILD) { // complete redraw
+ fl_draw_box(box(), 0, 0, w(), h(), button ? button->color() : color());
+ if (menu) {
+ const Fl_Menu_Item* m; int j;
+ for (m=menu->first(), j=0; m->text; j++, m = m->next()) drawentry(m, j, 0);
+ }
+ } else {
+ if (damage() & FL_DAMAGE_CHILD && selected!=drawn_selected) { // change selection
+ drawentry(menu->next(drawn_selected), drawn_selected, 1);
+ drawentry(menu->next(selected), selected, 1);
+ }
+ }
+ drawn_selected = selected;
+}
+
+void menuwindow::set_selected(int n) {
+ if (n != selected) {selected = n; damage(FL_DAMAGE_CHILD);}
+}
+
+////////////////////////////////////////////////////////////////
+
+int menuwindow::find_selected(int mx, int my) {
+ if (!menu || !menu->text) return -1;
+ mx -= x();
+ my -= y();
+ if (my < 0 || my >= h()) return -1;
+ if (!itemheight) { // menubar
+ int xx = 3; int n = 0;
+ const Fl_Menu_Item* m = menu ? menu->first() : 0;
+ for (; ; m = m->next(), n++) {
+ if (!m->text) return -1;
+ xx += m->measure(0, button) + 16;
+ if (xx > mx) break;
+ }
+ return n;
+ }
+ if (mx < Fl::box_dx(box()) || mx >= w()) return -1;
+ int n = (my-Fl::box_dx(box())-1)/itemheight;
+ if (n < 0 || n>=numitems) return -1;
+ return n;
+}
+
+// return horizontal position for item n in a menubar:
+int menuwindow::titlex(int n) {
+ const Fl_Menu_Item* m;
+ int xx = 3;
+ for (m=menu->first(); n--; m = m->next()) xx += m->measure(0, button) + 16;
+ return xx;
+}
+
+// return 1, if the given root coordinates are inside the window
+int menuwindow::is_inside(int mx, int my) {
+ if ( mx < x_root() || mx >= x_root() + w() ||
+ my < y_root() || my >= y_root() + h()) {
+ return 0;
+ }
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////
+// Fl_Menu_Item::popup(...)
+
+// Because Fl::grab() is done, all events go to one of the menu windows.
+// But the handle method needs to look at all of them to find out
+// what item the user is pointing at. And it needs a whole lot
+// of other state variables to determine what is going on with
+// the currently displayed menus.
+// So the main loop (handlemenu()) puts all the state in a structure
+// and puts a pointer to it in a static location, so the handle()
+// on menus can refer to it and alter it. The handle() method
+// changes variables in this state to indicate what item is
+// picked, but does not actually alter the display, instead the
+// main loop does that. This is because the X mapping and unmapping
+// of windows is slow, and we don't want to fall behind the events.
+
+// values for menustate.state:
+#define INITIAL_STATE 0 // no mouse up or down since popup() called
+#define PUSH_STATE 1 // mouse has been pushed on a normal item
+#define DONE_STATE 2 // exit the popup, the current item was picked
+#define MENU_PUSH_STATE 3 // mouse has been pushed on a menu title
+
+struct menustate {
+ const Fl_Menu_Item* current_item; // what mouse is pointing at
+ int menu_number; // which menu it is in
+ int item_number; // which item in that menu, -1 if none
+ menuwindow* p[20]; // pointers to menus
+ int nummenus;
+ int menubar; // if true p[0] is a menubar
+ int state;
+ menuwindow* fakemenu; // kludge for buttons in menubar
+ int is_inside(int mx, int my);
+};
+static menustate* p;
+
+// return 1 if the coordinates are inside any of the menuwindows
+int menustate::is_inside(int mx, int my) {
+ int i;
+ for (i=nummenus-1; i>=0; i--) {
+ if (p[i]->is_inside(mx, my))
+ return 1;
+ }
+ return 0;
+}
+
+static inline void setitem(const Fl_Menu_Item* i, int m, int n) {
+ p->current_item = i;
+ p->menu_number = m;
+ p->item_number = n;
+}
+
+static void setitem(int m, int n) {
+ menustate &pp = *p;
+ pp.current_item = (n >= 0) ? pp.p[m]->menu->next(n) : 0;
+ pp.menu_number = m;
+ pp.item_number = n;
+}
+
+static int forward(int menu) { // go to next item in menu menu if possible
+ menustate &pp = *p;
+ // Fl_Menu_Button can geberate menu=-1. This line fixes it and selectes the first item.
+ if (menu==-1)
+ menu = 0;
+ menuwindow &m = *(pp.p[menu]);
+ int item = (menu == pp.menu_number) ? pp.item_number : m.selected;
+ while (++item < m.numitems) {
+ const Fl_Menu_Item* m1 = m.menu->next(item);
+ if (m1->activevisible()) {setitem(m1, menu, item); return 1;}
+ }
+ return 0;
+}
+
+static int backward(int menu) { // previous item in menu menu if possible
+ menustate &pp = *p;
+ menuwindow &m = *(pp.p[menu]);
+ int item = (menu == pp.menu_number) ? pp.item_number : m.selected;
+ if (item < 0) item = m.numitems;
+ while (--item >= 0) {
+ const Fl_Menu_Item* m1 = m.menu->next(item);
+ if (m1->activevisible()) {setitem(m1, menu, item); return 1;}
+ }
+ return 0;
+}
+
+int menuwindow::handle(int e) {
+#ifdef __APPLE__
+ // This off-route takes care of the "detached menu" bug on OS X.
+ // Apple event handler requires that we hide all menu windows right
+ // now, so that Carbon can continue undisturbed with handling window
+ // manager events, like dragging the application window.
+ int ret = early_hide_handle(e);
+ menustate &pp = *p;
+ if (pp.state == DONE_STATE) {
+ hide();
+ if (pp.fakemenu) {
+ pp.fakemenu->hide();
+ if (pp.fakemenu->title)
+ pp.fakemenu->title->hide();
+ }
+ int i = pp.nummenus;
+ while (i>0) {
+ menuwindow *mw = pp.p[--i];
+ if (mw) {
+ mw->hide();
+ if (mw->title)
+ mw->title->hide();
+ }
+ }
+ }
+ return ret;
+}
+
+int menuwindow::early_hide_handle(int e) {
+#endif
+ menustate &pp = *p;
+ switch (e) {
+ case FL_KEYBOARD:
+ switch (Fl::event_key()) {
+ case FL_BackSpace:
+ case 0xFE20: // backtab
+ BACKTAB:
+ if (!backward(pp.menu_number)) {pp.item_number = -1;backward(pp.menu_number);}
+ return 1;
+ case FL_Up:
+ if (pp.menubar && pp.menu_number == 0) {
+ // Do nothing...
+ } else if (backward(pp.menu_number)) {
+ // Do nothing...
+ } else if (pp.menubar && pp.menu_number==1) {
+ setitem(0, pp.p[0]->selected);
+ }
+ return 1;
+ case FL_Tab:
+ if (Fl::event_shift()) goto BACKTAB;
+ case FL_Down:
+ if (pp.menu_number || !pp.menubar) {
+ if (!forward(pp.menu_number) && Fl::event_key()==FL_Tab) {
+ pp.item_number = -1;
+ forward(pp.menu_number);
+ }
+ } else if (pp.menu_number < pp.nummenus-1) {
+ forward(pp.menu_number+1);
+ }
+ return 1;
+ case FL_Right:
+ if (pp.menubar && (pp.menu_number<=0 || pp.menu_number==1 && pp.nummenus==2))
+ forward(0);
+ else if (pp.menu_number < pp.nummenus-1) forward(pp.menu_number+1);
+ return 1;
+ case FL_Left:
+ if (pp.menubar && pp.menu_number<=1) backward(0);
+ else if (pp.menu_number>0)
+ setitem(pp.menu_number-1, pp.p[pp.menu_number-1]->selected);
+ return 1;
+ case FL_Enter:
+ case FL_KP_Enter:
+ case ' ':
+ pp.state = DONE_STATE;
+ return 1;
+ case FL_Escape:
+ setitem(0, -1, 0);
+ pp.state = DONE_STATE;
+ return 1;
+ }
+ break;
+ case FL_SHORTCUT: {
+ for (int mymenu = pp.nummenus; mymenu--;) {
+ menuwindow &mw = *(pp.p[mymenu]);
+ int item; const Fl_Menu_Item* m = mw.menu->find_shortcut(&item);
+ if (m) {
+ setitem(m, mymenu, item);
+ if (!m->submenu()) pp.state = DONE_STATE;
+ return 1;
+ }
+ }} break;
+ case FL_ENTER:
+ case FL_MOVE:
+ case FL_PUSH:
+ case FL_DRAG: {
+#ifdef __QNX__
+ // STR 704: workaround QNX X11 bug - in QNX a FL_MOVE event is sent
+ // right after FL_RELEASE...
+ if (pp.state == DONE_STATE) return 1;
+#endif // __QNX__
+ int mx = Fl::event_x_root();
+ int my = Fl::event_y_root();
+ int item=0; int mymenu = pp.nummenus-1;
+ // Clicking or dragging outside menu cancels it...
+ if ((!pp.menubar || mymenu) && !pp.is_inside(mx, my)) {
+ setitem(0, -1, 0);
+ if (e==FL_PUSH)
+ pp.state = DONE_STATE;
+ return 1;
+ }
+ for (mymenu = pp.nummenus-1; ; mymenu--) {
+ item = pp.p[mymenu]->find_selected(mx, my);
+ if (item >= 0)
+ break;
+ if (mymenu <= 0) {
+ // buttons in menubars must be deselected if we move outside of them!
+ if (pp.menu_number==-1 && e==FL_PUSH) {
+ pp.state = DONE_STATE;
+ return 1;
+ }
+ if (pp.current_item && pp.menu_number==0 && !pp.current_item->submenu()) {
+ if (e==FL_PUSH)
+ pp.state = DONE_STATE;
+ setitem(0, -1, 0);
+ return 1;
+ }
+ // all others can stay selected
+ return 0;
+ }
+ }
+ if (my == 0 && item > 0) setitem(mymenu, item - 1);
+ else setitem(mymenu, item);
+ if (e == FL_PUSH) {
+ if (pp.current_item && pp.current_item->submenu() // this is a menu title
+ && item != pp.p[mymenu]->selected // and it is not already on
+ && !pp.current_item->callback_) // and it does not have a callback
+ pp.state = MENU_PUSH_STATE;
+ else
+ pp.state = PUSH_STATE;
+ }} return 1;
+ case FL_RELEASE:
+ // Mouse must either be held down/dragged some, or this must be
+ // the second click (not the one that popped up the menu):
+ if (!Fl::event_is_click() || pp.state == PUSH_STATE ||
+ pp.menubar && pp.current_item && !pp.current_item->submenu() // button
+ ) {
+#if 0 // makes the check/radio items leave the menu up
+ const Fl_Menu_Item* m = pp.current_item;
+ if (m && button && (m->flags & (FL_MENU_TOGGLE|FL_MENU_RADIO))) {
+ ((Fl_Menu_*)button)->picked(m);
+ pp.p[pp.menu_number]->redraw();
+ } else
+#endif
+ // do nothing if they try to pick inactive items
+ if (!pp.current_item || pp.current_item->activevisible())
+ pp.state = DONE_STATE;
+ }
+ return 1;
+ }
+ return Fl_Window::handle(e);
+}
+
+const Fl_Menu_Item* Fl_Menu_Item::pulldown(
+ int X, int Y, int W, int H,
+ const Fl_Menu_Item* initial_item,
+ const Fl_Menu_* pbutton,
+ const Fl_Menu_Item* t,
+ int menubar) const
+{
+ Fl_Group::current(0); // fix possible user error...
+
+ button = pbutton;
+ if (pbutton) {
+ for (Fl_Window* w = pbutton->window(); w; w = w->window()) {
+ X += w->x();
+ Y += w->y();
+ }
+ } else {
+ X += Fl::event_x_root()-Fl::event_x();
+ Y += Fl::event_y_root()-Fl::event_y();
+ }
+ menuwindow mw(this, X, Y, W, H, initial_item, t, menubar);
+ Fl::grab(mw);
+ menustate pp; p = &pp;
+ pp.p[0] = &mw;
+ pp.nummenus = 1;
+ pp.menubar = menubar;
+ pp.state = INITIAL_STATE;
+ pp.fakemenu = 0; // kludge for buttons in menubar
+
+ // preselected item, pop up submenus if necessary:
+ if (initial_item && mw.selected >= 0) {
+ setitem(0, mw.selected);
+ goto STARTUP;
+ }
+
+ pp.current_item = 0; pp.menu_number = 0; pp.item_number = -1;
+ if (menubar) {
+ // find the initial menu
+ if (!mw.handle(FL_DRAG)) {
+ Fl::release();
+ return 0;
+ }
+ }
+ initial_item = pp.current_item;
+ if (initial_item) goto STARTUP;
+
+ // the main loop, runs until p.state goes to DONE_STATE:
+ for (;;) {
+
+ // make sure all the menus are shown:
+ {for (int k = menubar; k < pp.nummenus; k++)
+ if (!pp.p[k]->shown()) {
+ if (pp.p[k]->title) pp.p[k]->title->show();
+ pp.p[k]->show();
+ }
+ }
+
+ // get events:
+ {const Fl_Menu_Item* oldi = pp.current_item;
+ Fl::wait();
+ if (pp.state == DONE_STATE) break; // done.
+ if (pp.current_item == oldi) continue;}
+ // only do rest if item changes:
+
+ delete pp.fakemenu; pp.fakemenu = 0; // turn off "menubar button"
+
+ if (!pp.current_item) { // pointing at nothing
+ // turn off selection in deepest menu, but don't erase other menus:
+ pp.p[pp.nummenus-1]->set_selected(-1);
+ continue;
+ }
+
+ delete pp.fakemenu; pp.fakemenu = 0;
+ initial_item = 0; // stop the startup code
+ pp.p[pp.menu_number]->autoscroll(pp.item_number);
+
+ STARTUP:
+ menuwindow& cw = *pp.p[pp.menu_number];
+ const Fl_Menu_Item* m = pp.current_item;
+ if (!m->activevisible()) { // pointing at inactive item
+ cw.set_selected(-1);
+ initial_item = 0; // turn off startup code
+ continue;
+ }
+ cw.set_selected(pp.item_number);
+
+ if (m==initial_item) initial_item=0; // stop the startup code if item found
+ if (m->submenu()) {
+ const Fl_Menu_Item* title = m;
+ const Fl_Menu_Item* menutable;
+ if (m->flags&FL_SUBMENU) menutable = m+1;
+ else menutable = (Fl_Menu_Item*)(m)->user_data_;
+ // figure out where new menu goes:
+ int nX, nY;
+ if (!pp.menu_number && pp.menubar) { // menu off a menubar:
+ nX = cw.x() + cw.titlex(pp.item_number);
+ nY = cw.y() + cw.h();
+ initial_item = 0;
+ } else {
+ nX = cw.x() + cw.w();
+ nY = cw.y() + pp.item_number * cw.itemheight;
+ title = 0;
+ }
+ if (initial_item) { // bring up submenu containing initial item:
+ menuwindow* n = new menuwindow(menutable,X,Y,W,H,initial_item,title,0,0,cw.x());
+ pp.p[pp.nummenus++] = n;
+ // move all earlier menus to line up with this new one:
+ if (n->selected>=0) {
+ int dy = n->y()-nY;
+ int dx = n->x()-nX;
+ for (int menu = 0; menu <= pp.menu_number; menu++) {
+ menuwindow* tt = pp.p[menu];
+ int nx = tt->x()+dx; if (nx < 0) {nx = 0; dx = -tt->x();}
+ int ny = tt->y()+dy; if (ny < 0) {ny = 0; dy = -tt->y();}
+ tt->position(nx, ny);
+ }
+ setitem(pp.nummenus-1, n->selected);
+ goto STARTUP;
+ }
+ } else if (pp.nummenus > pp.menu_number+1 &&
+ pp.p[pp.menu_number+1]->menu == menutable) {
+ // the menu is already up:
+ while (pp.nummenus > pp.menu_number+2) delete pp.p[--pp.nummenus];
+ pp.p[pp.nummenus-1]->set_selected(-1);
+ } else {
+ // delete all the old menus and create new one:
+ while (pp.nummenus > pp.menu_number+1) delete pp.p[--pp.nummenus];
+ pp.p[pp.nummenus++]= new menuwindow(menutable, nX, nY,
+ title?1:0, 0, 0, title, 0, menubar, cw.x());
+ }
+ } else { // !m->submenu():
+ while (pp.nummenus > pp.menu_number+1) delete pp.p[--pp.nummenus];
+ if (!pp.menu_number && pp.menubar) {
+ // kludge so "menubar buttons" turn "on" by using menu title:
+ pp.fakemenu = new menuwindow(0,
+ cw.x()+cw.titlex(pp.item_number),
+ cw.y()+cw.h(), 0, 0,
+ 0, m, 0, 1);
+ pp.fakemenu->title->show();
+ }
+ }
+ }
+ const Fl_Menu_Item* m = pp.current_item;
+ Fl::release();
+ delete pp.fakemenu;
+ while (pp.nummenus>1) delete pp.p[--pp.nummenus];
+ mw.hide();
+ return m;
+}
+
+const Fl_Menu_Item*
+Fl_Menu_Item::popup(
+ int X, int Y,
+ const char* title,
+ const Fl_Menu_Item* picked,
+ const Fl_Menu_* but
+ ) const
+{
+ static Fl_Menu_Item dummy; // static so it is all zeros
+ dummy.text = title;
+ return pulldown(X, Y, 0, 0, picked, but, title ? &dummy : 0);
+}
+
+// Search only the top level menu for a shortcut. Either &x in the
+// label or the shortcut fields are used:
+const Fl_Menu_Item* Fl_Menu_Item::find_shortcut(int* ip) const {
+ const Fl_Menu_Item* m = first();
+ if (m) for (int ii = 0; m->text; m = m->next(), ii++) {
+ if (m->activevisible()) {
+ if (Fl::test_shortcut(m->shortcut_)
+ || Fl_Widget::test_shortcut(m->text)) {
+ if (ip) *ip=ii;
+ return m;
+ }
+ }
+ }
+ return 0;
+}
+
+// Recursive search of all submenus for anything with this key as a
+// shortcut. Only uses the shortcut field, ignores &x in the labels:
+const Fl_Menu_Item* Fl_Menu_Item::test_shortcut() const {
+ const Fl_Menu_Item* m = first();
+ const Fl_Menu_Item* ret = 0;
+ if (m) for (; m->text; m = m->next()) {
+ if (m->activevisible()) {
+ // return immediately any match of an item in top level menu:
+ if (Fl::test_shortcut(m->shortcut_)) return m;
+ // if (Fl_Widget::test_shortcut(m->text)) return m;
+ // only return matches from lower menu if nothing found in top menu:
+ if (!ret && m->submenu()) {
+ const Fl_Menu_Item* s =
+ (m->flags&FL_SUBMENU) ? m+1:(const Fl_Menu_Item*)m->user_data_;
+ ret = s->test_shortcut();
+ }
+ }
+ }
+ return ret;
+}
+
+//
+// End of "$Id: Fl_Menu.cxx 6478 2008-10-19 21:28:06Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Menu_.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Menu_.cxx new file mode 100644 index 0000000..f8a8f59 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Menu_.cxx @@ -0,0 +1,232 @@ +//
+// "$Id: Fl_Menu_.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Common menu code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// This is a base class for all items that have a menu:
+// Fl_Menu_Bar, Fl_Menu_Button, Fl_Choice
+// This provides storage for a menu item, functions to add/modify/delete
+// items, and a call for when the user picks a menu item.
+
+// More code in Fl_Menu_add.cxx
+
+#include <FL/Fl.H>
+#include <FL/Fl_Menu_.H>
+#include "flstring.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+// Set 'pathname' of specified menuitem
+// If finditem==NULL, mvalue() is used (the most recently picked menuitem)
+// Returns:
+// 0 : OK
+// -1 : item not found (name="")
+// -2 : 'name' not large enough (name="")
+//
+#define SAFE_STRCAT(s) \
+ { len += strlen(s); if ( len >= namelen ) { *name='\0'; return(-2); } else strcat(name,(s)); }
+int Fl_Menu_::item_pathname(char *name, int namelen, const Fl_Menu_Item *finditem) const {
+ int len = 0;
+ finditem = finditem ? finditem : mvalue();
+ name[0] = '\0';
+ for ( int t=0; t<size(); t++ ) {
+ const Fl_Menu_Item *m = &(menu()[t]);
+ if ( m->submenu() ) { // submenu? descend
+ if (*name) SAFE_STRCAT("/");
+ if (m->label()) SAFE_STRCAT(m->label());
+ } else {
+ if (m->label()) { // menu item?
+ if ( m == finditem ) { // found? tack on itemname, done.
+ SAFE_STRCAT("/");
+ SAFE_STRCAT(m->label());
+ return(0);
+ }
+ } else { // end of submenu? pop
+ char *ss = strrchr(name, '/');
+ if ( ss ) { *ss = 0; len = strlen(name); } // "File/Edit" -> "File"
+ else { name[0] = '\0'; len = 0; } // "File" -> ""
+ continue;
+ }
+ }
+ }
+ *name = '\0';
+ return(-1); // item not found
+}
+
+// FIND MENU ITEM INDEX, GIVEN MENU PATHNAME
+// eg. "Edit/Copy"
+// Will also return submenus, eg. "Edit"
+// Returns NULL if not found.
+//
+const Fl_Menu_Item *
+Fl_Menu_::find_item(const char *name)
+{
+ char menupath[1024] = ""; // File/Export
+
+ for ( int t=0; t < size(); t++ ) {
+ Fl_Menu_Item *m = menu_ + t;
+
+ if (m->flags&FL_SUBMENU) {
+ // IT'S A SUBMENU
+ // we do not support searches through FL_SUBMENU_POINTER links
+ if (menupath[0]) strlcat(menupath, "/", sizeof(menupath));
+ strlcat(menupath, m->label(), sizeof(menupath));
+ if (!strcmp(menupath, name)) return m;
+ } else {
+ if (!m->label()) {
+ // END OF SUBMENU? Pop back one level.
+ char *ss = strrchr(menupath, '/');
+ if ( ss ) *ss = 0;
+ else menupath[0] = '\0';
+ continue;
+ }
+
+ // IT'S A MENU ITEM
+ char itempath[1024]; // eg. Edit/Copy
+ strcpy(itempath, menupath);
+ if (itempath[0]) strlcat(itempath, "/", sizeof(itempath));
+ strlcat(itempath, m->label(), sizeof(itempath));
+ if (!strcmp(itempath, name)) return m;
+ }
+ }
+
+ return (const Fl_Menu_Item *)0;
+}
+
+int Fl_Menu_::value(const Fl_Menu_Item* m) {
+ clear_changed();
+ if (value_ != m) {value_ = m; return 1;}
+ return 0;
+}
+
+// When user picks a menu item, call this. It will do the callback.
+// Unfortunatly this also casts away const for the checkboxes, but this
+// was necessary so non-checkbox menus can really be declared const...
+const Fl_Menu_Item* Fl_Menu_::picked(const Fl_Menu_Item* v) {
+ if (v) {
+ if (v->radio()) {
+ if (!v->value()) { // they are turning on a radio item
+ set_changed();
+ ((Fl_Menu_Item*)v)->setonly();
+ }
+ redraw();
+ } else if (v->flags & FL_MENU_TOGGLE) {
+ set_changed();
+ ((Fl_Menu_Item*)v)->flags ^= FL_MENU_VALUE;
+ redraw();
+ } else if (v != value_) { // normal item
+ set_changed();
+ }
+ value_ = v;
+ if (when()&(FL_WHEN_CHANGED|FL_WHEN_RELEASE)) {
+ if (changed() || when()&FL_WHEN_NOT_CHANGED) {
+ if (value_ && value_->callback_) value_->do_callback((Fl_Widget*)this);
+ else do_callback();
+ }
+ }
+ }
+ return v;
+}
+
+// turn on one of a set of radio buttons
+void Fl_Menu_Item::setonly() {
+ flags |= FL_MENU_RADIO | FL_MENU_VALUE;
+ Fl_Menu_Item* j;
+ for (j = this; ; ) { // go down
+ if (j->flags & FL_MENU_DIVIDER) break; // stop on divider lines
+ j++;
+ if (!j->text || !j->radio()) break; // stop after group
+ j->clear();
+ }
+ for (j = this-1; ; j--) { // go up
+ if (!j->text || (j->flags&FL_MENU_DIVIDER) || !j->radio()) break;
+ j->clear();
+ }
+}
+
+Fl_Menu_::Fl_Menu_(int X,int Y,int W,int H,const char* l)
+: Fl_Widget(X,Y,W,H,l) {
+ set_flag(SHORTCUT_LABEL);
+ box(FL_UP_BOX);
+ when(FL_WHEN_RELEASE_ALWAYS);
+ value_ = menu_ = 0;
+ alloc = 0;
+ selection_color(FL_SELECTION_COLOR);
+ textfont(FL_HELVETICA);
+ textsize((uchar)FL_NORMAL_SIZE);
+ textcolor(FL_FOREGROUND_COLOR);
+ down_box(FL_NO_BOX);
+}
+
+int Fl_Menu_::size() const {
+ if (!menu_) return 0;
+ return menu_->size();
+}
+
+void Fl_Menu_::menu(const Fl_Menu_Item* m) {
+ clear();
+ value_ = menu_ = (Fl_Menu_Item*)m;
+}
+
+// this version is ok with new Fl_Menu_add code with fl_menu_array_owner:
+
+void Fl_Menu_::copy(const Fl_Menu_Item* m, void* ud) {
+ int n = m->size();
+ Fl_Menu_Item* newMenu = new Fl_Menu_Item[n];
+ memcpy(newMenu, m, n*sizeof(Fl_Menu_Item));
+ menu(newMenu);
+ alloc = 1; // make destructor free array, but not strings
+ // for convienence, provide way to change all the user data pointers:
+ if (ud) for (; n--;) {
+ if (newMenu->callback_) newMenu->user_data_ = ud;
+ newMenu++;
+ }
+}
+
+Fl_Menu_::~Fl_Menu_() {
+ clear();
+}
+
+// Fl_Menu::add() uses this to indicate the owner of the dynamically-
+// expanding array. We must not free this array:
+Fl_Menu_* fl_menu_array_owner = 0;
+
+void Fl_Menu_::clear() {
+ if (alloc) {
+ if (alloc>1) for (int i = size(); i--;)
+ if (menu_[i].text) free((void*)menu_[i].text);
+ if (this == fl_menu_array_owner)
+ fl_menu_array_owner = 0;
+ else
+ delete[] menu_;
+ menu_ = 0;
+ value_ = 0;
+ alloc = 0;
+ }
+}
+
+//
+// End of "$Id: Fl_Menu_.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Menu_Bar.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Menu_Bar.cxx new file mode 100644 index 0000000..d8bba77 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Menu_Bar.cxx @@ -0,0 +1,78 @@ +//
+// "$Id: Fl_Menu_Bar.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Menu bar widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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_Menu_Bar.H>
+#include <FL/fl_draw.H>
+
+void Fl_Menu_Bar::draw() {
+ draw_box();
+ if (!menu() || !menu()->text) return;
+ const Fl_Menu_Item* m;
+ int X = x()+6;
+ for (m=menu()->first(); m->text; m = m->next()) {
+ int W = m->measure(0,this) + 16;
+ m->draw(X, y(), W, h(), this);
+ X += W;
+ if (m->flags & FL_MENU_DIVIDER) {
+ int y1 = y() + Fl::box_dy(box());
+ int y2 = y1 + h() - Fl::box_dh(box()) - 1;
+
+ // Draw a vertical divider between menus...
+ fl_color(FL_DARK3);
+ fl_yxline(X - 6, y1, y2);
+ fl_color(FL_LIGHT3);
+ fl_yxline(X - 5, y1, y2);
+ }
+ }
+}
+
+int Fl_Menu_Bar::handle(int event) {
+ const Fl_Menu_Item* v;
+ if (menu() && menu()->text) switch (event) {
+ case FL_ENTER:
+ case FL_LEAVE:
+ return 1;
+ case FL_PUSH:
+ v = 0;
+ J1:
+ v = menu()->pulldown(x(), y(), w(), h(), v, this, 0, 1);
+ picked(v);
+ return 1;
+ case FL_SHORTCUT:
+ if (visible_r()) {
+ v = menu()->find_shortcut();
+ if (v && v->submenu()) goto J1;
+ }
+ return test_shortcut() != 0;
+ }
+ return 0;
+}
+
+//
+// End of "$Id: Fl_Menu_Bar.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Menu_Button.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Menu_Button.cxx new file mode 100644 index 0000000..3097434 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Menu_Button.cxx @@ -0,0 +1,111 @@ +//
+// "$Id: Fl_Menu_Button.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Menu button widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2006 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_Menu_Button.H>
+#include <FL/fl_draw.H>
+
+
+static Fl_Menu_Button *pressed_menu_button_ = 0;
+
+void Fl_Menu_Button::draw() {
+ if (!box() || type()) return;
+ draw_box(pressed_menu_button_ == this ? fl_down(box()) : box(), color());
+ draw_label();
+ if (Fl::focus() == this) draw_focus();
+ if (box() == FL_FLAT_BOX) return; // for XForms compatability
+ int H = (labelsize()-3)&-2;
+ int X = x()+w()-H*2;
+ int Y = y()+(h()-H)/2;
+ fl_color(active_r() ? FL_DARK3 : fl_inactive(FL_DARK3));
+ fl_line(X+H/2, Y+H, X, Y, X+H, Y);
+ fl_color(active_r() ? FL_LIGHT3 : fl_inactive(FL_LIGHT3));
+ fl_line(X+H, Y, X+H/2, Y+H);
+}
+
+const Fl_Menu_Item* Fl_Menu_Button::popup() {
+ const Fl_Menu_Item* m;
+ pressed_menu_button_ = this;
+ redraw();
+ Fl_Widget *mb = this;
+ Fl::watch_widget_pointer(mb);
+ if (!box() || type()) {
+ m = menu()->popup(Fl::event_x(), Fl::event_y(), label(), mvalue(), this);
+ } else {
+ m = menu()->pulldown(x(), y(), w(), h(), 0, this);
+ }
+ picked(m);
+ pressed_menu_button_ = 0;
+ if (mb) mb->redraw();
+ Fl::release_widget_pointer(mb);
+ return m;
+}
+
+int Fl_Menu_Button::handle(int e) {
+ if (!menu() || !menu()->text) return 0;
+ switch (e) {
+ case FL_ENTER:
+ case FL_LEAVE:
+ return (box() && !type()) ? 1 : 0;
+ case FL_PUSH:
+ if (!box()) {
+ if (Fl::event_button() != 3) return 0;
+ } else if (type()) {
+ if (!(type() & (1 << (Fl::event_button()-1)))) return 0;
+ }
+ if (Fl::visible_focus()) Fl::focus(this);
+ popup();
+ return 1;
+ case FL_KEYBOARD:
+ if (!box()) return 0;
+ if (Fl::event_key() == ' ' &&
+ !(Fl::event_state() & (FL_SHIFT | FL_CTRL | FL_ALT | FL_META))) {
+ popup();
+ return 1;
+ } else return 0;
+ case FL_SHORTCUT:
+ if (Fl_Widget::test_shortcut()) {popup(); return 1;}
+ return test_shortcut() != 0;
+ case FL_FOCUS:
+ case FL_UNFOCUS:
+ if (box() && Fl::visible_focus()) {
+ redraw();
+ return 1;
+ }
+ default:
+ return 0;
+ }
+}
+
+Fl_Menu_Button::Fl_Menu_Button(int X,int Y,int W,int H,const char *l)
+: Fl_Menu_(X,Y,W,H,l) {
+ down_box(FL_NO_BOX);
+}
+
+//
+// End of "$Id: Fl_Menu_Button.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Menu_Window.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Menu_Window.cxx new file mode 100644 index 0000000..e89ae28 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Menu_Window.cxx @@ -0,0 +1,103 @@ +//
+// "$Id: Fl_Menu_Window.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Menu window code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// This is the window type used by Fl_Menu to make the pop-ups.
+// It draws in the overlay planes if possible.
+
+// Also here is the implementation of the mouse & keyboard grab,
+// which are used so that clicks outside the program's windows
+// can be used to dismiss the menus.
+
+#include <config.h>
+#include <FL/Fl.H>
+#include <FL/x.H>
+#include <FL/fl_draw.H>
+#include <FL/Fl_Menu_Window.H>
+
+// WIN32 note: HAVE_OVERLAY is false
+#if HAVE_OVERLAY
+extern XVisualInfo *fl_find_overlay_visual();
+extern XVisualInfo *fl_overlay_visual;
+extern Colormap fl_overlay_colormap;
+extern unsigned long fl_transparent_pixel;
+static GC gc; // the GC used by all X windows
+extern uchar fl_overlay; // changes how fl_color(x) works
+#endif
+
+#include <stdio.h>
+
+void Fl_Menu_Window::show() {
+#if HAVE_OVERLAY
+ if (!shown() && overlay() && fl_find_overlay_visual()) {
+ XInstallColormap(fl_display, fl_overlay_colormap);
+ fl_background_pixel = int(fl_transparent_pixel);
+ Fl_X::make_xid(this, fl_overlay_visual, fl_overlay_colormap);
+ fl_background_pixel = -1;
+ } else
+#endif
+ Fl_Single_Window::show();
+}
+
+void Fl_Menu_Window::flush() {
+#if HAVE_OVERLAY
+ if (!fl_overlay_visual || !overlay()) {Fl_Single_Window::flush(); return;}
+ Fl_X *myi = Fl_X::i(this);
+ fl_window = myi->xid;
+ if (!gc) gc = XCreateGC(fl_display, myi->xid, 0, 0);
+ fl_gc = gc;
+ fl_overlay = 1;
+ fl_clip_region(myi->region); myi->region = 0; current_ = this;
+ draw();
+ fl_overlay = 0;
+#else
+ Fl_Single_Window::flush();
+#endif
+}
+
+void Fl_Menu_Window::erase() {
+#if HAVE_OVERLAY
+ if (!gc || !shown()) return;
+//XSetForeground(fl_display, gc, 0);
+//XFillRectangle(fl_display, fl_xid(this), gc, 0, 0, w(), h());
+ XClearWindow(fl_display, fl_xid(this));
+#endif
+}
+
+// Fix the colormap flashing on Maximum Impact Graphics by erasing the
+// menu before unmapping it:
+void Fl_Menu_Window::hide() {
+ erase();
+ Fl_Single_Window::hide();
+}
+
+Fl_Menu_Window::~Fl_Menu_Window() {
+ hide();
+}
+
+//
+// End of "$Id: Fl_Menu_Window.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Menu_add.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Menu_add.cxx new file mode 100644 index 0000000..2b046e6 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Menu_add.cxx @@ -0,0 +1,268 @@ +//
+// "$Id: Fl_Menu_add.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Menu utilities for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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 the program only uses
+// constant menu tables.
+
+// Not at all guaranteed to be Forms compatable, 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* insert(
+ Fl_Menu_Item* array, int size,
+ int n,
+ const char *text,
+ int flags
+) {
+ 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->labelfont_ = m->labelsize_ = m->labelcolor_ = 0;
+ 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;
+ }
+ }
+}
+
+// Add 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
+) {
+ 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 assumme 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 */
+ 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 = m-array;
+ array = insert(array, msize, n, item, FL_SUBMENU|flags1);
+ msize++;
+ 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 = m-array;
+ array = insert(array, msize, n, item, myflags|flags1);
+ msize++;
+ if (myflags & FL_SUBMENU) { // add submenu delimiter
+ 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;
+}
+
+int Fl_Menu_::add(const char *t, int s, Fl_Callback *c,void *v,int f) {
+ // 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_->add(t,s,c,v,f);
+ // 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) compatable add function, it
+// adds many menu items, with '|' seperating the menu items, and tab
+// seperating the menu item names from an optional shortcut string.
+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;
+}
+
+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;
+}
+
+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 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Menu_global.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Menu_global.cxx new file mode 100644 index 0000000..3238fad --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Menu_global.cxx @@ -0,0 +1,50 @@ +//
+// "$Id: Fl_Menu_global.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Global menu shortcut code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Make all the shortcuts in this menu global.
+// Currently only one menu at a time and you cannot destruct the menu,
+// is this sufficient?
+
+#include <FL/Fl.H>
+#include <FL/Fl_Menu_.H>
+
+static Fl_Menu_* the_widget;
+
+static int handler(int e) {
+ if (e != FL_SHORTCUT || Fl::modal()) return 0;
+ Fl::first_window(the_widget->window());
+ return the_widget->handle(e);
+}
+
+void Fl_Menu_::global() {
+ if (!the_widget) Fl::add_handler(handler);
+ the_widget = this;
+}
+
+//
+// End of "$Id: Fl_Menu_global.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Multi_Label.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Multi_Label.cxx new file mode 100644 index 0000000..eafe3c8 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Multi_Label.cxx @@ -0,0 +1,80 @@ +//
+// "$Id: Fl_Multi_Label.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Multi-label widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Allows two labels to be used on a widget (by having one of them
+// be one of these it allows an infinte number!)
+
+#include <FL/Fl.H>
+#include <FL/Fl_Widget.H>
+#include <FL/Fl_Menu_Item.H>
+#include <FL/Fl_Multi_Label.H>
+
+static void multi_labeltype(
+ const Fl_Label* o, int x, int y, int w, int h, Fl_Align a)
+{
+ Fl_Multi_Label* b = (Fl_Multi_Label*)(o->value);
+ Fl_Label local = *o;
+ local.value = b->labela;
+ local.type = b->typea;
+ int W = w; int H = h; local.measure(W, H);
+ local.draw(x,y,w,h,a);
+ if (a & FL_ALIGN_BOTTOM) h -= H;
+ else if (a & FL_ALIGN_TOP) {y += H; h -= H;}
+ else if (a & FL_ALIGN_RIGHT) w -= W;
+ else if (a & FL_ALIGN_LEFT) {x += W; w -= W;}
+ else {int d = (h+H)/2; y += d; h -= d;}
+ local.value = b->labelb;
+ local.type = b->typeb;
+ local.draw(x,y,w,h,a);
+}
+
+// measurement is only correct for left-to-right appending...
+static void multi_measure(const Fl_Label* o, int& w, int& h) {
+ Fl_Multi_Label* b = (Fl_Multi_Label*)(o->value);
+ Fl_Label local = *o;
+ local.value = b->labela;
+ local.type = b->typea;
+ local.measure(w,h);
+ local.value = b->labelb;
+ local.type = b->typeb;
+ int W = 0; int H = 0; local.measure(W,H);
+ w += W; if (H>h) h = H;
+}
+
+void Fl_Multi_Label::label(Fl_Widget* o) {
+ Fl::set_labeltype(_FL_MULTI_LABEL, multi_labeltype, multi_measure);
+ o->label(_FL_MULTI_LABEL, (const char*)this);
+}
+
+void Fl_Multi_Label::label(Fl_Menu_Item* o) {
+ Fl::set_labeltype(_FL_MULTI_LABEL, multi_labeltype, multi_measure);
+ o->label(_FL_MULTI_LABEL, (const char*)this);
+}
+
+//
+// End of "$Id: Fl_Multi_Label.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Overlay_Window.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Overlay_Window.cxx new file mode 100644 index 0000000..8d31a5d --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Overlay_Window.cxx @@ -0,0 +1,155 @@ +//
+// "$Id: Fl_Overlay_Window.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Overlay window code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// A window using double-buffering and able to draw an overlay
+// on top of that. Uses the hardware to draw the overlay if
+// possible, otherwise it just draws in the front buffer.
+
+#include <config.h>
+#include <FL/Fl.H>
+#include <FL/Fl_Overlay_Window.H>
+#include <FL/fl_draw.H>
+#include <FL/x.H>
+
+void Fl_Overlay_Window::show() {
+ Fl_Double_Window::show();
+ if (overlay_ && overlay_ != this) overlay_->show();
+}
+
+void Fl_Overlay_Window::hide() {
+ Fl_Double_Window::hide();
+}
+
+void Fl_Overlay_Window::flush() {
+#ifdef BOXX_BUGS
+ if (overlay_ && overlay_ != this && overlay_->shown()) {
+ // all drawing to windows hidden by overlay windows is ignored, fix this
+ XUnmapWindow(fl_display, fl_xid(overlay_));
+ Fl_Double_Window::flush(0);
+ XMapWindow(fl_display, fl_xid(overlay_));
+ return;
+ }
+#endif
+ int erase_overlay = (damage()&FL_DAMAGE_OVERLAY);
+ clear_damage((uchar)(damage()&~FL_DAMAGE_OVERLAY));
+ Fl_Double_Window::flush(erase_overlay);
+ if (overlay_ == this) draw_overlay();
+}
+
+void Fl_Overlay_Window::resize(int X, int Y, int W, int H) {
+ Fl_Double_Window::resize(X,Y,W,H);
+ if (overlay_ && overlay_!=this) overlay_->resize(0,0,w(),h());
+}
+
+Fl_Overlay_Window::~Fl_Overlay_Window() {
+ hide();
+// delete overlay; this is done by ~Fl_Group
+}
+
+#if !HAVE_OVERLAY
+
+int Fl_Overlay_Window::can_do_overlay() {return 0;}
+
+void Fl_Overlay_Window::redraw_overlay() {
+ overlay_ = this;
+ clear_damage((uchar)(damage()|FL_DAMAGE_OVERLAY));
+ Fl::damage(FL_DAMAGE_CHILD);
+}
+
+#else
+
+extern XVisualInfo *fl_find_overlay_visual();
+extern XVisualInfo *fl_overlay_visual;
+extern Colormap fl_overlay_colormap;
+extern unsigned long fl_transparent_pixel;
+static GC gc; // the GC used by all X windows
+extern uchar fl_overlay; // changes how fl_color(x) works
+
+class _Fl_Overlay : public Fl_Window {
+ friend class Fl_Overlay_Window;
+ void flush();
+ void show();
+public:
+ _Fl_Overlay(int x, int y, int w, int h) :
+ Fl_Window(x,y,w,h) {set_flag(INACTIVE);}
+};
+
+int Fl_Overlay_Window::can_do_overlay() {
+ return fl_find_overlay_visual() != 0;
+}
+
+void _Fl_Overlay::show() {
+ if (shown()) {Fl_Window::show(); return;}
+ fl_background_pixel = int(fl_transparent_pixel);
+ Fl_X::make_xid(this, fl_overlay_visual, fl_overlay_colormap);
+ fl_background_pixel = -1;
+ // find the outermost window to tell wm about the colormap:
+ Fl_Window *w = window();
+ for (;;) {Fl_Window *w1 = w->window(); if (!w1) break; w = w1;}
+ XSetWMColormapWindows(fl_display, fl_xid(w), &(Fl_X::i(this)->xid), 1);
+}
+
+void _Fl_Overlay::flush() {
+ fl_window = fl_xid(this);
+ if (!gc) gc = XCreateGC(fl_display, fl_xid(this), 0, 0);
+ fl_gc = gc;
+ fl_overlay = 1;
+ Fl_Overlay_Window *w = (Fl_Overlay_Window *)parent();
+ Fl_X *myi = Fl_X::i(this);
+ if (damage() != FL_DAMAGE_EXPOSE) XClearWindow(fl_display, fl_xid(this));
+ fl_clip_region(myi->region); myi->region = 0;
+ w->draw_overlay();
+ fl_overlay = 0;
+}
+
+void Fl_Overlay_Window::redraw_overlay() {
+ if (!fl_display) return; // this prevents fluid -c from opening display
+ if (!overlay_) {
+ if (can_do_overlay()) {
+ Fl_Group::current(this);
+ overlay_ = new _Fl_Overlay(0,0,w(),h());
+ Fl_Group::current(0);
+ } else {
+ overlay_ = this; // fake the overlay
+ }
+ }
+ if (shown()) {
+ if (overlay_ == this) {
+ clear_damage(damage()|FL_DAMAGE_OVERLAY);
+ Fl::damage(FL_DAMAGE_CHILD);
+ } else if (!overlay_->shown())
+ overlay_->show();
+ else
+ overlay_->redraw();
+ }
+}
+
+#endif
+
+//
+// End of "$Id: Fl_Overlay_Window.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_PNG_Image.cxx b/third_party/windows/fltk-1.1.10/src/Fl_PNG_Image.cxx new file mode 100644 index 0000000..fa1deb4 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_PNG_Image.cxx @@ -0,0 +1,155 @@ +//
+// "$Id: Fl_PNG_Image.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Fl_PNG_Image routines.
+//
+// Copyright 1997-2005 by Easy Software Products.
+// Image support donated by Matthias Melcher, Copyright 2000.
+//
+// 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
+//
+// Contents:
+//
+// Fl_PNG_Image::Fl_PNG_Image() - Load a PNG image file.
+//
+
+//
+// Include necessary header files...
+//
+
+#include <FL/Fl.H>
+#include <FL/Fl_PNG_Image.H>
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+extern "C"
+{
+#if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ)
+# include <zlib.h>
+# ifdef HAVE_PNG_H
+# include <png.h>
+# else
+# include <libpng/png.h>
+# endif // HAVE_PNG_H
+#endif // HAVE_LIBPNG && HAVE_LIBZ
+}
+
+
+//
+// 'Fl_PNG_Image::Fl_PNG_Image()' - Load a PNG image file.
+//
+
+Fl_PNG_Image::Fl_PNG_Image(const char *png) // I - File to read
+ : Fl_RGB_Image(0,0,0) {
+#if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ)
+ int i; // Looping var
+ FILE *fp; // File pointer
+ int channels; // Number of color channels
+ png_structp pp; // PNG read pointer
+ png_infop info; // PNG info pointers
+ png_bytep *rows; // PNG row pointers
+
+
+ // Open the PNG file...
+ if ((fp = fopen(png, "rb")) == NULL) return;
+
+ // Setup the PNG data structures...
+ pp = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ info = png_create_info_struct(pp);
+
+ if (setjmp(pp->jmpbuf))
+ {
+ Fl::warning("PNG file \"%s\" contains errors!\n", png);
+ return;
+ }
+
+ // Initialize the PNG read "engine"...
+ png_init_io(pp, fp);
+
+ // Get the image dimensions and convert to grayscale or RGB...
+ png_read_info(pp, info);
+
+ if (info->color_type == PNG_COLOR_TYPE_PALETTE)
+ png_set_expand(pp);
+
+ if (info->color_type & PNG_COLOR_MASK_COLOR)
+ channels = 3;
+ else
+ channels = 1;
+
+ if ((info->color_type & PNG_COLOR_MASK_ALPHA) || info->num_trans)
+ channels ++;
+
+ w((int)(info->width));
+ h((int)(info->height));
+ d(channels);
+
+ if (info->bit_depth < 8)
+ {
+ png_set_packing(pp);
+ png_set_expand(pp);
+ }
+ else if (info->bit_depth == 16)
+ png_set_strip_16(pp);
+
+# if defined(HAVE_PNG_GET_VALID) && defined(HAVE_PNG_SET_TRNS_TO_ALPHA)
+ // Handle transparency...
+ if (png_get_valid(pp, info, PNG_INFO_tRNS))
+ png_set_tRNS_to_alpha(pp);
+# endif // HAVE_PNG_GET_VALID && HAVE_PNG_SET_TRNS_TO_ALPHA
+
+ array = new uchar[w() * h() * d()];
+ alloc_array = 1;
+
+ // Allocate pointers...
+ rows = new png_bytep[h()];
+
+ for (i = 0; i < h(); i ++)
+ rows[i] = (png_bytep)(array + i * w() * d());
+
+ // Read the image, handling interlacing as needed...
+ for (i = png_set_interlace_handling(pp); i > 0; i --)
+ png_read_rows(pp, rows, NULL, h());
+
+#ifdef WIN32
+ // Some Windows graphics drivers don't honor transparency when RGB == white
+ if (channels == 4) {
+ // Convert RGB to 0 when alpha == 0...
+ uchar *ptr = (uchar *)array;
+ for (i = w() * h(); i > 0; i --, ptr += 4)
+ if (!ptr[3]) ptr[0] = ptr[1] = ptr[2] = 0;
+ }
+#endif // WIN32
+
+ // Free memory and return...
+ delete[] rows;
+
+ png_read_end(pp, info);
+ png_destroy_read_struct(&pp, &info, NULL);
+
+ fclose(fp);
+#endif // HAVE_LIBPNG && HAVE_LIBZ
+}
+
+
+//
+// End of "$Id: Fl_PNG_Image.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_PNM_Image.cxx b/third_party/windows/fltk-1.1.10/src/Fl_PNM_Image.cxx new file mode 100644 index 0000000..59bf866 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_PNM_Image.cxx @@ -0,0 +1,190 @@ +//
+// "$Id: Fl_PNM_Image.cxx 6006 2007-12-20 16:32:56Z matt $"
+//
+// Fl_PNM_Image routines.
+//
+// Copyright 1997-2005 by Easy Software Products.
+//
+// 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
+//
+// Contents:
+//
+// Fl_PNM_Image::Fl_PNM_Image() - Load a PNM image...
+//
+
+//
+// Include necessary header files...
+//
+
+#include <FL/Fl.H>
+#include <FL/Fl_PNM_Image.H>
+#include <stdio.h>
+#include <stdlib.h>
+#include "flstring.h"
+
+
+//
+// 'Fl_PNM_Image::Fl_PNM_Image()' - Load a PNM image...
+//
+
+Fl_PNM_Image::Fl_PNM_Image(const char *name) // I - File to read
+ : Fl_RGB_Image(0,0,0) {
+ FILE *fp; // File pointer
+ int x, y; // Looping vars
+ char line[1024], // Input line
+ *lineptr; // Pointer in line
+ uchar *ptr, // Pointer to pixel values
+ byte, // Byte from file
+ bit; // Bit in pixel
+ int format, // Format of PNM file
+ val, // Pixel value
+ maxval; // Maximum pixel value
+
+
+ if ((fp = fopen(name, "rb")) == NULL) return;
+
+ //
+ // Read the file header in the format:
+ //
+ // Pformat
+ // # comment1
+ // # comment2
+ // ...
+ // # commentN
+ // width
+ // height
+ // max sample
+ //
+
+ lineptr = fgets(line, sizeof(line), fp);
+ if (!lineptr) {
+ fclose(fp);
+ Fl::error("Early end-of-file in PNM file \"%s\"!", name);
+ return;
+ }
+
+ lineptr ++;
+
+ format = atoi(lineptr);
+ while (isdigit(*lineptr)) lineptr ++;
+
+ if (format == 7) lineptr = (char *)"";
+
+ while (lineptr != NULL && w() == 0) {
+ if (*lineptr == '\0' || *lineptr == '#') {
+ lineptr = fgets(line, sizeof(line), fp);
+ } else if (isdigit(*lineptr)) {
+ w(strtol(lineptr, &lineptr, 10));
+ } else lineptr ++;
+ }
+
+ while (lineptr != NULL && h() == 0) {
+ if (*lineptr == '\0' || *lineptr == '#') {
+ lineptr = fgets(line, sizeof(line), fp);
+ } else if (isdigit(*lineptr)) {
+ h(strtol(lineptr, &lineptr, 10));
+ } else lineptr ++;
+ }
+
+ if (format != 1 && format != 4) {
+ maxval = 0;
+
+ while (lineptr != NULL && maxval == 0) {
+ if (*lineptr == '\0' || *lineptr == '#') {
+ lineptr = fgets(line, sizeof(line), fp);
+ } else if (isdigit(*lineptr)) {
+ maxval = strtol(lineptr, &lineptr, 10);
+ } else lineptr ++;
+ }
+ } else maxval = 1;
+
+ // Allocate memory...
+ if (format == 1 || format == 2 || format == 4 || format == 5) d(1);
+ else d(3);
+
+// printf("%s = %dx%dx%d\n", name, w(), h(), d());
+
+ array = new uchar[w() * h() * d()];
+ alloc_array = 1;
+
+ // Read the image file...
+ for (y = 0; y < h(); y ++) {
+ ptr = (uchar *)array + y * w() * d();
+
+ switch (format) {
+ case 1 :
+ case 2 :
+ for (x = w(); x > 0; x --)
+ if (fscanf(fp, "%d", &val) == 1) *ptr++ = (uchar)(255 * val / maxval);
+ break;
+
+ case 3 :
+ for (x = w(); x > 0; x --) {
+ if (fscanf(fp, "%d", &val) == 1) *ptr++ = (uchar)(255 * val / maxval);
+ if (fscanf(fp, "%d", &val) == 1) *ptr++ = (uchar)(255 * val / maxval);
+ if (fscanf(fp, "%d", &val) == 1) *ptr++ = (uchar)(255 * val / maxval);
+ }
+ break;
+
+ case 4 :
+ for (x = w(), byte = (uchar)getc(fp), bit = 128; x > 0; x --) {
+ if (byte & bit) *ptr++ = 255;
+ else *ptr++ = 0;
+
+ if (bit > 1) bit >>= 1;
+ else {
+ bit = 128;
+ byte = (uchar)getc(fp);
+ }
+ }
+ break;
+
+ case 5 :
+ case 6 :
+ if (maxval < 256) {
+ fread(ptr, w(), d(), fp);
+ } else {
+ for (x = d() * w(); x > 0; x --) {
+ val = (uchar)getc(fp);
+ val = (val<<8)|(uchar)getc(fp);
+ *ptr++ = (255*val)/maxval;
+ }
+ }
+ break;
+
+ case 7 : /* XV 3:3:2 thumbnail format */
+ for (x = w(); x > 0; x --) {
+ byte = (uchar)getc(fp);
+
+ *ptr++ = (uchar)(255 * ((byte >> 5) & 7) / 7);
+ *ptr++ = (uchar)(255 * ((byte >> 2) & 7) / 7);
+ *ptr++ = (uchar)(255 * (byte & 3) / 3);
+ }
+ break;
+ }
+ }
+
+ fclose(fp);
+}
+
+
+//
+// End of "$Id: Fl_PNM_Image.cxx 6006 2007-12-20 16:32:56Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Pack.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Pack.cxx new file mode 100644 index 0000000..7738172 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Pack.cxx @@ -0,0 +1,147 @@ +//
+// "$Id: Fl_Pack.cxx 6868 2009-09-13 12:10:56Z AlbrechtS $"
+//
+// Packing widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2006 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
+//
+
+// Based on code by Curtis Edwards
+// Group that compresses all it's children together and resizes to surround
+// them on each redraw (only if box() is zero)
+// Bugs: ?
+
+#include <FL/Fl.H>
+#include <FL/Fl_Pack.H>
+#include <FL/fl_draw.H>
+
+Fl_Pack::Fl_Pack(int X, int Y, int W, int H,const char *l)
+: Fl_Group(X, Y, W, H, l) {
+ resizable(0);
+ spacing_ = 0;
+ // type(VERTICAL); // already set like this
+}
+
+void Fl_Pack::draw() {
+ int tx = x()+Fl::box_dx(box());
+ int ty = y()+Fl::box_dy(box());
+ int tw = w()-Fl::box_dw(box());
+ int th = h()-Fl::box_dh(box());
+ int rw, rh;
+ int current_position = horizontal() ? tx : ty;
+ int maximum_position = current_position;
+ uchar d = damage();
+ Fl_Widget*const* a = array();
+ if (horizontal()) {
+ rw = -spacing_;
+ rh = th;
+
+ for (int i = children(); i--;)
+ if (child(i)->visible()) {
+ if (child(i) != this->resizable()) rw += child(i)->w();
+ rw += spacing_;
+ }
+ } else {
+ rw = tw;
+ rh = -spacing_;
+
+ for (int i = children(); i--;)
+ if (child(i)->visible()) {
+ if (child(i) != this->resizable()) rh += child(i)->h();
+ rh += spacing_;
+ }
+ }
+ for (int i = children(); i--;) {
+ Fl_Widget* o = *a++;
+ if (o->visible()) {
+ int X,Y,W,H;
+ if (horizontal()) {
+ X = current_position;
+ W = o->w();
+ Y = ty;
+ H = th;
+ } else {
+ X = tx;
+ W = tw;
+ Y = current_position;
+ H = o->h();
+ }
+ // Last child, if resizable, takes all remaining room
+ if(i == 0 && o == this->resizable()) {
+ if(horizontal())
+ W = tw - rw;
+ else
+ H = th - rh;
+ }
+ if (spacing_ && current_position>maximum_position && box() &&
+ (X != o->x() || Y != o->y() || d&FL_DAMAGE_ALL)) {
+ fl_color(color());
+ if (horizontal())
+ fl_rectf(maximum_position, ty, spacing_, th);
+ else
+ fl_rectf(tx, maximum_position, tw, spacing_);
+ }
+ if (X != o->x() || Y != o->y() || W != o->w() || H != o->h()) {
+ o->resize(X,Y,W,H);
+ o->clear_damage(FL_DAMAGE_ALL);
+ }
+ if (d&FL_DAMAGE_ALL) {
+ draw_child(*o);
+ draw_outside_label(*o);
+ } else update_child(*o);
+ // child's draw() can change it's size, so use new size:
+ current_position += (horizontal() ? o->w() : o->h());
+ if (current_position > maximum_position)
+ maximum_position = current_position;
+ current_position += spacing_;
+ }
+ }
+
+ if (horizontal()) {
+ if (maximum_position < tx+tw && box()) {
+ fl_color(color());
+ fl_rectf(maximum_position, ty, tx+tw-maximum_position, th);
+ }
+ tw = maximum_position-tx;
+ } else {
+ if (maximum_position < ty+th && box()) {
+ fl_color(color());
+ fl_rectf(tx, maximum_position, tw, ty+th-maximum_position);
+ }
+ th = maximum_position-ty;
+ }
+
+ tw += Fl::box_dw(box()); if (tw <= 0) tw = 1;
+ th += Fl::box_dh(box()); if (th <= 0) th = 1;
+ if (tw != w() || th != h()) {
+ Fl_Widget::resize(x(),y(),tw,th);
+ d = FL_DAMAGE_ALL;
+ }
+ if (d&FL_DAMAGE_ALL) {
+ draw_box();
+ draw_label();
+ }
+}
+
+//
+// End of "$Id: Fl_Pack.cxx 6868 2009-09-13 12:10:56Z AlbrechtS $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Pixmap.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Pixmap.cxx new file mode 100644 index 0000000..86e86fa --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Pixmap.cxx @@ -0,0 +1,495 @@ +//
+// "$Id: Fl_Pixmap.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Pixmap drawing code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Draws X pixmap data, keeping it stashed in a server pixmap so it
+// redraws fast.
+
+// See fl_draw_pixmap.cxx for code used to get the actual data into pixmap.
+// Implemented without using the xpm library (which I can't use because
+// it interferes with the color cube used by fl_draw_image).
+
+#include <FL/Fl.H>
+#include <FL/fl_draw.H>
+#include <FL/x.H>
+#include <FL/Fl_Widget.H>
+#include <FL/Fl_Menu_Item.H>
+#include <FL/Fl_Pixmap.H>
+
+#include <stdio.h>
+#include "flstring.h"
+#include <ctype.h>
+
+#ifdef WIN32
+extern void fl_release_dc(HWND, HDC); // located in Fl_win32.cxx
+#endif
+
+#ifdef __APPLE_QUARTZ__
+extern Fl_Offscreen fl_create_offscreen_with_alpha(int w, int h);
+#endif
+
+extern uchar **fl_mask_bitmap; // used by fl_draw_pixmap.cxx to store mask
+void fl_restore_clip(); // in fl_rect.cxx
+
+void Fl_Pixmap::measure() {
+ int W, H;
+
+ // ignore empty or bad pixmap data:
+ if (w()<0 && data()) {
+ fl_measure_pixmap(data(), W, H);
+ w(W); h(H);
+ }
+}
+
+void Fl_Pixmap::draw(int XP, int YP, int WP, int HP, int cx, int cy) {
+ // ignore empty or bad pixmap data:
+ if (!data()) {
+ draw_empty(XP, YP);
+ return;
+ }
+ if (w()<0) measure();
+ if (WP==-1) {
+ WP = w();
+ HP = h();
+ }
+ if (!w()) {
+ draw_empty(XP, YP);
+ return;
+ }
+ // account for current clip region (faster on Irix):
+ int X,Y,W,H; fl_clip_box(XP,YP,WP,HP,X,Y,W,H);
+ cx += X-XP; cy += Y-YP;
+ // clip the box down to the size of image, quit if empty:
+ if (cx < 0) {W += cx; X -= cx; cx = 0;}
+ if (cx+W > w()) W = w()-cx;
+ if (W <= 0) return;
+ if (cy < 0) {H += cy; Y -= cy; cy = 0;}
+ if (cy+H > h()) H = h()-cy;
+ if (H <= 0) return;
+ if (!id) {
+#ifdef __APPLE_QUARTZ__
+ id = fl_create_offscreen_with_alpha(w(), h());
+ fl_begin_offscreen((Fl_Offscreen)id);
+ fl_draw_pixmap(data(), 0, 0, FL_GREEN);
+ fl_end_offscreen();
+#else
+ id = fl_create_offscreen(w(), h());
+ fl_begin_offscreen((Fl_Offscreen)id);
+ uchar *bitmap = 0;
+ fl_mask_bitmap = &bitmap;
+ fl_draw_pixmap(data(), 0, 0, FL_BLACK);
+ fl_mask_bitmap = 0;
+ if (bitmap) {
+ mask = fl_create_bitmask(w(), h(), bitmap);
+ delete[] bitmap;
+ }
+ fl_end_offscreen();
+#endif
+ }
+#ifdef WIN32
+ if (mask) {
+ HDC new_gc = CreateCompatibleDC(fl_gc);
+ int save = SaveDC(new_gc);
+ SelectObject(new_gc, (void*)mask);
+ BitBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, SRCAND);
+ SelectObject(new_gc, (void*)id);
+ BitBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, SRCPAINT);
+ RestoreDC(new_gc,save);
+ DeleteDC(new_gc);
+ } else {
+ fl_copy_offscreen(X, Y, W, H, (Fl_Offscreen)id, cx, cy);
+ }
+#elif defined(__APPLE_QD__)
+ if (mask) {
+ Rect src, dst;
+ src.left = cx; src.right = cx+W;
+ src.top = cy; src.bottom = cy+H;
+ dst.left = X; dst.right = X+W;
+ dst.top = Y; dst.bottom = Y+H;
+ RGBColor rgb, oldfg, oldbg;
+ GetForeColor(&oldfg);
+ GetBackColor(&oldbg);
+ rgb.red = 0xffff; rgb.green = 0xffff; rgb.blue = 0xffff;
+ RGBBackColor(&rgb);
+ rgb.red = 0x0000; rgb.green = 0x0000; rgb.blue = 0x0000;
+ RGBForeColor(&rgb);
+ CopyMask(GetPortBitMapForCopyBits((GrafPtr)id),
+ GetPortBitMapForCopyBits((GrafPtr)mask),
+ GetPortBitMapForCopyBits(GetWindowPort(fl_window)),
+ &src, &src, &dst);
+ RGBBackColor(&oldbg);
+ RGBForeColor(&oldfg);
+ } else {
+ fl_copy_offscreen(X, Y, W, H, (Fl_Offscreen)id, cx, cy);
+ }
+#elif defined(__APPLE_QUARTZ__)
+ fl_copy_offscreen(X, Y, W, H, (Fl_Offscreen)id, cx, cy);
+#else
+ if (mask) {
+ // I can't figure out how to combine a mask with existing region,
+ // so cut the image down to a clipped rectangle:
+ int nx, ny; fl_clip_box(X,Y,W,H,nx,ny,W,H);
+ cx += nx-X; X = nx;
+ cy += ny-Y; Y = ny;
+ // make X use the bitmap as a mask:
+ XSetClipMask(fl_display, fl_gc, mask);
+ int ox = X-cx; if (ox < 0) ox += w();
+ int oy = Y-cy; if (oy < 0) oy += h();
+ XSetClipOrigin(fl_display, fl_gc, X-cx, Y-cy);
+ }
+ fl_copy_offscreen(X, Y, W, H, id, cx, cy);
+ if (mask) {
+ // put the old clip region back
+ XSetClipOrigin(fl_display, fl_gc, 0, 0);
+ fl_restore_clip();
+ }
+#endif
+}
+
+Fl_Pixmap::~Fl_Pixmap() {
+ uncache();
+ delete_data();
+}
+
+void Fl_Pixmap::uncache() {
+ if (id) {
+ fl_delete_offscreen((Fl_Offscreen)id);
+ id = 0;
+ }
+
+ if (mask) {
+ fl_delete_bitmask((Fl_Bitmask)mask);
+ mask = 0;
+ }
+}
+
+void Fl_Pixmap::label(Fl_Widget* widget) {
+ widget->image(this);
+}
+
+void Fl_Pixmap::label(Fl_Menu_Item* m) {
+ Fl::set_labeltype(_FL_IMAGE_LABEL, labeltype, Fl_Image::measure);
+ m->label(_FL_IMAGE_LABEL, (const char*)this);
+}
+
+void Fl_Pixmap::copy_data() {
+ if (alloc_data) return;
+
+ char **new_data, // New data array
+ **new_row; // Current row in image
+ int i, // Looping var
+ ncolors, // Number of colors in image
+ chars_per_pixel,// Characters per color
+ chars_per_line; // Characters per line
+
+ // Figure out how many colors there are, and how big they are...
+ sscanf(data()[0],"%*d%*d%d%d", &ncolors, &chars_per_pixel);
+ chars_per_line = chars_per_pixel * w() + 1;
+
+ // Allocate memory for the new array...
+ if (ncolors < 0) new_data = new char *[h() + 2];
+ else new_data = new char *[h() + ncolors + 1];
+
+ new_data[0] = new char[strlen(data()[0]) + 1];
+ strcpy(new_data[0], data()[0]);
+
+ // Copy colors...
+ if (ncolors < 0) {
+ // Copy FLTK colormap values...
+ ncolors = -ncolors;
+ new_row = new_data + 1;
+ *new_row = new char[ncolors * 4];
+ memcpy(*new_row, data()[1], ncolors * 4);
+ ncolors = 1;
+ new_row ++;
+ } else {
+ // Copy standard XPM colormap values...
+ for (i = 0, new_row = new_data + 1; i < ncolors; i ++, new_row ++) {
+ *new_row = new char[strlen(data()[i + 1]) + 1];
+ strcpy(*new_row, data()[i + 1]);
+ }
+ }
+
+ // Copy image data...
+ for (i = 0; i < h(); i ++, new_row ++) {
+ *new_row = new char[chars_per_line];
+ memcpy(*new_row, data()[i + ncolors + 1], chars_per_line);
+ }
+
+ // Update pointers...
+ data((const char **)new_data, h() + ncolors + 1);
+ alloc_data = 1;
+}
+
+Fl_Image *Fl_Pixmap::copy(int W, int H) {
+ Fl_Pixmap *new_image; // New pixmap
+
+ // Optimize the simple copy where the width and height are the same...
+ if (W == w() && H == h()) {
+ // Make an exact copy of the image and return it...
+ new_image = new Fl_Pixmap(data());
+ new_image->copy_data();
+ return new_image;
+ }
+ if (W <= 0 || H <= 0) return 0;
+
+ // OK, need to resize the image data; allocate memory and
+ char **new_data, // New array for image data
+ **new_row, // Pointer to row in image data
+ *new_ptr, // Pointer into new array
+ new_info[255]; // New information line
+ const char *old_ptr; // Pointer into old array
+ int i, // Looping var
+ c, // Channel number
+ sy, // Source coordinate
+ dx, dy, // Destination coordinates
+ xerr, yerr, // X & Y errors
+ xmod, ymod, // X & Y moduli
+ xstep, ystep; // X & Y step increments
+ int ncolors, // Number of colors in image
+ chars_per_pixel,// Characters per color
+ chars_per_line; // Characters per line
+
+ // Figure out how many colors there are, and how big they are...
+ sscanf(data()[0],"%*d%*d%d%d", &ncolors, &chars_per_pixel);
+ chars_per_line = chars_per_pixel * W + 1;
+
+ sprintf(new_info, "%d %d %d %d", W, H, ncolors, chars_per_pixel);
+
+ // Figure out Bresenheim step/modulus values...
+ xmod = w() % W;
+ xstep = (w() / W) * chars_per_pixel;
+ ymod = h() % H;
+ ystep = h() / H;
+
+ // Allocate memory for the new array...
+ if (ncolors < 0) new_data = new char *[H + 2];
+ else new_data = new char *[H + ncolors + 1];
+ new_data[0] = new char[strlen(new_info) + 1];
+ strcpy(new_data[0], new_info);
+
+ // Copy colors...
+ if (ncolors < 0) {
+ // Copy FLTK colormap values...
+ ncolors = -ncolors;
+ new_row = new_data + 1;
+ *new_row = new char[ncolors * 4];
+ memcpy(*new_row, data()[1], ncolors * 4);
+ ncolors = 1;
+ new_row ++;
+ } else {
+ // Copy standard XPM colormap values...
+ for (i = 0, new_row = new_data + 1; i < ncolors; i ++, new_row ++) {
+ *new_row = new char[strlen(data()[i + 1]) + 1];
+ strcpy(*new_row, data()[i + 1]);
+ }
+ }
+
+ // Scale the image using a nearest-neighbor algorithm...
+ for (dy = H, sy = 0, yerr = H; dy > 0; dy --, new_row ++) {
+ *new_row = new char[chars_per_line];
+ new_ptr = *new_row;
+
+ for (dx = W, xerr = W, old_ptr = data()[sy + ncolors + 1];
+ dx > 0;
+ dx --) {
+ for (c = 0; c < chars_per_pixel; c ++) *new_ptr++ = old_ptr[c];
+
+ old_ptr += xstep;
+ xerr -= xmod;
+
+ if (xerr <= 0) {
+ xerr += W;
+ old_ptr += chars_per_pixel;
+ }
+ }
+
+ *new_ptr = '\0';
+ sy += ystep;
+ yerr -= ymod;
+ if (yerr <= 0) {
+ yerr += H;
+ sy ++;
+ }
+ }
+
+ new_image = new Fl_Pixmap((char*const*)new_data);
+ new_image->alloc_data = 1;
+
+ return new_image;
+}
+
+void Fl_Pixmap::color_average(Fl_Color c, float i) {
+ // Delete any existing pixmap/mask objects...
+ uncache();
+
+ // Allocate memory as needed...
+ copy_data();
+
+ // Get the color to blend with...
+ uchar r, g, b;
+ unsigned ia, ir, ig, ib;
+
+ Fl::get_color(c, r, g, b);
+ if (i < 0.0f) i = 0.0f;
+ else if (i > 1.0f) i = 1.0f;
+
+ ia = (unsigned)(256 * i);
+ ir = r * (256 - ia);
+ ig = g * (256 - ia);
+ ib = b * (256 - ia);
+
+ // Update the colormap to do the blend...
+ char line[255]; // New colormap line
+ int color, // Looping var
+ ncolors, // Number of colors in image
+ chars_per_pixel;// Characters per color
+
+
+ sscanf(data()[0],"%*d%*d%d%d", &ncolors, &chars_per_pixel);
+
+ if (ncolors < 0) {
+ // Update FLTK colormap...
+ ncolors = -ncolors;
+ uchar *cmap = (uchar *)(data()[1]);
+ for (color = 0; color < ncolors; color ++, cmap += 4) {
+ cmap[1] = (ia * cmap[1] + ir) >> 8;
+ cmap[2] = (ia * cmap[2] + ig) >> 8;
+ cmap[3] = (ia * cmap[3] + ib) >> 8;
+ }
+ } else {
+ // Update standard XPM colormap...
+ for (color = 0; color < ncolors; color ++) {
+ // look for "c word", or last word if none:
+ const char *p = data()[color + 1] + chars_per_pixel + 1;
+ const char *previous_word = p;
+ for (;;) {
+ while (*p && isspace(*p)) p++;
+ char what = *p++;
+ while (*p && !isspace(*p)) p++;
+ while (*p && isspace(*p)) p++;
+ if (!*p) {p = previous_word; break;}
+ if (what == 'c') break;
+ previous_word = p;
+ while (*p && !isspace(*p)) p++;
+ }
+
+ if (fl_parse_color(p, r, g, b)) {
+ r = (ia * r + ir) >> 8;
+ g = (ia * g + ig) >> 8;
+ b = (ia * b + ib) >> 8;
+
+ if (chars_per_pixel > 1) sprintf(line, "%c%c c #%02X%02X%02X",
+ data()[color + 1][0],
+ data()[color + 1][1], r, g, b);
+ else sprintf(line, "%c c #%02X%02X%02X", data()[color + 1][0], r, g, b);
+
+ delete[] (char *)data()[color + 1];
+ ((char **)data())[color + 1] = new char[strlen(line) + 1];
+ strcpy((char *)data()[color + 1], line);
+ }
+ }
+ }
+}
+
+void Fl_Pixmap::delete_data() {
+ if (alloc_data) {
+ for (int i = 0; i < count(); i ++) delete[] (char *)data()[i];
+ delete[] (char **)data();
+ }
+}
+
+void Fl_Pixmap::set_data(const char * const * p) {
+ int height, // Number of lines in image
+ ncolors; // Number of colors in image
+
+ if (p) {
+ sscanf(p[0],"%*d%d%d", &height, &ncolors);
+ if (ncolors < 0) data(p, height + 2);
+ else data(p, height + ncolors + 1);
+ }
+}
+
+
+void Fl_Pixmap::desaturate() {
+ // Delete any existing pixmap/mask objects...
+ uncache();
+
+ // Allocate memory as needed...
+ copy_data();
+
+ // Update the colormap to grayscale...
+ char line[255]; // New colormap line
+ int i, // Looping var
+ ncolors, // Number of colors in image
+ chars_per_pixel;// Characters per color
+ uchar r, g, b;
+
+ sscanf(data()[0],"%*d%*d%d%d", &ncolors, &chars_per_pixel);
+
+ if (ncolors < 0) {
+ // Update FLTK colormap...
+ ncolors = -ncolors;
+ uchar *cmap = (uchar *)(data()[1]);
+ for (i = 0; i < ncolors; i ++, cmap += 4) {
+ g = (uchar)((cmap[1] * 31 + cmap[2] * 61 + cmap[3] * 8) / 100);
+ cmap[1] = cmap[2] = cmap[3] = g;
+ }
+ } else {
+ // Update standard XPM colormap...
+ for (i = 0; i < ncolors; i ++) {
+ // look for "c word", or last word if none:
+ const char *p = data()[i + 1] + chars_per_pixel + 1;
+ const char *previous_word = p;
+ for (;;) {
+ while (*p && isspace(*p)) p++;
+ char what = *p++;
+ while (*p && !isspace(*p)) p++;
+ while (*p && isspace(*p)) p++;
+ if (!*p) {p = previous_word; break;}
+ if (what == 'c') break;
+ previous_word = p;
+ while (*p && !isspace(*p)) p++;
+ }
+
+ if (fl_parse_color(p, r, g, b)) {
+ g = (uchar)((r * 31 + g * 61 + b * 8) / 100);
+
+ if (chars_per_pixel > 1) sprintf(line, "%c%c c #%02X%02X%02X", data()[i + 1][0],
+ data()[i + 1][1], g, g, g);
+ else sprintf(line, "%c c #%02X%02X%02X", data()[i + 1][0], g, g, g);
+
+ delete[] (char *)data()[i + 1];
+ ((char **)data())[i + 1] = new char[strlen(line) + 1];
+ strcpy((char *)data()[i + 1], line);
+ }
+ }
+ }
+}
+
+//
+// End of "$Id: Fl_Pixmap.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Positioner.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Positioner.cxx new file mode 100644 index 0000000..f0c6bd8 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Positioner.cxx @@ -0,0 +1,151 @@ +//
+// "$Id: Fl_Positioner.cxx 5347 2006-08-23 12:57:42Z matt $"
+//
+// Positioner widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// The positioner widget from Forms, gives 2D input
+// Written by: Mark Overmars
+
+#include <FL/Fl.H>
+#include <FL/Fl_Positioner.H>
+#include <FL/fl_draw.H>
+
+static double flinear(double val, double smin, double smax, double gmin, double gmax)
+{
+ if (smin == smax) return gmax;
+ else return gmin + (gmax - gmin) * (val - smin) / (smax - smin);
+}
+
+void Fl_Positioner::draw(int X, int Y, int W, int H) {
+ int x1 = X + 4;
+ int y1 = Y + 4;
+ int w1 = W - 2 * 4;
+ int h1 = H - 2 * 4;
+ int xx = int(flinear(xvalue(), xmin, xmax, x1, x1+w1-1)+.5);
+ int yy = int(flinear(yvalue(), ymin, ymax, y1, y1+h1-1)+.5);
+ draw_box(box(), X, Y, W, H, color());
+ fl_color(selection_color());
+ fl_xyline(x1, yy, x1+w1);
+ fl_yxline(xx, y1, y1+h1);
+}
+
+void Fl_Positioner::draw() {
+ draw(x(), y(), w(), h());
+ draw_label();
+}
+
+int Fl_Positioner::value(double X, double Y) {
+ clear_changed();
+ if (X == xvalue_ && Y == yvalue_) return 0;
+ xvalue_ = X; yvalue_ = Y;
+ redraw();
+ return 1;
+}
+
+int Fl_Positioner::xvalue(double X) {
+ return(value(X, yvalue_));
+}
+
+int Fl_Positioner::yvalue(double Y) {
+ return(value(xvalue_, Y));
+}
+
+int Fl_Positioner::handle(int event, int X, int Y, int W, int H) {
+ switch (event) {
+ case FL_PUSH:
+ case FL_DRAG:
+ case FL_RELEASE: {
+ double x1 = X + 4;
+ double y1 = Y + 4;
+ double w1 = W - 2 * 4;
+ double h1 = H - 2 * 4;
+ double xx = flinear(Fl::event_x(), x1, x1+w1-1.0, xmin, xmax);
+ if (xstep_) xx = int(xx/xstep_+0.5) * xstep_;
+ if (xmin < xmax) {
+ if (xx < xmin) xx = xmin;
+ if (xx > xmax) xx = xmax;
+ } else {
+ if (xx > xmin) xx = xmin;
+ if (xx < xmax) xx = xmax;
+ }
+ double yy = flinear(Fl::event_y(), y1, y1+h1-1.0, ymin, ymax);
+ if (ystep_) yy = int(yy/ystep_+0.5) * ystep_;
+ if (ymin < ymax) {
+ if (yy < ymin) yy = ymin;
+ if (yy > ymax) yy = ymax;
+ } else {
+ if (yy > ymin) yy = ymin;
+ if (yy < ymax) yy = ymax;
+ }
+ if (xx != xvalue_ || yy != yvalue_) {
+ xvalue_ = xx; yvalue_ = yy;
+ set_changed();
+ redraw();
+ } }
+ if (!(when() & FL_WHEN_CHANGED ||
+ (when() & FL_WHEN_RELEASE && event == FL_RELEASE))) return 1;
+ if (changed() || when()&FL_WHEN_NOT_CHANGED) {
+ if (event == FL_RELEASE) clear_changed();
+ do_callback();
+ }
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+int Fl_Positioner::handle(int e) {
+ return handle(e, x(), y(), w(), h());
+}
+
+Fl_Positioner::Fl_Positioner(int X, int Y, int W, int H, const char* l)
+: Fl_Widget(X, Y, W, H, l) {
+ box(FL_DOWN_BOX);
+ selection_color(FL_RED);
+ align(FL_ALIGN_BOTTOM);
+ when(FL_WHEN_CHANGED);
+ xmin = ymin = 0;
+ xmax = ymax = 1;
+ xvalue_ = yvalue_ = .5;
+ xstep_ = ystep_ = 0;
+}
+
+void Fl_Positioner::xbounds(double a, double b) {
+ if (a != xmin || b != xmax) {
+ xmin = a; xmax = b;
+ redraw();
+ }
+}
+
+void Fl_Positioner::ybounds(double a, double b) {
+ if (a != ymin || b != ymax) {
+ ymin = a; ymax = b;
+ redraw();
+ }
+}
+
+//
+// End of "$Id: Fl_Positioner.cxx 5347 2006-08-23 12:57:42Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Preferences.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Preferences.cxx new file mode 100644 index 0000000..9693720 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Preferences.cxx @@ -0,0 +1,1182 @@ +//
+// "$Id: Fl_Preferences.cxx 6015 2008-01-09 21:23:51Z matt $"
+//
+// Preferences methods for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 2002-2005 by Matthias Melcher.
+//
+// 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_Preferences.H>
+#include <FL/filename.H>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include "flstring.h"
+#include <sys/stat.h>
+
+#if defined(WIN32) && !defined(__CYGWIN__)
+# include <direct.h>
+# include <io.h>
+// Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs
+// on Windows, which is supposed to be POSIX compliant...
+# define access _access
+# define mkdir _mkdir
+#elif defined (__APPLE__)
+# include <Carbon/Carbon.h>
+# include <unistd.h>
+#else
+# include <unistd.h>
+#endif
+
+
+char Fl_Preferences::nameBuffer[128];
+
+
+/**
+ * create the initial preferences base
+ * - root: machine or user preferences
+ * - vendor: unique identification of author or vendor of application
+ * Must be a valid directory name.
+ * - application: vendor unique application name, i.e. "PreferencesTest"
+ * multiple preferences files can be created per application.
+ * Must be a valid file name.
+ * example: Fl_Preferences base( Fl_Preferences::USER, "fltk.org", "test01");
+ */
+Fl_Preferences::Fl_Preferences( Root root, const char *vendor, const char *application )
+{
+ node = new Node( "." );
+ rootNode = new RootNode( this, root, vendor, application );
+}
+
+
+/**
+ * create the initial preferences base
+ * - path: an application-supplied path
+ * example: Fl_Preferences base( "/usr/foo" );
+ */
+Fl_Preferences::Fl_Preferences( const char *path, const char *vendor, const char *application )
+{
+ node = new Node( "." );
+ rootNode = new RootNode( this, path, vendor, application );
+}
+
+
+/**
+ * create a Preferences node in relation to a parent node for reading and writing
+ * - parent: base name for group
+ * - group: group name (can contain '/' seperated group names)
+ * example: Fl_Preferences colors( base, "setup/colors" );
+ */
+Fl_Preferences::Fl_Preferences( Fl_Preferences &parent, const char *key )
+{
+ rootNode = parent.rootNode;
+ node = parent.node->addChild( key );
+}
+
+
+/**
+ * create a Preferences node in relation to a parent node for reading and writing
+ * - parent: base name for group
+ * - group: group name (can contain '/' seperated group names)
+ * example: Fl_Preferences colors( base, "setup/colors" );
+ */
+Fl_Preferences::Fl_Preferences( Fl_Preferences *parent, const char *key )
+{
+ rootNode = parent->rootNode;
+ node = parent->node->addChild( key );
+}
+
+
+/**
+ * destroy individual keys
+ * - destroying the base preferences will flush changes to the prefs file
+ * - after destroying the base, none of the depending preferences must be read or written
+ */
+Fl_Preferences::~Fl_Preferences()
+{
+ if (node && !node->parent()) delete rootNode;
+ // DO NOT delete nodes! The root node will do that after writing the preferences
+ // zero all pointer to avoid memory errors, event though
+ // Valgrind does not complain (Cygwind does though)
+ node = 0L;
+ rootNode = 0L;
+}
+
+
+/**
+ * return the number of groups that are contained within a group
+ * example: int n = base.groups();
+ */
+int Fl_Preferences::groups()
+{
+ return node->nChildren();
+}
+
+
+/**
+ * return the group name of the n'th group
+ * - there is no guaranteed order of group names
+ * - the index must be within the range given by groups()
+ * example: printf( "Group(%d)='%s'\n", ix, base.group(ix) );
+ */
+const char *Fl_Preferences::group( int ix )
+{
+ return node->child( ix );
+}
+
+
+/**
+ * return 1, if a group with this name exists
+ * example: if ( base.groupExists( "setup/colors" ) ) ...
+ */
+char Fl_Preferences::groupExists( const char *key )
+{
+ return node->search( key ) ? 1 : 0 ;
+}
+
+
+/**
+ * delete a group
+ * example: setup.deleteGroup( "colors/buttons" );
+ */
+char Fl_Preferences::deleteGroup( const char *key )
+{
+ Node *nd = node->search( key );
+ if ( nd ) return nd->remove();
+ return 0;
+}
+
+
+/**
+ * return the number of entries (name/value) pairs for a group
+ * example: int n = buttonColor.entries();
+ */
+int Fl_Preferences::entries()
+{
+ return node->nEntry;
+}
+
+
+/**
+ * return the name of an entry
+ * - there is no guaranteed order of entry names
+ * - the index must be within the range given by entries()
+ * example: printf( "Entry(%d)='%s'\n", ix, buttonColor.entry(ix) );
+ */
+const char *Fl_Preferences::entry( int ix )
+{
+ return node->entry[ix].name;
+}
+
+
+/**
+ * return 1, if an entry with this name exists
+ * example: if ( buttonColor.entryExists( "red" ) ) ...
+ */
+char Fl_Preferences::entryExists( const char *key )
+{
+ return node->getEntry( key )>=0 ? 1 : 0 ;
+}
+
+
+/**
+ * remove a single entry (name/value pair)
+ * example: buttonColor.deleteEntry( "red" );
+ */
+char Fl_Preferences::deleteEntry( const char *key )
+{
+ return node->deleteEntry( key );
+}
+
+
+/**
+ * read an entry from the group
+ */
+char Fl_Preferences::get( const char *key, int &value, int defaultValue )
+{
+ const char *v = node->get( key );
+ value = v ? atoi( v ) : defaultValue;
+ return ( v != 0 );
+}
+
+
+/**
+ * set an entry (name/value pair)
+ */
+char Fl_Preferences::set( const char *key, int value )
+{
+ sprintf( nameBuffer, "%d", value );
+ node->set( key, nameBuffer );
+ return 1;
+}
+
+
+/**
+ * read an entry from the group
+ */
+char Fl_Preferences::get( const char *key, float &value, float defaultValue )
+{
+ const char *v = node->get( key );
+ value = v ? (float)atof( v ) : defaultValue;
+ return ( v != 0 );
+}
+
+
+/**
+ * set an entry (name/value pair)
+ */
+char Fl_Preferences::set( const char *key, float value )
+{
+ sprintf( nameBuffer, "%g", value );
+ node->set( key, nameBuffer );
+ return 1;
+}
+
+
+/**
+ * set an entry (name/value pair)
+ */
+char Fl_Preferences::set( const char *key, float value, int precision )
+{
+ sprintf( nameBuffer, "%.*g", precision, value );
+ node->set( key, nameBuffer );
+ return 1;
+}
+
+
+/**
+ * read an entry from the group
+ */
+char Fl_Preferences::get( const char *key, double &value, double defaultValue )
+{
+ const char *v = node->get( key );
+ value = v ? atof( v ) : defaultValue;
+ return ( v != 0 );
+}
+
+
+/**
+ * set an entry (name/value pair)
+ */
+char Fl_Preferences::set( const char *key, double value )
+{
+ sprintf( nameBuffer, "%g", value );
+ node->set( key, nameBuffer );
+ return 1;
+}
+
+
+/**
+ * set an entry (name/value pair)
+ */
+char Fl_Preferences::set( const char *key, double value, int precision )
+{
+ sprintf( nameBuffer, "%.*g", precision, value );
+ node->set( key, nameBuffer );
+ return 1;
+}
+
+
+// remove control sequences from a string
+static char *decodeText( const char *src )
+{
+ int len = 0;
+ const char *s = src;
+ for ( ; *s; s++, len++ )
+ {
+ if ( *s == '\\' )
+ if ( isdigit( s[1] ) ) s+=3; else s+=1;
+ }
+ char *dst = (char*)malloc( len+1 ), *d = dst;
+ for ( s = src; *s; s++ )
+ {
+ char c = *s;
+ if ( c == '\\' )
+ {
+ if ( s[1] == '\\' ) { *d++ = c; s++; }
+ else if ( s[1] == 'n' ) { *d++ = '\n'; s++; }
+ else if ( s[1] == 'r' ) { *d++ = '\r'; s++; }
+ else if ( isdigit( s[1] ) ) { *d++ = ((s[1]-'0')<<6) + ((s[2]-'0')<<3) + (s[3]-'0'); s+=3; }
+ else s++; // error
+ }
+ else
+ *d++ = c;
+ }
+ *d = 0;
+ return dst;
+}
+
+
+/**
+ * read a text entry from the group
+ * the text will be moved into the given text buffer
+ * text will be clipped to the buffer size
+ */
+char Fl_Preferences::get( const char *key, char *text, const char *defaultValue, int maxSize )
+{
+ const char *v = node->get( key );
+ if ( v && strchr( v, '\\' ) ) {
+ char *w = decodeText( v );
+ strlcpy(text, w, maxSize);
+ free( w );
+ return 1;
+ }
+ if ( !v ) v = defaultValue;
+ if ( v ) strlcpy(text, v, maxSize);
+ else text = 0;
+ return ( v != defaultValue );
+}
+
+
+/**
+ * read a text entry from the group
+ * 'text' will be changed to point to a new text buffer
+ * the text buffer must be deleted with 'free(text)' by the user.
+ */
+char Fl_Preferences::get( const char *key, char *&text, const char *defaultValue )
+{
+ const char *v = node->get( key );
+ if ( v && strchr( v, '\\' ) )
+ {
+ text = decodeText( v );
+ return 1;
+ }
+ if ( !v ) v = defaultValue;
+ if ( v )
+ text = strdup( v );
+ else
+ text = 0;
+ return ( v != defaultValue );
+}
+
+
+/**
+ * set an entry (name/value pair)
+ */
+char Fl_Preferences::set( const char *key, const char *text )
+{
+ const char *s = text ? text : "";
+ int n=0, ns=0;
+ for ( ; *s; s++ ) { n++; if ( *s<32 || *s=='\\' || *s==0x7f ) ns+=4; }
+ if ( ns )
+ {
+ char *buffer = (char*)malloc( n+ns+1 ), *d = buffer;
+ for ( s=text; *s; )
+ {
+ char c = *s;
+ if ( c=='\\' ) { *d++ = '\\'; *d++ = '\\'; s++; }
+ else if ( c=='\n' ) { *d++ = '\\'; *d++ = 'n'; s++; }
+ else if ( c=='\r' ) { *d++ = '\\'; *d++ = 'r'; s++; }
+ else if ( c<32 || c==0x7f )
+ { *d++ = '\\'; *d++ = '0'+((c>>6)&3); *d++ = '0'+((c>>3)&7); *d++ = '0'+(c&7); s++; }
+ else *d++ = *s++;
+ }
+ *d = 0;
+ node->set( key, buffer );
+ free( buffer );
+ }
+ else
+ node->set( key, text );
+ return 1;
+}
+
+
+// convert a hex string to binary data
+static void *decodeHex( const char *src, int &size )
+{
+ size = strlen( src )/2;
+ unsigned char *data = (unsigned char*)malloc( size ), *d = data;
+ const char *s = src;
+ int i;
+
+ for ( i=size; i>0; i-- )
+ {
+ int v;
+ char x = tolower(*s++);
+ if ( x >= 'a' ) v = x-'a'+10; else v = x-'0';
+ v = v<<4;
+ x = tolower(*s++);
+ if ( x >= 'a' ) v += x-'a'+10; else v += x-'0';
+ *d++ = (uchar)v;
+ }
+
+ return (void*)data;
+}
+
+
+/**
+ * read a binary entry from the group
+ * the data will be moved into the given destination buffer
+ * data will be clipped to the buffer size
+ */
+char Fl_Preferences::get( const char *key, void *data, const void *defaultValue, int defaultSize, int maxSize )
+{
+ const char *v = node->get( key );
+ if ( v )
+ {
+ int dsize;
+ void *w = decodeHex( v, dsize );
+ memmove( data, w, dsize>maxSize?maxSize:dsize );
+ free( w );
+ return 1;
+ }
+ if ( defaultValue )
+ memmove( data, defaultValue, defaultSize>maxSize?maxSize:defaultSize );
+ return 0;
+}
+
+
+/**
+ * read a binary entry from the group
+ * 'data' will be changed to point to a new data buffer
+ * the data buffer must be deleted with 'free(data)' by the user.
+ */
+char Fl_Preferences::get( const char *key, void *&data, const void *defaultValue, int defaultSize )
+{
+ const char *v = node->get( key );
+ if ( v )
+ {
+ int dsize;
+ data = decodeHex( v, dsize );
+ return 1;
+ }
+ if ( defaultValue )
+ {
+ data = (void*)malloc( defaultSize );
+ memmove( data, defaultValue, defaultSize );
+ }
+ else
+ data = 0;
+ return 0;
+}
+
+
+/**
+ * set an entry (name/value pair)
+ */
+char Fl_Preferences::set( const char *key, const void *data, int dsize )
+{
+ char *buffer = (char*)malloc( dsize*2+1 ), *d = buffer;;
+ unsigned char *s = (unsigned char*)data;
+ for ( ; dsize>0; dsize-- )
+ {
+ static char lu[] = "0123456789abcdef";
+ unsigned char v = *s++;
+ *d++ = lu[v>>4];
+ *d++ = lu[v&0xf];
+ }
+ *d = 0;
+ node->set( key, buffer );
+ free( buffer );
+ return 1;
+}
+
+
+/**
+ * return the size of the value part of an entry
+ */
+int Fl_Preferences::size( const char *key )
+{
+ const char *v = node->get( key );
+ return v ? strlen( v ) : 0 ;
+}
+
+/**
+ * creates a path that is related to the preferences file
+ * and that is usable for application data beyond what is covered
+ * by Fl_Preferences.
+ * - 'getUserdataPath' actually creates the directory
+ * - 'path' must be large enough to receive a complete file path
+ * example:
+ * Fl_Preferences prefs( USER, "matthiasm.com", "test" );
+ * char path[FL_PATH_MAX];
+ * prefs.getUserdataPath( path );
+ * sample returns:
+ * Win32: c:/Documents and Settings/matt/Application Data/matthiasm.com/test/
+ * prefs: c:/Documents and Settings/matt/Application Data/matthiasm.com/test.prefs
+ */
+char Fl_Preferences::getUserdataPath( char *path, int pathlen )
+{
+ if ( rootNode )
+ return rootNode->getPath( path, pathlen );
+ return 0;
+}
+
+/**
+ * write all preferences to disk
+ * - this function works only with the base preference group
+ * - this function is rarely used as deleting the base preferences flushes automatically
+ */
+void Fl_Preferences::flush()
+{
+ if ( rootNode && node->dirty() )
+ rootNode->write();
+}
+
+//-----------------------------------------------------------------------------
+// helper class to create dynamic group and entry names on the fly
+//
+
+/**
+ * create a group name or entry name on the fly
+ * - this version creates a simple unsigned integer as an entry name
+ * example:
+ * int n, i;
+ * Fl_Preferences prev( appPrefs, "PreviousFiles" );
+ * prev.get( "n", 0 );
+ * for ( i=0; i<n; i++ )
+ * prev.get( Fl_Preferences::Name(i), prevFile[i], "" );
+ */
+Fl_Preferences::Name::Name( unsigned int n )
+{
+ data_ = (char*)malloc(20);
+ sprintf(data_, "%u", n);
+}
+
+/**
+ * create a group name or entry name on the fly
+ * - this version creates entry names as in 'printf'
+ * example:
+ * int n, i;
+ * Fl_Preferences prefs( USER, "matthiasm.com", "test" );
+ * prev.get( "nFiles", 0 );
+ * for ( i=0; i<n; i++ )
+ * prev.get( Fl_Preferences::Name( "File%d", i ), prevFile[i], "" );
+ */
+Fl_Preferences::Name::Name( const char *format, ... )
+{
+ data_ = (char*)malloc(1024);
+ va_list args;
+ va_start(args, format);
+ vsnprintf(data_, 1024, format, args);
+ va_end(args);
+}
+
+// delete the name
+Fl_Preferences::Name::~Name()
+{
+ if (data_) {
+ free(data_);
+ data_ = 0L;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// internal methods, do not modify or use as they will change without notice
+//
+
+int Fl_Preferences::Node::lastEntrySet = -1;
+
+// recursively create a path in the file system
+static char makePath( const char *path ) {
+ if (access(path, 0)) {
+ const char *s = strrchr( path, '/' );
+ if ( !s ) return 0;
+ int len = s-path;
+ char *p = (char*)malloc( len+1 );
+ memcpy( p, path, len );
+ p[len] = 0;
+ makePath( p );
+ free( p );
+#if defined(WIN32) && !defined(__CYGWIN__)
+ return ( mkdir( path ) == 0 );
+#else
+ return ( mkdir( path, 0777 ) == 0 );
+#endif // WIN32 && !__CYGWIN__
+ }
+ return 1;
+}
+
+// strip the filename and create a path
+static void makePathForFile( const char *path )
+{
+ const char *s = strrchr( path, '/' );
+ if ( !s ) return;
+ int len = s-path;
+ char *p = (char*)malloc( len+1 );
+ memcpy( p, path, len );
+ p[len] = 0;
+ makePath( p );
+ free( p );
+}
+
+// create the root node
+// - construct the name of the file that will hold our preferences
+Fl_Preferences::RootNode::RootNode( Fl_Preferences *prefs, Root root, const char *vendor, const char *application )
+{
+ char filename[ FL_PATH_MAX ]; filename[0] = 0;
+#ifdef WIN32
+# define FLPREFS_RESOURCE "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"
+ int appDataLen = strlen(vendor) + strlen(application) + 8;
+ DWORD type, nn;
+ LONG err;
+ HKEY key;
+
+ switch (root) {
+ case SYSTEM:
+ err = RegOpenKey( HKEY_LOCAL_MACHINE, FLPREFS_RESOURCE, &key );
+ if (err == ERROR_SUCCESS) {
+ nn = FL_PATH_MAX - appDataLen;
+ err = RegQueryValueEx( key, "Common AppData", 0L, &type, (BYTE*)filename, &nn );
+ if ( ( err != ERROR_SUCCESS ) && ( type == REG_SZ ) )
+ filename[0] = 0;
+ RegCloseKey(key);
+ }
+ break;
+ case USER:
+ err = RegOpenKey( HKEY_CURRENT_USER, FLPREFS_RESOURCE, &key );
+ if (err == ERROR_SUCCESS) {
+ nn = FL_PATH_MAX - appDataLen;
+ err = RegQueryValueEx( key, "AppData", 0L, &type, (BYTE*)filename, &nn );
+ if ( ( err != ERROR_SUCCESS ) && ( type == REG_SZ ) )
+ {
+ err = RegQueryValueEx( key, "Personal", 0L, &type, (BYTE*)filename, &nn );
+ if ( ( err != ERROR_SUCCESS ) && ( type == REG_SZ ) )
+ filename[0] = 0;
+ }
+ RegCloseKey(key);
+ }
+ break;
+ }
+
+ if (!filename[0]) {
+ strcpy(filename, "C:\\FLTK");
+ }
+
+ snprintf(filename + strlen(filename), sizeof(filename) - strlen(filename),
+ "/%s/%s.prefs", vendor, application);
+ for (char *s = filename; *s; s++) if (*s == '\\') *s = '/';
+#elif defined ( __APPLE__ )
+ FSSpec spec = { 0 };
+ FSRef ref;
+ OSErr err = fnfErr;
+ switch (root) {
+ case SYSTEM:
+ err = FindFolder( kLocalDomain, kPreferencesFolderType,
+ 1, &spec.vRefNum, &spec.parID );
+ break;
+ case USER:
+ err = FindFolder( kUserDomain, kPreferencesFolderType,
+ 1, &spec.vRefNum, &spec.parID );
+ break;
+ }
+ FSpMakeFSRef( &spec, &ref );
+ FSRefMakePath( &ref, (UInt8*)filename, FL_PATH_MAX );
+ snprintf(filename + strlen(filename), sizeof(filename) - strlen(filename),
+ "/%s/%s.prefs", vendor, application );
+#else
+ const char *e;
+ switch (root) {
+ case USER:
+ if ((e = getenv("HOME")) != NULL) {
+ strlcpy(filename, e, sizeof(filename));
+
+ if (filename[strlen(filename)-1] != '/') {
+ strlcat(filename, "/.fltk/", sizeof(filename));
+ } else {
+ strlcat(filename, ".fltk/", sizeof(filename));
+ }
+ break;
+ }
+
+ case SYSTEM:
+ strcpy(filename, "/etc/fltk/");
+ break;
+ }
+
+ snprintf(filename + strlen(filename), sizeof(filename) - strlen(filename),
+ "%s/%s.prefs", vendor, application);
+#endif
+
+ prefs_ = prefs;
+ filename_ = strdup(filename);
+ vendor_ = strdup(vendor);
+ application_ = strdup(application);
+
+ read();
+}
+
+// create the root node
+// - construct the name of the file that will hold our preferences
+Fl_Preferences::RootNode::RootNode( Fl_Preferences *prefs, const char *path, const char *vendor, const char *application )
+{
+ if (!vendor)
+ vendor = "unknown";
+ if (!application) {
+ application = "unknown";
+ filename_ = strdup(path);
+ } else {
+ char filename[ FL_PATH_MAX ]; filename[0] = 0;
+ snprintf(filename, sizeof(filename), "%s/%s.prefs", path, application);
+ filename_ = strdup(filename);
+ }
+ prefs_ = prefs;
+ vendor_ = strdup(vendor);
+ application_ = strdup(application);
+
+ read();
+}
+
+// destroy the root node and all depending nodes
+Fl_Preferences::RootNode::~RootNode()
+{
+ if ( prefs_->node->dirty() )
+ write();
+ if ( filename_ ) {
+ free( filename_ );
+ filename_ = 0L;
+ }
+ if ( vendor_ ) {
+ free( vendor_ );
+ vendor_ = 0L;
+ }
+ if ( application_ ) {
+ free( application_ );
+ application_ = 0L;
+ }
+ delete prefs_->node;
+ prefs_->node = 0L;
+}
+
+// read a preferences file and construct the group tree and with all entry leafs
+int Fl_Preferences::RootNode::read()
+{
+ char buf[1024];
+ FILE *f = fopen( filename_, "rb" );
+ if ( !f ) return 0;
+ fgets( buf, 1024, f );
+ fgets( buf, 1024, f );
+ fgets( buf, 1024, f );
+ Node *nd = prefs_->node;
+ for (;;)
+ {
+ if ( !fgets( buf, 1024, f ) ) break; // EOF or Error
+ if ( buf[0]=='[' ) // read a new group
+ {
+ int end = strcspn( buf+1, "]\n\r" );
+ buf[ end+1 ] = 0;
+ nd = prefs_->node->find( buf+1 );
+ }
+ else if ( buf[0]=='+' ) //
+ { // value of previous name/value pair spans multiple lines
+ int end = strcspn( buf+1, "\n\r" );
+ if ( end != 0 ) // if entry is not empty
+ {
+ buf[ end+1 ] = 0;
+ nd->add( buf+1 );
+ }
+ }
+ else // read a name/value pair
+ {
+ int end = strcspn( buf, "\n\r" );
+ if ( end != 0 ) // if entry is not empty
+ {
+ buf[ end ] = 0;
+ nd->set( buf );
+ }
+ }
+ }
+ fclose( f );
+ return 0;
+}
+
+// write the group tree and all entry leafs
+int Fl_Preferences::RootNode::write()
+{
+ makePathForFile(filename_);
+ FILE *f = fopen( filename_, "wb" );
+ if ( !f ) return 1;
+ fprintf( f, "; FLTK preferences file format 1.0\n" );
+ fprintf( f, "; vendor: %s\n", vendor_ );
+ fprintf( f, "; application: %s\n", application_ );
+ prefs_->node->write( f );
+ fclose( f );
+ return 0;
+}
+
+// get the path to the preferences directory
+char Fl_Preferences::RootNode::getPath( char *path, int pathlen )
+{
+ strlcpy( path, filename_, pathlen);
+
+ char *s;
+ for ( s = path; *s; s++ ) if ( *s == '\\' ) *s = '/';
+ s = strrchr( path, '.' );
+ if ( !s ) return 0;
+ *s = 0;
+ char ret = makePath( path );
+ strcpy( s, "/" );
+ return ret;
+}
+
+// create a node that represents a group
+// - path must be a single word, prferable alnum(), dot and underscore only. Space is ok.
+Fl_Preferences::Node::Node( const char *path )
+{
+ if ( path ) path_ = strdup( path ); else path_ = 0;
+ child_ = 0; next_ = 0; parent_ = 0;
+ entry = 0;
+ nEntry = NEntry = 0;
+ dirty_ = 0;
+}
+
+// delete this and all depending nodes
+Fl_Preferences::Node::~Node()
+{
+ Node *nx;
+ for ( Node *nd = child_; nd; nd = nx )
+ {
+ nx = nd->next_;
+ delete nd;
+ }
+ child_ = 0L;
+ if ( entry )
+ {
+ for ( int i = 0; i < nEntry; i++ )
+ {
+ if ( entry[i].name ) {
+ free( entry[i].name );
+ entry[i].name = 0L;
+ }
+ if ( entry[i].value ) {
+ free( entry[i].value );
+ entry[i].value = 0L;
+ }
+ }
+ free( entry );
+ entry = 0L;
+ nEntry = 0;
+ }
+ if ( path_ ) {
+ free( path_ );
+ path_ = 0L;
+ }
+ next_ = 0L;
+ parent_ = 0L;
+}
+
+// recursively check if any entry is dirty (was changed after loading a fresh prefs file)
+char Fl_Preferences::Node::dirty()
+{
+ if ( dirty_ ) return 1;
+ if ( next_ && next_->dirty() ) return 1;
+ if ( child_ && child_->dirty() ) return 1;
+ return 0;
+}
+
+// write this node (recursively from the last neighbor back to this)
+// write all entries
+// write all children
+int Fl_Preferences::Node::write( FILE *f )
+{
+ if ( next_ ) next_->write( f );
+ fprintf( f, "\n[%s]\n\n", path_ );
+ for ( int i = 0; i < nEntry; i++ )
+ {
+ char *src = entry[i].value;
+ if ( src )
+ { // hack it into smaller pieces if needed
+ fprintf( f, "%s:", entry[i].name );
+ int cnt;
+ for ( cnt = 0; cnt < 60; cnt++ )
+ if ( src[cnt]==0 ) break;
+ fwrite( src, cnt, 1, f );
+ fprintf( f, "\n" );
+ src += cnt;
+ for (;*src;)
+ {
+ for ( cnt = 0; cnt < 80; cnt++ )
+ if ( src[cnt]==0 ) break;
+ fputc( '+', f );
+ fwrite( src, cnt, 1, f );
+ fputc( '\n', f );
+ src += cnt;
+ }
+ }
+ else
+ fprintf( f, "%s\n", entry[i].name );
+ }
+ if ( child_ ) child_->write( f );
+ dirty_ = 0;
+ return 0;
+}
+
+// set the parent node and create the full path
+void Fl_Preferences::Node::setParent( Node *pn )
+{
+ parent_ = pn;
+ next_ = pn->child_;
+ pn->child_ = this;
+ sprintf( nameBuffer, "%s/%s", pn->path_, path_ );
+ free( path_ );
+ path_ = strdup( nameBuffer );
+}
+
+// add a child to this node and set its path (try to find it first...)
+Fl_Preferences::Node *Fl_Preferences::Node::addChild( const char *path )
+{
+ sprintf( nameBuffer, "%s/%s", path_, path );
+ char *name = strdup( nameBuffer );
+ Node *nd = find( name );
+ free( name );
+ dirty_ = 1;
+ return nd;
+}
+
+// create and set, or change an entry within this node
+void Fl_Preferences::Node::set( const char *name, const char *value )
+{
+ for ( int i=0; i<nEntry; i++ )
+ {
+ if ( strcmp( name, entry[i].name ) == 0 )
+ {
+ if ( !value ) return; // annotation
+ if ( strcmp( value, entry[i].value ) != 0 )
+ {
+ if ( entry[i].value )
+ free( entry[i].value );
+ entry[i].value = strdup( value );
+ dirty_ = 1;
+ }
+ lastEntrySet = i;
+ return;
+ }
+ }
+ if ( NEntry==nEntry )
+ {
+ NEntry = NEntry ? NEntry*2 : 10;
+ entry = (Entry*)realloc( entry, NEntry * sizeof(Entry) );
+ }
+ entry[ nEntry ].name = strdup( name );
+ entry[ nEntry ].value = value?strdup( value ):0;
+ lastEntrySet = nEntry;
+ nEntry++;
+ dirty_ = 1;
+}
+
+// create or set a value (or annotation) from a single line in the file buffer
+void Fl_Preferences::Node::set( const char *line )
+{
+ // hmm. If we assume that we always read this file in the beginning,
+ // we can handle the dirty flag 'quick and dirty'
+ char dirt = dirty_;
+ if ( line[0]==';' || line[0]==0 || line[0]=='#' )
+ {
+ set( line, 0 );
+ }
+ else
+ {
+ const char *c = strchr( line, ':' );
+ if ( c )
+ {
+ unsigned int len = c-line+1;
+ if ( len >= sizeof( nameBuffer ) )
+ len = sizeof( nameBuffer );
+ strlcpy( nameBuffer, line, len );
+ set( nameBuffer, c+1 );
+ }
+ else
+ set( line, "" );
+ }
+ dirty_ = dirt;
+}
+
+// add more data to an existing entry
+void Fl_Preferences::Node::add( const char *line )
+{
+ if ( lastEntrySet<0 || lastEntrySet>=nEntry ) return;
+ char *&dst = entry[ lastEntrySet ].value;
+ int a = strlen( dst );
+ int b = strlen( line );
+ dst = (char*)realloc( dst, a+b+1 );
+ memcpy( dst+a, line, b+1 );
+ dirty_ = 1;
+}
+
+// get the value for a name, returns 0 if no such name
+const char *Fl_Preferences::Node::get( const char *name )
+{
+ int i = getEntry( name );
+ return i>=0 ? entry[i].value : 0 ;
+}
+
+// find the index of an entry, returns -1 if no such entry
+int Fl_Preferences::Node::getEntry( const char *name )
+{
+ for ( int i=0; i<nEntry; i++ )
+ {
+ if ( strcmp( name, entry[i].name ) == 0 )
+ {
+ return i;
+ }
+ }
+ return -1;
+}
+
+// remove one entry form this group
+char Fl_Preferences::Node::deleteEntry( const char *name )
+{
+ int ix = getEntry( name );
+ if ( ix == -1 ) return 0;
+ memmove( entry+ix, entry+ix+1, (nEntry-ix-1) * sizeof(Entry) );
+ nEntry--;
+ dirty_ = 1;
+ return 1;
+}
+
+// find a group somewhere in the tree starting here
+// - this method will always return a valid node (except for memory allocation problems)
+// - if the node was not found, 'find' will create the required branch
+Fl_Preferences::Node *Fl_Preferences::Node::find( const char *path )
+{
+ int len = strlen( path_ );
+ if ( strncmp( path, path_, len ) == 0 )
+ {
+ if ( path[ len ] == 0 )
+ return this;
+ if ( path[ len ] == '/' )
+ {
+ Node *nd;
+ for ( nd = child_; nd; nd = nd->next_ )
+ {
+ Node *nn = nd->find( path );
+ if ( nn ) return nn;
+ }
+ const char *s = path+len+1;
+ const char *e = strchr( s, '/' );
+ if (e) strlcpy( nameBuffer, s, e-s+1 );
+ else strlcpy( nameBuffer, s, sizeof(nameBuffer));
+ nd = new Node( nameBuffer );
+ nd->setParent( this );
+ return nd->find( path );
+ }
+ }
+ return 0;
+}
+
+// find a group somewhere in the tree starting here
+// caller must not set 'offset' argument
+// - if the node does not exist, 'search' returns NULL
+// - if the pathname is "." (current node) return this node
+// - if the pathname is "./" (root node) return the topmost node
+// - if the pathname starts with "./", start the search at the root node instead
+Fl_Preferences::Node *Fl_Preferences::Node::search( const char *path, int offset )
+{
+
+ if ( offset == 0 )
+ {
+ if ( path[0] == '.' )
+ {
+ if ( path[1] == 0 )
+ {
+ return this; // user was searching for current node
+ }
+ else if ( path[1] == '/' )
+ {
+ Node *nn = this;
+ while ( nn->parent_ ) nn = nn->parent_;
+ if ( path[2]==0 )
+ { // user is searching for root ( "./" )
+ return nn;
+ }
+ return nn->search( path+2, 2 ); // do a relative search on the root node
+ }
+ }
+ offset = strlen( path_ ) + 1;
+ }
+
+ int len = strlen( path_ );
+ if ( len < offset-1 ) return 0;
+ len -= offset;
+ if ( ( len <= 0 ) || ( strncmp( path, path_+offset, len ) == 0 ) )
+ {
+ if ( len > 0 && path[ len ] == 0 )
+ return this;
+ if ( len <= 0 || path[ len ] == '/' )
+ {
+ for ( Node *nd = child_; nd; nd = nd->next_ )
+ {
+ Node *nn = nd->search( path, offset );
+ if ( nn ) return nn;
+ }
+ return 0;
+ }
+ }
+ return 0;
+}
+
+// return the number of child nodes (groups)
+int Fl_Preferences::Node::nChildren()
+{
+ int cnt = 0;
+ for ( Node *nd = child_; nd; nd = nd->next_ )
+ cnt++;
+ return cnt;
+}
+
+// return the n'th child node
+const char *Fl_Preferences::Node::child( int ix )
+{
+ Node *nd;
+ for ( nd = child_; nd; nd = nd->next_ )
+ {
+ if ( !ix-- ) break;
+ }
+ if ( nd && nd->path_ )
+ {
+ char *r = strrchr( nd->path_, '/' );
+ return r ? r+1 : nd->path_ ;
+ }
+ return 0L ;
+}
+
+// remove myself from the list and delete me (and all children)
+char Fl_Preferences::Node::remove()
+{
+ Node *nd = 0, *np;
+ if ( parent_ )
+ {
+ nd = parent_->child_; np = 0L;
+ for ( ; nd; np = nd, nd = nd->next_ )
+ {
+ if ( nd == this )
+ {
+ if ( np )
+ np->next_ = nd->next_;
+ else
+ parent_->child_ = nd->next_;
+ break;
+ }
+ }
+ parent_->dirty_ = 1;
+ }
+ delete this;
+ return ( nd != 0 );
+}
+
+
+//
+// End of "$Id: Fl_Preferences.cxx 6015 2008-01-09 21:23:51Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Progress.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Progress.cxx new file mode 100644 index 0000000..5613449 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Progress.cxx @@ -0,0 +1,117 @@ +//
+// "$Id: Fl_Progress.cxx 5540 2006-11-12 20:44:12Z matt $"
+//
+// Progress bar widget routines.
+//
+// Copyright 2000-2005 by Michael Sweet.
+//
+// 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
+//
+// Contents:
+//
+// Fl_Progress::draw() - Draw the check button.
+// Fl_Progress::Fl_Progress() - Construct a Fl_Progress widget.
+//
+
+//
+// Include necessary header files...
+//
+
+#include <FL/Fl.H>
+#include <FL/Fl_Progress.H>
+#include <FL/fl_draw.H>
+
+
+//
+// Fl_Progress is a progress bar widget based off Fl_Widget that shows a
+// standard progress bar...
+//
+
+
+//
+// 'Fl_Progress::draw()' - Draw the check button.
+//
+
+void Fl_Progress::draw()
+{
+ int progress; // Size of progress bar...
+ int bx, by, bw, bh; // Box areas...
+ int tx, tw; // Temporary X + width
+
+
+ // Get the box borders...
+ bx = Fl::box_dx(box());
+ by = Fl::box_dy(box());
+ bw = Fl::box_dw(box());
+ bh = Fl::box_dh(box());
+
+ tx = x() + bx;
+ tw = w() - bw;
+
+ // Draw the progress bar...
+ if (maximum_ > minimum_)
+ progress = (int)(w() * (value_ - minimum_) / (maximum_ - minimum_) + 0.5f);
+ else
+ progress = 0;
+
+ // Draw the box and label...
+ if (progress > 0) {
+ Fl_Color c = labelcolor();
+ labelcolor(fl_contrast(labelcolor(), color2()));
+
+ fl_clip(x(), y(), progress + bx, h());
+ draw_box(box(), x(), y(), w(), h(), active_r() ? color2() : fl_inactive(color2()));
+ draw_label(tx, y() + by, tw, h() - bh);
+ fl_pop_clip();
+
+ labelcolor(c);
+
+ if (progress<w()) {
+ fl_clip(tx + progress, y(), w() - progress, h());
+ draw_box(box(), x(), y(), w(), h(), active_r() ? color() : fl_inactive(color()));
+ draw_label(tx, y() + by, tw, h() - bh);
+ fl_pop_clip();
+ }
+ } else {
+ draw_box(box(), x(), y(), w(), h(), active_r() ? color() : fl_inactive(color()));
+ draw_label(tx, y() + by, tw, h() - bh);
+ }
+}
+
+
+//
+// 'Fl_Progress::Fl_Progress()' - Construct a Fl_Progress widget.
+//
+
+Fl_Progress::Fl_Progress(int X, int Y, int W, int H, const char* l)
+: Fl_Widget(X, Y, W, H, l)
+{
+ align(FL_ALIGN_INSIDE);
+ box(FL_DOWN_BOX);
+ color(FL_BACKGROUND2_COLOR, FL_YELLOW);
+ minimum(0.0f);
+ maximum(100.0f);
+ value(0.0f);
+}
+
+
+//
+// End of "$Id: Fl_Progress.cxx 5540 2006-11-12 20:44:12Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Repeat_Button.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Repeat_Button.cxx new file mode 100644 index 0000000..5c9379b --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Repeat_Button.cxx @@ -0,0 +1,70 @@ +//
+// "$Id: Fl_Repeat_Button.cxx 5219 2006-06-21 06:52:10Z matt $"
+//
+// Repeat button widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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_Repeat_Button.H>
+
+#define INITIALREPEAT .5
+#define REPEAT .1
+
+void Fl_Repeat_Button::repeat_callback(void *v) {
+ Fl_Button *b = (Fl_Button*)v;
+ Fl::add_timeout(REPEAT,repeat_callback,b);
+ b->do_callback();
+}
+
+int Fl_Repeat_Button::handle(int event) {
+ int newval;
+ switch (event) {
+ case FL_HIDE:
+ case FL_DEACTIVATE:
+ case FL_RELEASE:
+ newval = 0; goto J1;
+ case FL_PUSH:
+ case FL_DRAG:
+ if (Fl::visible_focus()) Fl::focus(this);
+ newval = Fl::event_inside(this);
+ J1:
+ if (!active())
+ newval = 0;
+ if (value(newval)) {
+ if (newval) {
+ Fl::add_timeout(INITIALREPEAT,repeat_callback,this);
+ do_callback();
+ } else {
+ Fl::remove_timeout(repeat_callback,this);
+ }
+ }
+ return 1;
+ default:
+ return Fl_Button::handle(event);
+ }
+}
+
+//
+// End of "$Id: Fl_Repeat_Button.cxx 5219 2006-06-21 06:52:10Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Return_Button.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Return_Button.cxx new file mode 100644 index 0000000..57e1979 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Return_Button.cxx @@ -0,0 +1,72 @@ +//
+// "$Id: Fl_Return_Button.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Return button widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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_Return_Button.H>
+#include <FL/fl_draw.H>
+
+int fl_return_arrow(int x, int y, int w, int h) {
+ int size = w; if (h<size) size = h;
+ int d = (size+2)/4; if (d<3) d = 3;
+ int t = (size+9)/12; if (t<1) t = 1;
+ int x0 = x+(w-2*d-2*t-1)/2;
+ int x1 = x0+d;
+ int y0 = y+h/2;
+ fl_color(FL_LIGHT3);
+ fl_line(x0, y0, x1, y0+d);
+ fl_yxline(x1, y0+d, y0+t, x1+d+2*t, y0-d);
+ fl_yxline(x1, y0-t, y0-d);
+ fl_color(fl_gray_ramp(0));
+ fl_line(x0, y0, x1, y0-d);
+ fl_color(FL_DARK3);
+ fl_xyline(x1+1, y0-t, x1+d, y0-d, x1+d+2*t);
+ return 1;
+}
+
+void Fl_Return_Button::draw() {
+ if (type() == FL_HIDDEN_BUTTON) return;
+ draw_box(value() ? (down_box()?down_box():fl_down(box())) : box(),
+ value() ? selection_color() : color());
+ int W = h();
+ if (w()/3 < W) W = w()/3;
+ fl_return_arrow(x()+w()-W-4, y(), W, h());
+ draw_label(x(), y(), w()-W+4, h());
+ if (Fl::focus() == this) draw_focus();
+}
+
+int Fl_Return_Button::handle(int event) {
+ if (event == FL_SHORTCUT &&
+ (Fl::event_key() == FL_Enter || Fl::event_key() == FL_KP_Enter)) {
+ do_callback();
+ return 1;
+ } else
+ return Fl_Button::handle(event);
+}
+
+//
+// End of "$Id: Fl_Return_Button.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Roller.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Roller.cxx new file mode 100644 index 0000000..6e1dd7c --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Roller.cxx @@ -0,0 +1,180 @@ +//
+// "$Id: Fl_Roller.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Roller widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Rapid-App style knob
+
+#include <FL/Fl.H>
+#include <FL/Fl_Roller.H>
+#include <FL/fl_draw.H>
+#include <math.h>
+
+int Fl_Roller::handle(int event) {
+ static int ipos;
+ int newpos = horizontal() ? Fl::event_x() : Fl::event_y();
+ switch (event) {
+ case FL_PUSH:
+ if (Fl::visible_focus()) {
+ Fl::focus(this);
+ redraw();
+ }
+ handle_push();
+ ipos = newpos;
+ return 1;
+ case FL_DRAG:
+ handle_drag(clamp(round(increment(previous_value(),newpos-ipos))));
+ return 1;
+ case FL_RELEASE:
+ handle_release();
+ return 1;
+ case FL_KEYBOARD :
+ switch (Fl::event_key()) {
+ case FL_Up:
+ if (horizontal()) return 0;
+ handle_drag(clamp(increment(value(),-1)));
+ return 1;
+ case FL_Down:
+ if (horizontal()) return 0;
+ handle_drag(clamp(increment(value(),1)));
+ return 1;
+ case FL_Left:
+ if (!horizontal()) return 0;
+ handle_drag(clamp(increment(value(),-1)));
+ return 1;
+ case FL_Right:
+ if (!horizontal()) return 0;
+ handle_drag(clamp(increment(value(),1)));
+ return 1;
+ default:
+ return 0;
+ }
+ // break not required because of switch...
+ case FL_FOCUS :
+ case FL_UNFOCUS :
+ if (Fl::visible_focus()) {
+ redraw();
+ return 1;
+ } else return 0;
+ case FL_ENTER :
+ case FL_LEAVE :
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+void Fl_Roller::draw() {
+ if (damage()&FL_DAMAGE_ALL) draw_box();
+ int X = x()+Fl::box_dx(box());
+ int Y = y()+Fl::box_dy(box());
+ int W = w()-Fl::box_dw(box())-1;
+ int H = h()-Fl::box_dh(box())-1;
+ if (W<=0 || H <=0) return;
+ int offset = step() ? int(value()/step()) : 0;
+ const double ARC = 1.5; // 1/2 the number of radians visible
+ const double delta = .2; // radians per knurl
+ if (horizontal()) { // horizontal one
+ // draw shaded ends of wheel:
+ int h1 = W/4+1; // distance from end that shading starts
+ fl_color(color()); fl_rectf(X+h1,Y,W-2*h1,H);
+ for (int i=0; h1; i++) {
+ fl_color((Fl_Color)(FL_GRAY-i-1));
+ int h2 = FL_GRAY-i-1 > FL_DARK3 ? 2*h1/3+1 : 0;
+ fl_rectf(X+h2,Y,h1-h2,H);
+ fl_rectf(X+W-h1,Y,h1-h2,H);
+ h1 = h2;
+ }
+ if (active_r()) {
+ // draw ridges:
+ double junk;
+ for (double yy = -ARC+modf(offset*sin(ARC)/(W/2)/delta,&junk)*delta;;
+ yy += delta) {
+ int yy1 = int((sin(yy)/sin(ARC)+1)*W/2);
+ if (yy1 <= 0) continue; else if (yy1 >= W-1) break;
+ fl_color(FL_DARK3); fl_yxline(X+yy1,Y+1,Y+H-1);
+ if (yy < 0) yy1--; else yy1++;
+ fl_color(FL_LIGHT1);fl_yxline(X+yy1,Y+1,Y+H-1);
+ }
+ // draw edges:
+ h1 = W/8+1; // distance from end the color inverts
+ fl_color(FL_DARK2);
+ fl_xyline(X+h1,Y+H-1,X+W-h1);
+ fl_color(FL_DARK3);
+ fl_yxline(X,Y+H,Y,X+h1);
+ fl_xyline(X+W-h1,Y,X+W);
+ fl_color(FL_LIGHT2);
+ fl_xyline(X+h1,Y-1,X+W-h1);
+ fl_yxline(X+W,Y,Y+H,X+W-h1);
+ fl_xyline(X+h1,Y+H,X);
+ }
+ } else { // vertical one
+ // draw shaded ends of wheel:
+ int h1 = H/4+1; // distance from end that shading starts
+ fl_color(color()); fl_rectf(X,Y+h1,W,H-2*h1);
+ for (int i=0; h1; i++) {
+ fl_color((Fl_Color)(FL_GRAY-i-1));
+ int h2 = FL_GRAY-i-1 > FL_DARK3 ? 2*h1/3+1 : 0;
+ fl_rectf(X,Y+h2,W,h1-h2);
+ fl_rectf(X,Y+H-h1,W,h1-h2);
+ h1 = h2;
+ }
+ if (active_r()) {
+ // draw ridges:
+ double junk;
+ for (double yy = -ARC+modf(offset*sin(ARC)/(H/2)/delta,&junk)*delta;
+ ; yy += delta) {
+ int yy1 = int((sin(yy)/sin(ARC)+1)*H/2);
+ if (yy1 <= 0) continue; else if (yy1 >= H-1) break;
+ fl_color(FL_DARK3); fl_xyline(X+1,Y+yy1,X+W-1);
+ if (yy < 0) yy1--; else yy1++;
+ fl_color(FL_LIGHT1);fl_xyline(X+1,Y+yy1,X+W-1);
+ }
+ // draw edges:
+ h1 = H/8+1; // distance from end the color inverts
+ fl_color(FL_DARK2);
+ fl_yxline(X+W-1,Y+h1,Y+H-h1);
+ fl_color(FL_DARK3);
+ fl_xyline(X+W,Y,X,Y+h1);
+ fl_yxline(X,Y+H-h1,Y+H);
+ fl_color(FL_LIGHT2);
+ fl_yxline(X,Y+h1,Y+H-h1);
+ fl_xyline(X,Y+H,X+W,Y+H-h1);
+ fl_yxline(X+W,Y+h1,Y);
+ }
+ }
+
+ if (Fl::focus() == this) draw_focus(FL_THIN_UP_FRAME, x(), y(), w(), h());
+}
+
+Fl_Roller::Fl_Roller(int X,int Y,int W,int H,const char* L)
+ : Fl_Valuator(X,Y,W,H,L) {
+ box(FL_UP_BOX);
+ step(1,1000);
+}
+
+//
+// End of "$Id: Fl_Roller.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Round_Button.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Round_Button.cxx new file mode 100644 index 0000000..2a91862 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Round_Button.cxx @@ -0,0 +1,44 @@ +//
+// "$Id: Fl_Round_Button.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Round button for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// A subclass of Fl_Button that always draws as a round circle. This
+// circle is smaller than the widget size and can be surrounded by
+// another box type, for compatability with Forms.
+
+#include <FL/Fl.H>
+#include <FL/Fl_Round_Button.H>
+
+Fl_Round_Button::Fl_Round_Button(int X,int Y,int W,int H, const char *l)
+: Fl_Light_Button(X,Y,W,H,l) {
+ box(FL_NO_BOX);
+ down_box(FL_ROUND_DOWN_BOX);
+ selection_color(FL_FOREGROUND_COLOR);
+}
+
+//
+// End of "$Id: Fl_Round_Button.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Scroll.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Scroll.cxx new file mode 100644 index 0000000..5b07ad3 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Scroll.cxx @@ -0,0 +1,298 @@ +//
+// "$Id: Fl_Scroll.cxx 6927 2009-11-07 21:02:52Z matt $"
+//
+// Scroll widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2006 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_Tiled_Image.H>
+#include <FL/Fl_Scroll.H>
+#include <FL/fl_draw.H>
+
+// Clear all but the scrollbars...
+void Fl_Scroll::clear() {
+ for (int i=children() - 1; i >= 0; i --) {
+ Fl_Widget* o = child(i);
+ if (o != &hscrollbar && o != &scrollbar) {
+ remove(o);
+ delete o;
+ }
+ }
+}
+
+// Insure the scrollbars are the last children:
+void Fl_Scroll::fix_scrollbar_order() {
+ Fl_Widget** a = (Fl_Widget**)array();
+ if (a[children()-1] != &scrollbar) {
+ int i,j; for (i = j = 0; j < children(); j++)
+ if (a[j] != &hscrollbar && a[j] != &scrollbar) a[i++] = a[j];
+ a[i++] = &hscrollbar;
+ a[i++] = &scrollbar;
+ }
+}
+
+void Fl_Scroll::draw_clip(void* v,int X, int Y, int W, int H) {
+ fl_clip(X,Y,W,H);
+ Fl_Scroll* s = (Fl_Scroll*)v;
+ // erase background as needed...
+ switch (s->box()) {
+ case FL_NO_BOX :
+ case FL_UP_FRAME :
+ case FL_DOWN_FRAME :
+ case FL_THIN_UP_FRAME :
+ case FL_THIN_DOWN_FRAME :
+ case FL_ENGRAVED_FRAME :
+ case FL_EMBOSSED_FRAME :
+ case FL_BORDER_FRAME :
+ case _FL_SHADOW_FRAME :
+ case _FL_ROUNDED_FRAME :
+ case _FL_OVAL_FRAME :
+ case _FL_PLASTIC_UP_FRAME :
+ case _FL_PLASTIC_DOWN_FRAME :
+ if (s->parent() == (Fl_Group *)s->window() && Fl::scheme_bg_) {
+ Fl::scheme_bg_->draw(X-(X%((Fl_Tiled_Image *)Fl::scheme_bg_)->image()->w()),
+ Y-(Y%((Fl_Tiled_Image *)Fl::scheme_bg_)->image()->h()),
+ W+((Fl_Tiled_Image *)Fl::scheme_bg_)->image()->w(),
+ H+((Fl_Tiled_Image *)Fl::scheme_bg_)->image()->h());
+ break;
+ }
+
+ default :
+ fl_color(s->color());
+ fl_rectf(X,Y,W,H);
+ break;
+ }
+ Fl_Widget*const* a = s->array();
+ for (int i=s->children()-2; i--;) {
+ Fl_Widget& o = **a++;
+ s->draw_child(o);
+ s->draw_outside_label(o);
+ }
+ fl_pop_clip();
+}
+
+void Fl_Scroll::bbox(int& X, int& Y, int& W, int& H) {
+ X = x()+Fl::box_dx(box());
+ Y = y()+Fl::box_dy(box());
+ W = w()-Fl::box_dw(box());
+ H = h()-Fl::box_dh(box());
+ if (scrollbar.visible()) {
+ W -= scrollbar.w();
+ if (scrollbar.align() & FL_ALIGN_LEFT) X += scrollbar.w();
+ }
+ if (hscrollbar.visible()) {
+ H -= hscrollbar.h();
+ if (scrollbar.align() & FL_ALIGN_TOP) Y += hscrollbar.h();
+ }
+}
+
+void Fl_Scroll::draw() {
+ fix_scrollbar_order();
+ int X,Y,W,H; bbox(X,Y,W,H);
+
+ uchar d = damage();
+
+ if (d & FL_DAMAGE_ALL) { // full redraw
+ draw_box(box(),x(),y(),w(),h(),color());
+ draw_clip(this, X, Y, W, H);
+ } else {
+ if (d & FL_DAMAGE_SCROLL) {
+ // scroll the contents:
+ fl_scroll(X, Y, W, H, oldx-xposition_, oldy-yposition_, draw_clip, this);
+
+ // Erase the background as needed...
+ Fl_Widget*const* a = array();
+ int L, R, T, B;
+ L = 999999;
+ R = 0;
+ T = 999999;
+ B = 0;
+ for (int i=children()-2; i--; a++) {
+ if ((*a)->x() < L) L = (*a)->x();
+ if (((*a)->x() + (*a)->w()) > R) R = (*a)->x() + (*a)->w();
+ if ((*a)->y() < T) T = (*a)->y();
+ if (((*a)->y() + (*a)->h()) > B) B = (*a)->y() + (*a)->h();
+ }
+ if (L > X) draw_clip(this, X, Y, L - X, H);
+ if (R < (X + W)) draw_clip(this, R, Y, X + W - R, H);
+ if (T > Y) draw_clip(this, X, Y, W, T - Y);
+ if (B < (Y + H)) draw_clip(this, X, B, W, Y + H - B);
+ }
+ if (d & FL_DAMAGE_CHILD) { // draw damaged children
+ fl_clip(X, Y, W, H);
+ Fl_Widget*const* a = array();
+ for (int i=children()-2; i--;) update_child(**a++);
+ fl_pop_clip();
+ }
+ }
+
+ // accumulate bounding box of children:
+ int l = X; int r = X; int t = Y; int b = Y;
+ Fl_Widget*const* a = array();
+ for (int i=children()-2; i--;) {
+ Fl_Object* o = *a++;
+ if (o->x() < l) l = o->x();
+ if (o->y() < t) t = o->y();
+ if (o->x()+o->w() > r) r = o->x()+o->w();
+ if (o->y()+o->h() > b) b = o->y()+o->h();
+ }
+
+ // turn the scrollbars on and off as necessary:
+ // See if children would fit if we had no scrollbars...
+ X = x()+Fl::box_dx(box());
+ Y = y()+Fl::box_dy(box());
+ W = w()-Fl::box_dw(box());
+ H = h()-Fl::box_dh(box());
+ int vneeded = 0;
+ int hneeded = 0;
+ if (type() & VERTICAL) {
+ if ((type() & ALWAYS_ON) || t < Y || b > Y+H) {
+ vneeded = 1;
+ W -= scrollbar.w();
+ if (scrollbar.align() & FL_ALIGN_LEFT) X += scrollbar.w();
+ }
+ }
+ if (type() & HORIZONTAL) {
+ if ((type() & ALWAYS_ON) || l < X || r > X+W) {
+ hneeded = 1;
+ H -= hscrollbar.h();
+ if (scrollbar.align() & FL_ALIGN_TOP) Y += hscrollbar.h();
+ // recheck vertical since we added a horizontal scrollbar
+ if (!vneeded && (type() & VERTICAL)) {
+ if ((type() & ALWAYS_ON) || t < Y || b > Y+H) {
+ vneeded = 1;
+ W -= scrollbar.w();
+ if (scrollbar.align() & FL_ALIGN_LEFT) X += scrollbar.w();
+ }
+ }
+ }
+ }
+ // Now that we know what's needed, make it so.
+ if (vneeded && !scrollbar.visible()) {
+ scrollbar.set_visible();
+ d = FL_DAMAGE_ALL;
+ }
+ else if (!vneeded && scrollbar.visible()) {
+ scrollbar.clear_visible();
+ draw_clip(this,
+ scrollbar.align()&FL_ALIGN_LEFT ? X : X+W-scrollbar.w(),
+ Y, scrollbar.w(), H);
+ d = FL_DAMAGE_ALL;
+ }
+ if (hneeded && !hscrollbar.visible()) {
+ hscrollbar.set_visible();
+ d = FL_DAMAGE_ALL;
+ }
+ else if (!hneeded && hscrollbar.visible()) {
+ hscrollbar.clear_visible();
+ draw_clip(this,
+ X, scrollbar.align()&FL_ALIGN_TOP ? Y : Y+H-hscrollbar.h(),
+ W, hscrollbar.h());
+ d = FL_DAMAGE_ALL;
+ }
+
+ scrollbar.resize(scrollbar.align()&FL_ALIGN_LEFT ? X-scrollbar.w() : X+W,
+ Y, scrollbar.w(), H);
+ scrollbar.value(oldy = yposition_ = (Y-t), H, 0, b-t);
+
+ hscrollbar.resize(X,
+ scrollbar.align()&FL_ALIGN_TOP ? Y-hscrollbar.h() : Y+H,
+ W, hscrollbar.h());
+ hscrollbar.value(oldx = xposition_ = (X-l), W, 0, r-l);
+
+ // draw the scrollbars:
+ if (d & FL_DAMAGE_ALL) {
+ draw_child(scrollbar);
+ draw_child(hscrollbar);
+ if (scrollbar.visible() && hscrollbar.visible()) {
+ // fill in the little box in the corner
+ fl_color(color());
+ fl_rectf(scrollbar.x(), hscrollbar.y(), scrollbar.w(), hscrollbar.h());
+ }
+ } else {
+ update_child(scrollbar);
+ update_child(hscrollbar);
+ }
+}
+
+void Fl_Scroll::resize(int X, int Y, int W, int H) {
+ int dx = X-x(), dy = Y-y();
+ Fl_Widget::resize(X,Y,W,H); // resize _before_ moving children around
+ fix_scrollbar_order();
+ // move all the children:
+ Fl_Widget*const* a = array();
+ for (int i=children()-2; i--;) {
+ Fl_Object* o = *a++;
+ o->position(o->x()+dx, o->y()+dy);
+ }
+}
+
+void Fl_Scroll::position(int X, int Y) {
+ int dx = xposition_-X;
+ int dy = yposition_-Y;
+ if (!dx && !dy) return;
+ xposition_ = X;
+ yposition_ = Y;
+ Fl_Widget*const* a = array();
+ for (int i=children(); i--;) {
+ Fl_Widget* o = *a++;
+ if (o == &hscrollbar || o == &scrollbar) continue;
+ o->position(o->x()+dx, o->y()+dy);
+ }
+ if (parent() == (Fl_Group *)window() && Fl::scheme_bg_) damage(FL_DAMAGE_ALL);
+ else damage(FL_DAMAGE_SCROLL);
+}
+
+void Fl_Scroll::hscrollbar_cb(Fl_Widget* o, void*) {
+ Fl_Scroll* s = (Fl_Scroll*)(o->parent());
+ s->position(int(((Fl_Scrollbar*)o)->value()), s->yposition());
+}
+
+void Fl_Scroll::scrollbar_cb(Fl_Widget* o, void*) {
+ Fl_Scroll* s = (Fl_Scroll*)(o->parent());
+ s->position(s->xposition(), int(((Fl_Scrollbar*)o)->value()));
+}
+
+Fl_Scroll::Fl_Scroll(int X,int Y,int W,int H,const char* L)
+ : Fl_Group(X,Y,W,H,L),
+ scrollbar(X+W-Fl::scrollbar_size(),Y,
+ Fl::scrollbar_size(),H-Fl::scrollbar_size()),
+ hscrollbar(X,Y+H-Fl::scrollbar_size(),
+ W-Fl::scrollbar_size(),Fl::scrollbar_size()) {
+ type(BOTH);
+ xposition_ = oldx = 0;
+ yposition_ = oldy = 0;
+ hscrollbar.type(FL_HORIZONTAL);
+ hscrollbar.callback(hscrollbar_cb);
+ scrollbar.callback(scrollbar_cb);
+}
+
+int Fl_Scroll::handle(int event) {
+ fix_scrollbar_order();
+ return Fl_Group::handle(event);
+}
+
+//
+// End of "$Id: Fl_Scroll.cxx 6927 2009-11-07 21:02:52Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Scrollbar.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Scrollbar.cxx new file mode 100644 index 0000000..f3a43c7 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Scrollbar.cxx @@ -0,0 +1,277 @@ +//
+// "$Id: Fl_Scrollbar.cxx 6042 2008-02-25 13:00:53Z matt $"
+//
+// Scroll bar widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2006 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_Scrollbar.H>
+#include <FL/fl_draw.H>
+#include <math.h>
+#include "flstring.h"
+
+#define INITIALREPEAT .5
+#define REPEAT .05
+
+void Fl_Scrollbar::increment_cb() {
+ int ls = maximum()>=minimum() ? linesize_ : -linesize_;
+ int i;
+ switch (pushed_) {
+ case 1:
+ i = -ls;
+ break;
+ default:
+ i = ls;
+ break;
+ case 5:
+ i = -int((maximum()-minimum())*slider_size()/(1.0-slider_size())) + ls;
+ if (i > -ls) i = -ls;
+ break;
+ case 6:
+ i = int((maximum()-minimum())*slider_size()/(1.0-slider_size())) - ls;
+ if (i < ls) i = ls;
+ break;
+ }
+ handle_drag(clamp(value() + i));
+}
+
+void Fl_Scrollbar::timeout_cb(void* v) {
+ Fl_Scrollbar* s = (Fl_Scrollbar*)v;
+ s->increment_cb();
+ Fl::add_timeout(REPEAT, timeout_cb, s);
+}
+
+int Fl_Scrollbar::handle(int event) {
+ // area of scrollbar:
+ int area;
+ int X=x(); int Y=y(); int W=w(); int H=h();
+
+ // adjust slider area to be inside the arrow buttons:
+ if (horizontal()) {
+ if (W >= 3*H) {X += H; W -= 2*H;}
+ } else {
+ if (H >= 3*W) {Y += W; H -= 2*W;}
+ }
+
+ // which widget part is highlighted?
+ int relx;
+ int ww;
+ if (horizontal()) {
+ relx = Fl::event_x()-X;
+ ww = W;
+ } else {
+ relx = Fl::event_y()-Y;
+ ww = H;
+ }
+ if (relx < 0) area = 1;
+ else if (relx >= ww) area = 2;
+ else {
+ int S = int(slider_size()*ww+.5);
+ int T = (horizontal() ? H : W)/2+1;
+ if (type()==FL_VERT_NICE_SLIDER || type()==FL_HOR_NICE_SLIDER) T += 4;
+ if (S < T) S = T;
+ double val =
+ (maximum()-minimum()) ? (value()-minimum())/(maximum()-minimum()) : 0.5;
+ int sliderx;
+ if (val >= 1.0) sliderx = ww-S;
+ else if (val <= 0.0) sliderx = 0;
+ else sliderx = int(val*(ww-S)+.5);
+ if (Fl::event_button() == FL_MIDDLE_MOUSE) area = 8;
+ else if (relx < sliderx) area = 5;
+ else if (relx >= sliderx+S) area = 6;
+ else area = 8;
+ }
+
+ switch (event) {
+ case FL_ENTER:
+ case FL_LEAVE:
+ return 1;
+ case FL_RELEASE:
+ damage(FL_DAMAGE_ALL);
+ if (pushed_) {
+ Fl::remove_timeout(timeout_cb, this);
+ pushed_ = 0;
+ }
+ handle_release();
+ return 1;
+ case FL_PUSH:
+ if (pushed_) return 1;
+ if (area != 8) pushed_ = area;
+ if (pushed_) {
+ handle_push();
+ Fl::add_timeout(INITIALREPEAT, timeout_cb, this);
+ increment_cb();
+ damage(FL_DAMAGE_ALL);
+ return 1;
+ }
+ return Fl_Slider::handle(event, X,Y,W,H);
+ case FL_DRAG:
+ if (pushed_) return 1;
+ return Fl_Slider::handle(event, X,Y,W,H);
+ case FL_MOUSEWHEEL :
+ if (horizontal()) {
+ if (Fl::e_dx==0) return 0;
+ handle_drag(clamp(value() + linesize_ * Fl::e_dx));
+ return 1;
+ } else {
+ if (Fl::e_dy==0) return 0;
+ handle_drag(clamp(value() + linesize_ * Fl::e_dy));
+ return 1;
+ }
+ case FL_SHORTCUT:
+ case FL_KEYBOARD: {
+ int v = value();
+ int ls = maximum()>=minimum() ? linesize_ : -linesize_;
+ if (horizontal()) {
+ switch (Fl::event_key()) {
+ case FL_Left:
+ v -= ls;
+ break;
+ case FL_Right:
+ v += ls;
+ break;
+ default:
+ return 0;
+ }
+ } else { // vertical
+ switch (Fl::event_key()) {
+ case FL_Up:
+ v -= ls;
+ break;
+ case FL_Down:
+ v += ls;
+ break;
+ case FL_Page_Up:
+ if (slider_size() >= 1.0) return 0;
+ v -= int((maximum()-minimum())*slider_size()/(1.0-slider_size()));
+ v += ls;
+ break;
+ case FL_Page_Down:
+ if (slider_size() >= 1.0) return 0;
+ v += int((maximum()-minimum())*slider_size()/(1.0-slider_size()));
+ v -= ls;
+ break;
+ case FL_Home:
+ v = int(minimum());
+ break;
+ case FL_End:
+ v = int(maximum());
+ break;
+ default:
+ return 0;
+ }
+ }
+ v = int(clamp(v));
+ if (v != value()) {
+ Fl_Slider::value(v);
+ value_damage();
+ set_changed();
+ do_callback();
+ }
+ return 1;}
+ }
+ return 0;
+}
+
+void Fl_Scrollbar::draw() {
+ if (damage()&FL_DAMAGE_ALL) draw_box();
+ int X = x()+Fl::box_dx(box());
+ int Y = y()+Fl::box_dy(box());
+ int W = w()-Fl::box_dw(box());
+ int H = h()-Fl::box_dh(box());
+ if (horizontal()) {
+ if (W < 3*H) {Fl_Slider::draw(X,Y,W,H); return;}
+ Fl_Slider::draw(X+H,Y,W-2*H,H);
+ if (damage()&FL_DAMAGE_ALL) {
+ draw_box((pushed_==1) ? fl_down(slider()) : slider(),
+ X, Y, H, H, selection_color());
+ draw_box((pushed_==2) ? fl_down(slider()) : slider(),
+ X+W-H, Y, H, H, selection_color());
+ if (active_r())
+ fl_color(labelcolor());
+ else
+ fl_color(fl_inactive(labelcolor()));
+ int w1 = (H-4)/3; if (w1 < 1) w1 = 1;
+ int x1 = X+(H-w1-1)/2;
+ int yy1 = Y+(H-2*w1-1)/2;
+ if (Fl::scheme_ && !strcmp(Fl::scheme_, "gtk+")) {
+ fl_polygon(x1, yy1+w1, x1+w1, yy1+2*w1, x1+w1-1, yy1+w1, x1+w1, yy1);
+ x1 += (W-H);
+ fl_polygon(x1, yy1, x1+1, yy1+w1, x1, yy1+2*w1, x1+w1, yy1+w1);
+ } else {
+ fl_polygon(x1, yy1+w1, x1+w1, yy1+2*w1, x1+w1, yy1);
+ x1 += (W-H);
+ fl_polygon(x1, yy1, x1, yy1+2*w1, x1+w1, yy1+w1);
+ }
+ }
+ } else { // vertical
+ if (H < 3*W) {Fl_Slider::draw(X,Y,W,H); return;}
+ Fl_Slider::draw(X,Y+W,W,H-2*W);
+ if (damage()&FL_DAMAGE_ALL) {
+ draw_box((pushed_==1) ? fl_down(slider()) : slider(),
+ X, Y, W, W, selection_color());
+ draw_box((pushed_==2) ? fl_down(slider()) : slider(),
+ X, Y+H-W, W, W, selection_color());
+ if (active_r())
+ fl_color(labelcolor());
+ else
+ fl_color(fl_inactive(labelcolor()));
+ int w1 = (W-4)/3; if (w1 < 1) w1 = 1;
+ int x1 = X+(W-2*w1-1)/2;
+ int yy1 = Y+(W-w1-1)/2;
+ if (Fl::scheme_ && !strcmp(Fl::scheme_, "gtk+")) {
+ fl_polygon(x1, yy1+w1, x1+w1, yy1+w1-1, x1+2*w1, yy1+w1, x1+w1, yy1);
+ yy1 += H-W;
+ fl_polygon(x1, yy1, x1+w1, yy1+1, x1+w1, yy1+w1);
+ fl_polygon(x1+w1, yy1+1, x1+2*w1, yy1, x1+w1, yy1+w1);
+ } else {
+ fl_polygon(x1, yy1+w1, x1+2*w1, yy1+w1, x1+w1, yy1);
+ yy1 += H-W;
+ fl_polygon(x1, yy1, x1+w1, yy1+w1, x1+2*w1, yy1);
+ }
+ }
+ }
+}
+
+Fl_Scrollbar::Fl_Scrollbar(int X, int Y, int W, int H, const char* L)
+ : Fl_Slider(X, Y, W, H, L)
+{
+ box(FL_FLAT_BOX);
+ color(FL_DARK2);
+ slider(FL_UP_BOX);
+ linesize_ = 16;
+ pushed_ = 0;
+ step(1);
+}
+
+Fl_Scrollbar::~Fl_Scrollbar()
+{
+ if (pushed_)
+ Fl::remove_timeout(timeout_cb, this);
+}
+
+
+//
+// End of "$Id: Fl_Scrollbar.cxx 6042 2008-02-25 13:00:53Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Shared_Image.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Shared_Image.cxx new file mode 100644 index 0000000..365e904 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Shared_Image.cxx @@ -0,0 +1,467 @@ +//
+// "$Id: Fl_Shared_Image.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Shared image code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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 <stdio.h>
+#include <stdlib.h>
+#include "flstring.h"
+
+#include <FL/Fl.H>
+#include <FL/Fl_Shared_Image.H>
+#include <FL/Fl_XBM_Image.H>
+#include <FL/Fl_XPM_Image.H>
+
+
+//
+// Global class vars...
+//
+
+Fl_Shared_Image **Fl_Shared_Image::images_ = 0; // Shared images
+int Fl_Shared_Image::num_images_ = 0; // Number of shared images
+int Fl_Shared_Image::alloc_images_ = 0; // Allocated shared images
+
+Fl_Shared_Handler *Fl_Shared_Image::handlers_ = 0;// Additional format handlers
+int Fl_Shared_Image::num_handlers_ = 0; // Number of format handlers
+int Fl_Shared_Image::alloc_handlers_ = 0; // Allocated format handlers
+
+
+//
+// Typedef the C API sort function type the only way I know how...
+//
+
+extern "C" {
+ typedef int (*compare_func_t)(const void *, const void *);
+}
+
+
+// Static methods that really should be inline, but some WIN32 compilers
+// can't handle it...
+Fl_Shared_Image **Fl_Shared_Image::images() {
+ return images_;
+}
+
+int Fl_Shared_Image::num_images() {
+ return num_images_;
+}
+
+
+//
+// 'Fl_Shared_Image::compare()' - Compare two shared images...
+//
+
+int
+Fl_Shared_Image::compare(Fl_Shared_Image **i0, // I - First image
+ Fl_Shared_Image **i1) { // I - Second image
+ int i = strcmp((*i0)->name(), (*i1)->name());
+
+ if (i) return i;
+ else if (((*i0)->w() == 0 && (*i1)->original_) ||
+ ((*i1)->w() == 0 && (*i0)->original_)) return 0;
+ else if ((*i0)->w() != (*i1)->w()) return (*i0)->w() - (*i1)->w();
+ else return (*i0)->h() - (*i1)->h();
+}
+
+
+//
+// 'Fl_Shared_Image::Fl_Shared_Image()' - Basic constructor.
+//
+
+Fl_Shared_Image::Fl_Shared_Image() : Fl_Image(0,0,0) {
+ name_ = 0;
+ refcount_ = 1;
+ original_ = 0;
+ image_ = 0;
+ alloc_image_ = 0;
+}
+
+
+//
+// 'Fl_Shared_Image::Fl_Shared_Image()' - Add an image to the image cache.
+//
+
+Fl_Shared_Image::Fl_Shared_Image(const char *n, // I - Filename
+ Fl_Image *img) // I - Image
+ : Fl_Image(0,0,0) {
+ name_ = new char[strlen(n) + 1];
+ strcpy((char *)name_, n);
+
+ refcount_ = 1;
+ image_ = img;
+ alloc_image_ = !img;
+ original_ = 1;
+
+ if (!img) reload();
+ else update();
+}
+
+
+//
+// 'Fl_Shared_Image::add()' - Add a shared image to the array.
+//
+
+void
+Fl_Shared_Image::add() {
+ Fl_Shared_Image **temp; // New image pointer array...
+
+ if (num_images_ >= alloc_images_) {
+ // Allocate more memory...
+ temp = new Fl_Shared_Image *[alloc_images_ + 32];
+
+ if (alloc_images_) {
+ memcpy(temp, images_, alloc_images_ * sizeof(Fl_Shared_Image *));
+
+ delete[] images_;
+ }
+
+ images_ = temp;
+ alloc_images_ += 32;
+ }
+
+ images_[num_images_] = this;
+ num_images_ ++;
+
+ if (num_images_ > 1) {
+ qsort(images_, num_images_, sizeof(Fl_Shared_Image *),
+ (compare_func_t)compare);
+ }
+}
+
+
+//
+// 'Fl_Shared_Image::update()' - Update the dimensions of the shared images.
+//
+
+void
+Fl_Shared_Image::update() {
+ if (image_) {
+ w(image_->w());
+ h(image_->h());
+ d(image_->d());
+ data(image_->data(), image_->count());
+ }
+}
+
+
+//
+// 'Fl_Shared_Image::~Fl_Shared_Image()' - Destroy a shared image...
+//
+
+Fl_Shared_Image::~Fl_Shared_Image() {
+ if (name_) delete[] (char *)name_;
+ if (alloc_image_) delete image_;
+}
+
+
+//
+// 'Fl_Shared_Image::release()' - Release and possibly destroy a shared image.
+//
+
+void
+Fl_Shared_Image::release() {
+ int i; // Looping var...
+
+ refcount_ --;
+ if (refcount_ > 0) return;
+
+ for (i = 0; i < num_images_; i ++)
+ if (images_[i] == this) {
+ num_images_ --;
+
+ if (i < num_images_) {
+ memmove(images_ + i, images_ + i + 1,
+ (num_images_ - i) * sizeof(Fl_Shared_Image *));
+ }
+
+ break;
+ }
+
+ delete this;
+
+ if (num_images_ == 0 && images_) {
+ delete[] images_;
+
+ images_ = 0;
+ alloc_images_ = 0;
+ }
+}
+
+
+//
+// 'Fl_Shared_Image::reload()' - Reload the shared image...
+//
+
+void
+Fl_Shared_Image::reload() {
+ // Load image from disk...
+ int i; // Looping var
+ FILE *fp; // File pointer
+ uchar header[64]; // Buffer for auto-detecting files
+ Fl_Image *img; // New image
+
+ if (!name_) return;
+
+ if ((fp = fopen(name_, "rb")) != NULL) {
+ fread(header, 1, sizeof(header), fp);
+ fclose(fp);
+ } else {
+ return;
+ }
+
+ // Load the image as appropriate...
+ if (memcmp(header, "#define", 7) == 0) // XBM file
+ img = new Fl_XBM_Image(name_);
+ else if (memcmp(header, "/* XPM */", 9) == 0) // XPM file
+ img = new Fl_XPM_Image(name_);
+ else {
+ // Not a standard format; try an image handler...
+ for (i = 0, img = 0; i < num_handlers_; i ++) {
+ img = (handlers_[i])(name_, header, sizeof(header));
+
+ if (img) break;
+ }
+ }
+
+ if (img) {
+ if (alloc_image_) delete image_;
+
+ alloc_image_ = 1;
+
+ if ((img->w() != w() && w()) || (img->h() != h() && h())) {
+ // Make sure the reloaded image is the same size as the existing one.
+ Fl_Image *temp = img->copy(w(), h());
+ delete img;
+ image_ = temp;
+ } else {
+ image_ = img;
+ }
+
+ update();
+ }
+}
+
+
+//
+// 'Fl_Shared_Image::copy()' - Copy and resize a shared image...
+//
+
+Fl_Image *
+Fl_Shared_Image::copy(int W, int H) {
+ Fl_Image *temp_image; // New image file
+ Fl_Shared_Image *temp_shared; // New shared image
+
+ // Make a copy of the image we're sharing...
+ if (!image_) temp_image = 0;
+ else temp_image = image_->copy(W, H);
+
+ // Then make a new shared image...
+ temp_shared = new Fl_Shared_Image();
+
+ temp_shared->name_ = new char[strlen(name_) + 1];
+ strcpy((char *)temp_shared->name_, name_);
+
+ temp_shared->refcount_ = 1;
+ temp_shared->image_ = temp_image;
+ temp_shared->alloc_image_ = 1;
+
+ temp_shared->update();
+
+ return temp_shared;
+}
+
+
+//
+// 'Fl_Shared_Image::color_average()' - Blend colors...
+//
+
+void
+Fl_Shared_Image::color_average(Fl_Color c, // I - Color to blend with
+ float i) { // I - Blend fraction
+ if (!image_) return;
+
+ image_->color_average(c, i);
+ update();
+}
+
+
+//
+// 'Fl_Shared_Image::desaturate()' - Convert the image to grayscale...
+//
+
+void
+Fl_Shared_Image::desaturate() {
+ if (!image_) return;
+
+ image_->desaturate();
+ update();
+}
+
+
+//
+// 'Fl_Shared_Image::draw()' - Draw a shared image...
+//
+
+void
+Fl_Shared_Image::draw(int X, int Y, int W, int H, int cx, int cy) {
+ if (image_) image_->draw(X, Y, W, H, cx, cy);
+ else Fl_Image::draw(X, Y, W, H, cx, cy);
+}
+
+
+//
+// 'Fl_Shared_Image::uncache()' - Uncache the shared image...
+//
+
+void
+Fl_Shared_Image::uncache()
+{
+ if (image_) image_->uncache();
+}
+
+
+//
+// 'Fl_Shared_Image::find()' - Find a shared image...
+//
+
+Fl_Shared_Image *
+Fl_Shared_Image::find(const char *n, int W, int H) {
+ Fl_Shared_Image *key, // Image key
+ **match; // Matching image
+
+ if (num_images_) {
+ key = new Fl_Shared_Image();
+ key->name_ = new char[strlen(n) + 1];
+ strcpy((char *)key->name_, n);
+ key->w(W);
+ key->h(H);
+
+ match = (Fl_Shared_Image **)bsearch(&key, images_, num_images_,
+ sizeof(Fl_Shared_Image *),
+ (compare_func_t)compare);
+
+ delete key;
+
+ if (match) {
+ (*match)->refcount_ ++;
+ return *match;
+ }
+ }
+
+ return 0;
+}
+
+
+//
+// 'Fl_Shared_Image::get()' - Get a shared image...
+//
+
+Fl_Shared_Image *
+Fl_Shared_Image::get(const char *n, int W, int H) {
+ Fl_Shared_Image *temp; // Image
+
+ if ((temp = find(n, W, H)) != NULL) return temp;
+
+ if ((temp = find(n)) == NULL) {
+ temp = new Fl_Shared_Image(n);
+
+ if (!temp->image_) {
+ delete temp;
+ return NULL;
+ }
+
+ temp->add();
+ }
+
+ if ((temp->w() != W || temp->h() != H) && W && H) {
+ temp = (Fl_Shared_Image *)temp->copy(W, H);
+ temp->add();
+ }
+
+ return temp;
+}
+
+
+//
+// 'Fl_Shared_Image::add_handler()' - Add a shared image handler.
+//
+
+void
+Fl_Shared_Image::add_handler(Fl_Shared_Handler f) {
+ int i; // Looping var...
+ Fl_Shared_Handler *temp; // New image handler array...
+
+ // First see if we have already added the handler...
+ for (i = 0; i < num_handlers_; i ++) {
+ if (handlers_[i] == f) return;
+ }
+
+ if (num_handlers_ >= alloc_handlers_) {
+ // Allocate more memory...
+ temp = new Fl_Shared_Handler [alloc_handlers_ + 32];
+
+ if (alloc_handlers_) {
+ memcpy(temp, handlers_, alloc_handlers_ * sizeof(Fl_Shared_Handler));
+
+ delete[] handlers_;
+ }
+
+ handlers_ = temp;
+ alloc_handlers_ += 32;
+ }
+
+ handlers_[num_handlers_] = f;
+ num_handlers_ ++;
+}
+
+
+//
+// 'Fl_Shared_Image::remove_handler()' - Remove a shared image handler.
+//
+
+void
+Fl_Shared_Image::remove_handler(Fl_Shared_Handler f) {
+ int i; // Looping var...
+
+ // First see if the handler has been added...
+ for (i = 0; i < num_handlers_; i ++) {
+ if (handlers_[i] == f) break;
+ }
+
+ if (i >= num_handlers_) return;
+
+ // OK, remove the handler from the array...
+ num_handlers_ --;
+
+ if (i < num_handlers_) {
+ // Shift later handlers down 1...
+ memmove(handlers_ + i, handlers_ + i + 1,
+ (num_handlers_ - i) * sizeof(Fl_Shared_Handler ));
+ }
+}
+
+
+//
+// End of "$Id: Fl_Shared_Image.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Single_Window.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Single_Window.cxx new file mode 100644 index 0000000..380ae94 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Single_Window.cxx @@ -0,0 +1,41 @@ +//
+// "$Id: Fl_Single_Window.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Single-buffered window for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// A window with a single-buffered context
+//
+// This is provided for systems where the base class is double
+// buffered. You can turn it off using this subclass in case
+// your display looks better without it.
+
+#include <FL/Fl_Single_Window.H>
+
+void Fl_Single_Window::show() {Fl_Window::show();}
+void Fl_Single_Window::flush() {Fl_Window::flush();}
+
+//
+// End of "$Id: Fl_Single_Window.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Slider.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Slider.cxx new file mode 100644 index 0000000..5776ef6 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Slider.cxx @@ -0,0 +1,339 @@ +//
+// "$Id: Fl_Slider.cxx 5438 2006-09-17 14:58:25Z mike $"
+//
+// Slider widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2006 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_Slider.H>
+#include <FL/fl_draw.H>
+#include <math.h>
+#include "flstring.h"
+
+void Fl_Slider::_Fl_Slider() {
+ slider_size_ = 0;
+ slider_ = 0; // FL_UP_BOX;
+}
+
+Fl_Slider::Fl_Slider(int X, int Y, int W, int H, const char* l)
+: Fl_Valuator(X, Y, W, H, l) {
+ box(FL_DOWN_BOX);
+ _Fl_Slider();
+}
+
+Fl_Slider::Fl_Slider(uchar t, int X, int Y, int W, int H, const char* l)
+ : Fl_Valuator(X, Y, W, H, l) {
+ type(t);
+ box(t==FL_HOR_NICE_SLIDER || t==FL_VERT_NICE_SLIDER ?
+ FL_FLAT_BOX : FL_DOWN_BOX);
+ _Fl_Slider();
+}
+
+void Fl_Slider::slider_size(double v) {
+ if (v < 0) v = 0;
+ if (v > 1) v = 1;
+ if (slider_size_ != float(v)) {
+ slider_size_ = float(v);
+ damage(FL_DAMAGE_EXPOSE);
+ }
+}
+
+void Fl_Slider::bounds(double a, double b) {
+ if (minimum() != a || maximum() != b) {
+ Fl_Valuator::bounds(a, b);
+ damage(FL_DAMAGE_EXPOSE);
+ }
+}
+
+int Fl_Slider::scrollvalue(int p, int W, int t, int l) {
+// p = position, first line displayed
+// w = window, number of lines displayed
+// t = top, number of first line
+// l = length, total number of lines
+ step(1, 1);
+ if (p+W > t+l) l = p+W-t;
+ slider_size(W >= l ? 1.0 : double(W)/double(l));
+ bounds(t, l-W+t);
+ return value(p);
+}
+
+// All slider interaction is done as though the slider ranges from
+// zero to one, and the left (bottom) edge of the slider is at the
+// given position. Since when the slider is all the way to the
+// right (top) the left (bottom) edge is not all the way over, a
+// position on the widget itself covers a wider range than 0-1,
+// actually it ranges from 0 to 1/(1-size).
+
+void Fl_Slider::draw_bg(int X, int Y, int W, int H) {
+ fl_push_clip(X, Y, W, H);
+ draw_box();
+ fl_pop_clip();
+
+ Fl_Color black = active_r() ? FL_FOREGROUND_COLOR : FL_INACTIVE_COLOR;
+ if (type() == FL_VERT_NICE_SLIDER) {
+ draw_box(FL_THIN_DOWN_BOX, X+W/2-2, Y, 4, H, black);
+ } else if (type() == FL_HOR_NICE_SLIDER) {
+ draw_box(FL_THIN_DOWN_BOX, X, Y+H/2-2, W, 4, black);
+ }
+}
+
+void Fl_Slider::draw(int X, int Y, int W, int H) {
+
+ double val;
+ if (minimum() == maximum())
+ val = 0.5;
+ else {
+ val = (value()-minimum())/(maximum()-minimum());
+ if (val > 1.0) val = 1.0;
+ else if (val < 0.0) val = 0.0;
+ }
+
+ int ww = (horizontal() ? W : H);
+ int xx, S;
+ if (type()==FL_HOR_FILL_SLIDER || type() == FL_VERT_FILL_SLIDER) {
+ S = int(val*ww+.5);
+ if (minimum()>maximum()) {S = ww-S; xx = ww-S;}
+ else xx = 0;
+ } else {
+ S = int(slider_size_*ww+.5);
+ int T = (horizontal() ? H : W)/2+1;
+ if (type()==FL_VERT_NICE_SLIDER || type()==FL_HOR_NICE_SLIDER) T += 4;
+ if (S < T) S = T;
+ xx = int(val*(ww-S)+.5);
+ }
+ int xsl, ysl, wsl, hsl;
+ if (horizontal()) {
+ xsl = X+xx;
+ wsl = S;
+ ysl = Y;
+ hsl = H;
+ } else {
+ ysl = Y+xx;
+ hsl = S;
+ xsl = X;
+ wsl = W;
+ }
+
+ draw_bg(X, Y, W, H);
+
+ Fl_Boxtype box1 = slider();
+ if (!box1) {box1 = (Fl_Boxtype)(box()&-2); if (!box1) box1 = FL_UP_BOX;}
+ if (type() == FL_VERT_NICE_SLIDER) {
+ draw_box(box1, xsl, ysl, wsl, hsl, FL_GRAY);
+ int d = (hsl-4)/2;
+ draw_box(FL_THIN_DOWN_BOX, xsl+2, ysl+d, wsl-4, hsl-2*d,selection_color());
+ } else if (type() == FL_HOR_NICE_SLIDER) {
+ draw_box(box1, xsl, ysl, wsl, hsl, FL_GRAY);
+ int d = (wsl-4)/2;
+ draw_box(FL_THIN_DOWN_BOX, xsl+d, ysl+2, wsl-2*d, hsl-4,selection_color());
+ } else {
+ if (wsl>0 && hsl>0) draw_box(box1, xsl, ysl, wsl, hsl, selection_color());
+
+ if (type()!=FL_HOR_FILL_SLIDER && type() != FL_VERT_FILL_SLIDER &&
+ Fl::scheme_ && !strcmp(Fl::scheme_, "gtk+")) {
+ if (W>H && wsl>(hsl+8)) {
+ // Draw horizontal grippers
+ int yy, hh;
+ hh = hsl-8;
+ xx = xsl+(wsl-hsl-4)/2;
+ yy = ysl+3;
+
+ fl_color(fl_darker(selection_color()));
+ fl_line(xx, yy+hh, xx+hh, yy);
+ fl_line(xx+6, yy+hh, xx+hh+6, yy);
+ fl_line(xx+12, yy+hh, xx+hh+12, yy);
+
+ xx++;
+ fl_color(fl_lighter(selection_color()));
+ fl_line(xx, yy+hh, xx+hh, yy);
+ fl_line(xx+6, yy+hh, xx+hh+6, yy);
+ fl_line(xx+12, yy+hh, xx+hh+12, yy);
+ } else if (H>W && hsl>(wsl+8)) {
+ // Draw vertical grippers
+ int yy;
+ xx = xsl+4;
+ ww = wsl-8;
+ yy = ysl+(hsl-wsl-4)/2;
+
+ fl_color(fl_darker(selection_color()));
+ fl_line(xx, yy+ww, xx+ww, yy);
+ fl_line(xx, yy+ww+6, xx+ww, yy+6);
+ fl_line(xx, yy+ww+12, xx+ww, yy+12);
+
+ yy++;
+ fl_color(fl_lighter(selection_color()));
+ fl_line(xx, yy+ww, xx+ww, yy);
+ fl_line(xx, yy+ww+6, xx+ww, yy+6);
+ fl_line(xx, yy+ww+12, xx+ww, yy+12);
+ }
+ }
+ }
+
+ draw_label(xsl, ysl, wsl, hsl);
+ if (Fl::focus() == this) {
+ if (type() == FL_HOR_FILL_SLIDER || type() == FL_VERT_FILL_SLIDER) draw_focus();
+ else draw_focus(box1, xsl, ysl, wsl, hsl);
+ }
+}
+
+void Fl_Slider::draw() {
+ if (damage()&FL_DAMAGE_ALL) draw_box();
+ draw(x()+Fl::box_dx(box()),
+ y()+Fl::box_dy(box()),
+ w()-Fl::box_dw(box()),
+ h()-Fl::box_dh(box()));
+}
+
+int Fl_Slider::handle(int event, int X, int Y, int W, int H) {
+ switch (event) {
+ case FL_PUSH:
+ if (!Fl::event_inside(X, Y, W, H)) return 0;
+ handle_push();
+ case FL_DRAG: {
+
+ double val;
+ if (minimum() == maximum())
+ val = 0.5;
+ else {
+ val = (value()-minimum())/(maximum()-minimum());
+ if (val > 1.0) val = 1.0;
+ else if (val < 0.0) val = 0.0;
+ }
+
+ int ww = (horizontal() ? W : H);
+ int mx = (horizontal() ? Fl::event_x()-X : Fl::event_y()-Y);
+ int S;
+ static int offcenter;
+
+ if (type() == FL_HOR_FILL_SLIDER || type() == FL_VERT_FILL_SLIDER) {
+
+ S = 0;
+ if (event == FL_PUSH) {
+ int xx = int(val*ww+.5);
+ offcenter = mx-xx;
+ if (offcenter < -10 || offcenter > 10) offcenter = 0;
+ else return 1;
+ }
+
+ } else {
+
+ S = int(slider_size_*ww+.5); if (S >= ww) return 0;
+ int T = (horizontal() ? H : W)/2+1;
+ if (type()==FL_VERT_NICE_SLIDER || type()==FL_HOR_NICE_SLIDER) T += 4;
+ if (S < T) S = T;
+ if (event == FL_PUSH) {
+ int xx = int(val*(ww-S)+.5);
+ offcenter = mx-xx;
+ if (offcenter < 0) offcenter = 0;
+ else if (offcenter > S) offcenter = S;
+ else return 1;
+ }
+ }
+
+ int xx = mx-offcenter;
+ double v;
+ char tryAgain = 1;
+ while (tryAgain)
+ {
+ tryAgain = 0;
+ if (xx < 0) {
+ xx = 0;
+ offcenter = mx; if (offcenter < 0) offcenter = 0;
+ } else if (xx > (ww-S)) {
+ xx = ww-S;
+ offcenter = mx-xx; if (offcenter > S) offcenter = S;
+ }
+ v = round(xx*(maximum()-minimum())/(ww-S) + minimum());
+ // make sure a click outside the sliderbar moves it:
+ if (event == FL_PUSH && v == value()) {
+ offcenter = S/2;
+ event = FL_DRAG;
+ tryAgain = 1;
+ }
+ }
+ handle_drag(clamp(v));
+ } return 1;
+ case FL_RELEASE:
+ handle_release();
+ return 1;
+ case FL_KEYBOARD :
+ switch (Fl::event_key()) {
+ case FL_Up:
+ if (horizontal()) return 0;
+ handle_push();
+ handle_drag(clamp(increment(value(),-1)));
+ handle_release();
+ return 1;
+ case FL_Down:
+ if (horizontal()) return 0;
+ handle_push();
+ handle_drag(clamp(increment(value(),1)));
+ handle_release();
+ return 1;
+ case FL_Left:
+ if (!horizontal()) return 0;
+ handle_push();
+ handle_drag(clamp(increment(value(),-1)));
+ handle_release();
+ return 1;
+ case FL_Right:
+ if (!horizontal()) return 0;
+ handle_push();
+ handle_drag(clamp(increment(value(),1)));
+ handle_release();
+ return 1;
+ default:
+ return 0;
+ }
+ // break not required because of switch...
+ case FL_FOCUS :
+ case FL_UNFOCUS :
+ if (Fl::visible_focus()) {
+ redraw();
+ return 1;
+ } else return 0;
+ case FL_ENTER :
+ case FL_LEAVE :
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+int Fl_Slider::handle(int event) {
+ if (event == FL_PUSH && Fl::visible_focus()) {
+ Fl::focus(this);
+ redraw();
+ }
+
+ return handle(event,
+ x()+Fl::box_dx(box()),
+ y()+Fl::box_dy(box()),
+ w()-Fl::box_dw(box()),
+ h()-Fl::box_dh(box()));
+}
+
+//
+// End of "$Id: Fl_Slider.cxx 5438 2006-09-17 14:58:25Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Sys_Menu_Bar.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Sys_Menu_Bar.cxx new file mode 100644 index 0000000..a8800ea --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Sys_Menu_Bar.cxx @@ -0,0 +1,334 @@ +//
+// "$Id: Fl_Sys_Menu_Bar.cxx 6016 2008-01-09 21:32:40Z matt $"
+//
+// MacOS system menu bar widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+/**
+ * This code is a quick hack! It was written as a proof of concept.
+ * It has been tested on the "menubar" sample program and provides
+ * basic functionality.
+ *
+ * To use the System Menu Bar, simply replace the main Fl_Menu_Bar
+ * in an application with Fl_Sys_Menu_Bar.
+ *
+ * FLTK features not supported by the Mac System menu
+ *
+ * - no invisible menu items
+ * - no sybolic labels
+ * - embossed labels will be underlined instead
+ * - no font sizes
+ * - Shortcut Characters should be English alphanumeric only, no modifiers yet
+ * - no disable main menus
+ * - changes to menubar in run-time don't update!
+ * (disable, etc. - toggle and readio button do!)
+ *
+ * No care was taken to clean up the menu bar after destruction!
+ * ::menu(bar) should only be called once!
+ * Many other calls of the parent class don't work.
+ * Changing the menu items has no effect on the menu bar.
+ * Starting with OS X 10.5, FLTK applications must be created as
+ * a bundle for the System Menu Bar (and maybe other features) to work!
+ */
+
+#if defined(__APPLE__)
+
+#include <FL/x.H>
+#include <FL/Fl.H>
+#include <FL/Fl_Sys_Menu_Bar.H>
+
+#include "flstring.h"
+#include <stdio.h>
+#include <ctype.h>
+
+typedef const Fl_Menu_Item *pFl_Menu_Item;
+
+/**
+ * copy the text of a menuitem into a buffer.
+ * Skip all '&' which would mark the shortcut in FLTK
+ * Skip all Mac control characters ('(', '<', ';', '^', '!' )
+ */
+static void catMenuText( const char *src, char *dst )
+{
+ char c;
+ while ( *dst )
+ dst++;
+ if ( *src == '-' )
+ src++;
+ while ( ( c = *src++ ) )
+ {
+ if ( !strchr( "&(<;^!", c ) )
+ *dst++ = c;
+ }
+ *dst = 0;
+}
+
+/**
+ * append a marker to identify the menu font style
+ * <B, I, U, O, and S
+ */
+static void catMenuFont( const Fl_Menu_Item *m, char *dst )
+{
+ if ( !m->labeltype_ && !m->labelfont_ )
+ return;
+ while ( *dst )
+ dst++;
+
+ if ( m->labelfont_ & FL_BOLD )
+ strcat( dst, "<B" );
+ if ( m->labelfont_ & FL_ITALIC )
+ strcat( dst, "<I" );
+ //if ( m->labelfont_ & FL_UNDERLINE )
+ // strcat( dst, "<U" );
+
+ if ( m->labeltype_ == FL_EMBOSSED_LABEL )
+ strcat( dst, "<U" );
+ else if ( m->labeltype_ == FL_ENGRAVED_LABEL )
+ strcat( dst, "<O" );
+ else if ( m->labeltype_ == FL_SHADOW_LABEL )
+ strcat( dst, "<S" );
+ //else if ( m->labeltype_ == FL_SYMBOL_LABEL )
+ ; // not supported
+}
+
+/**
+ * append a marker to identify the menu shortcut
+ * <B, I, U, O, and S
+enum {
+ kMenuNoModifiers = 0,
+ kMenuShiftModifier = (1 << 0),
+ kMenuOptionModifier = (1 << 1),
+ kMenuControlModifier = (1 << 2),
+ kMenuNoCommandModifier = (1 << 3)
+};
+ */
+static void setMenuShortcut( MenuHandle mh, int miCnt, const Fl_Menu_Item *m )
+{
+ if ( !m->shortcut_ )
+ return;
+ if ( m->flags & FL_SUBMENU )
+ return;
+ if ( m->flags & FL_SUBMENU_POINTER )
+ return;
+ char key = m->shortcut_ & 0xff;
+ if ( !isalnum( key ) )
+ return;
+
+ long macMod = kMenuNoCommandModifier;
+ if ( m->shortcut_ & FL_META ) macMod = kMenuNoModifiers;
+ if ( m->shortcut_ & FL_SHIFT || isupper(key) ) macMod |= kMenuShiftModifier;
+ if ( m->shortcut_ & FL_ALT ) macMod |= kMenuOptionModifier;
+ if ( m->shortcut_ & FL_CTRL ) macMod |= kMenuControlModifier;
+
+ //SetMenuItemKeyGlyph( mh, miCnt, key );
+ SetItemCmd( mh, miCnt, toupper(key) );
+ SetMenuItemModifiers( mh, miCnt, macMod );
+}
+
+#if 0
+// this function needs to be verified before we compile it back in.
+static void catMenuShortcut( const Fl_Menu_Item *m, char *dst )
+{
+ if ( !m->shortcut_ )
+ return;
+ char c = m->shortcut_ & 0xff;
+ if ( !isalnum( c & 0xff ) )
+ return;
+ while ( *dst )
+ dst++;
+ if ( m->shortcut_ & FL_CTRL )
+ {
+ sprintf( dst, "/%c", toupper( c ) );
+ }
+ //if ( isalnum( mm->shortcut_ ) && !( mm->flags & FL_SUBMENU ) )
+ //sprintf( buf+strlen(buf), "/%c", mm->shortcut_ );
+}
+#endif
+
+static void setMenuFlags( MenuHandle mh, int miCnt, const Fl_Menu_Item *m )
+{
+ if ( m->flags & FL_MENU_TOGGLE )
+ {
+ SetItemMark( mh, miCnt, ( m->flags & FL_MENU_VALUE ) ? 0x12 : 0 );
+ }
+ else if ( m->flags & FL_MENU_RADIO )
+ SetItemMark( mh, miCnt, ( m->flags & FL_MENU_VALUE ) ? 0x13 : 0 );
+}
+
+static void catMenuFlags( const Fl_Menu_Item *m, char *dst )
+{
+ if ( !m->flags )
+ return;
+ if ( m->flags & FL_MENU_INACTIVE )
+ strcat( dst, "(" );
+}
+
+/**
+ * create a sub menu for a specific menu handle
+ */
+static void createSubMenu( MenuHandle mh, int &cnt, pFl_Menu_Item &mm )
+{
+ char buf[255];
+ int miCnt = 1;
+ while ( mm->text )
+ {
+ MenuHandle smh = 0;
+ buf[1] = 0;
+ catMenuFont( mm, buf+1 );
+ //catMenuShortcut( mm, buf+1 );
+ catMenuText( mm->text, buf+1 );
+ catMenuFlags( mm, buf+1 );
+ if ( mm->flags & (FL_SUBMENU | FL_SUBMENU_POINTER) )
+ {
+ cnt++;
+ smh = NewMenu( cnt, (unsigned char*)"\001 " );
+ sprintf( buf+1+strlen(buf+1), "/\033!%c", cnt );
+ }
+ if ( mm->flags & FL_MENU_DIVIDER )
+ strcat( buf+1, ";-" );
+ buf[0] = strlen( buf+1 );
+ AppendMenu( mh, (unsigned char*)buf );
+ // insert Appearanc manager functions here!
+ setMenuFlags( mh, miCnt, mm );
+ setMenuShortcut( mh, miCnt, mm );
+ SetMenuItemRefCon( mh, miCnt, (UInt32)mm );
+ miCnt++;
+ if ( mm->flags & FL_MENU_DIVIDER )
+ miCnt++;
+ if ( mm->flags & FL_SUBMENU )
+ {
+ createSubMenu( smh, cnt, ++mm );
+ }
+ else if ( mm->flags & FL_SUBMENU_POINTER )
+ {
+ const Fl_Menu_Item *smm = (Fl_Menu_Item*)mm->user_data_;
+ createSubMenu( mh, cnt, smm );
+ }
+ mm++;
+ }
+ InsertMenu( mh, -1 );
+}
+
+
+/**
+ * create a system menu bar using the given list of menu structs
+ *
+ * \author Matthias Melcher
+ *
+ * @param m list of Fl_Menu_Item
+ */
+void Fl_Sys_Menu_Bar::menu(const Fl_Menu_Item *m)
+{
+ fl_open_display();
+ Fl_Menu_Bar::menu( m );
+ fl_sys_menu_bar = this;
+
+ char buf[255];
+
+ int cnt = 1; // first menu is no 2. no 1 is the Apple Menu
+ const Fl_Menu_Item *mm = m;
+ for (;;)
+ {
+ if ( !mm || !mm->text )
+ break;
+ char visible = mm->visible() ? 1 : 0;
+ buf[1] = 0;
+ catMenuText( mm->text, buf+1 );
+ buf[0] = strlen( buf+1 );
+ MenuHandle mh = NewMenu( ++cnt, (unsigned char*)buf );
+ if ( mm->flags & FL_MENU_INACTIVE ) {
+ ChangeMenuAttributes(mh, kMenuAttrAutoDisable, 0);
+ DisableAllMenuItems(mh);
+ DisableMenuItem(mh, 0);
+ }
+ if ( mm->flags & FL_SUBMENU )
+ createSubMenu( mh, cnt, ++mm );
+ else if ( mm->flags & FL_SUBMENU_POINTER ) {
+ const Fl_Menu_Item *smm = (Fl_Menu_Item*)mm->user_data_;
+ createSubMenu( mh, cnt, smm );
+ }
+ if ( visible ) {
+ InsertMenu( mh, 0 );
+ }
+ mm++;
+ }
+ DrawMenuBar();
+}
+
+/*
+const Fl_Menu_Item* Fl_Sys_Menu_Bar::picked(const Fl_Menu_Item* v) {
+ Fl_menu_Item *ret = Fl_Menu_Bar::picked( v );
+
+ if ( m->flags & FL_MENU_TOGGLE )
+ {
+ SetItemMark( mh, miCnt, ( m->flags & FL_MENU_VALUE ) ? 0x12 : 0 );
+ }
+
+ return ret;
+}
+*/
+
+void Fl_Sys_Menu_Bar::draw() {
+/* -- nothing to do, system should take care of this
+ draw_box();
+ if (!menu() || !menu()->text) return;
+ const Fl_Menu_Item* m;
+ int X = x()+6;
+ for (m=menu(); m->text; m = m->next()) {
+ int W = m->measure(0,this) + 16;
+ m->draw(X, y(), W, h(), this);
+ X += W;
+ }
+ */
+}
+
+/*
+int Fl_Menu_Bar::handle(int event) {
+ const Fl_Menu_Item* v;
+ if (menu() && menu()->text) switch (event) {
+ case FL_ENTER:
+ case FL_LEAVE:
+ return 1;
+ case FL_PUSH:
+ v = 0;
+ J1:
+ v = menu()->pulldown(x(), y(), w(), h(), v, this, 0, 1);
+ picked(v);
+ return 1;
+ case FL_SHORTCUT:
+ if (visible_r()) {
+ v = menu()->find_shortcut();
+ if (v && v->submenu()) goto J1;
+ }
+ return test_shortcut() != 0;
+ }
+ return 0;
+}
+*/
+
+#endif /* __APPLE__ */
+
+//
+// End of "$Id: Fl_Sys_Menu_Bar.cxx 6016 2008-01-09 21:32:40Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Tabs.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Tabs.cxx new file mode 100644 index 0000000..fd83a58 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Tabs.cxx @@ -0,0 +1,403 @@ +//
+// "$Id: Fl_Tabs.cxx 5791 2007-05-01 20:20:21Z matt $"
+//
+// Tab widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// This is the "file card tabs" interface to allow you to put lots and lots
+// of buttons and switches in a panel, as popularized by many toolkits.
+
+// Each child widget is a card, and it's label() is printed on the card tab.
+// Clicking the tab makes that card visible.
+
+#include <stdio.h>
+#include <FL/Fl.H>
+#include <FL/Fl_Tabs.H>
+#include <FL/fl_draw.H>
+#include <FL/Fl_Tooltip.H>
+
+#define BORDER 2
+#define EXTRASPACE 10
+
+// return the left edges of each tab (plus a fake left edge for a tab
+// past the right-hand one). These position are actually of the left
+// edge of the slope. They are either seperated by the correct distance
+// or by EXTRASPACE or by zero.
+// Return value is the index of the selected item.
+
+int Fl_Tabs::tab_positions(int* p, int* wp) {
+ int selected = 0;
+ Fl_Widget*const* a = array();
+ int i;
+ char prev_draw_shortcut = fl_draw_shortcut;
+ fl_draw_shortcut = 1;
+
+ p[0] = Fl::box_dx(box());
+ for (i=0; i<children(); i++) {
+ Fl_Widget* o = *a++;
+ if (o->visible()) selected = i;
+
+ int wt = 0; int ht = 0;
+ o->measure_label(wt,ht);
+
+ wp[i] = wt+EXTRASPACE;
+ p[i+1] = p[i]+wp[i]+BORDER;
+ }
+ fl_draw_shortcut = prev_draw_shortcut;
+
+ int r = w();
+ if (p[i] <= r) return selected;
+ // uh oh, they are too big:
+ // pack them against right edge:
+ p[i] = r;
+ for (i = children(); i--;) {
+ int l = r-wp[i];
+ if (p[i+1] < l) l = p[i+1];
+ if (p[i] <= l) break;
+ p[i] = l;
+ r -= EXTRASPACE;
+ }
+ // pack them against left edge and truncate width if they still don't fit:
+ for (i = 0; i<children(); i++) {
+ if (p[i] >= i*EXTRASPACE) break;
+ p[i] = i*EXTRASPACE;
+ int W = w()-1-EXTRASPACE*(children()-i) - p[i];
+ if (wp[i] > W) wp[i] = W;
+ }
+ // adjust edges according to visiblity:
+ for (i = children(); i > selected; i--) {
+ p[i] = p[i-1]+wp[i-1];
+ }
+ return selected;
+}
+
+// return space needed for tabs. Negative to put them on the bottom:
+int Fl_Tabs::tab_height() {
+ int H = h();
+ int H2 = y();
+ Fl_Widget*const* a = array();
+ for (int i=children(); i--;) {
+ Fl_Widget* o = *a++;
+ if (o->y() < y()+H) H = o->y()-y();
+ if (o->y()+o->h() > H2) H2 = o->y()+o->h();
+ }
+ H2 = y()+h()-H2;
+ if (H2 > H) return (H2 <= 0) ? 0 : -H2;
+ else return (H <= 0) ? 0 : H;
+}
+
+// this is used by fluid to pick tabs:
+Fl_Widget *Fl_Tabs::which(int event_x, int event_y) {
+ int H = tab_height();
+ if (H < 0) {
+ if (event_y > y()+h() || event_y < y()+h()+H) return 0;
+ } else {
+ if (event_y > y()+H || event_y < y()) return 0;
+ }
+ if (event_x < x()) return 0;
+ int p[128], wp[128];
+ tab_positions(p, wp);
+ for (int i=0; i<children(); i++) {
+ if (event_x < x()+p[i+1]) return child(i);
+ }
+ return 0;
+}
+
+void Fl_Tabs::redraw_tabs()
+{
+ int H = tab_height();
+ if (H >= 0) {
+ H += Fl::box_dy(box());
+ damage(FL_DAMAGE_SCROLL, x(), y(), w(), H);
+ } else {
+ H = Fl::box_dy(box()) - H;
+ damage(FL_DAMAGE_SCROLL, x(), y() + h() - H, w(), H);
+ }
+}
+
+int Fl_Tabs::handle(int event) {
+
+ Fl_Widget *o;
+ int i;
+
+ switch (event) {
+
+ case FL_PUSH: {
+ int H = tab_height();
+ if (H >= 0) {
+ if (Fl::event_y() > y()+H) return Fl_Group::handle(event);
+ } else {
+ if (Fl::event_y() < y()+h()+H) return Fl_Group::handle(event);
+ }}
+ case FL_DRAG:
+ case FL_RELEASE:
+ o = which(Fl::event_x(), Fl::event_y());
+ if (event == FL_RELEASE) {
+ push(0);
+ if (o && Fl::visible_focus() && Fl::focus()!=this) {
+ Fl::focus(this);
+ redraw_tabs();
+ }
+ if (o && value(o)) {
+ set_changed();
+ do_callback();
+ }
+ Fl_Tooltip::current(o);
+ } else {
+ push(o);
+ }
+ return 1;
+ case FL_MOVE: {
+ int ret = Fl_Group::handle(event);
+ Fl_Widget *o = Fl_Tooltip::current(), *n = o;
+ int H = tab_height();
+ if ( (H>=0) && (Fl::event_y()>y()+H) )
+ return ret;
+ else if ( (H<0) && (Fl::event_y() < y()+h()+H) )
+ return ret;
+ else {
+ n = which(Fl::event_x(), Fl::event_y());
+ if (!n) n = this;
+ }
+ if (n!=o)
+ Fl_Tooltip::enter(n);
+ return ret; }
+ case FL_FOCUS:
+ case FL_UNFOCUS:
+ if (!Fl::visible_focus()) return Fl_Group::handle(event);
+ if (Fl::event() == FL_RELEASE ||
+ Fl::event() == FL_SHORTCUT ||
+ Fl::event() == FL_KEYBOARD ||
+ Fl::event() == FL_FOCUS ||
+ Fl::event() == FL_UNFOCUS) {
+ redraw_tabs();
+ if (Fl::event() == FL_FOCUS || Fl::event() == FL_UNFOCUS) return 0;
+ else return 1;
+ } else return Fl_Group::handle(event);
+ case FL_KEYBOARD:
+ switch (Fl::event_key()) {
+ case FL_Left:
+ if (child(0)->visible()) return 0;
+ for (i = 1; i < children(); i ++)
+ if (child(i)->visible()) break;
+ value(child(i - 1));
+ set_changed();
+ do_callback();
+ return 1;
+ case FL_Right:
+ if (child(children() - 1)->visible()) return 0;
+ for (i = 0; i < children(); i ++)
+ if (child(i)->visible()) break;
+ value(child(i + 1));
+ set_changed();
+ do_callback();
+ return 1;
+ case FL_Down:
+ redraw();
+ return Fl_Group::handle(FL_FOCUS);
+ default:
+ break;
+ }
+ return Fl_Group::handle(event);
+ case FL_SHORTCUT:
+ for (i = 0; i < children(); ++i) {
+ Fl_Widget *c = child(i);
+ if (c->test_shortcut(c->label())) {
+ char sc = !c->visible();
+ value(c);
+ if (sc) set_changed();
+ do_callback();
+ return 1;
+ }
+ }
+ return Fl_Group::handle(event);
+ case FL_SHOW:
+ value(); // update visibilities and fall through
+ default:
+ return Fl_Group::handle(event);
+
+ }
+}
+
+int Fl_Tabs::push(Fl_Widget *o) {
+ if (push_ == o) return 0;
+ if (push_ && !push_->visible() || o && !o->visible())
+ redraw_tabs();
+ push_ = o;
+ return 1;
+}
+
+// The value() is the first visible child (or the last child if none
+// are visible) and this also hides any other children.
+// This allows the tabs to be deleted, moved to other groups, and
+// show()/hide() called without it screwing up.
+Fl_Widget* Fl_Tabs::value() {
+ Fl_Widget* v = 0;
+ Fl_Widget*const* a = array();
+ for (int i=children(); i--;) {
+ Fl_Widget* o = *a++;
+ if (v) o->hide();
+ else if (o->visible()) v = o;
+ else if (!i) {o->show(); v = o;}
+ }
+ return v;
+}
+
+// Setting the value hides all other children, and makes this one
+// visible, iff it is really a child:
+int Fl_Tabs::value(Fl_Widget *newvalue) {
+ Fl_Widget*const* a = array();
+ int ret = 0;
+ for (int i=children(); i--;) {
+ Fl_Widget* o = *a++;
+ if (o == newvalue) {
+ if (!o->visible()) ret = 1;
+ o->show();
+ } else {
+ o->hide();
+ }
+ }
+ return ret;
+}
+
+enum {LEFT, RIGHT, SELECTED};
+
+void Fl_Tabs::draw() {
+ Fl_Widget *v = value();
+ int H = tab_height();
+
+ if (damage() & FL_DAMAGE_ALL) { // redraw the entire thing:
+ Fl_Color c = v ? v->color() : color();
+
+ draw_box(box(), x(), y()+(H>=0?H:0), w(), h()-(H>=0?H:-H), c);
+
+ if (selection_color() != c) {
+ // Draw the top 5 lines of the tab pane in the selection color so
+ // that the user knows which tab is selected...
+ if (H >= 0) fl_push_clip(x(), y() + H, w(), 5);
+ else fl_push_clip(x(), y() + h() - H - 4, w(), 5);
+
+ draw_box(box(), x(), y()+(H>=0?H:0), w(), h()-(H>=0?H:-H),
+ selection_color());
+
+ fl_pop_clip();
+ }
+ if (v) draw_child(*v);
+ } else { // redraw the child
+ if (v) update_child(*v);
+ }
+ if (damage() & (FL_DAMAGE_SCROLL|FL_DAMAGE_ALL)) {
+ int p[128]; int wp[128];
+ int selected = tab_positions(p,wp);
+ int i;
+ Fl_Widget*const* a = array();
+ for (i=0; i<selected; i++)
+ draw_tab(x()+p[i], x()+p[i+1], wp[i], H, a[i], LEFT);
+ for (i=children()-1; i > selected; i--)
+ draw_tab(x()+p[i], x()+p[i+1], wp[i], H, a[i], RIGHT);
+ if (v) {
+ i = selected;
+ draw_tab(x()+p[i], x()+p[i+1], wp[i], H, a[i], SELECTED);
+ }
+ }
+}
+
+void Fl_Tabs::draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int what) {
+ int sel = (what == SELECTED);
+ int dh = Fl::box_dh(box());
+ int dy = Fl::box_dy(box());
+ char prev_draw_shortcut = fl_draw_shortcut;
+ fl_draw_shortcut = 1;
+
+ Fl_Boxtype bt = (o==push_ &&!sel) ? fl_down(box()) : box();
+
+ // compute offsets to make selected tab look bigger
+ int yofs = sel ? 0 : BORDER;
+
+ if ((x2 < x1+W) && what == RIGHT) x1 = x2 - W;
+
+ if (H >= 0) {
+ if (sel) fl_clip(x1, y(), x2 - x1, H + dh - dy);
+ else fl_clip(x1, y(), x2 - x1, H);
+
+ H += dh;
+
+ Fl_Color c = sel ? selection_color() : o->selection_color();
+
+ draw_box(bt, x1, y() + yofs, W, H + 10 - yofs, c);
+
+ // Save the previous label color
+ Fl_Color oc = o->labelcolor();
+
+ // Draw the label using the current color...
+ o->labelcolor(sel ? labelcolor() : o->labelcolor());
+ o->draw_label(x1, y() + yofs, W, H - yofs, FL_ALIGN_CENTER);
+
+ // Restore the original label color...
+ o->labelcolor(oc);
+
+ if (Fl::focus() == this && o->visible())
+ draw_focus(box(), x1, y(), W, H);
+
+ fl_pop_clip();
+ } else {
+ H = -H;
+
+ if (sel) fl_clip(x1, y() + h() - H - dy, x2 - x1, H + dy);
+ else fl_clip(x1, y() + h() - H, x2 - x1, H);
+
+ H += dh;
+
+ Fl_Color c = sel ? selection_color() : o->selection_color();
+
+ draw_box(bt, x1, y() + h() - H - 10, W, H + 10 - yofs, c);
+
+ // Save the previous label color
+ Fl_Color oc = o->labelcolor();
+
+ // Draw the label using the current color...
+ o->labelcolor(sel ? labelcolor() : o->labelcolor());
+ o->draw_label(x1, y() + h() - H, W, H - yofs, FL_ALIGN_CENTER);
+
+ // Restore the original label color...
+ o->labelcolor(oc);
+
+ if (Fl::focus() == this && o->visible())
+ draw_focus(box(), x1, y() + h() - H, W, H);
+
+ fl_pop_clip();
+ }
+ fl_draw_shortcut = prev_draw_shortcut;
+}
+
+Fl_Tabs::Fl_Tabs(int X,int Y,int W, int H, const char *l) :
+ Fl_Group(X,Y,W,H,l)
+{
+ box(FL_THIN_UP_BOX);
+ push_ = 0;
+}
+
+//
+// End of "$Id: Fl_Tabs.cxx 5791 2007-05-01 20:20:21Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Text_Buffer.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Text_Buffer.cxx new file mode 100644 index 0000000..64ee22f --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Text_Buffer.cxx @@ -0,0 +1,2534 @@ +//
+// "$Id: Fl_Text_Buffer.cxx 6011 2008-01-04 20:32:37Z matt $"
+//
+// Copyright 2001-2005 by Bill Spitzak and others.
+// Original code Copyright Mark Edel. Permission to distribute under
+// the LGPL for the FLTK library granted by Mark Edel.
+//
+// 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 <stdio.h>
+#include <stdlib.h>
+#include "flstring.h"
+#include <ctype.h>
+#include <FL/Fl.H>
+#include <FL/Fl_Text_Buffer.H>
+
+
+#define PREFERRED_GAP_SIZE 1024
+/* Initial size for the buffer gap (empty space
+in the buffer where text might be inserted
+if the user is typing sequential chars ) */
+
+static void histogramCharacters( const char *string, int length, char hist[ 256 ],
+ int init );
+static void subsChars( char *string, int length, char fromChar, char toChar );
+static char chooseNullSubsChar( char hist[ 256 ] );
+static void insertColInLine( const char *line, char *insLine, int column, int insWidth,
+ int tabDist, int useTabs, char nullSubsChar, char *outStr, int *outLen,
+ int *endOffset );
+static void deleteRectFromLine( const char *line, int rectStart, int rectEnd,
+ int tabDist, int useTabs, char nullSubsChar, char *outStr, int *outLen,
+ int *endOffset );
+static void overlayRectInLine( const char *line, char *insLine, int rectStart,
+ int rectEnd, int tabDist, int useTabs, char nullSubsChar, char *outStr,
+ int *outLen, int *endOffset );
+
+static void addPadding( char *string, int startIndent, int toIndent,
+ int tabDist, int useTabs, char nullSubsChar, int *charsAdded );
+static char *copyLine( const char* text, int *lineLen );
+static int countLines( const char *string );
+static int textWidth( const char *text, int tabDist, char nullSubsChar );
+static char *realignTabs( const char *text, int origIndent, int newIndent,
+ int tabDist, int useTabs, char nullSubsChar, int *newLength );
+static char *expandTabs( const char *text, int startIndent, int tabDist,
+ char nullSubsChar, int *newLen );
+static char *unexpandTabs( char *text, int startIndent, int tabDist,
+ char nullSubsChar, int *newLen );
+static int max( int i1, int i2 );
+static int min( int i1, int i2 );
+
+static const char *ControlCodeTable[ 32 ] = {
+ "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
+ "bs", "ht", "nl", "vt", "np", "cr", "so", "si",
+ "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb",
+ "can", "em", "sub", "esc", "fs", "gs", "rs", "us"};
+
+static char* undobuffer;
+static int undobufferlength;
+static Fl_Text_Buffer* undowidget;
+static int undoat; // points after insertion
+static int undocut; // number of characters deleted there
+static int undoinsert; // number of characters inserted
+static int undoyankcut; // length of valid contents of buffer, even if undocut=0
+
+static void undobuffersize(int n) {
+ if (n > undobufferlength) {
+ if (undobuffer) {
+ do {undobufferlength *= 2;} while (undobufferlength < n);
+ undobuffer = (char*)realloc(undobuffer, undobufferlength);
+ } else {
+ undobufferlength = n+9;
+ undobuffer = (char*)malloc(undobufferlength);
+ }
+ }
+}
+
+/*
+** Create an empty text buffer of a pre-determined size (use this to
+** avoid unnecessary re-allocation if you know exactly how much the buffer
+** will need to hold
+*/
+Fl_Text_Buffer::Fl_Text_Buffer( int requestedSize ) {
+ mLength = 0;
+ mBuf = (char *)malloc( requestedSize + PREFERRED_GAP_SIZE );
+ mGapStart = 0;
+ mGapEnd = PREFERRED_GAP_SIZE;
+ mTabDist = 8;
+ mUseTabs = 1;
+ mPrimary.mSelected = 0;
+ mPrimary.mRectangular = 0;
+ mPrimary.mStart = mPrimary.mEnd = 0;
+ mSecondary.mSelected = 0;
+ mSecondary.mStart = mSecondary.mEnd = 0;
+ mSecondary.mRectangular = 0;
+ mHighlight.mSelected = 0;
+ mHighlight.mStart = mHighlight.mEnd = 0;
+ mHighlight.mRectangular = 0;
+ mNodifyProcs = NULL;
+ mCbArgs = NULL;
+ mNModifyProcs = 0;
+ mNPredeleteProcs = 0;
+ mPredeleteProcs = NULL;
+ mPredeleteCbArgs = NULL;
+ mCursorPosHint = 0;
+ mNullSubsChar = '\0';
+ mCanUndo = 1;
+#ifdef PURIFY
+{ int i; for (i = mGapStart; i < mGapEnd; i++) mBuf[ i ] = '.'; }
+#endif
+}
+
+/*
+** Free a text buffer
+*/
+Fl_Text_Buffer::~Fl_Text_Buffer() {
+ free( mBuf );
+ if ( mNModifyProcs != 0 ) {
+ delete[] mNodifyProcs;
+ delete[] mCbArgs;
+ }
+ if ( mNPredeleteProcs != 0 ) {
+ delete[] mPredeleteProcs;
+ delete[] mPredeleteCbArgs;
+ }
+}
+
+/*
+** Get the entire contents of a text buffer. Memory is allocated to contain
+** the returned string, which the caller must free.
+*/
+char * Fl_Text_Buffer::text() {
+ char *t;
+
+ t = (char *)malloc( mLength + 1 );
+ memcpy( t, mBuf, mGapStart );
+ memcpy( &t[ mGapStart ], &mBuf[ mGapEnd ],
+ mLength - mGapStart );
+ t[ mLength ] = '\0';
+ return t;
+}
+
+/*
+** Replace the entire contents of the text buffer
+*/
+void Fl_Text_Buffer::text( const char *t ) {
+ int insertedLength, deletedLength;
+ const char *deletedText;
+
+ call_predelete_callbacks(0, length());
+
+ /* Save information for redisplay, and get rid of the old buffer */
+ deletedText = text();
+ deletedLength = mLength;
+ free( (void *)mBuf );
+
+ /* Start a new buffer with a gap of PREFERRED_GAP_SIZE in the center */
+ insertedLength = strlen( t );
+ mBuf = (char *)malloc( insertedLength + PREFERRED_GAP_SIZE );
+ mLength = insertedLength;
+ mGapStart = insertedLength / 2;
+ mGapEnd = mGapStart + PREFERRED_GAP_SIZE;
+ memcpy( mBuf, t, mGapStart );
+ memcpy( &mBuf[ mGapEnd ], &t[ mGapStart ], insertedLength - mGapStart );
+#ifdef PURIFY
+{ int i; for ( i = mGapStart; i < mGapEnd; i++ ) mBuf[ i ] = '.'; }
+#endif
+
+ /* Zero all of the existing selections */
+ update_selections( 0, deletedLength, 0 );
+
+ /* Call the saved display routine(s) to update the screen */
+ call_modify_callbacks( 0, deletedLength, insertedLength, 0, deletedText );
+ free( (void *)deletedText );
+}
+
+/*
+** Return a copy of the text between "start" and "end" character positions
+** from text buffer "buf". Positions start at 0, and the range does not
+** include the character pointed to by "end"
+*/
+char * Fl_Text_Buffer::text_range( int start, int end ) {
+ char * s;
+ int copiedLength, part1Length;
+
+ /* Make sure start and end are ok, and allocate memory for returned string.
+ If start is bad, return "", if end is bad, adjust it. */
+ if ( start < 0 || start > mLength ) {
+ s = (char *)malloc( 1 );
+ s[ 0 ] = '\0';
+ return s;
+ }
+ if ( end < start ) {
+ int temp = start;
+ start = end;
+ end = temp;
+ }
+ if ( end > mLength )
+ end = mLength;
+ copiedLength = end - start;
+ s = (char *)malloc( copiedLength + 1 );
+
+ /* Copy the text from the buffer to the returned string */
+ if ( end <= mGapStart ) {
+ memcpy( s, &mBuf[ start ], copiedLength );
+ } else if ( start >= mGapStart ) {
+ memcpy( s, &mBuf[ start + ( mGapEnd - mGapStart ) ], copiedLength );
+ } else {
+ part1Length = mGapStart - start;
+ memcpy( s, &mBuf[ start ], part1Length );
+ memcpy( &s[ part1Length ], &mBuf[ mGapEnd ], copiedLength - part1Length );
+ }
+ s[ copiedLength ] = '\0';
+ return s;
+}
+
+/*
+** Return the character at buffer position "pos". Positions start at 0.
+*/
+char Fl_Text_Buffer::character( int pos ) {
+ if ( pos < 0 || pos >= mLength )
+ return '\0';
+ if ( pos < mGapStart )
+ return mBuf[ pos ];
+ else
+ return mBuf[ pos + mGapEnd - mGapStart ];
+}
+
+/*
+** Insert null-terminated string "text" at position "pos" in "buf"
+*/
+void Fl_Text_Buffer::insert( int pos, const char *s ) {
+ int nInserted;
+
+ /* if pos is not contiguous to existing text, make it */
+ if ( pos > mLength ) pos = mLength;
+ if ( pos < 0 ) pos = 0;
+
+ /* Even if nothing is deleted, we must call these callbacks */
+ call_predelete_callbacks( pos, 0 );
+
+ /* insert and redisplay */
+ nInserted = insert_( pos, s );
+ mCursorPosHint = pos + nInserted;
+ call_modify_callbacks( pos, 0, nInserted, 0, NULL );
+}
+
+/*
+** Delete the characters between "start" and "end", and insert the
+** null-terminated string "text" in their place in in "buf"
+*/
+void Fl_Text_Buffer::replace( int start, int end, const char *s ) {
+ const char * deletedText;
+ int nInserted;
+
+ // Range check...
+ if (!s) return;
+ if (start < 0) start = 0;
+ if (end > mLength) end = mLength;
+
+ call_predelete_callbacks( start, end-start );
+ deletedText = text_range( start, end );
+ remove_( start, end );
+ //undoyankcut = undocut;
+ nInserted = insert_( start, s );
+ mCursorPosHint = start + nInserted;
+ call_modify_callbacks( start, end - start, nInserted, 0, deletedText );
+ free( (void *)deletedText );
+}
+
+void Fl_Text_Buffer::remove( int start, int end ) {
+ const char * deletedText;
+
+ /* Make sure the arguments make sense */
+ if ( start > end ) {
+ int temp = start;
+ start = end;
+ end = temp;
+ }
+ if ( start > mLength ) start = mLength;
+ if ( start < 0 ) start = 0;
+ if ( end > mLength ) end = mLength;
+ if ( end < 0 ) end = 0;
+
+ if (start == end) return;
+
+ call_predelete_callbacks( start, end-start );
+ /* Remove and redisplay */
+ deletedText = text_range( start, end );
+ remove_( start, end );
+ mCursorPosHint = start;
+ call_modify_callbacks( start, end - start, 0, 0, deletedText );
+ free( (void *)deletedText );
+}
+
+void Fl_Text_Buffer::copy( Fl_Text_Buffer *fromBuf, int fromStart,
+ int fromEnd, int toPos ) {
+ int copiedLength = fromEnd - fromStart;
+ int part1Length;
+
+ /* Prepare the buffer to receive the new text. If the new text fits in
+ the current buffer, just move the gap (if necessary) to where
+ the text should be inserted. If the new text is too large, reallocate
+ the buffer with a gap large enough to accomodate the new text and a
+ gap of PREFERRED_GAP_SIZE */
+ if ( copiedLength > mGapEnd - mGapStart )
+ reallocate_with_gap( toPos, copiedLength + PREFERRED_GAP_SIZE );
+ else if ( toPos != mGapStart )
+ move_gap( toPos );
+
+ /* Insert the new text (toPos now corresponds to the start of the gap) */
+ if ( fromEnd <= fromBuf->mGapStart ) {
+ memcpy( &mBuf[ toPos ], &fromBuf->mBuf[ fromStart ], copiedLength );
+ } else if ( fromStart >= fromBuf->mGapStart ) {
+ memcpy( &mBuf[ toPos ],
+ &fromBuf->mBuf[ fromStart + ( fromBuf->mGapEnd - fromBuf->mGapStart ) ],
+ copiedLength );
+ } else {
+ part1Length = fromBuf->mGapStart - fromStart;
+ memcpy( &mBuf[ toPos ], &fromBuf->mBuf[ fromStart ], part1Length );
+ memcpy( &mBuf[ toPos + part1Length ], &fromBuf->mBuf[ fromBuf->mGapEnd ],
+ copiedLength - part1Length );
+ }
+ mGapStart += copiedLength;
+ mLength += copiedLength;
+ update_selections( toPos, 0, copiedLength );
+}
+
+/*
+** remove text according to the undo variables or insert text
+** from the undo buffer
+*/
+int Fl_Text_Buffer::undo(int *cursorPos) {
+ if (undowidget != this || !undocut && !undoinsert &&!mCanUndo) return 0;
+
+ int ilen = undocut;
+ int xlen = undoinsert;
+ int b = undoat-xlen;
+
+ if (xlen && undoyankcut && !ilen) {
+ ilen = undoyankcut;
+ }
+
+ if (xlen && ilen) {
+ undobuffersize(ilen+1);
+ undobuffer[ilen] = 0;
+ char *tmp = strdup(undobuffer);
+ replace(b, undoat, tmp);
+ if (cursorPos) *cursorPos = mCursorPosHint;
+ free(tmp);
+ }
+ else if (xlen) {
+ remove(b, undoat);
+ if (cursorPos) *cursorPos = mCursorPosHint;
+ }
+ else if (ilen) {
+ undobuffersize(ilen+1);
+ undobuffer[ilen] = 0;
+ insert(undoat, undobuffer);
+ if (cursorPos) *cursorPos = mCursorPosHint;
+ undoyankcut = 0;
+ }
+
+ return 1;
+}
+
+/*
+** let the undo system know if we can undo changes
+*/
+void Fl_Text_Buffer::canUndo(char flag) {
+ mCanUndo = flag;
+}
+
+/*
+** Insert "text" columnwise into buffer starting at displayed character
+** position "column" on the line beginning at "startPos". Opens a rectangular
+** space the width and height of "text", by moving all text to the right of
+** "column" right. If charsInserted and charsDeleted are not NULL, the
+** number of characters inserted and deleted in the operation (beginning
+** at startPos) are returned in these arguments
+*/
+void Fl_Text_Buffer::insert_column( int column, int startPos, const char *s,
+ int *charsInserted, int *charsDeleted ) {
+ int nLines, lineStartPos, nDeleted, insertDeleted, nInserted;
+ const char *deletedText;
+
+ nLines = countLines( s );
+ lineStartPos = line_start( startPos );
+ nDeleted = line_end( skip_lines( startPos, nLines ) ) -
+ lineStartPos;
+ call_predelete_callbacks( lineStartPos, nDeleted );
+ deletedText = text_range( lineStartPos, lineStartPos + nDeleted );
+ insert_column_( column, lineStartPos, s, &insertDeleted, &nInserted,
+ &mCursorPosHint );
+ if ( nDeleted != insertDeleted )
+ Fl::error("Fl_Text_Buffer::insert_column(): internal consistency check ins1 failed");
+ call_modify_callbacks( lineStartPos, nDeleted, nInserted, 0, deletedText );
+ free( (void *) deletedText );
+ if ( charsInserted != NULL )
+ * charsInserted = nInserted;
+ if ( charsDeleted != NULL )
+ * charsDeleted = nDeleted;
+}
+
+/*
+** Overlay "text" between displayed character positions "rectStart" and
+** "rectEnd" on the line beginning at "startPos". If charsInserted and
+** charsDeleted are not NULL, the number of characters inserted and deleted
+** in the operation (beginning at startPos) are returned in these arguments.
+*/
+void Fl_Text_Buffer::overlay_rectangular( int startPos, int rectStart,
+ int rectEnd, const char *s, int *charsInserted, int *charsDeleted ) {
+ int nLines, lineStartPos, nDeleted, insertDeleted, nInserted;
+ const char *deletedText;
+
+ nLines = countLines( s );
+ lineStartPos = line_start( startPos );
+ nDeleted = line_end( skip_lines( startPos, nLines ) ) -
+ lineStartPos;
+ call_predelete_callbacks( lineStartPos, nDeleted );
+ deletedText = text_range( lineStartPos, lineStartPos + nDeleted );
+ overlay_rectangular_( lineStartPos, rectStart, rectEnd, s, &insertDeleted,
+ &nInserted, &mCursorPosHint );
+ if ( nDeleted != insertDeleted )
+ Fl::error("Fl_Text_Buffer::overlay_rectangle(): internal consistency check ovly1 failed");
+ call_modify_callbacks( lineStartPos, nDeleted, nInserted, 0, deletedText );
+ free( (void *) deletedText );
+ if ( charsInserted != NULL )
+ * charsInserted = nInserted;
+ if ( charsDeleted != NULL )
+ * charsDeleted = nDeleted;
+}
+
+/*
+** Replace a rectangular area in buf, given by "start", "end", "rectStart",
+** and "rectEnd", with "text". If "text" is vertically longer than the
+** rectangle, add extra lines to make room for it.
+*/
+void Fl_Text_Buffer::replace_rectangular( int start, int end, int rectStart,
+ int rectEnd, const char *s ) {
+ char *insPtr;
+ const char *deletedText;
+ char *insText = (char *)"";
+ int i, nInsertedLines, nDeletedLines, insLen, hint;
+ int insertDeleted, insertInserted, deleteInserted;
+ int linesPadded = 0;
+
+ /* Make sure start and end refer to complete lines, since the
+ columnar delete and insert operations will replace whole lines */
+ start = line_start( start );
+ end = line_end( end );
+
+ call_predelete_callbacks( start, end-start );
+
+ /* If more lines will be deleted than inserted, pad the inserted text
+ with newlines to make it as long as the number of deleted lines. This
+ will indent all of the text to the right of the rectangle to the same
+ column. If more lines will be inserted than deleted, insert extra
+ lines in the buffer at the end of the rectangle to make room for the
+ additional lines in "text" */
+ nInsertedLines = countLines( s );
+ nDeletedLines = count_lines( start, end );
+ if ( nInsertedLines < nDeletedLines ) {
+ insLen = strlen( s );
+ insText = (char *)malloc( insLen + nDeletedLines - nInsertedLines + 1 );
+ strcpy( insText, s );
+ insPtr = insText + insLen;
+ for ( i = 0; i < nDeletedLines - nInsertedLines; i++ )
+ *insPtr++ = '\n';
+ *insPtr = '\0';
+ } else if ( nDeletedLines < nInsertedLines ) {
+ linesPadded = nInsertedLines - nDeletedLines;
+ for ( i = 0; i < linesPadded; i++ )
+ insert_( end, "\n" );
+ } /* else nDeletedLines == nInsertedLines; */
+
+ /* Save a copy of the text which will be modified for the modify CBs */
+ deletedText = text_range( start, end );
+
+ /* Delete then insert */
+ remove_rectangular_( start, end, rectStart, rectEnd, &deleteInserted, &hint );
+ insert_column_( rectStart, start, insText, &insertDeleted, &insertInserted,
+ &mCursorPosHint );
+
+ /* Figure out how many chars were inserted and call modify callbacks */
+ if ( insertDeleted != deleteInserted + linesPadded )
+ Fl::error("Fl_Text_Buffer::replace_rectangular(): internal consistency check repl1 failed");
+ call_modify_callbacks( start, end - start, insertInserted, 0, deletedText );
+ free( (void *) deletedText );
+ if ( nInsertedLines < nDeletedLines )
+ free( (void *) insText );
+}
+
+/*
+** Remove a rectangular swath of characters between character positions start
+** and end and horizontal displayed-character offsets rectStart and rectEnd.
+*/
+void Fl_Text_Buffer::remove_rectangular( int start, int end, int rectStart,
+ int rectEnd ) {
+ const char * deletedText;
+ int nInserted;
+
+ start = line_start( start );
+ end = line_end( end );
+ call_predelete_callbacks( start, end-start );
+ deletedText = text_range( start, end );
+ remove_rectangular_( start, end, rectStart, rectEnd, &nInserted,
+ &mCursorPosHint );
+ call_modify_callbacks( start, end - start, nInserted, 0, deletedText );
+ free( (void *) deletedText );
+}
+
+/*
+** Clear a rectangular "hole" out of the buffer between character positions
+** start and end and horizontal displayed-character offsets rectStart and
+** rectEnd.
+*/
+void Fl_Text_Buffer::clear_rectangular( int start, int end, int rectStart,
+ int rectEnd ) {
+ int i, nLines;
+ char *newlineString;
+
+ nLines = count_lines( start, end );
+ newlineString = (char *)malloc( nLines + 1 );
+ for ( i = 0; i < nLines; i++ )
+ newlineString[ i ] = '\n';
+ newlineString[ i ] = '\0';
+ overlay_rectangular( start, rectStart, rectEnd, newlineString,
+ NULL, NULL );
+ free( (void *) newlineString );
+}
+
+char * Fl_Text_Buffer::text_in_rectangle( int start, int end,
+ int rectStart, int rectEnd ) {
+ int lineStart, selLeft, selRight, len;
+ char *textOut, *outPtr, *retabbedStr;
+ const char *textIn;
+
+ start = line_start( start );
+ end = line_end( end );
+ textOut = (char *)malloc( ( end - start ) + 1 );
+ lineStart = start;
+ outPtr = textOut;
+ while ( lineStart <= end ) {
+ rectangular_selection_boundaries( lineStart, rectStart, rectEnd,
+ &selLeft, &selRight );
+ textIn = text_range( selLeft, selRight );
+ len = selRight - selLeft;
+ memcpy( outPtr, textIn, len );
+ free( (void *) textIn );
+ outPtr += len;
+ lineStart = line_end( selRight ) + 1;
+ *outPtr++ = '\n';
+ }
+ if ( outPtr != textOut )
+ outPtr--; /* don't leave trailing newline */
+ *outPtr = '\0';
+
+ /* If necessary, realign the tabs in the selection as if the text were
+ positioned at the left margin */
+ retabbedStr = realignTabs( textOut, rectStart, 0, mTabDist,
+ mUseTabs, mNullSubsChar, &len );
+ free( (void *) textOut );
+ return retabbedStr;
+}
+
+/*
+** Set the hardware tab distance used by all displays for this buffer,
+** and used in computing offsets for rectangular selection operations.
+*/
+void Fl_Text_Buffer::tab_distance( int tabDist ) {
+ const char * deletedText;
+
+ /* First call the pre-delete callbacks with the previous tab setting
+ still active. */
+ call_predelete_callbacks( 0, mLength );
+
+ /* Change the tab setting */
+ mTabDist = tabDist;
+
+ /* Force any display routines to redisplay everything (unfortunately,
+ this means copying the whole buffer contents to provide "deletedText" */
+ deletedText = text();
+ call_modify_callbacks( 0, mLength, mLength, 0, deletedText );
+ free( (void *) deletedText );
+}
+
+void Fl_Text_Buffer::select( int start, int end ) {
+ Fl_Text_Selection oldSelection = mPrimary;
+
+ mPrimary.set( start, end );
+ redisplay_selection( &oldSelection, &mPrimary );
+}
+
+void Fl_Text_Buffer::unselect() {
+ Fl_Text_Selection oldSelection = mPrimary;
+
+ mPrimary.mSelected = 0;
+ redisplay_selection( &oldSelection, &mPrimary );
+}
+
+void Fl_Text_Buffer::select_rectangular( int start, int end, int rectStart,
+ int rectEnd ) {
+ Fl_Text_Selection oldSelection = mPrimary;
+
+ mPrimary.set_rectangular( start, end, rectStart, rectEnd );
+ redisplay_selection( &oldSelection, &mPrimary );
+}
+
+int Fl_Text_Buffer::selection_position( int *start, int *end
+ ) {
+ return mPrimary.position( start, end );
+}
+
+int Fl_Text_Buffer::selection_position( int *start, int *end,
+ int *isRect, int *rectStart, int *rectEnd ) {
+ return mPrimary.position( start, end, isRect, rectStart,
+ rectEnd );
+}
+
+char * Fl_Text_Buffer::selection_text() {
+ return selection_text_( &mPrimary );
+}
+
+void Fl_Text_Buffer::remove_selection() {
+ remove_selection_( &mPrimary );
+}
+
+void Fl_Text_Buffer::replace_selection( const char *s ) {
+ replace_selection_( &mPrimary, s );
+}
+
+void Fl_Text_Buffer::secondary_select( int start, int end ) {
+ Fl_Text_Selection oldSelection = mSecondary;
+
+ mSecondary.set( start, end );
+ redisplay_selection( &oldSelection, &mSecondary );
+}
+
+void Fl_Text_Buffer::secondary_unselect() {
+ Fl_Text_Selection oldSelection = mSecondary;
+
+ mSecondary.mSelected = 0;
+ redisplay_selection( &oldSelection, &mSecondary );
+}
+
+void Fl_Text_Buffer::secondary_select_rectangular( int start, int end,
+ int rectStart, int rectEnd ) {
+ Fl_Text_Selection oldSelection = mSecondary;
+
+ mSecondary.set_rectangular( start, end, rectStart, rectEnd );
+ redisplay_selection( &oldSelection, &mSecondary );
+}
+
+int Fl_Text_Buffer::secondary_selection_position( int *start, int *end
+ ) {
+ return mSecondary.position( start, end );
+}
+
+int Fl_Text_Buffer::secondary_selection_position( int *start, int *end,
+ int *isRect, int *rectStart, int *rectEnd ) {
+ return mSecondary.position( start, end, isRect, rectStart,
+ rectEnd );
+}
+
+char * Fl_Text_Buffer::secondary_selection_text() {
+ return selection_text_( &mSecondary );
+}
+
+void Fl_Text_Buffer::remove_secondary_selection() {
+ remove_selection_( &mSecondary );
+}
+
+void Fl_Text_Buffer::replace_secondary_selection( const char *s ) {
+ replace_selection_( &mSecondary, s );
+}
+
+void Fl_Text_Buffer::highlight( int start, int end ) {
+ Fl_Text_Selection oldSelection = mHighlight;
+
+ mHighlight.set( start, end );
+ redisplay_selection( &oldSelection, &mHighlight );
+}
+
+void Fl_Text_Buffer::unhighlight() {
+ Fl_Text_Selection oldSelection = mHighlight;
+
+ mHighlight.mSelected = 0;
+ redisplay_selection( &oldSelection, &mHighlight );
+}
+
+void Fl_Text_Buffer::highlight_rectangular( int start, int end,
+ int rectStart, int rectEnd ) {
+ Fl_Text_Selection oldSelection = mHighlight;
+
+ mHighlight.set_rectangular( start, end, rectStart, rectEnd );
+ redisplay_selection( &oldSelection, &mHighlight );
+}
+
+int Fl_Text_Buffer::highlight_position( int *start, int *end
+ ) {
+ return mHighlight.position( start, end );
+}
+
+int Fl_Text_Buffer::highlight_position( int *start, int *end,
+ int *isRect, int *rectStart, int *rectEnd ) {
+ return mHighlight.position( start, end, isRect, rectStart,
+ rectEnd );
+}
+
+char * Fl_Text_Buffer::highlight_text() {
+ return selection_text_( &mHighlight );
+}
+
+/*
+** Add a callback routine to be called when the buffer is modified
+*/
+void Fl_Text_Buffer::add_modify_callback( Fl_Text_Modify_Cb bufModifiedCB,
+ void *cbArg ) {
+ Fl_Text_Modify_Cb * newModifyProcs;
+ void **newCBArgs;
+ int i;
+
+ newModifyProcs = new Fl_Text_Modify_Cb [ mNModifyProcs + 1 ];
+ newCBArgs = new void * [ mNModifyProcs + 1 ];
+ for ( i = 0; i < mNModifyProcs; i++ ) {
+ newModifyProcs[ i + 1 ] = mNodifyProcs[ i ];
+ newCBArgs[ i + 1 ] = mCbArgs[ i ];
+ }
+ if ( mNModifyProcs != 0 ) {
+ delete [] mNodifyProcs;
+ delete [] mCbArgs;
+ }
+ newModifyProcs[ 0 ] = bufModifiedCB;
+ newCBArgs[ 0 ] = cbArg;
+ mNModifyProcs++;
+ mNodifyProcs = newModifyProcs;
+ mCbArgs = newCBArgs;
+}
+
+void Fl_Text_Buffer::remove_modify_callback( Fl_Text_Modify_Cb bufModifiedCB,
+ void *cbArg ) {
+ int i, toRemove = -1;
+ Fl_Text_Modify_Cb *newModifyProcs;
+ void **newCBArgs;
+
+ /* find the matching callback to remove */
+ for ( i = 0; i < mNModifyProcs; i++ ) {
+ if ( mNodifyProcs[ i ] == bufModifiedCB && mCbArgs[ i ] == cbArg ) {
+ toRemove = i;
+ break;
+ }
+ }
+ if ( toRemove == -1 ) {
+ Fl::error("Fl_Text_Buffer::remove_modify_callback(): Can't find modify CB to remove");
+ return;
+ }
+
+ /* Allocate new lists for remaining callback procs and args (if
+ any are left) */
+ mNModifyProcs--;
+ if ( mNModifyProcs == 0 ) {
+ mNModifyProcs = 0;
+ delete[] mNodifyProcs;
+ mNodifyProcs = NULL;
+ delete[] mCbArgs;
+ mCbArgs = NULL;
+ return;
+ }
+ newModifyProcs = new Fl_Text_Modify_Cb [ mNModifyProcs ];
+ newCBArgs = new void * [ mNModifyProcs ];
+
+ /* copy out the remaining members and free the old lists */
+ for ( i = 0; i < toRemove; i++ ) {
+ newModifyProcs[ i ] = mNodifyProcs[ i ];
+ newCBArgs[ i ] = mCbArgs[ i ];
+ }
+ for ( ; i < mNModifyProcs; i++ ) {
+ newModifyProcs[ i ] = mNodifyProcs[ i + 1 ];
+ newCBArgs[ i ] = mCbArgs[ i + 1 ];
+ }
+ delete[] mNodifyProcs;
+ delete[] mCbArgs;
+ mNodifyProcs = newModifyProcs;
+ mCbArgs = newCBArgs;
+}
+
+/*
+** Add a callback routine to be called before text is deleted from the buffer.
+*/
+void Fl_Text_Buffer::add_predelete_callback(Fl_Text_Predelete_Cb bufPreDeleteCB,
+ void *cbArg) {
+ Fl_Text_Predelete_Cb *newPreDeleteProcs;
+ void **newCBArgs;
+ int i;
+
+ newPreDeleteProcs = new Fl_Text_Predelete_Cb[ mNPredeleteProcs + 1 ];
+ newCBArgs = new void * [ mNPredeleteProcs + 1 ];
+ for ( i = 0; i < mNPredeleteProcs; i++ ) {
+ newPreDeleteProcs[i + 1] = mPredeleteProcs[i];
+ newCBArgs[i + 1] = mPredeleteCbArgs[i];
+ }
+ if (! mNPredeleteProcs != 0) {
+ delete [] mPredeleteProcs;
+ delete [] mPredeleteCbArgs;
+ }
+ newPreDeleteProcs[0] = bufPreDeleteCB;
+ newCBArgs[0] = cbArg;
+ mNPredeleteProcs++;
+ mPredeleteProcs = newPreDeleteProcs;
+ mPredeleteCbArgs = newCBArgs;
+}
+
+void Fl_Text_Buffer::remove_predelete_callback(
+ Fl_Text_Predelete_Cb bufPreDeleteCB, void *cbArg) {
+ int i, toRemove = -1;
+ Fl_Text_Predelete_Cb *newPreDeleteProcs;
+ void **newCBArgs;
+
+ /* find the matching callback to remove */
+ for ( i = 0; i < mNPredeleteProcs; i++) {
+ if (mPredeleteProcs[i] == bufPreDeleteCB &&
+ mPredeleteCbArgs[i] == cbArg) {
+ toRemove = i;
+ break;
+ }
+ }
+ if (toRemove == -1) {
+ Fl::error("Fl_Text_Buffer::remove_predelete_callback(): Can't find pre-delete CB to remove");
+ return;
+ }
+
+ /* Allocate new lists for remaining callback procs and args (if
+ any are left) */
+ mNPredeleteProcs--;
+ if (mNPredeleteProcs == 0) {
+ mNPredeleteProcs = 0;
+ delete[] mPredeleteProcs;
+ mPredeleteProcs = NULL;
+ delete[] mPredeleteCbArgs;
+ mPredeleteCbArgs = NULL;
+ return;
+ }
+ newPreDeleteProcs = new Fl_Text_Predelete_Cb [ mNPredeleteProcs ];
+ newCBArgs = new void * [ mNPredeleteProcs ];
+
+ /* copy out the remaining members and free the old lists */
+ for ( i = 0; i < toRemove; i++) {
+ newPreDeleteProcs[i] = mPredeleteProcs[i];
+ newCBArgs[i] = mPredeleteCbArgs[i];
+ }
+ for ( ; i < mNPredeleteProcs; i++) {
+ newPreDeleteProcs[i] = mPredeleteProcs[i+1];
+ newCBArgs[i] = mPredeleteCbArgs[i+1];
+ }
+ delete[] mPredeleteProcs;
+ delete[] mPredeleteCbArgs;
+ mPredeleteProcs = newPreDeleteProcs;
+ mPredeleteCbArgs = newCBArgs;
+}
+
+/*
+** Return the text from the entire line containing position "pos"
+*/
+char * Fl_Text_Buffer::line_text( int pos ) {
+ return text_range( line_start( pos ), line_end( pos ) );
+}
+
+/*
+** Find the position of the start of the line containing position "pos"
+*/
+int Fl_Text_Buffer::line_start( int pos ) {
+ if ( !findchar_backward( pos, '\n', &pos ) )
+ return 0;
+ return pos + 1;
+}
+
+/*
+** Find the position of the end of the line containing position "pos"
+** (which is either a pointer to the newline character ending the line,
+** or a pointer to one character beyond the end of the buffer)
+*/
+int Fl_Text_Buffer::line_end( int pos ) {
+ if ( !findchar_forward( pos, '\n', &pos ) )
+ pos = mLength;
+ return pos;
+}
+
+int Fl_Text_Buffer::word_start( int pos ) {
+ while ( pos && ( isalnum( character( pos ) ) || character( pos ) == '_' ) ) {
+ pos--;
+ }
+ if ( !( isalnum( character( pos ) ) || character( pos ) == '_' ) ) pos++;
+ return pos;
+}
+
+int Fl_Text_Buffer::word_end( int pos ) {
+ while (pos < length() && (isalnum(character(pos)) || character(pos) == '_' )) {
+ pos++;
+ }
+ return pos;
+}
+
+/*
+** Get a character from the text buffer expanded into it's screen
+** representation (which may be several characters for a tab or a
+** control code). Returns the number of characters written to "outStr".
+** "indent" is the number of characters from the start of the line
+** for figuring tabs. Output string is guranteed to be shorter or
+** equal in length to FL_TEXT_MAX_EXP_CHAR_LEN
+*/
+int Fl_Text_Buffer::expand_character( int pos, int indent, char *outStr ) {
+ return expand_character( character( pos ), indent, outStr,
+ mTabDist, mNullSubsChar );
+}
+
+/*
+** Expand a single character from the text buffer into it's screen
+** representation (which may be several characters for a tab or a
+** control code). Returns the number of characters added to "outStr".
+** "indent" is the number of characters from the start of the line
+** for figuring tabs. Output string is guranteed to be shorter or
+** equal in length to FL_TEXT_MAX_EXP_CHAR_LEN
+*/
+int Fl_Text_Buffer::expand_character( char c, int indent, char *outStr, int tabDist,
+ char nullSubsChar ) {
+ int i, nSpaces;
+
+ /* Convert tabs to spaces */
+ if ( c == '\t' ) {
+ nSpaces = tabDist - ( indent % tabDist );
+ for ( i = 0; i < nSpaces; i++ )
+ outStr[ i ] = ' ';
+ return nSpaces;
+ }
+
+ /* Convert control codes to readable character sequences */
+ /*... is this safe with international character sets? */
+ if ( ( ( unsigned char ) c ) <= 31 ) {
+ sprintf( outStr, "<%s>", ControlCodeTable[ ( unsigned char ) c ] );
+ return strlen( outStr );
+ } else if ( c == 127 ) {
+ sprintf( outStr, "<del>" );
+ return 5;
+ } else if ( c == nullSubsChar ) {
+ sprintf( outStr, "<nul>" );
+ return 5;
+ }
+
+ /* Otherwise, just return the character */
+ *outStr = c;
+ return 1;
+}
+
+/*
+** Return the length in displayed characters of character "c" expanded
+** for display (as discussed above in BufGetExpandedChar). If the
+** buffer for which the character width is being measured is doing null
+** substitution, nullSubsChar should be passed as that character (or nul
+** to ignore).
+*/
+int Fl_Text_Buffer::character_width( char c, int indent, int tabDist, char nullSubsChar ) {
+ /* Note, this code must parallel that in Fl_Text_Buffer::ExpandCharacter */
+ if ( c == '\t' )
+ return tabDist - ( indent % tabDist );
+ else if ( ( ( unsigned char ) c ) <= 31 )
+ return strlen( ControlCodeTable[ ( unsigned char ) c ] ) + 2;
+ else if ( c == 127 )
+ return 5;
+ else if ( c == nullSubsChar )
+ return 5;
+ return 1;
+}
+
+/*
+** Count the number of displayed characters between buffer position
+** "lineStartPos" and "targetPos". (displayed characters are the characters
+** shown on the screen to represent characters in the buffer, where tabs and
+** control characters are expanded)
+*/
+int Fl_Text_Buffer::count_displayed_characters( int lineStartPos, int targetPos ) {
+ int pos, charCount = 0;
+ char expandedChar[ FL_TEXT_MAX_EXP_CHAR_LEN ];
+
+ pos = lineStartPos;
+ while ( pos < targetPos )
+ charCount += expand_character( pos++, charCount, expandedChar );
+ return charCount;
+}
+
+/*
+** Count forward from buffer position "startPos" in displayed characters
+** (displayed characters are the characters shown on the screen to represent
+** characters in the buffer, where tabs and control characters are expanded)
+*/
+int Fl_Text_Buffer::skip_displayed_characters( int lineStartPos, int nChars ) {
+ int pos, charCount = 0;
+ char c;
+
+ pos = lineStartPos;
+ while ( charCount < nChars && pos < mLength ) {
+ c = character( pos );
+ if ( c == '\n' )
+ return pos;
+ charCount += character_width( c, charCount, mTabDist, mNullSubsChar );
+ pos++;
+ }
+ return pos;
+}
+
+/*
+** Count the number of newlines between startPos and endPos in buffer "buf".
+** The character at position "endPos" is not counted.
+*/
+int Fl_Text_Buffer::count_lines( int startPos, int endPos ) {
+ int pos, gapLen = mGapEnd - mGapStart;
+ int lineCount = 0;
+
+ pos = startPos;
+ while ( pos < mGapStart ) {
+ if ( pos == endPos )
+ return lineCount;
+ if ( mBuf[ pos++ ] == '\n' )
+ lineCount++;
+ }
+ while ( pos < mLength ) {
+ if ( pos == endPos )
+ return lineCount;
+ if ( mBuf[ pos++ + gapLen ] == '\n' )
+ lineCount++;
+ }
+ return lineCount;
+}
+
+/*
+** Find the first character of the line "nLines" forward from "startPos"
+** in "buf" and return its position
+*/
+int Fl_Text_Buffer::skip_lines( int startPos, int nLines ) {
+ int pos, gapLen = mGapEnd - mGapStart;
+ int lineCount = 0;
+
+ if ( nLines == 0 )
+ return startPos;
+
+ pos = startPos;
+ while ( pos < mGapStart ) {
+ if ( mBuf[ pos++ ] == '\n' ) {
+ lineCount++;
+ if ( lineCount == nLines )
+ return pos;
+ }
+ }
+ while ( pos < mLength ) {
+ if ( mBuf[ pos++ + gapLen ] == '\n' ) {
+ lineCount++;
+ if ( lineCount >= nLines )
+ return pos;
+ }
+ }
+ return pos;
+}
+
+/*
+** Find the position of the first character of the line "nLines" backwards
+** from "startPos" (not counting the character pointed to by "startpos" if
+** that is a newline) in "buf". nLines == 0 means find the beginning of
+** the line
+*/
+int Fl_Text_Buffer::rewind_lines( int startPos, int nLines ) {
+ int pos, gapLen = mGapEnd - mGapStart;
+ int lineCount = -1;
+
+ pos = startPos - 1;
+ if ( pos <= 0 )
+ return 0;
+
+ while ( pos >= mGapStart ) {
+ if ( mBuf[ pos + gapLen ] == '\n' ) {
+ if ( ++lineCount >= nLines )
+ return pos + 1;
+ }
+ pos--;
+ }
+ while ( pos >= 0 ) {
+ if ( mBuf[ pos ] == '\n' ) {
+ if ( ++lineCount >= nLines )
+ return pos + 1;
+ }
+ pos--;
+ }
+ return 0;
+}
+
+/*
+** Search forwards in buffer for string "searchString", starting with the
+** character "startPos", and returning the result in "foundPos"
+** returns 1 if found, 0 if not.
+*/
+int Fl_Text_Buffer::search_forward( int startPos, const char *searchString,
+ int *foundPos, int matchCase )
+{
+ if (!searchString) return 0;
+ int bp;
+ const char* sp;
+ while (startPos < length()) {
+ bp = startPos;
+ sp = searchString;
+ do {
+ if (!*sp) { *foundPos = startPos; return 1; }
+ } while ((matchCase ? character(bp++) == *sp++ :
+ toupper(character(bp++)) == toupper(*sp++))
+ && bp < length());
+ startPos++;
+ }
+ return 0;
+}
+
+/*
+** Search backwards in buffer for string "searchString", starting with the
+** character BEFORE "startPos", returning the result in "foundPos"
+** returns 1 if found, 0 if not.
+*/
+int Fl_Text_Buffer::search_backward( int startPos, const char *searchString,
+ int *foundPos, int matchCase )
+{
+ if (!searchString) return 0;
+ int bp;
+ const char* sp;
+ while (startPos > 0) {
+ bp = startPos-1;
+ sp = searchString+strlen(searchString)-1;
+ do {
+ if (sp < searchString) { *foundPos = bp+1; return 1; }
+ } while ((matchCase ? character(bp--) == *sp-- :
+ toupper(character(bp--)) == toupper(*sp--))
+ && bp >= 0);
+ startPos--;
+ }
+ return 0;
+}
+
+/*
+** Search forwards in buffer for characters in "searchChars", starting
+** with the character "startPos", and returning the result in "foundPos"
+** returns 1 if found, 0 if not.
+*/
+int Fl_Text_Buffer::findchars_forward( int startPos, const char *searchChars,
+ int *foundPos ) {
+ int pos, gapLen = mGapEnd - mGapStart;
+ const char *c;
+
+ pos = startPos;
+ while ( pos < mGapStart ) {
+ for ( c = searchChars; *c != '\0'; c++ ) {
+ if ( mBuf[ pos ] == *c ) {
+ *foundPos = pos;
+ return 1;
+ }
+ }
+ pos++;
+ }
+ while ( pos < mLength ) {
+ for ( c = searchChars; *c != '\0'; c++ ) {
+ if ( mBuf[ pos + gapLen ] == *c ) {
+ *foundPos = pos;
+ return 1;
+ }
+ }
+ pos++;
+ }
+ *foundPos = mLength;
+ return 0;
+}
+
+/*
+** Search backwards in buffer for characters in "searchChars", starting
+** with the character BEFORE "startPos", returning the result in "foundPos"
+** returns 1 if found, 0 if not.
+*/
+int Fl_Text_Buffer::findchars_backward( int startPos, const char *searchChars,
+ int *foundPos ) {
+ int pos, gapLen = mGapEnd - mGapStart;
+ const char *c;
+
+ if ( startPos == 0 ) {
+ *foundPos = 0;
+ return 0;
+ }
+ pos = startPos == 0 ? 0 : startPos - 1;
+ while ( pos >= mGapStart ) {
+ for ( c = searchChars; *c != '\0'; c++ ) {
+ if ( mBuf[ pos + gapLen ] == *c ) {
+ *foundPos = pos;
+ return 1;
+ }
+ }
+ pos--;
+ }
+ while ( pos >= 0 ) {
+ for ( c = searchChars; *c != '\0'; c++ ) {
+ if ( mBuf[ pos ] == *c ) {
+ *foundPos = pos;
+ return 1;
+ }
+ }
+ pos--;
+ }
+ *foundPos = 0;
+ return 0;
+}
+
+/*
+** A horrible design flaw in NEdit (from the very start, before we knew that
+** NEdit would become so popular), is that it uses C NULL terminated strings
+** to hold text. This means editing text containing NUL characters is not
+** possible without special consideration. Here is the special consideration.
+** The routines below maintain a special substitution-character which stands
+** in for a null, and translates strings an buffers back and forth from/to
+** the substituted form, figure out what to substitute, and figure out
+** when we're in over our heads and no translation is possible.
+*/
+
+/*
+** The primary routine for integrating new text into a text buffer with
+** substitution of another character for ascii nuls. This substitutes null
+** characters in the string in preparation for being copied or replaced
+** into the buffer, and if neccessary, adjusts the buffer as well, in the
+** event that the string contains the character it is currently using for
+** substitution. Returns 0, if substitution is no longer possible
+** because all non-printable characters are already in use.
+*/
+int Fl_Text_Buffer::substitute_null_characters( char *string, int len ) {
+ char histogram[ 256 ];
+
+ /* Find out what characters the string contains */
+ histogramCharacters( string, len, histogram, 1 );
+
+ /* Does the string contain the null-substitute character? If so, re-
+ histogram the buffer text to find a character which is ok in both the
+ string and the buffer, and change the buffer's null-substitution
+ character. If none can be found, give up and return 0 */
+ if ( histogram[ ( unsigned char ) mNullSubsChar ] != 0 ) {
+ char * bufString;
+ char newSubsChar;
+ bufString = (char*)text();
+ histogramCharacters( bufString, mLength, histogram, 0 );
+ newSubsChar = chooseNullSubsChar( histogram );
+ if ( newSubsChar == '\0' )
+ return 0;
+ subsChars( bufString, mLength, mNullSubsChar, newSubsChar );
+ remove_( 0, mLength );
+ insert_( 0, bufString );
+ free( (void *) bufString );
+ mNullSubsChar = newSubsChar;
+ }
+
+ /* If the string contains null characters, substitute them with the
+ buffer's null substitution character */
+ if ( histogram[ 0 ] != 0 )
+ subsChars( string, len, '\0', mNullSubsChar );
+ return 1;
+}
+
+/*
+** Convert strings obtained from buffers which contain null characters, which
+** have been substituted for by a special substitution character, back to
+** a null-containing string. There is no time penalty for calling this
+** routine if no substitution has been done.
+*/
+void Fl_Text_Buffer::unsubstitute_null_characters( char *string ) {
+ register char * c, subsChar = mNullSubsChar;
+
+ if ( subsChar == '\0' )
+ return;
+ for ( c = string; *c != '\0'; c++ )
+ if ( *c == subsChar )
+ * c = '\0';
+}
+
+/*
+** Create a pseudo-histogram of the characters in a string (don't actually
+** count, because we don't want overflow, just mark the character's presence
+** with a 1). If init is true, initialize the histogram before acumulating.
+** if not, add the new data to an existing histogram.
+*/
+static void histogramCharacters( const char *string, int length, char hist[ 256 ],
+ int init ) {
+ int i;
+ const char *c;
+
+ if ( init )
+ for ( i = 0; i < 256; i++ )
+ hist[ i ] = 0;
+ for ( c = string; c < &string[ length ]; c++ )
+ hist[ *( ( unsigned char * ) c ) ] |= 1;
+}
+
+/*
+** Substitute fromChar with toChar in string.
+*/
+static void subsChars( char *string, int length, char fromChar, char toChar ) {
+ char * c;
+
+ for ( c = string; c < &string[ length ]; c++ )
+ if ( *c == fromChar ) * c = toChar;
+}
+
+/*
+** Search through ascii control characters in histogram in order of least
+** likelihood of use, find an unused character to use as a stand-in for a
+** null. If the character set is full (no available characters outside of
+** the printable set, return the null character.
+*/
+static char chooseNullSubsChar( char hist[ 256 ] ) {
+#define N_REPLACEMENTS 25
+ static char replacements[ N_REPLACEMENTS ] = {1, 2, 3, 4, 5, 6, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 28, 29, 30, 31, 11, 7};
+ int i;
+ for ( i = 0; i < N_REPLACEMENTS; i++ )
+ if ( hist[ replacements[ i ] ] == 0 )
+ return replacements[ i ];
+ return '\0';
+}
+
+/*
+** Internal (non-redisplaying) version of BufInsert. Returns the length of
+** text inserted (this is just strlen(text), however this calculation can be
+** expensive and the length will be required by any caller who will continue
+** on to call redisplay). pos must be contiguous with the existing text in
+** the buffer (i.e. not past the end).
+*/
+int Fl_Text_Buffer::insert_( int pos, const char *s ) {
+ int insertedLength = strlen( s );
+
+ /* Prepare the buffer to receive the new text. If the new text fits in
+ the current buffer, just move the gap (if necessary) to where
+ the text should be inserted. If the new text is too large, reallocate
+ the buffer with a gap large enough to accomodate the new text and a
+ gap of PREFERRED_GAP_SIZE */
+ if ( insertedLength > mGapEnd - mGapStart )
+ reallocate_with_gap( pos, insertedLength + PREFERRED_GAP_SIZE );
+ else if ( pos != mGapStart )
+ move_gap( pos );
+
+ /* Insert the new text (pos now corresponds to the start of the gap) */
+ memcpy( &mBuf[ pos ], s, insertedLength );
+ mGapStart += insertedLength;
+ mLength += insertedLength;
+ update_selections( pos, 0, insertedLength );
+
+ if (mCanUndo) {
+ if ( undowidget==this && undoat==pos && undoinsert ) {
+ undoinsert += insertedLength;
+ }
+ else {
+ undoinsert = insertedLength;
+ undoyankcut = (undoat==pos) ? undocut : 0 ;
+ }
+ undoat = pos+insertedLength;
+ undocut = 0;
+ undowidget = this;
+ }
+
+ return insertedLength;
+}
+
+/*
+** Internal (non-redisplaying) version of BufRemove. Removes the contents
+** of the buffer between start and end (and moves the gap to the site of
+** the delete).
+*/
+void Fl_Text_Buffer::remove_( int start, int end ) {
+ /* if the gap is not contiguous to the area to remove, move it there */
+
+ if (mCanUndo) {
+ if ( undowidget==this && undoat==end && undocut ) {
+ undobuffersize( undocut+end-start+1 );
+ memmove( undobuffer+end-start, undobuffer, undocut );
+ undocut += end-start;
+ }
+ else {
+ undocut = end-start;
+ undobuffersize(undocut);
+ }
+ undoat = start;
+ undoinsert = 0;
+ undoyankcut = 0;
+ undowidget = this;
+ }
+
+ if ( start > mGapStart ) {
+ if (mCanUndo)
+ memcpy( undobuffer, mBuf+(mGapEnd-mGapStart)+start, end-start );
+ move_gap( start );
+ }
+ else if ( end < mGapStart ) {
+ if (mCanUndo)
+ memcpy( undobuffer, mBuf+start, end-start );
+ move_gap( end );
+ }
+ else {
+ int prelen = mGapStart - start;
+ if (mCanUndo) {
+ memcpy( undobuffer, mBuf+start, prelen );
+ memcpy( undobuffer+prelen, mBuf+mGapEnd, end-start-prelen);
+ }
+ }
+
+ /* expand the gap to encompass the deleted characters */
+ mGapEnd += end - mGapStart;
+ mGapStart -= mGapStart - start;
+
+ /* update the length */
+ mLength -= end - start;
+
+ /* fix up any selections which might be affected by the change */
+ update_selections( start, end - start, 0 );
+}
+
+/*
+** Insert a column of text without calling the modify callbacks. Note that
+** in some pathological cases, inserting can actually decrease the size of
+** the buffer because of spaces being coalesced into tabs. "nDeleted" and
+** "nInserted" return the number of characters deleted and inserted beginning
+** at the start of the line containing "startPos". "endPos" returns buffer
+** position of the lower left edge of the inserted column (as a hint for
+** routines which need to set a cursor position).
+*/
+void Fl_Text_Buffer::insert_column_( int column, int startPos, const char *insText,
+ int *nDeleted, int *nInserted, int *endPos ) {
+ int nLines, start, end, insWidth, lineStart, lineEnd;
+ int expReplLen, expInsLen, len, endOffset;
+ char *c, *outStr, *outPtr, *expText, *insLine;
+ const char *line;
+ const char *replText;
+ const char *insPtr;
+
+ if ( column < 0 )
+ column = 0;
+
+ /* Allocate a buffer for the replacement string large enough to hold
+ possibly expanded tabs in both the inserted text and the replaced
+ area, as well as per line: 1) an additional 2*FL_TEXT_MAX_EXP_CHAR_LEN
+ characters for padding where tabs and control characters cross the
+ column of the selection, 2) up to "column" additional spaces per
+ line for padding out to the position of "column", 3) padding up
+ to the width of the inserted text if that must be padded to align
+ the text beyond the inserted column. (Space for additional
+ newlines if the inserted text extends beyond the end of the buffer
+ is counted with the length of insText) */
+ start = line_start( startPos );
+ nLines = countLines( insText ) + 1;
+ insWidth = textWidth( insText, mTabDist, mNullSubsChar );
+ end = line_end( skip_lines( start, nLines - 1 ) );
+ replText = text_range( start, end );
+ expText = expandTabs( replText, 0, mTabDist, mNullSubsChar,
+ &expReplLen );
+ free( (void *) replText );
+ free( (void *) expText );
+ expText = expandTabs( insText, 0, mTabDist, mNullSubsChar,
+ &expInsLen );
+ free( (void *) expText );
+ outStr = (char *)malloc( expReplLen + expInsLen +
+ nLines * ( column + insWidth + FL_TEXT_MAX_EXP_CHAR_LEN ) + 1 );
+
+ /* Loop over all lines in the buffer between start and end removing the
+ text between rectStart and rectEnd and padding appropriately. Trim
+ trailing space from line (whitespace at the ends of lines otherwise
+ tends to multiply, since additional padding is added to maintain it */
+ outPtr = outStr;
+ lineStart = start;
+ insPtr = insText;
+ for (;;) {
+ lineEnd = line_end( lineStart );
+ line = text_range( lineStart, lineEnd );
+ insLine = copyLine( insPtr, &len );
+ insPtr += len;
+ insertColInLine( line, insLine, column, insWidth, mTabDist,
+ mUseTabs, mNullSubsChar, outPtr, &len, &endOffset );
+ free( (void *) line );
+ free( (void *) insLine );
+ for ( c = outPtr + len - 1; c > outPtr && isspace( *c ); c-- )
+ len--;
+ outPtr += len;
+ *outPtr++ = '\n';
+ lineStart = lineEnd < mLength ? lineEnd + 1 : mLength;
+ if ( *insPtr == '\0' )
+ break;
+ insPtr++;
+ }
+ if ( outPtr != outStr )
+ outPtr--; /* trim back off extra newline */
+ *outPtr = '\0';
+
+ /* replace the text between start and end with the new stuff */
+ remove_( start, end );
+ insert_( start, outStr );
+ *nInserted = outPtr - outStr;
+ *nDeleted = end - start;
+ *endPos = start + ( outPtr - outStr ) - len + endOffset;
+ free( (void *) outStr );
+}
+
+/*
+** Delete a rectangle of text without calling the modify callbacks. Returns
+** the number of characters replacing those between start and end. Note that
+** in some pathological cases, deleting can actually increase the size of
+** the buffer because of tab expansions. "endPos" returns the buffer position
+** of the point in the last line where the text was removed (as a hint for
+** routines which need to position the cursor after a delete operation)
+*/
+void Fl_Text_Buffer::remove_rectangular_( int start, int end, int rectStart,
+ int rectEnd, int *replaceLen, int *endPos ) {
+ int nLines, lineStart, lineEnd, len, endOffset;
+ char *outStr, *outPtr, *expText;
+ const char *s, *line;
+
+ /* allocate a buffer for the replacement string large enough to hold
+ possibly expanded tabs as well as an additional FL_TEXT_MAX_EXP_CHAR_LEN * 2
+ characters per line for padding where tabs and control characters cross
+ the edges of the selection */
+ start = line_start( start );
+ end = line_end( end );
+ nLines = count_lines( start, end ) + 1;
+ s = text_range( start, end );
+ expText = expandTabs( s, 0, mTabDist, mNullSubsChar, &len );
+ free( (void *) s );
+ free( (void *) expText );
+ outStr = (char *)malloc( len + nLines * FL_TEXT_MAX_EXP_CHAR_LEN * 2 + 1 );
+
+ /* loop over all lines in the buffer between start and end removing
+ the text between rectStart and rectEnd and padding appropriately */
+ lineStart = start;
+ outPtr = outStr;
+ endOffset = 0;
+ while ( lineStart <= mLength && lineStart <= end ) {
+ lineEnd = line_end( lineStart );
+ line = text_range( lineStart, lineEnd );
+ deleteRectFromLine( line, rectStart, rectEnd, mTabDist,
+ mUseTabs, mNullSubsChar, outPtr, &len, &endOffset );
+ free( (void *) line );
+ outPtr += len;
+ *outPtr++ = '\n';
+ lineStart = lineEnd + 1;
+ }
+ if ( outPtr != outStr )
+ outPtr--; /* trim back off extra newline */
+ *outPtr = '\0';
+
+ /* replace the text between start and end with the newly created string */
+ remove_( start, end );
+ insert_( start, outStr );
+ *replaceLen = outPtr - outStr;
+ *endPos = start + ( outPtr - outStr ) - len + endOffset;
+ free( (void *) outStr );
+}
+
+/*
+** Overlay a rectangular area of text without calling the modify callbacks.
+** "nDeleted" and "nInserted" return the number of characters deleted and
+** inserted beginning at the start of the line containing "startPos".
+** "endPos" returns buffer position of the lower left edge of the inserted
+** column (as a hint for routines which need to set a cursor position).
+*/
+void Fl_Text_Buffer::overlay_rectangular_(int startPos, int rectStart,
+ int rectEnd, const char *insText,
+ int *nDeleted, int *nInserted,
+ int *endPos ) {
+ int nLines, start, end, lineStart, lineEnd;
+ int expInsLen, len, endOffset;
+ char *c, *outStr, *outPtr, *expText, *insLine;
+ const char *line;
+ const char *insPtr;
+
+ /* Allocate a buffer for the replacement string large enough to hold
+ possibly expanded tabs in the inserted text, as well as per line: 1)
+ an additional 2*FL_TEXT_MAX_EXP_CHAR_LEN characters for padding where tabs
+ and control characters cross the column of the selection, 2) up to
+ "column" additional spaces per line for padding out to the position
+ of "column", 3) padding up to the width of the inserted text if that
+ must be padded to align the text beyond the inserted column. (Space
+ for additional newlines if the inserted text extends beyond the end
+ of the buffer is counted with the length of insText) */
+ start = line_start( startPos );
+ nLines = countLines( insText ) + 1;
+ end = line_end( skip_lines( start, nLines - 1 ) );
+ expText = expandTabs( insText, 0, mTabDist, mNullSubsChar,
+ &expInsLen );
+ free( (void *) expText );
+ outStr = (char *)malloc( end - start + expInsLen +
+ nLines * ( rectEnd + FL_TEXT_MAX_EXP_CHAR_LEN ) + 1 );
+
+ /* Loop over all lines in the buffer between start and end overlaying the
+ text between rectStart and rectEnd and padding appropriately. Trim
+ trailing space from line (whitespace at the ends of lines otherwise
+ tends to multiply, since additional padding is added to maintain it */
+ outPtr = outStr;
+ lineStart = start;
+ insPtr = insText;
+ for (;;) {
+ lineEnd = line_end( lineStart );
+ line = text_range( lineStart, lineEnd );
+ insLine = copyLine( insPtr, &len );
+ insPtr += len;
+ overlayRectInLine( line, insLine, rectStart, rectEnd, mTabDist,
+ mUseTabs, mNullSubsChar, outPtr, &len, &endOffset );
+ free( (void *) line );
+ free( (void *) insLine );
+ for ( c = outPtr + len - 1; c > outPtr && isspace( *c ); c-- )
+ len--;
+ outPtr += len;
+ *outPtr++ = '\n';
+ lineStart = lineEnd < mLength ? lineEnd + 1 : mLength;
+ if ( *insPtr == '\0' )
+ break;
+ insPtr++;
+ }
+ if ( outPtr != outStr )
+ outPtr--; /* trim back off extra newline */
+ *outPtr = '\0';
+
+ /* replace the text between start and end with the new stuff */
+ remove_( start, end );
+ insert_( start, outStr );
+ *nInserted = outPtr - outStr;
+ *nDeleted = end - start;
+ *endPos = start + ( outPtr - outStr ) - len + endOffset;
+ free( (void *) outStr );
+}
+
+/*
+** Insert characters from single-line string "insLine" in single-line string
+** "line" at "column", leaving "insWidth" space before continuing line.
+** "outLen" returns the number of characters written to "outStr", "endOffset"
+** returns the number of characters from the beginning of the string to
+** the right edge of the inserted text (as a hint for routines which need
+** to position the cursor).
+*/
+static void insertColInLine( const char *line, char *insLine, int column, int insWidth,
+ int tabDist, int useTabs, char nullSubsChar, char *outStr, int *outLen,
+ int *endOffset ) {
+ char * c, *outPtr, *retabbedStr;
+ const char *linePtr;
+ int indent, toIndent, len, postColIndent;
+
+ /* copy the line up to "column" */
+ outPtr = outStr;
+ indent = 0;
+ for ( linePtr = line; *linePtr != '\0'; linePtr++ ) {
+ len = Fl_Text_Buffer::character_width( *linePtr, indent, tabDist, nullSubsChar );
+ if ( indent + len > column )
+ break;
+ indent += len;
+ *outPtr++ = *linePtr;
+ }
+
+ /* If "column" falls in the middle of a character, and the character is a
+ tab, leave it off and leave the indent short and it will get padded
+ later. If it's a control character, insert it and adjust indent
+ accordingly. */
+ if ( indent < column && *linePtr != '\0' ) {
+ postColIndent = indent + len;
+ if ( *linePtr == '\t' )
+ linePtr++;
+ else {
+ *outPtr++ = *linePtr++;
+ indent += len;
+ }
+ } else
+ postColIndent = indent;
+
+ /* If there's no text after the column and no text to insert, that's all */
+ if ( *insLine == '\0' && *linePtr == '\0' ) {
+ *outLen = *endOffset = outPtr - outStr;
+ return;
+ }
+
+ /* pad out to column if text is too short */
+ if ( indent < column ) {
+ addPadding( outPtr, indent, column, tabDist, useTabs, nullSubsChar, &len );
+ outPtr += len;
+ indent = column;
+ }
+
+ /* Copy the text from "insLine" (if any), recalculating the tabs as if
+ the inserted string began at column 0 to its new column destination */
+ if ( *insLine != '\0' ) {
+ retabbedStr = realignTabs( insLine, 0, indent, tabDist, useTabs,
+ nullSubsChar, &len );
+ for ( c = retabbedStr; *c != '\0'; c++ ) {
+ *outPtr++ = *c;
+ len = Fl_Text_Buffer::character_width( *c, indent, tabDist, nullSubsChar );
+ indent += len;
+ }
+ free( (void *) retabbedStr );
+ }
+
+ /* If the original line did not extend past "column", that's all */
+ if ( *linePtr == '\0' ) {
+ *outLen = *endOffset = outPtr - outStr;
+ return;
+ }
+
+ /* Pad out to column + width of inserted text + (additional original
+ offset due to non-breaking character at column) */
+ toIndent = column + insWidth + postColIndent - column;
+ addPadding( outPtr, indent, toIndent, tabDist, useTabs, nullSubsChar, &len );
+ outPtr += len;
+ indent = toIndent;
+
+ /* realign tabs for text beyond "column" and write it out */
+ retabbedStr = realignTabs( linePtr, postColIndent, indent, tabDist,
+ useTabs, nullSubsChar, &len );
+ strcpy( outPtr, retabbedStr );
+ free( (void *) retabbedStr );
+ *endOffset = outPtr - outStr;
+ *outLen = ( outPtr - outStr ) + len;
+}
+
+/*
+** Remove characters in single-line string "line" between displayed positions
+** "rectStart" and "rectEnd", and write the result to "outStr", which is
+** assumed to be large enough to hold the returned string. Note that in
+** certain cases, it is possible for the string to get longer due to
+** expansion of tabs. "endOffset" returns the number of characters from
+** the beginning of the string to the point where the characters were
+** deleted (as a hint for routines which need to position the cursor).
+*/
+static void deleteRectFromLine( const char *line, int rectStart, int rectEnd,
+ int tabDist, int useTabs, char nullSubsChar, char *outStr, int *outLen,
+ int *endOffset ) {
+ int indent, preRectIndent, postRectIndent, len;
+ const char *c;
+ char *retabbedStr, *outPtr;
+
+ /* copy the line up to rectStart */
+ outPtr = outStr;
+ indent = 0;
+ for ( c = line; *c != '\0'; c++ ) {
+ if ( indent > rectStart )
+ break;
+ len = Fl_Text_Buffer::character_width( *c, indent, tabDist, nullSubsChar );
+ if ( indent + len > rectStart && ( indent == rectStart || *c == '\t' ) )
+ break;
+ indent += len;
+ *outPtr++ = *c;
+ }
+ preRectIndent = indent;
+
+ /* skip the characters between rectStart and rectEnd */
+ for ( ; *c != '\0' && indent < rectEnd; c++ )
+ indent += Fl_Text_Buffer::character_width( *c, indent, tabDist, nullSubsChar );
+ postRectIndent = indent;
+
+ /* If the line ended before rectEnd, there's nothing more to do */
+ if ( *c == '\0' ) {
+ *outPtr = '\0';
+ *outLen = *endOffset = outPtr - outStr;
+ return;
+ }
+
+ /* fill in any space left by removed tabs or control characters
+ which straddled the boundaries */
+ indent = max( rectStart + postRectIndent - rectEnd, preRectIndent );
+ addPadding( outPtr, preRectIndent, indent, tabDist, useTabs, nullSubsChar,
+ &len );
+ outPtr += len;
+
+ /* Copy the rest of the line. If the indentation has changed, preserve
+ the position of non-whitespace characters by converting tabs to
+ spaces, then back to tabs with the correct offset */
+ retabbedStr = realignTabs( c, postRectIndent, indent, tabDist, useTabs,
+ nullSubsChar, &len );
+ strcpy( outPtr, retabbedStr );
+ free( (void *) retabbedStr );
+ *endOffset = outPtr - outStr;
+ *outLen = ( outPtr - outStr ) + len;
+}
+
+/*
+** Overlay characters from single-line string "insLine" on single-line string
+** "line" between displayed character offsets "rectStart" and "rectEnd".
+** "outLen" returns the number of characters written to "outStr", "endOffset"
+** returns the number of characters from the beginning of the string to
+** the right edge of the inserted text (as a hint for routines which need
+** to position the cursor).
+*/
+static void overlayRectInLine( const char *line, char *insLine, int rectStart,
+ int rectEnd, int tabDist, int useTabs, char nullSubsChar, char *outStr,
+ int *outLen, int *endOffset ) {
+ char * c, *outPtr, *retabbedStr;
+ int inIndent, outIndent, len, postRectIndent;
+ const char *linePtr;
+
+ /* copy the line up to "rectStart" */
+ outPtr = outStr;
+ inIndent = outIndent = 0;
+ for ( linePtr = line; *linePtr != '\0'; linePtr++ ) {
+ len = Fl_Text_Buffer::character_width( *linePtr, inIndent, tabDist, nullSubsChar );
+ if ( inIndent + len > rectStart )
+ break;
+ inIndent += len;
+ outIndent += len;
+ *outPtr++ = *linePtr;
+ }
+
+ /* If "rectStart" falls in the middle of a character, and the character
+ is a tab, leave it off and leave the outIndent short and it will get
+ padded later. If it's a control character, insert it and adjust
+ outIndent accordingly. */
+ if ( inIndent < rectStart && *linePtr != '\0' ) {
+ if ( *linePtr == '\t' ) {
+ linePtr++;
+ inIndent += len;
+ } else {
+ *outPtr++ = *linePtr++;
+ outIndent += len;
+ inIndent += len;
+ }
+ }
+
+ /* skip the characters between rectStart and rectEnd */
+ postRectIndent = rectEnd;
+ for ( ; *linePtr != '\0'; linePtr++ ) {
+ inIndent += Fl_Text_Buffer::character_width( *linePtr, inIndent, tabDist, nullSubsChar );
+ if ( inIndent >= rectEnd ) {
+ linePtr++;
+ postRectIndent = inIndent;
+ break;
+ }
+ }
+
+ /* If there's no text after rectStart and no text to insert, that's all */
+ if ( *insLine == '\0' && *linePtr == '\0' ) {
+ *outLen = *endOffset = outPtr - outStr;
+ return;
+ }
+
+ /* pad out to rectStart if text is too short */
+ if ( outIndent < rectStart ) {
+ addPadding( outPtr, outIndent, rectStart, tabDist, useTabs, nullSubsChar,
+ &len );
+ outPtr += len;
+ }
+ outIndent = rectStart;
+
+ /* Copy the text from "insLine" (if any), recalculating the tabs as if
+ the inserted string began at column 0 to its new column destination */
+ if ( *insLine != '\0' ) {
+ retabbedStr = realignTabs( insLine, 0, rectStart, tabDist, useTabs,
+ nullSubsChar, &len );
+ for ( c = retabbedStr; *c != '\0'; c++ ) {
+ *outPtr++ = *c;
+ len = Fl_Text_Buffer::character_width( *c, outIndent, tabDist, nullSubsChar );
+ outIndent += len;
+ }
+ free( (void *) retabbedStr );
+ }
+
+ /* If the original line did not extend past "rectStart", that's all */
+ if ( *linePtr == '\0' ) {
+ *outLen = *endOffset = outPtr - outStr;
+ return;
+ }
+
+ /* Pad out to rectEnd + (additional original offset
+ due to non-breaking character at right boundary) */
+ addPadding( outPtr, outIndent, postRectIndent, tabDist, useTabs,
+ nullSubsChar, &len );
+ outPtr += len;
+ outIndent = postRectIndent;
+
+ /* copy the text beyond "rectEnd" */
+ strcpy( outPtr, linePtr );
+ *endOffset = outPtr - outStr;
+ *outLen = ( outPtr - outStr ) + strlen( linePtr );
+}
+
+void Fl_Text_Selection::set( int startpos, int endpos ) {
+ mSelected = startpos != endpos;
+ mRectangular = 0;
+ mStart = min( startpos, endpos );
+ mEnd = max( startpos, endpos );
+}
+
+void Fl_Text_Selection::set_rectangular( int startpos, int endpos,
+ int rectStart, int rectEnd ) {
+ mSelected = rectStart < rectEnd;
+ mRectangular = 1;
+ mStart = startpos;
+ mEnd = endpos;
+ mRectStart = rectStart;
+ mRectEnd = rectEnd;
+}
+
+int Fl_Text_Selection::position( int *startpos, int *endpos ) {
+ if ( !mSelected )
+ return 0;
+ *startpos = mStart;
+ *endpos = mEnd;
+
+ return 1;
+}
+
+int Fl_Text_Selection::position( int *startpos, int *endpos,
+ int *isRect, int *rectStart, int *rectEnd ) {
+ if ( !mSelected )
+ return 0;
+ *isRect = mRectangular;
+ *startpos = mStart;
+ *endpos = mEnd;
+ if ( mRectangular ) {
+ *rectStart = mRectStart;
+ *rectEnd = mRectEnd;
+ }
+ return 1;
+}
+
+/*
+** Return true if position "pos" with indentation "dispIndex" is in
+** the Fl_Text_Selection.
+*/
+int Fl_Text_Selection::includes(int pos, int lineStartPos, int dispIndex) {
+ return selected() &&
+ ( (!rectangular() && pos >= start() && pos < end()) ||
+ (rectangular() && pos >= start() && lineStartPos <= end() &&
+ dispIndex >= rect_start() && dispIndex < rect_end())
+ );
+}
+
+
+
+char * Fl_Text_Buffer::selection_text_( Fl_Text_Selection *sel ) {
+ int start, end, isRect, rectStart, rectEnd;
+ char *s;
+
+ /* If there's no selection, return an allocated empty string */
+ if ( !sel->position( &start, &end, &isRect, &rectStart, &rectEnd ) ) {
+ s = (char *)malloc( 1 );
+ *s = '\0';
+ return s;
+ }
+
+ /* If the selection is not rectangular, return the selected range */
+ if ( isRect )
+ return text_in_rectangle( start, end, rectStart, rectEnd );
+ else
+ return text_range( start, end );
+}
+
+void Fl_Text_Buffer::remove_selection_( Fl_Text_Selection *sel ) {
+ int start, end;
+ int isRect, rectStart, rectEnd;
+
+ if ( !sel->position( &start, &end, &isRect, &rectStart, &rectEnd ) )
+ return;
+ if ( isRect )
+ remove_rectangular( start, end, rectStart, rectEnd );
+ else {
+ remove( start, end );
+ //undoyankcut = undocut;
+ }
+}
+
+void Fl_Text_Buffer::replace_selection_( Fl_Text_Selection *sel, const char *s ) {
+ int start, end, isRect, rectStart, rectEnd;
+ Fl_Text_Selection oldSelection = *sel;
+
+ /* If there's no selection, return */
+ if ( !sel->position( &start, &end, &isRect, &rectStart, &rectEnd ) )
+ return;
+
+ /* Do the appropriate type of replace */
+ if ( isRect )
+ replace_rectangular( start, end, rectStart, rectEnd, s );
+ else
+ replace( start, end, s );
+
+ /* Unselect (happens automatically in BufReplace, but BufReplaceRect
+ can't detect when the contents of a selection goes away) */
+ sel->mSelected = 0;
+ redisplay_selection( &oldSelection, sel );
+}
+
+static void addPadding( char *string, int startIndent, int toIndent,
+ int tabDist, int useTabs, char nullSubsChar, int *charsAdded ) {
+ char * outPtr;
+ int len, indent;
+
+ indent = startIndent;
+ outPtr = string;
+ if ( useTabs ) {
+ while ( indent < toIndent ) {
+ len = Fl_Text_Buffer::character_width( '\t', indent, tabDist, nullSubsChar );
+ if ( len > 1 && indent + len <= toIndent ) {
+ *outPtr++ = '\t';
+ indent += len;
+ } else {
+ *outPtr++ = ' ';
+ indent++;
+ }
+ }
+ } else {
+ while ( indent < toIndent ) {
+ *outPtr++ = ' ';
+ indent++;
+ }
+ }
+ *charsAdded = outPtr - string;
+}
+
+/*
+** Call the stored modify callback procedure(s) for this buffer to update the
+** changed area(s) on the screen and any other listeners.
+*/
+void Fl_Text_Buffer::call_modify_callbacks( int pos, int nDeleted,
+ int nInserted, int nRestyled, const char *deletedText ) {
+ int i;
+
+ for ( i = 0; i < mNModifyProcs; i++ )
+ ( *mNodifyProcs[ i ] ) ( pos, nInserted, nDeleted, nRestyled,
+ deletedText, mCbArgs[ i ] );
+}
+
+/*
+** Call the stored pre-delete callback procedure(s) for this buffer to update
+** the changed area(s) on the screen and any other listeners.
+*/
+void Fl_Text_Buffer::call_predelete_callbacks(int pos, int nDeleted) {
+ int i;
+
+ for (i=0; i<mNPredeleteProcs; i++)
+ (*mPredeleteProcs[i])(pos, nDeleted, mPredeleteCbArgs[i]);
+}
+
+/*
+** Call the stored redisplay procedure(s) for this buffer to update the
+** screen for a change in a selection.
+*/
+void Fl_Text_Buffer::redisplay_selection( Fl_Text_Selection *oldSelection,
+ Fl_Text_Selection *newSelection ) {
+ int oldStart, oldEnd, newStart, newEnd, ch1Start, ch1End, ch2Start, ch2End;
+
+ /* If either selection is rectangular, add an additional character to
+ the end of the selection to request the redraw routines to wipe out
+ the parts of the selection beyond the end of the line */
+ oldStart = oldSelection->mStart;
+ newStart = newSelection->mStart;
+ oldEnd = oldSelection->mEnd;
+ newEnd = newSelection->mEnd;
+ if ( oldSelection->mRectangular )
+ oldEnd++;
+ if ( newSelection->mRectangular )
+ newEnd++;
+
+ /* If the old or new selection is unselected, just redisplay the
+ single area that is (was) selected and return */
+ if ( !oldSelection->mSelected && !newSelection->mSelected )
+ return;
+ if ( !oldSelection->mSelected ) {
+ call_modify_callbacks( newStart, 0, 0, newEnd - newStart, NULL );
+ return;
+ }
+ if ( !newSelection->mSelected ) {
+ call_modify_callbacks( oldStart, 0, 0, oldEnd - oldStart, NULL );
+ return;
+ }
+
+ /* If the selection changed from normal to rectangular or visa versa, or
+ if a rectangular selection changed boundaries, redisplay everything */
+ if ( ( oldSelection->mRectangular && !newSelection->mRectangular ) ||
+ ( !oldSelection->mRectangular && newSelection->mRectangular ) ||
+ ( oldSelection->mRectangular && (
+ ( oldSelection->mRectStart != newSelection->mRectStart ) ||
+ ( oldSelection->mRectEnd != newSelection->mRectEnd ) ) ) ) {
+ call_modify_callbacks( min( oldStart, newStart ), 0, 0,
+ max( oldEnd, newEnd ) - min( oldStart, newStart ), NULL );
+ return;
+ }
+
+ /* If the selections are non-contiguous, do two separate updates
+ and return */
+ if ( oldEnd < newStart || newEnd < oldStart ) {
+ call_modify_callbacks( oldStart, 0, 0, oldEnd - oldStart, NULL );
+ call_modify_callbacks( newStart, 0, 0, newEnd - newStart, NULL );
+ return;
+ }
+
+ /* Otherwise, separate into 3 separate regions: ch1, and ch2 (the two
+ changed areas), and the unchanged area of their intersection,
+ and update only the changed area(s) */
+ ch1Start = min( oldStart, newStart );
+ ch2End = max( oldEnd, newEnd );
+ ch1End = max( oldStart, newStart );
+ ch2Start = min( oldEnd, newEnd );
+ if ( ch1Start != ch1End )
+ call_modify_callbacks( ch1Start, 0, 0, ch1End - ch1Start, NULL );
+ if ( ch2Start != ch2End )
+ call_modify_callbacks( ch2Start, 0, 0, ch2End - ch2Start, NULL );
+}
+
+void Fl_Text_Buffer::move_gap( int pos ) {
+ int gapLen = mGapEnd - mGapStart;
+
+ if ( pos > mGapStart )
+ memmove( &mBuf[ mGapStart ], &mBuf[ mGapEnd ],
+ pos - mGapStart );
+ else
+ memmove( &mBuf[ pos + gapLen ], &mBuf[ pos ], mGapStart - pos );
+ mGapEnd += pos - mGapStart;
+ mGapStart += pos - mGapStart;
+}
+
+/*
+** reallocate the text storage in "buf" to have a gap starting at "newGapStart"
+** and a gap size of "newGapLen", preserving the buffer's current contents.
+*/
+void Fl_Text_Buffer::reallocate_with_gap( int newGapStart, int newGapLen ) {
+ char * newBuf;
+ int newGapEnd;
+
+ newBuf = (char *)malloc( mLength + newGapLen );
+ newGapEnd = newGapStart + newGapLen;
+ if ( newGapStart <= mGapStart ) {
+ memcpy( newBuf, mBuf, newGapStart );
+ memcpy( &newBuf[ newGapEnd ], &mBuf[ newGapStart ],
+ mGapStart - newGapStart );
+ memcpy( &newBuf[ newGapEnd + mGapStart - newGapStart ],
+ &mBuf[ mGapEnd ], mLength - mGapStart );
+ } else { /* newGapStart > mGapStart */
+ memcpy( newBuf, mBuf, mGapStart );
+ memcpy( &newBuf[ mGapStart ], &mBuf[ mGapEnd ],
+ newGapStart - mGapStart );
+ memcpy( &newBuf[ newGapEnd ],
+ &mBuf[ mGapEnd + newGapStart - mGapStart ],
+ mLength - newGapStart );
+ }
+ free( (void *) mBuf );
+ mBuf = newBuf;
+ mGapStart = newGapStart;
+ mGapEnd = newGapEnd;
+#ifdef PURIFY
+{int i; for ( i = mGapStart; i < mGapEnd; i++ ) mBuf[ i ] = '.'; }
+#endif
+}
+
+/*
+** Update all of the selections in "buf" for changes in the buffer's text
+*/
+void Fl_Text_Buffer::update_selections( int pos, int nDeleted,
+ int nInserted ) {
+ mPrimary.update( pos, nDeleted, nInserted );
+ mSecondary.update( pos, nDeleted, nInserted );
+ mHighlight.update( pos, nDeleted, nInserted );
+}
+
+/*
+** Update an individual selection for changes in the corresponding text
+*/
+void Fl_Text_Selection::update( int pos, int nDeleted,
+ int nInserted ) {
+ if ( !mSelected || pos > mEnd )
+ return;
+ if ( pos + nDeleted <= mStart ) {
+ mStart += nInserted - nDeleted;
+ mEnd += nInserted - nDeleted;
+ } else if ( pos <= mStart && pos + nDeleted >= mEnd ) {
+ mStart = pos;
+ mEnd = pos;
+ mSelected = 0;
+ } else if ( pos <= mStart && pos + nDeleted < mEnd ) {
+ mStart = pos;
+ mEnd = nInserted + mEnd - nDeleted;
+ } else if ( pos < mEnd ) {
+ mEnd += nInserted - nDeleted;
+ if ( mEnd <= mStart )
+ mSelected = 0;
+ }
+}
+
+/*
+** Search forwards in buffer "buf" for character "searchChar", starting
+** with the character "startPos", and returning the result in "foundPos"
+** returns 1 if found, 0 if not. (The difference between this and
+** BufSearchForward is that it's optimized for single characters. The
+** overall performance of the text widget is dependent on its ability to
+** count lines quickly, hence searching for a single character: newline)
+*/
+int Fl_Text_Buffer::findchar_forward( int startPos, char searchChar,
+ int *foundPos ) {
+ int pos, gapLen = mGapEnd - mGapStart;
+
+ if (startPos < 0 || startPos >= mLength) {
+ *foundPos = mLength;
+ return 0;
+ }
+
+ pos = startPos;
+ while ( pos < mGapStart ) {
+ if ( mBuf[ pos ] == searchChar ) {
+ *foundPos = pos;
+ return 1;
+ }
+ pos++;
+ }
+ while ( pos < mLength ) {
+ if ( mBuf[ pos + gapLen ] == searchChar ) {
+ *foundPos = pos;
+ return 1;
+ }
+ pos++;
+ }
+ *foundPos = mLength;
+ return 0;
+}
+
+/*
+** Search backwards in buffer "buf" for character "searchChar", starting
+** with the character BEFORE "startPos", returning the result in "foundPos"
+** returns 1 if found, 0 if not. (The difference between this and
+** BufSearchBackward is that it's optimized for single characters. The
+** overall performance of the text widget is dependent on its ability to
+** count lines quickly, hence searching for a single character: newline)
+*/
+int Fl_Text_Buffer::findchar_backward( int startPos, char searchChar,
+ int *foundPos ) {
+ int pos, gapLen = mGapEnd - mGapStart;
+
+ if ( startPos <= 0 || startPos > mLength ) {
+ *foundPos = 0;
+ return 0;
+ }
+ pos = startPos - 1;
+ while ( pos >= mGapStart ) {
+ if ( mBuf[ pos + gapLen ] == searchChar ) {
+ *foundPos = pos;
+ return 1;
+ }
+ pos--;
+ }
+ while ( pos >= 0 ) {
+ if ( mBuf[ pos ] == searchChar ) {
+ *foundPos = pos;
+ return 1;
+ }
+ pos--;
+ }
+ *foundPos = 0;
+ return 0;
+}
+
+/*
+** Copy from "text" to end up to but not including newline (or end of "text")
+** and return the copy as the function value, and the length of the line in
+** "lineLen"
+*/
+static char *copyLine( const char *text, int *lineLen ) {
+ int len = 0;
+ const char *c;
+ char *outStr;
+
+ for ( c = text; *c != '\0' && *c != '\n'; c++ )
+ len++;
+ outStr = (char *)malloc( len + 1 );
+ strlcpy( outStr, text, len + 1);
+ *lineLen = len;
+ return outStr;
+}
+
+/*
+** Count the number of newlines in a null-terminated text string;
+*/
+static int countLines( const char *string ) {
+ const char * c;
+ int lineCount = 0;
+
+ for ( c = string; *c != '\0'; c++ )
+ if ( *c == '\n' ) lineCount++;
+ return lineCount;
+}
+
+/*
+** Measure the width in displayed characters of string "text"
+*/
+static int textWidth( const char *text, int tabDist, char nullSubsChar ) {
+ int width = 0, maxWidth = 0;
+ const char *c;
+
+ for ( c = text; *c != '\0'; c++ ) {
+ if ( *c == '\n' ) {
+ if ( width > maxWidth )
+ maxWidth = width;
+ width = 0;
+ } else
+ width += Fl_Text_Buffer::character_width( *c, width, tabDist, nullSubsChar );
+ }
+ if ( width > maxWidth )
+ return width;
+ return maxWidth;
+}
+
+/*
+** Find the first and last character position in a line within a rectangular
+** selection (for copying). Includes tabs which cross rectStart, but not
+** control characters which do so. Leaves off tabs which cross rectEnd.
+**
+** Technically, the calling routine should convert tab characters which
+** cross the right boundary of the selection to spaces which line up with
+** the edge of the selection. Unfortunately, the additional memory
+** management required in the parent routine to allow for the changes
+** in string size is not worth all the extra work just for a couple of
+** shifted characters, so if a tab protrudes, just lop it off and hope
+** that there are other characters in the selection to establish the right
+** margin for subsequent columnar pastes of this data.
+*/
+void Fl_Text_Buffer::rectangular_selection_boundaries( int lineStartPos,
+ int rectStart, int rectEnd, int *selStart, int *selEnd ) {
+ int pos, width, indent = 0;
+ char c;
+
+ /* find the start of the selection */
+ for ( pos = lineStartPos; pos < mLength; pos++ ) {
+ c = character( pos );
+ if ( c == '\n' )
+ break;
+ width = Fl_Text_Buffer::character_width( c, indent, mTabDist, mNullSubsChar );
+ if ( indent + width > rectStart ) {
+ if ( indent != rectStart && c != '\t' ) {
+ pos++;
+ indent += width;
+ }
+ break;
+ }
+ indent += width;
+ }
+ *selStart = pos;
+
+ /* find the end */
+ for ( ; pos < mLength; pos++ ) {
+ c = character( pos );
+ if ( c == '\n' )
+ break;
+ width = Fl_Text_Buffer::character_width( c, indent, mTabDist, mNullSubsChar );
+ indent += width;
+ if ( indent > rectEnd ) {
+ if ( indent - width != rectEnd && c != '\t' )
+ pos++;
+ break;
+ }
+ }
+ *selEnd = pos;
+}
+
+/*
+** Adjust the space and tab characters from string "text" so that non-white
+** characters remain stationary when the text is shifted from starting at
+** "origIndent" to starting at "newIndent". Returns an allocated string
+** which must be freed by the caller with XtFree.
+*/
+static char *realignTabs( const char *text, int origIndent, int newIndent,
+ int tabDist, int useTabs, char nullSubsChar, int *newLength ) {
+ char * expStr, *outStr;
+ int len;
+
+ /* If the tabs settings are the same, retain original tabs */
+ if ( origIndent % tabDist == newIndent % tabDist ) {
+ len = strlen( text );
+ outStr = (char *)malloc( len + 1 );
+ strcpy( outStr, text );
+ *newLength = len;
+ return outStr;
+ }
+
+ /* If the tab settings are not the same, brutally convert tabs to
+ spaces, then back to tabs in the new position */
+ expStr = expandTabs( text, origIndent, tabDist, nullSubsChar, &len );
+ if ( !useTabs ) {
+ *newLength = len;
+ return expStr;
+ }
+ outStr = unexpandTabs( expStr, newIndent, tabDist, nullSubsChar, newLength );
+ free( (void *) expStr );
+ return outStr;
+}
+
+/*
+** Expand tabs to spaces for a block of text. The additional parameter
+** "startIndent" if nonzero, indicates that the text is a rectangular selection
+** beginning at column "startIndent"
+*/
+static char *expandTabs( const char *text, int startIndent, int tabDist,
+ char nullSubsChar, int *newLen ) {
+ char * outStr, *outPtr;
+ const char *c;
+ int indent, len, outLen = 0;
+
+ /* rehearse the expansion to figure out length for output string */
+ indent = startIndent;
+ for ( c = text; *c != '\0'; c++ ) {
+ if ( *c == '\t' ) {
+ len = Fl_Text_Buffer::character_width( *c, indent, tabDist, nullSubsChar );
+ outLen += len;
+ indent += len;
+ } else if ( *c == '\n' ) {
+ indent = startIndent;
+ outLen++;
+ } else {
+ indent += Fl_Text_Buffer::character_width( *c, indent, tabDist, nullSubsChar );
+ outLen++;
+ }
+ }
+
+ /* do the expansion */
+ outStr = (char *)malloc( outLen + 1 );
+ outPtr = outStr;
+ indent = startIndent;
+ for ( c = text; *c != '\0'; c++ ) {
+ if ( *c == '\t' ) {
+ len = Fl_Text_Buffer::expand_character( *c, indent, outPtr, tabDist, nullSubsChar );
+ outPtr += len;
+ indent += len;
+ } else if ( *c == '\n' ) {
+ indent = startIndent;
+ *outPtr++ = *c;
+ } else {
+ indent += Fl_Text_Buffer::character_width( *c, indent, tabDist, nullSubsChar );
+ *outPtr++ = *c;
+ }
+ }
+ outStr[ outLen ] = '\0';
+ *newLen = outLen;
+ return outStr;
+}
+
+/*
+** Convert sequences of spaces into tabs. The threshold for conversion is
+** when 3 or more spaces can be converted into a single tab, this avoids
+** converting double spaces after a period withing a block of text.
+*/
+static char *unexpandTabs( char *text, int startIndent, int tabDist,
+ char nullSubsChar, int *newLen ) {
+ char * outStr, *outPtr, *c, expandedChar[ FL_TEXT_MAX_EXP_CHAR_LEN ];
+ int indent, len;
+
+ outStr = (char *)malloc( strlen( text ) + 1 );
+ outPtr = outStr;
+ indent = startIndent;
+ for ( c = text; *c != '\0'; ) {
+ if ( *c == ' ' ) {
+ len = Fl_Text_Buffer::expand_character( '\t', indent, expandedChar, tabDist,
+ nullSubsChar );
+ if ( len >= 3 && !strncmp( c, expandedChar, len ) ) {
+ c += len;
+ *outPtr++ = '\t';
+ indent += len;
+ } else {
+ *outPtr++ = *c++;
+ indent++;
+ }
+ } else if ( *c == '\n' ) {
+ indent = startIndent;
+ *outPtr++ = *c++;
+ } else {
+ *outPtr++ = *c++;
+ indent++;
+ }
+ }
+ *outPtr = '\0';
+ *newLen = outPtr - outStr;
+ return outStr;
+}
+
+static int max( int i1, int i2 ) {
+ return i1 >= i2 ? i1 : i2;
+}
+
+static int min( int i1, int i2 ) {
+ return i1 <= i2 ? i1 : i2;
+}
+
+int
+Fl_Text_Buffer::insertfile(const char *file, int pos, int buflen) {
+ FILE *fp; int r;
+ if (!(fp = fopen(file, "r"))) return 1;
+ char *buffer = new char[buflen];
+ for (; (r = fread(buffer, 1, buflen - 1, fp)) > 0; pos += r) {
+ buffer[r] = (char)0;
+ insert(pos, buffer);
+ }
+
+ int e = ferror(fp) ? 2 : 0;
+ fclose(fp);
+ delete[] buffer;
+ return e;
+}
+
+int
+Fl_Text_Buffer::outputfile(const char *file, int start, int end, int buflen) {
+ FILE *fp;
+ if (!(fp = fopen(file, "w"))) return 1;
+ for (int n; (n = min(end - start, buflen)); start += n) {
+ const char *p = text_range(start, start + n);
+ int r = fwrite(p, 1, n, fp);
+ free((void *)p);
+ if (r != n) break;
+ }
+
+ int e = ferror(fp) ? 2 : 0;
+ fclose(fp);
+ return e;
+}
+
+
+//
+// End of "$Id: Fl_Text_Buffer.cxx 6011 2008-01-04 20:32:37Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Text_Display.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Text_Display.cxx new file mode 100644 index 0000000..4f0f1c1 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Text_Display.cxx @@ -0,0 +1,3272 @@ +//
+// "$Id: Fl_Text_Display.cxx 6105 2008-04-21 21:03:22Z matt $"
+//
+// Copyright 2001-2006 by Bill Spitzak and others.
+// Original code Copyright Mark Edel. Permission to distribute under
+// the LGPL for the FLTK library granted by Mark Edel.
+//
+// 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 <stdio.h>
+#include <stdlib.h>
+#include "flstring.h"
+#include <limits.h>
+#include <ctype.h>
+#include <FL/Fl.H>
+#include <FL/Fl_Text_Buffer.H>
+#include <FL/Fl_Text_Display.H>
+#include <FL/Fl_Window.H>
+
+#undef min
+#undef max
+
+// Text area margins. Left & right margins should be at least 3 so that
+// there is some room for the overhanging parts of the cursor!
+#define TOP_MARGIN 1
+#define BOTTOM_MARGIN 1
+#define LEFT_MARGIN 3
+#define RIGHT_MARGIN 3
+
+#define NO_HINT -1
+
+/* Masks for text drawing methods. These are or'd together to form an
+ integer which describes what drawing calls to use to draw a string */
+#define FILL_MASK 0x0100
+#define SECONDARY_MASK 0x0200
+#define PRIMARY_MASK 0x0400
+#define HIGHLIGHT_MASK 0x0800
+#define BG_ONLY_MASK 0x1000
+#define TEXT_ONLY_MASK 0x2000
+#define STYLE_LOOKUP_MASK 0xff
+
+/* Maximum displayable line length (how many characters will fit across the
+ widest window). This amount of memory is temporarily allocated from the
+ stack in the draw_vline() method for drawing strings */
+#define MAX_DISP_LINE_LEN 1000
+
+static int max( int i1, int i2 );
+static int min( int i1, int i2 );
+static int countlines( const char *string );
+
+/* The variables below are used in a timer event to allow smooth
+ scrolling of the text area when the pointer has left the area. */
+static int scroll_direction = 0;
+static int scroll_amount = 0;
+static int scroll_y = 0;
+static int scroll_x = 0;
+
+// CET - FIXME
+#define TMPFONTWIDTH 6
+
+Fl_Text_Display::Fl_Text_Display(int X, int Y, int W, int H, const char* l)
+ : Fl_Group(X, Y, W, H, l) {
+ int i;
+
+ mMaxsize = 0;
+ damage_range1_start = damage_range1_end = -1;
+ damage_range2_start = damage_range2_end = -1;
+ dragPos = dragType = dragging = 0;
+ display_insert_position_hint = 0;
+
+ color(FL_BACKGROUND2_COLOR, FL_SELECTION_COLOR);
+ box(FL_DOWN_FRAME);
+ textsize((uchar)FL_NORMAL_SIZE);
+ textcolor(FL_FOREGROUND_COLOR);
+ textfont(FL_HELVETICA);
+
+ text_area.x = 0;
+ text_area.y = 0;
+ text_area.w = 0;
+ text_area.h = 0;
+
+ mVScrollBar = new Fl_Scrollbar(0,0,1,1);
+ mVScrollBar->callback((Fl_Callback*)v_scrollbar_cb, this);
+ mHScrollBar = new Fl_Scrollbar(0,0,1,1);
+ mHScrollBar->callback((Fl_Callback*)h_scrollbar_cb, this);
+ mHScrollBar->type(FL_HORIZONTAL);
+
+ end();
+
+ scrollbar_width(Fl::scrollbar_size());
+ scrollbar_align(FL_ALIGN_BOTTOM_RIGHT);
+
+ mCursorOn = 0;
+ mCursorPos = 0;
+ mCursorOldY = -100;
+ mCursorToHint = NO_HINT;
+ mCursorStyle = NORMAL_CURSOR;
+ mCursorPreferredCol = -1;
+ mBuffer = 0;
+ mFirstChar = 0;
+ mLastChar = 0;
+ mNBufferLines = 0;
+ mTopLineNum = mTopLineNumHint = 1;
+ mAbsTopLineNum = 1;
+ mNeedAbsTopLineNum = 0;
+ mHorizOffset = mHorizOffsetHint = 0;
+
+ mCursor_color = FL_FOREGROUND_COLOR;
+
+ mFixedFontWidth = -1;
+ mStyleBuffer = 0;
+ mStyleTable = 0;
+ mNStyles = 0;
+ mNVisibleLines = 1;
+ mLineStarts = new int[mNVisibleLines];
+ mLineStarts[0] = 0;
+ for (i=1; i<mNVisibleLines; i++)
+ mLineStarts[i] = -1;
+ mSuppressResync = 0;
+ mNLinesDeleted = 0;
+ mModifyingTabDistance = 0;
+
+ mUnfinishedStyle = 0;
+ mUnfinishedHighlightCB = 0;
+ mHighlightCBArg = 0;
+
+ mLineNumLeft = mLineNumWidth = 0;
+ mContinuousWrap = 0;
+ mWrapMargin = 0;
+ mSuppressResync = mNLinesDeleted = mModifyingTabDistance = 0;
+}
+
+/*
+** Free a text display and release its associated memory. Note, the text
+** BUFFER that the text display displays is a separate entity and is not
+** freed, nor are the style buffer or style table.
+*/
+Fl_Text_Display::~Fl_Text_Display() {
+ if (scroll_direction) {
+ Fl::remove_timeout(scroll_timer_cb, this);
+ scroll_direction = 0;
+ }
+ if (mBuffer) {
+ mBuffer->remove_modify_callback(buffer_modified_cb, this);
+ mBuffer->remove_predelete_callback(buffer_predelete_cb, this);
+ }
+ if (mLineStarts) delete[] mLineStarts;
+}
+
+/*
+** Attach a text buffer to display, replacing the current buffer (if any)
+*/
+void Fl_Text_Display::buffer( Fl_Text_Buffer *buf ) {
+ /* If the text display is already displaying a buffer, clear it off
+ of the display and remove our callback from it */
+ if ( buf == mBuffer) return;
+ if ( mBuffer != 0 ) {
+ buffer_modified_cb( 0, 0, mBuffer->length(), 0, 0, this );
+ mNBufferLines = 0;
+ mBuffer->remove_modify_callback( buffer_modified_cb, this );
+ mBuffer->remove_predelete_callback( buffer_predelete_cb, this );
+ }
+
+ /* Add the buffer to the display, and attach a callback to the buffer for
+ receiving modification information when the buffer contents change */
+ mBuffer = buf;
+ if (mBuffer) {
+ mBuffer->add_modify_callback( buffer_modified_cb, this );
+ mBuffer->add_predelete_callback( buffer_predelete_cb, this );
+
+ /* Update the display */
+ buffer_modified_cb( 0, buf->length(), 0, 0, 0, this );
+ }
+
+ /* Resize the widget to update the screen... */
+ resize(x(), y(), w(), h());
+}
+
+/*
+** Attach (or remove) highlight information in text display and redisplay.
+** Highlighting information consists of a style buffer which parallels the
+** normal text buffer, but codes font and color information for the display;
+** a style table which translates style buffer codes (indexed by buffer
+** character - 'A') into fonts and colors; and a callback mechanism for
+** as-needed highlighting, triggered by a style buffer entry of
+** "unfinishedStyle". Style buffer can trigger additional redisplay during
+** a normal buffer modification if the buffer contains a primary Fl_Text_Selection
+** (see extendRangeForStyleMods for more information on this protocol).
+**
+** Style buffers, tables and their associated memory are managed by the caller.
+*/
+void
+Fl_Text_Display::highlight_data(Fl_Text_Buffer *styleBuffer,
+ const Style_Table_Entry *styleTable,
+ int nStyles, char unfinishedStyle,
+ Unfinished_Style_Cb unfinishedHighlightCB,
+ void *cbArg ) {
+ mStyleBuffer = styleBuffer;
+ mStyleTable = styleTable;
+ mNStyles = nStyles;
+ mUnfinishedStyle = unfinishedStyle;
+ mUnfinishedHighlightCB = unfinishedHighlightCB;
+ mHighlightCBArg = cbArg;
+
+ mStyleBuffer->canUndo(0);
+#if 0
+ // FIXME: this is in nedit code -- is it needed?
+ /* Call TextDSetFont to combine font information from style table and
+ primary font, adjust font-related parameters, and then redisplay */
+ TextDSetFont(textD, textD->fontStruct);
+#endif
+ damage(FL_DAMAGE_EXPOSE);
+}
+
+#if 0
+ // FIXME: this is in nedit code -- is it needed?
+/*
+** Change the (non highlight) font
+*/
+void TextDSetFont(textDisp *textD, XFontStruct *fontStruct) {
+ Display *display = XtDisplay(textD->w);
+ int i, maxAscent = fontStruct->ascent, maxDescent = fontStruct->descent;
+ int width, height, fontWidth;
+ Pixel bgPixel, fgPixel, selectFGPixel, selectBGPixel;
+ Pixel highlightFGPixel, highlightBGPixel;
+ XGCValues values;
+ XFontStruct *styleFont;
+
+ /* If font size changes, cursor will be redrawn in a new position */
+ blankCursorProtrusions(textD);
+
+ /* If there is a (syntax highlighting) style table in use, find the new
+ maximum font height for this text display */
+ for (i=0; i<textD->nStyles; i++) {
+ styleFont = textD->styleTable[i].font;
+ if (styleFont != NULL && styleFont->ascent > maxAscent)
+ maxAscent = styleFont->ascent;
+ if (styleFont != NULL && styleFont->descent > maxDescent)
+ maxDescent = styleFont->descent;
+ }
+ textD->ascent = maxAscent;
+ textD->descent = maxDescent;
+
+ /* If all of the current fonts are fixed and match in width, compute */
+ fontWidth = fontStruct->max_bounds.width;
+ if (fontWidth != fontStruct->min_bounds.width)
+ fontWidth = -1;
+ else {
+ for (i=0; i<textD->nStyles; i++) {
+ styleFont = textD->styleTable[i].font;
+ if (styleFont != NULL && (styleFont->max_bounds.width != fontWidth ||
+ styleFont->max_bounds.width != styleFont->min_bounds.width))
+ fontWidth = -1;
+ }
+ }
+ textD->fixedFontWidth = fontWidth;
+
+ /* Don't let the height dip below one line, or bad things can happen */
+ if (textD->height < maxAscent + maxDescent)
+ textD->height = maxAscent + maxDescent;
+
+ /* Change the font. In most cases, this means re-allocating the
+ affected GCs (they are shared with other widgets, and if the primary
+ font changes, must be re-allocated to change it). Unfortunately,
+ this requres recovering all of the colors from the existing GCs */
+ textD->fontStruct = fontStruct;
+ XGetGCValues(display, textD->gc, GCForeground|GCBackground, &values);
+ fgPixel = values.foreground;
+ bgPixel = values.background;
+ XGetGCValues(display, textD->selectGC, GCForeground|GCBackground, &values);
+ selectFGPixel = values.foreground;
+ selectBGPixel = values.background;
+ XGetGCValues(display, textD->highlightGC,GCForeground|GCBackground,&values);
+ highlightFGPixel = values.foreground;
+ highlightBGPixel = values.background;
+ releaseGC(textD->w, textD->gc);
+ releaseGC(textD->w, textD->selectGC);
+ releaseGC(textD->w, textD->highlightGC);
+ releaseGC(textD->w, textD->selectBGGC);
+ releaseGC(textD->w, textD->highlightBGGC);
+ if (textD->lineNumGC != NULL)
+ releaseGC(textD->w, textD->lineNumGC);
+ textD->lineNumGC = NULL;
+ allocateFixedFontGCs(textD, fontStruct, bgPixel, fgPixel, selectFGPixel,
+ selectBGPixel, highlightFGPixel, highlightBGPixel);
+ XSetFont(display, textD->styleGC, fontStruct->fid);
+
+ /* Do a full resize to force recalculation of font related parameters */
+ width = textD->width;
+ height = textD->height;
+ textD->width = textD->height = 0;
+ TextDResize(textD, width, height);
+
+ /* Redisplay */
+ TextDRedisplayRect(textD, textD->left, textD->top, textD->width,
+ textD->height);
+
+ /* Clean up line number area in case spacing has changed */
+ draw_line_numbers(textD, True);
+}
+
+int TextDMinFontWidth(textDisp *textD, Boolean considerStyles) {
+ int fontWidth = textD->fontStruct->max_bounds.width;
+ int i;
+
+ if (considerStyles) {
+ for (i = 0; i < textD->nStyles; ++i) {
+ int thisWidth = (textD->styleTable[i].font)->min_bounds.width;
+ if (thisWidth < fontWidth) {
+ fontWidth = thisWidth;
+ }
+ }
+ }
+ return(fontWidth);
+}
+
+int TextDMaxFontWidth(textDisp *textD, Boolean considerStyles) {
+ int fontWidth = textD->fontStruct->max_bounds.width;
+ int i;
+
+ if (considerStyles) {
+ for (i = 0; i < textD->nStyles; ++i) {
+ int thisWidth = (textD->styleTable[i].font)->max_bounds.width;
+ if (thisWidth > fontWidth) {
+ fontWidth = thisWidth;
+ }
+ }
+ }
+ return(fontWidth);
+}
+#endif
+
+int Fl_Text_Display::longest_vline() {
+ int longest = 0;
+ for (int i = 0; i < mNVisibleLines; i++)
+ longest = max(longest, measure_vline(i));
+ return longest;
+}
+
+/*
+** Change the size of the displayed text area
+*/
+void Fl_Text_Display::resize(int X, int Y, int W, int H) {
+#ifdef DEBUG
+ printf("Fl_Text_Display::resize(X=%d, Y=%d, W=%d, H=%d)\n", X, Y, W, H);
+#endif // DEBUG
+ const int oldWidth = w();
+#ifdef DEBUG
+ printf(" oldWidth=%d, mContinuousWrap=%d, mWrapMargin=%d\n", oldWidth,
+ mContinuousWrap, mWrapMargin);
+#endif // DEBUG
+ Fl_Widget::resize(X,Y,W,H);
+ if (!buffer()) return;
+ X += Fl::box_dx(box());
+ Y += Fl::box_dy(box());
+ W -= Fl::box_dw(box());
+ H -= Fl::box_dh(box());
+
+ text_area.x = X+LEFT_MARGIN;
+ text_area.y = Y+BOTTOM_MARGIN;
+ text_area.w = W-LEFT_MARGIN-RIGHT_MARGIN;
+ text_area.h = H-TOP_MARGIN-BOTTOM_MARGIN;
+ int i;
+
+ /* Find the new maximum font height for this text display */
+ for (i = 0, mMaxsize = fl_height(textfont(), textsize()); i < mNStyles; i++)
+ mMaxsize = max(mMaxsize, fl_height(mStyleTable[i].font, mStyleTable[i].size));
+
+ // did we have scrollbars initially?
+ int hscrollbarvisible = mHScrollBar->visible();
+ int vscrollbarvisible = mVScrollBar->visible();
+
+ // try without scrollbars first
+ mVScrollBar->clear_visible();
+ mHScrollBar->clear_visible();
+
+ for (int again = 1; again;) {
+ again = 0;
+ /* In continuous wrap mode, a change in width affects the total number of
+ lines in the buffer, and can leave the top line number incorrect, and
+ the top character no longer pointing at a valid line start */
+ if (mContinuousWrap && !mWrapMargin && W!=oldWidth) {
+ int oldFirstChar = mFirstChar;
+ mNBufferLines = count_lines(0, buffer()->length(), true);
+ mFirstChar = line_start(mFirstChar);
+ mTopLineNum = count_lines(0, mFirstChar, true)+1;
+ absolute_top_line_number(oldFirstChar);
+
+#ifdef DEBUG
+ printf(" mNBufferLines=%d\n", mNBufferLines);
+#endif // DEBUG
+ }
+
+ /* reallocate and update the line starts array, which may have changed
+ size and / or contents. */
+ int nvlines = (text_area.h + mMaxsize - 1) / mMaxsize;
+ if (nvlines < 1) nvlines = 1;
+ if (mNVisibleLines != nvlines) {
+ mNVisibleLines = nvlines;
+ if (mLineStarts) delete[] mLineStarts;
+ mLineStarts = new int [mNVisibleLines];
+ }
+
+ calc_line_starts(0, mNVisibleLines);
+ calc_last_char();
+
+ // figure the scrollbars
+ if (scrollbar_width()) {
+ /* Decide if the vertical scroll bar needs to be visible */
+ if (scrollbar_align() & (FL_ALIGN_LEFT|FL_ALIGN_RIGHT) &&
+ mNBufferLines >= mNVisibleLines - 1)
+ {
+ mVScrollBar->set_visible();
+ if (scrollbar_align() & FL_ALIGN_LEFT) {
+ text_area.x = X+scrollbar_width()+LEFT_MARGIN;
+ text_area.w = W-scrollbar_width()-LEFT_MARGIN-RIGHT_MARGIN;
+ mVScrollBar->resize(X, text_area.y-TOP_MARGIN, scrollbar_width(),
+ text_area.h+TOP_MARGIN+BOTTOM_MARGIN);
+ } else {
+ text_area.x = X+LEFT_MARGIN;
+ text_area.w = W-scrollbar_width()-LEFT_MARGIN-RIGHT_MARGIN;
+ mVScrollBar->resize(X+W-scrollbar_width(), text_area.y-TOP_MARGIN,
+ scrollbar_width(), text_area.h+TOP_MARGIN+BOTTOM_MARGIN);
+ }
+ }
+
+ /*
+ Decide if the horizontal scroll bar needs to be visible. If there
+ is a vertical scrollbar, a horizontal is always created too. This
+ is because the alternatives are unatractive:
+ * Dynamically creating a horizontal scrollbar based on the currently
+ visible lines is what the original nedit does, but it always wastes
+ space for the scrollbar even when it's not used. Since the FLTK
+ widget dynamically allocates the space for the scrollbar and
+ rearranges the widget to make room for it, this would create a very
+ visually displeasing "bounce" effect when the vertical scrollbar is
+ dragged. Trust me, I tried it and it looks really bad.
+ * The other alternative would be to keep track of what the longest
+ line in the entire buffer is and base the scrollbar on that. I
+ didn't do this because I didn't see any easy way to do that using
+ the nedit code and this could involve a lengthy calculation for
+ large buffers. If an efficient and non-costly way of doing this
+ can be found, this might be a way to go.
+ */
+ /* WAS: Suggestion: Try turning the horizontal scrollbar on when
+ you first see a line that is too wide in the window, but then
+ don't turn it off (ie mix both of your solutions). */
+ if (scrollbar_align() & (FL_ALIGN_TOP|FL_ALIGN_BOTTOM) &&
+ (mVScrollBar->visible() || longest_vline() > text_area.w))
+ {
+ if (!mHScrollBar->visible()) {
+ mHScrollBar->set_visible();
+ again = 1; // loop again to see if we now need vert. & recalc sizes
+ }
+ if (scrollbar_align() & FL_ALIGN_TOP) {
+ text_area.y = Y + scrollbar_width()+TOP_MARGIN;
+ text_area.h = H - scrollbar_width()-TOP_MARGIN-BOTTOM_MARGIN;
+ mHScrollBar->resize(text_area.x-LEFT_MARGIN, Y,
+ text_area.w+LEFT_MARGIN+RIGHT_MARGIN, scrollbar_width());
+ } else {
+ text_area.y = Y+TOP_MARGIN;
+ text_area.h = H - scrollbar_width()-TOP_MARGIN-BOTTOM_MARGIN;
+ mHScrollBar->resize(text_area.x-LEFT_MARGIN, Y+H-scrollbar_width(),
+ text_area.w+LEFT_MARGIN+RIGHT_MARGIN, scrollbar_width());
+ }
+ }
+ }
+ }
+
+ // user request to change viewport
+ if (mTopLineNumHint != mTopLineNum || mHorizOffsetHint != mHorizOffset)
+ scroll_(mTopLineNumHint, mHorizOffsetHint);
+
+ // everything will fit in the viewport
+ if (mNBufferLines < mNVisibleLines || mBuffer == NULL || mBuffer->length() == 0)
+ scroll_(1, mHorizOffset);
+ /* if empty lines become visible, there may be an opportunity to
+ display more text by scrolling down */
+ else while (mLineStarts[mNVisibleLines-2] == -1)
+ scroll_(mTopLineNum-1, mHorizOffset);
+
+ // user request to display insert position
+ if (display_insert_position_hint)
+ display_insert();
+
+ // in case horizontal offset is now greater than longest line
+ int maxhoffset = max(0, longest_vline()-text_area.w);
+ if (mHorizOffset > maxhoffset)
+ scroll_(mTopLineNumHint, maxhoffset);
+
+ mTopLineNumHint = mTopLineNum;
+ mHorizOffsetHint = mHorizOffset;
+ display_insert_position_hint = 0;
+
+ if (mContinuousWrap ||
+ hscrollbarvisible != mHScrollBar->visible() ||
+ vscrollbarvisible != mVScrollBar->visible())
+ redraw();
+
+ update_v_scrollbar();
+ update_h_scrollbar();
+}
+
+/*
+** Refresh a rectangle of the text display. left and top are in coordinates of
+** the text drawing window
+*/
+void Fl_Text_Display::draw_text( int left, int top, int width, int height ) {
+ int fontHeight, firstLine, lastLine, line;
+
+ /* find the line number range of the display */
+ fontHeight = mMaxsize ? mMaxsize : textsize_;
+ firstLine = ( top - text_area.y - fontHeight + 1 ) / fontHeight;
+ lastLine = ( top + height - text_area.y ) / fontHeight + 1;
+
+ fl_push_clip( left, top, width, height );
+
+ /* draw the lines */
+ for ( line = firstLine; line <= lastLine; line++ )
+ draw_vline( line, left, left + width, 0, INT_MAX );
+
+ /* draw the line numbers if exposed area includes them */
+ if (mLineNumWidth != 0 && left <= mLineNumLeft + mLineNumWidth)
+ draw_line_numbers(false);
+
+ fl_pop_clip();
+}
+
+void Fl_Text_Display::redisplay_range(int startpos, int endpos) {
+ if (damage_range1_start == -1 && damage_range1_end == -1) {
+ damage_range1_start = startpos;
+ damage_range1_end = endpos;
+ } else if ((startpos >= damage_range1_start && startpos <= damage_range1_end) ||
+ (endpos >= damage_range1_start && endpos <= damage_range1_end)) {
+ damage_range1_start = min(damage_range1_start, startpos);
+ damage_range1_end = max(damage_range1_end, endpos);
+ } else if (damage_range2_start == -1 && damage_range2_end == -1) {
+ damage_range2_start = startpos;
+ damage_range2_end = endpos;
+ } else {
+ damage_range2_start = min(damage_range2_start, startpos);
+ damage_range2_end = max(damage_range2_end, endpos);
+ }
+ damage(FL_DAMAGE_SCROLL);
+}
+/*
+** Refresh all of the text between buffer positions "start" and "end"
+** not including the character at the position "end".
+** If end points beyond the end of the buffer, refresh the whole display
+** after pos, including blank lines which are not technically part of
+** any range of characters.
+*/
+void Fl_Text_Display::draw_range(int startpos, int endpos) {
+ int i, startLine, lastLine, startIndex, endIndex;
+
+ /* If the range is outside of the displayed text, just return */
+ if ( endpos < mFirstChar || ( startpos > mLastChar &&
+ !empty_vlines() ) ) return;
+
+ /* Clean up the starting and ending values */
+ if ( startpos < 0 ) startpos = 0;
+ if ( startpos > mBuffer->length() ) startpos = mBuffer->length();
+ if ( endpos < 0 ) endpos = 0;
+ if ( endpos > mBuffer->length() ) endpos = mBuffer->length();
+
+ /* Get the starting and ending lines */
+ if ( startpos < mFirstChar )
+ startpos = mFirstChar;
+ if ( !position_to_line( startpos, &startLine ) )
+ startLine = mNVisibleLines - 1;
+ if ( endpos >= mLastChar ) {
+ lastLine = mNVisibleLines - 1;
+ } else {
+ if ( !position_to_line( endpos, &lastLine ) ) {
+ /* shouldn't happen */
+ lastLine = mNVisibleLines - 1;
+ }
+ }
+
+ /* Get the starting and ending positions within the lines */
+ startIndex = mLineStarts[ startLine ] == -1 ? 0 :
+ startpos - mLineStarts[ startLine ];
+ if ( endpos >= mLastChar )
+ endIndex = INT_MAX;
+ else if ( mLineStarts[ lastLine ] == -1 )
+ endIndex = 0;
+ else
+ endIndex = endpos - mLineStarts[ lastLine ];
+
+ /* If the starting and ending lines are the same, redisplay the single
+ line between "start" and "end" */
+ if ( startLine == lastLine ) {
+ draw_vline( startLine, 0, INT_MAX, startIndex, endIndex );
+ return;
+ }
+
+ /* Redisplay the first line from "start" */
+ draw_vline( startLine, 0, INT_MAX, startIndex, INT_MAX );
+
+ /* Redisplay the lines in between at their full width */
+ for ( i = startLine + 1; i < lastLine; i++ )
+ draw_vline( i, 0, INT_MAX, 0, INT_MAX );
+
+ /* Redisplay the last line to "end" */
+ draw_vline( lastLine, 0, INT_MAX, 0, endIndex );
+}
+
+/*
+** Set the position of the text insertion cursor for text display
+*/
+void Fl_Text_Display::insert_position( int newPos ) {
+ /* make sure new position is ok, do nothing if it hasn't changed */
+ if ( newPos == mCursorPos )
+ return;
+ if ( newPos < 0 ) newPos = 0;
+ if ( newPos > mBuffer->length() ) newPos = mBuffer->length();
+
+ /* cursor movement cancels vertical cursor motion column */
+ mCursorPreferredCol = -1;
+
+ /* erase the cursor at it's previous position */
+ redisplay_range(mCursorPos - 1, mCursorPos + 1);
+
+ mCursorPos = newPos;
+
+ /* draw cursor at its new position */
+ redisplay_range(mCursorPos - 1, mCursorPos + 1);
+}
+
+void Fl_Text_Display::show_cursor(int b) {
+ mCursorOn = b;
+ redisplay_range(mCursorPos - 1, mCursorPos + 1);
+}
+
+void Fl_Text_Display::cursor_style(int style) {
+ mCursorStyle = style;
+ if (mCursorOn) show_cursor();
+}
+
+void Fl_Text_Display::wrap_mode(int wrap, int wrapMargin) {
+ mWrapMargin = wrapMargin;
+ mContinuousWrap = wrap;
+
+ if (buffer()) {
+ /* wrapping can change the total number of lines, re-count */
+ mNBufferLines = count_lines(0, buffer()->length(), true);
+
+ /* changing wrap margins or changing from wrapped mode to non-wrapped
+ can leave the character at the top no longer at a line start, and/or
+ change the line number */
+ mFirstChar = line_start(mFirstChar);
+ mTopLineNum = count_lines(0, mFirstChar, true) + 1;
+
+ reset_absolute_top_line_number();
+
+ /* update the line starts array */
+ calc_line_starts(0, mNVisibleLines);
+ calc_last_char();
+ } else {
+ // No buffer, so just clear the state info for later...
+ mNBufferLines = 0;
+ mFirstChar = 0;
+ mTopLineNum = 1;
+ mAbsTopLineNum = 0;
+ }
+
+ resize(x(), y(), w(), h());
+}
+
+/*
+** Insert "text" at the current cursor location. This has the same
+** effect as inserting the text into the buffer using BufInsert and
+** then moving the insert position after the newly inserted text, except
+** that it's optimized to do less redrawing.
+*/
+void Fl_Text_Display::insert(const char* text) {
+ int pos = mCursorPos;
+
+ mCursorToHint = pos + strlen( text );
+ mBuffer->insert( pos, text );
+ mCursorToHint = NO_HINT;
+}
+
+/*
+** Insert "text" (which must not contain newlines), overstriking the current
+** cursor location.
+*/
+void Fl_Text_Display::overstrike(const char* text) {
+ int startPos = mCursorPos;
+ Fl_Text_Buffer *buf = mBuffer;
+ int lineStart = buf->line_start( startPos );
+ int textLen = strlen( text );
+ int i, p, endPos, indent, startIndent, endIndent;
+ const char *c;
+ char ch, *paddedText = NULL;
+
+ /* determine how many displayed character positions are covered */
+ startIndent = mBuffer->count_displayed_characters( lineStart, startPos );
+ indent = startIndent;
+ for ( c = text; *c != '\0'; c++ )
+ indent += Fl_Text_Buffer::character_width( *c, indent, buf->tab_distance(), buf->null_substitution_character() );
+ endIndent = indent;
+
+ /* find which characters to remove, and if necessary generate additional
+ padding to make up for removed control characters at the end */
+ indent = startIndent;
+ for ( p = startPos; ; p++ ) {
+ if ( p == buf->length() )
+ break;
+ ch = buf->character( p );
+ if ( ch == '\n' )
+ break;
+ indent += Fl_Text_Buffer::character_width( ch, indent, buf->tab_distance(), buf->null_substitution_character() );
+ if ( indent == endIndent ) {
+ p++;
+ break;
+ } else if ( indent > endIndent ) {
+ if ( ch != '\t' ) {
+ p++;
+ paddedText = new char [ textLen + FL_TEXT_MAX_EXP_CHAR_LEN + 1 ];
+ strcpy( paddedText, text );
+ for ( i = 0; i < indent - endIndent; i++ )
+ paddedText[ textLen + i ] = ' ';
+ paddedText[ textLen + i ] = '\0';
+ }
+ break;
+ }
+ }
+ endPos = p;
+
+ mCursorToHint = startPos + textLen;
+ buf->replace( startPos, endPos, paddedText == NULL ? text : paddedText );
+ mCursorToHint = NO_HINT;
+ if ( paddedText != NULL )
+ delete [] paddedText;
+}
+
+/*
+** Translate a buffer text position to the XY location where the top left
+** of the cursor would be positioned to point to that character. Returns
+** 0 if the position is not displayed because it is VERTICALLY out
+** of view. If the position is horizontally out of view, returns the
+** X coordinate where the position would be if it were visible.
+*/
+
+int Fl_Text_Display::position_to_xy( int pos, int* X, int* Y ) {
+ int charIndex, lineStartPos, fontHeight, lineLen;
+ int visLineNum, charLen, outIndex, xStep, charStyle;
+ char expandedChar[ FL_TEXT_MAX_EXP_CHAR_LEN ];
+ const char *lineStr;
+
+// printf("position_to_xy(pos=%d, X=%p, Y=%p)\n", pos, X, Y);
+
+ /* If position is not displayed, return false */
+ if (pos < mFirstChar || (pos > mLastChar && !empty_vlines())) {
+// printf(" returning 0\n"
+// " mFirstChar=%d, mLastChar=%d, empty_vlines()=0\n",
+// mFirstChar, mLastChar);
+ return 0;
+ }
+
+ /* Calculate Y coordinate */
+ if (!position_to_line(pos, &visLineNum)) {
+// puts(" returning 0\n"
+// " position_to_line()=0");
+ return 0;
+ }
+
+ if (visLineNum < 0 || visLineNum > mNBufferLines) {
+// printf(" returning 0\n"
+// " visLineNum=%d, mNBufferLines=%d\n",
+// visLineNum, mNBufferLines);
+ return 0;
+ }
+
+ fontHeight = mMaxsize;
+ *Y = text_area.y + visLineNum * fontHeight;
+
+ /* Get the text, length, and buffer position of the line. If the position
+ is beyond the end of the buffer and should be at the first position on
+ the first empty line, don't try to get or scan the text */
+ lineStartPos = mLineStarts[visLineNum];
+ if ( lineStartPos == -1 ) {
+ *X = text_area.x - mHorizOffset;
+ return 1;
+ }
+ lineLen = vline_length( visLineNum );
+ lineStr = mBuffer->text_range( lineStartPos, lineStartPos + lineLen );
+
+ /* Step through character positions from the beginning of the line
+ to "pos" to calculate the X coordinate */
+ xStep = text_area.x - mHorizOffset;
+ outIndex = 0;
+ for ( charIndex = 0; charIndex < lineLen && charIndex < pos - lineStartPos; charIndex++ ) {
+ charLen = Fl_Text_Buffer::expand_character( lineStr[ charIndex ], outIndex, expandedChar,
+ mBuffer->tab_distance(), mBuffer->null_substitution_character() );
+ charStyle = position_style( lineStartPos, lineLen, charIndex,
+ outIndex );
+ xStep += string_width( expandedChar, charLen, charStyle );
+ outIndex += charLen;
+ }
+ *X = xStep;
+ free((char *)lineStr);
+ return 1;
+}
+
+/*
+** Find the line number of position "pos". Note: this only works for
+** displayed lines. If the line is not displayed, the function returns
+** 0 (without the mLineStarts array it could turn in to very long
+** calculation involving scanning large amounts of text in the buffer).
+** If continuous wrap mode is on, returns the absolute line number (as opposed
+** to the wrapped line number which is used for scrolling).
+*/
+int Fl_Text_Display::position_to_linecol( int pos, int* lineNum, int* column ) {
+ int retVal;
+
+ /* In continuous wrap mode, the absolute (non-wrapped) line count is
+ maintained separately, as needed. Only return it if we're actually
+ keeping track of it and pos is in the displayed text */
+ if (mContinuousWrap) {
+ if (!maintaining_absolute_top_line_number() ||
+ pos < mFirstChar || pos > mLastChar)
+ return 0;
+ *lineNum = mAbsTopLineNum + buffer()->count_lines(mFirstChar, pos);
+ *column
+ = buffer()->count_displayed_characters(buffer()->line_start(pos), pos);
+ return 1;
+ }
+
+ retVal = position_to_line( pos, lineNum );
+ if ( retVal ) {
+ *column = mBuffer->count_displayed_characters(
+ mLineStarts[ *lineNum ], pos );
+ *lineNum += mTopLineNum;
+ }
+ return retVal;
+}
+
+/*
+** Return 1 if position (X, Y) is inside of the primary Fl_Text_Selection
+*/
+int Fl_Text_Display::in_selection( int X, int Y ) {
+ int row, column, pos = xy_to_position( X, Y, CHARACTER_POS );
+ Fl_Text_Buffer *buf = mBuffer;
+
+ xy_to_rowcol( X, Y, &row, &column, CHARACTER_POS );
+ if (range_touches_selection(buf->primary_selection(), mFirstChar, mLastChar))
+ column = wrapped_column(row, column);
+ return buf->primary_selection()->includes(pos, buf->line_start( pos ), column);
+}
+
+/*
+** Correct a column number based on an unconstrained position (as returned by
+** TextDXYToUnconstrainedPosition) to be relative to the last actual newline
+** in the buffer before the row and column position given, rather than the
+** last line start created by line wrapping. This is an adapter
+** for rectangular selections and code written before continuous wrap mode,
+** which thinks that the unconstrained column is the number of characters
+** from the last newline. Obviously this is time consuming, because it
+** invloves character re-counting.
+*/
+int Fl_Text_Display::wrapped_column(int row, int column) {
+ int lineStart, dispLineStart;
+
+ if (!mContinuousWrap || row < 0 || row > mNVisibleLines)
+ return column;
+ dispLineStart = mLineStarts[row];
+ if (dispLineStart == -1)
+ return column;
+ lineStart = buffer()->line_start(dispLineStart);
+ return column
+ + buffer()->count_displayed_characters(lineStart, dispLineStart);
+}
+
+/*
+** Correct a row number from an unconstrained position (as returned by
+** TextDXYToUnconstrainedPosition) to a straight number of newlines from the
+** top line of the display. Because rectangular selections are based on
+** newlines, rather than display wrapping, and anywhere a rectangular selection
+** needs a row, it needs it in terms of un-wrapped lines.
+*/
+int Fl_Text_Display::wrapped_row(int row) {
+ if (!mContinuousWrap || row < 0 || row > mNVisibleLines)
+ return row;
+ return buffer()->count_lines(mFirstChar, mLineStarts[row]);
+}
+
+/*
+** Scroll the display to bring insertion cursor into view.
+**
+** Note: it would be nice to be able to do this without counting lines twice
+** (scroll_() counts them too) and/or to count from the most efficient
+** starting point, but the efficiency of this routine is not as important to
+** the overall performance of the text display.
+*/
+void Fl_Text_Display::display_insert() {
+ int hOffset, topLine, X, Y;
+ hOffset = mHorizOffset;
+ topLine = mTopLineNum;
+
+// FIXME: I don't understand this well enough to know if it is correct
+// it is different than nedit 5.3
+ if (insert_position() < mFirstChar) {
+ topLine -= count_lines(insert_position(), mFirstChar, false);
+ } else if (mLineStarts[mNVisibleLines-2] != -1) {
+ int lastChar = line_end(mLineStarts[mNVisibleLines-2],true);
+ if (insert_position() >= lastChar)
+ topLine
+ += count_lines(lastChar - (wrap_uses_character(mLastChar) ? 0 : 1),
+ insert_position(), false);
+ }
+
+ /* Find the new setting for horizontal offset (this is a bit ungraceful).
+ If the line is visible, just use PositionToXY to get the position
+ to scroll to, otherwise, do the vertical scrolling first, then the
+ horizontal */
+ if (!position_to_xy( mCursorPos, &X, &Y )) {
+ scroll_(topLine, hOffset);
+ if (!position_to_xy( mCursorPos, &X, &Y )) {
+ #ifdef DEBUG
+ printf ("*** display_insert/position_to_xy # GIVE UP !\n"); fflush(stdout);
+ #endif // DEBUG
+ return; /* Give up, it's not worth it (but why does it fail?) */
+ }
+ }
+ if (X > text_area.x + text_area.w)
+ hOffset += X-(text_area.x + text_area.w);
+ else if (X < text_area.x)
+ hOffset += X-text_area.x;
+
+ /* Do the scroll */
+ if (topLine != mTopLineNum || hOffset != mHorizOffset)
+ scroll_(topLine, hOffset);
+}
+
+void Fl_Text_Display::show_insert_position() {
+ display_insert_position_hint = 1;
+ resize(x(), y(), w(), h());
+}
+
+/*
+** Cursor movement functions
+*/
+int Fl_Text_Display::move_right() {
+ if ( mCursorPos >= mBuffer->length() )
+ return 0;
+ insert_position( mCursorPos + 1 );
+ return 1;
+}
+
+int Fl_Text_Display::move_left() {
+ if ( mCursorPos <= 0 )
+ return 0;
+ insert_position( mCursorPos - 1 );
+ return 1;
+}
+
+int Fl_Text_Display::move_up() {
+ int lineStartPos, column, prevLineStartPos, newPos, visLineNum;
+
+ /* Find the position of the start of the line. Use the line starts array
+ if possible */
+ if ( position_to_line( mCursorPos, &visLineNum ) )
+ lineStartPos = mLineStarts[ visLineNum ];
+ else {
+ lineStartPos = line_start( mCursorPos );
+ visLineNum = -1;
+ }
+ if ( lineStartPos == 0 )
+ return 0;
+
+ /* Decide what column to move to, if there's a preferred column use that */
+ column = mCursorPreferredCol >= 0 ? mCursorPreferredCol :
+ mBuffer->count_displayed_characters( lineStartPos, mCursorPos );
+
+ /* count forward from the start of the previous line to reach the column */
+ if ( visLineNum != -1 && visLineNum != 0 )
+ prevLineStartPos = mLineStarts[ visLineNum - 1 ];
+ else
+ prevLineStartPos = rewind_lines( lineStartPos, 1 );
+ newPos = mBuffer->skip_displayed_characters( prevLineStartPos, column );
+ if (mContinuousWrap)
+ newPos = min(newPos, line_end(prevLineStartPos, true));
+
+ /* move the cursor */
+ insert_position( newPos );
+
+ /* if a preferred column wasn't aleady established, establish it */
+ mCursorPreferredCol = column;
+ return 1;
+}
+
+int Fl_Text_Display::move_down() {
+ int lineStartPos, column, nextLineStartPos, newPos, visLineNum;
+
+ if ( mCursorPos == mBuffer->length() )
+ return 0;
+ if ( position_to_line( mCursorPos, &visLineNum ) )
+ lineStartPos = mLineStarts[ visLineNum ];
+ else {
+ lineStartPos = line_start( mCursorPos );
+ visLineNum = -1;
+ }
+ column = mCursorPreferredCol >= 0 ? mCursorPreferredCol :
+ mBuffer->count_displayed_characters( lineStartPos, mCursorPos );
+ nextLineStartPos = skip_lines( lineStartPos, 1, true );
+ newPos = mBuffer->skip_displayed_characters( nextLineStartPos, column );
+ if (mContinuousWrap)
+ newPos = min(newPos, line_end(nextLineStartPos, true));
+
+ insert_position( newPos );
+ mCursorPreferredCol = column;
+ return 1;
+}
+
+/*
+** Same as BufCountLines, but takes in to account wrapping if wrapping is
+** turned on. If the caller knows that startPos is at a line start, it
+** can pass "startPosIsLineStart" as True to make the call more efficient
+** by avoiding the additional step of scanning back to the last newline.
+*/
+int Fl_Text_Display::count_lines(int startPos, int endPos,
+ bool startPosIsLineStart) {
+ int retLines, retPos, retLineStart, retLineEnd;
+
+#ifdef DEBUG
+ printf("Fl_Text_Display::count_lines(startPos=%d, endPos=%d, startPosIsLineStart=%d\n",
+ startPos, endPos, startPosIsLineStart);
+#endif // DEBUG
+
+ /* If we're not wrapping use simple (and more efficient) BufCountLines */
+ if (!mContinuousWrap)
+ return buffer()->count_lines(startPos, endPos);
+
+ wrapped_line_counter(buffer(), startPos, endPos, INT_MAX,
+ startPosIsLineStart, 0, &retPos, &retLines, &retLineStart,
+ &retLineEnd);
+
+#ifdef DEBUG
+ printf(" # after WLC: retPos=%d, retLines=%d, retLineStart=%d, retLineEnd=%d\n",
+ retPos, retLines, retLineStart, retLineEnd);
+#endif // DEBUG
+
+ return retLines;
+}
+
+/*
+** Same as BufCountForwardNLines, but takes in to account line breaks when
+** wrapping is turned on. If the caller knows that startPos is at a line start,
+** it can pass "startPosIsLineStart" as True to make the call more efficient
+** by avoiding the additional step of scanning back to the last newline.
+*/
+int Fl_Text_Display::skip_lines(int startPos, int nLines,
+ bool startPosIsLineStart) {
+ int retLines, retPos, retLineStart, retLineEnd;
+
+ /* if we're not wrapping use more efficient BufCountForwardNLines */
+ if (!mContinuousWrap)
+ return buffer()->skip_lines(startPos, nLines);
+
+ /* wrappedLineCounter can't handle the 0 lines case */
+ if (nLines == 0)
+ return startPos;
+
+ /* use the common line counting routine to count forward */
+ wrapped_line_counter(buffer(), startPos, buffer()->length(),
+ nLines, startPosIsLineStart, 0, &retPos, &retLines, &retLineStart,
+ &retLineEnd);
+ return retPos;
+}
+
+/*
+** Same as BufEndOfLine, but takes in to account line breaks when wrapping
+** is turned on. If the caller knows that startPos is at a line start, it
+** can pass "startPosIsLineStart" as True to make the call more efficient
+** by avoiding the additional step of scanning back to the last newline.
+**
+** Note that the definition of the end of a line is less clear when continuous
+** wrap is on. With continuous wrap off, it's just a pointer to the newline
+** that ends the line. When it's on, it's the character beyond the last
+** DISPLAYABLE character on the line, where a whitespace character which has
+** been "converted" to a newline for wrapping is not considered displayable.
+** Also note that, a line can be wrapped at a non-whitespace character if the
+** line had no whitespace. In this case, this routine returns a pointer to
+** the start of the next line. This is also consistent with the model used by
+** visLineLength.
+*/
+int Fl_Text_Display::line_end(int pos, bool startPosIsLineStart) {
+ int retLines, retPos, retLineStart, retLineEnd;
+
+ /* If we're not wrapping use more efficien BufEndOfLine */
+ if (!mContinuousWrap)
+ return buffer()->line_end(pos);
+
+ if (pos == buffer()->length())
+ return pos;
+ wrapped_line_counter(buffer(), pos, buffer()->length(), 1,
+ startPosIsLineStart, 0, &retPos, &retLines, &retLineStart,
+ &retLineEnd);
+ return retLineEnd;
+}
+
+/*
+** Same as BufStartOfLine, but returns the character after last wrap point
+** rather than the last newline.
+*/
+int Fl_Text_Display::line_start(int pos) {
+ int retLines, retPos, retLineStart, retLineEnd;
+
+ /* If we're not wrapping, use the more efficient BufStartOfLine */
+ if (!mContinuousWrap)
+ return buffer()->line_start(pos);
+
+ wrapped_line_counter(buffer(), buffer()->line_start(pos), pos, INT_MAX, true, 0,
+ &retPos, &retLines, &retLineStart, &retLineEnd);
+ return retLineStart;
+}
+
+/*
+** Same as BufCountBackwardNLines, but takes in to account line breaks when
+** wrapping is turned on.
+*/
+int Fl_Text_Display::rewind_lines(int startPos, int nLines) {
+ Fl_Text_Buffer *buf = buffer();
+ int pos, lineStart, retLines, retPos, retLineStart, retLineEnd;
+
+ /* If we're not wrapping, use the more efficient BufCountBackwardNLines */
+ if (!mContinuousWrap)
+ return buf->rewind_lines(startPos, nLines);
+
+ pos = startPos;
+ for (;;) {
+ lineStart = buf->line_start(pos);
+ wrapped_line_counter(buf, lineStart, pos, INT_MAX,
+ true, 0, &retPos, &retLines, &retLineStart, &retLineEnd, false);
+ if (retLines > nLines)
+ return skip_lines(lineStart, retLines-nLines,
+ true);
+ nLines -= retLines;
+ pos = lineStart - 1;
+ if (pos < 0)
+ return 0;
+ nLines -= 1;
+ }
+}
+
+static inline int fl_isseparator(int c) {
+ return c != '$' && c != '_' && (isspace(c) || ispunct(c));
+}
+
+void Fl_Text_Display::next_word() {
+ int pos = insert_position();
+ while (pos < buffer()->length() && !fl_isseparator(buffer()->character(pos))) {
+ pos++;
+ }
+ while (pos < buffer()->length() && fl_isseparator(buffer()->character(pos))) {
+ pos++;
+ }
+
+ insert_position( pos );
+}
+
+void Fl_Text_Display::previous_word() {
+ int pos = insert_position();
+ if (pos==0) return;
+ pos--;
+ while (pos && fl_isseparator(buffer()->character(pos))) {
+ pos--;
+ }
+ while (pos && !fl_isseparator(buffer()->character(pos))) {
+ pos--;
+ }
+ if (fl_isseparator(buffer()->character(pos))) pos++;
+
+ insert_position( pos );
+}
+
+/*
+** Callback attached to the text buffer to receive delete information before
+** the modifications are actually made.
+*/
+void Fl_Text_Display::buffer_predelete_cb(int pos, int nDeleted, void *cbArg) {
+ Fl_Text_Display *textD = (Fl_Text_Display *)cbArg;
+ if (textD->mContinuousWrap &&
+ (textD->mFixedFontWidth == -1 || textD->mModifyingTabDistance))
+ /* Note: we must perform this measurement, even if there is not a
+ single character deleted; the number of "deleted" lines is the
+ number of visual lines spanned by the real line in which the
+ modification takes place.
+ Also, a modification of the tab distance requires the same
+ kind of calculations in advance, even if the font width is "fixed",
+ because when the width of the tab characters changes, the layout
+ of the text may be completely different. */
+ textD->measure_deleted_lines(pos, nDeleted);
+ else
+ textD->mSuppressResync = 0; /* Probably not needed, but just in case */
+}
+
+/*
+** Callback attached to the text buffer to receive modification information
+*/
+void Fl_Text_Display::buffer_modified_cb( int pos, int nInserted, int nDeleted,
+ int nRestyled, const char *deletedText, void *cbArg ) {
+ int linesInserted, linesDeleted, startDispPos, endDispPos;
+ Fl_Text_Display *textD = ( Fl_Text_Display * ) cbArg;
+ Fl_Text_Buffer *buf = textD->mBuffer;
+ int oldFirstChar = textD->mFirstChar;
+ int scrolled, origCursorPos = textD->mCursorPos;
+ int wrapModStart, wrapModEnd;
+
+ /* buffer modification cancels vertical cursor motion column */
+ if ( nInserted != 0 || nDeleted != 0 )
+ textD->mCursorPreferredCol = -1;
+
+ /* Count the number of lines inserted and deleted, and in the case
+ of continuous wrap mode, how much has changed */
+ if (textD->mContinuousWrap) {
+ textD->find_wrap_range(deletedText, pos, nInserted, nDeleted,
+ &wrapModStart, &wrapModEnd, &linesInserted, &linesDeleted);
+ } else {
+ linesInserted = nInserted == 0 ? 0 :
+ buf->count_lines( pos, pos + nInserted );
+ linesDeleted = nDeleted == 0 ? 0 : countlines( deletedText );
+ }
+
+ /* Update the line starts and mTopLineNum */
+ if ( nInserted != 0 || nDeleted != 0 ) {
+ if (textD->mContinuousWrap) {
+ textD->update_line_starts( wrapModStart, wrapModEnd-wrapModStart,
+ nDeleted + pos-wrapModStart + (wrapModEnd-(pos+nInserted)),
+ linesInserted, linesDeleted, &scrolled );
+ } else {
+ textD->update_line_starts( pos, nInserted, nDeleted, linesInserted,
+ linesDeleted, &scrolled );
+ }
+ } else
+ scrolled = 0;
+
+ /* If we're counting non-wrapped lines as well, maintain the absolute
+ (non-wrapped) line number of the text displayed */
+ if (textD->maintaining_absolute_top_line_number() &&
+ (nInserted != 0 || nDeleted != 0)) {
+ if (pos + nDeleted < oldFirstChar)
+ textD->mAbsTopLineNum += buf->count_lines(pos, pos + nInserted) -
+ countlines(deletedText);
+ else if (pos < oldFirstChar)
+ textD->reset_absolute_top_line_number();
+ }
+
+ /* Update the line count for the whole buffer */
+ textD->mNBufferLines += linesInserted - linesDeleted;
+
+ /* Update the cursor position */
+ if ( textD->mCursorToHint != NO_HINT ) {
+ textD->mCursorPos = textD->mCursorToHint;
+ textD->mCursorToHint = NO_HINT;
+ } else if ( textD->mCursorPos > pos ) {
+ if ( textD->mCursorPos < pos + nDeleted )
+ textD->mCursorPos = pos;
+ else
+ textD->mCursorPos += nInserted - nDeleted;
+ }
+
+ // refigure scrollbars & stuff
+ textD->resize(textD->x(), textD->y(), textD->w(), textD->h());
+
+ // don't need to do anything else if not visible?
+ if (!textD->visible_r()) return;
+
+ /* If the changes caused scrolling, re-paint everything and we're done. */
+ if ( scrolled ) {
+ textD->damage(FL_DAMAGE_EXPOSE);
+ if ( textD->mStyleBuffer ) /* See comments in extendRangeForStyleMods */
+ textD->mStyleBuffer->primary_selection()->selected(0);
+ return;
+ }
+
+ /* If the changes didn't cause scrolling, decide the range of characters
+ that need to be re-painted. Also if the cursor position moved, be
+ sure that the redisplay range covers the old cursor position so the
+ old cursor gets erased, and erase the bits of the cursor which extend
+ beyond the left and right edges of the text. */
+ startDispPos = textD->mContinuousWrap ? wrapModStart : pos;
+ if ( origCursorPos == startDispPos && textD->mCursorPos != startDispPos )
+ startDispPos = min( startDispPos, origCursorPos - 1 );
+ if ( linesInserted == linesDeleted ) {
+ if ( nInserted == 0 && nDeleted == 0 )
+ endDispPos = pos + nRestyled;
+ else {
+ endDispPos = textD->mContinuousWrap ? wrapModEnd :
+ buf->line_end( pos + nInserted ) + 1;
+ // CET - FIXME if ( origCursorPos >= startDispPos &&
+ // ( origCursorPos <= endDispPos || endDispPos == buf->length() ) )
+ }
+
+ if (linesInserted > 1) textD->draw_line_numbers(false);
+ } else {
+ endDispPos = textD->mLastChar + 1;
+ // CET - FIXME if ( origCursorPos >= pos )
+ /* If more than one line is inserted/deleted, a line break may have
+ been inserted or removed in between, and the line numbers may
+ have changed. If only one line is altered, line numbers cannot
+ be affected (the insertion or removal of a line break always
+ results in at least two lines being redrawn). */
+ textD->draw_line_numbers(false);
+ }
+
+ /* If there is a style buffer, check if the modification caused additional
+ changes that need to be redisplayed. (Redisplaying separately would
+ cause double-redraw on almost every modification involving styled
+ text). Extend the redraw range to incorporate style changes */
+ if ( textD->mStyleBuffer )
+ textD->extend_range_for_styles( &startDispPos, &endDispPos );
+
+ /* Redisplay computed range */
+ textD->redisplay_range( startDispPos, endDispPos );
+}
+
+/*
+** In continuous wrap mode, internal line numbers are calculated after
+** wrapping. A separate non-wrapped line count is maintained when line
+** numbering is turned on. There is some performance cost to maintaining this
+** line count, so normally absolute line numbers are not tracked if line
+** numbering is off. This routine allows callers to specify that they still
+** want this line count maintained (for use via TextDPosToLineAndCol).
+** More specifically, this allows the line number reported in the statistics
+** line to be calibrated in absolute lines, rather than post-wrapped lines.
+*/
+void Fl_Text_Display::maintain_absolute_top_line_number(int state) {
+ mNeedAbsTopLineNum = state;
+ reset_absolute_top_line_number();
+}
+
+/*
+** Returns the absolute (non-wrapped) line number of the first line displayed.
+** Returns 0 if the absolute top line number is not being maintained.
+*/
+int Fl_Text_Display::get_absolute_top_line_number() {
+ if (!mContinuousWrap)
+ return mTopLineNum;
+ if (maintaining_absolute_top_line_number())
+ return mAbsTopLineNum;
+ return 0;
+}
+
+/*
+** Re-calculate absolute top line number for a change in scroll position.
+*/
+void Fl_Text_Display::absolute_top_line_number(int oldFirstChar) {
+ if (maintaining_absolute_top_line_number()) {
+ if (mFirstChar < oldFirstChar)
+ mAbsTopLineNum -= buffer()->count_lines(mFirstChar, oldFirstChar);
+ else
+ mAbsTopLineNum += buffer()->count_lines(oldFirstChar, mFirstChar);
+ }
+}
+
+/*
+** Return true if a separate absolute top line number is being maintained
+** (for displaying line numbers or showing in the statistics line).
+*/
+int Fl_Text_Display::maintaining_absolute_top_line_number() {
+ return mContinuousWrap &&
+ (mLineNumWidth != 0 || mNeedAbsTopLineNum);
+}
+
+/*
+** Count lines from the beginning of the buffer to reestablish the
+** absolute (non-wrapped) top line number. If mode is not continuous wrap,
+** or the number is not being maintained, does nothing.
+*/
+void Fl_Text_Display::reset_absolute_top_line_number() {
+ mAbsTopLineNum = 1;
+ absolute_top_line_number(0);
+}
+
+/*
+** Find the line number of position "pos" relative to the first line of
+** displayed text. Returns 0 if the line is not displayed.
+*/
+int Fl_Text_Display::position_to_line( int pos, int *lineNum ) {
+ int i;
+
+ *lineNum = 0;
+ if ( pos < mFirstChar ) return 0;
+ if ( pos > mLastChar ) {
+ if ( empty_vlines() ) {
+ if ( mLastChar < mBuffer->length() ) {
+ if ( !position_to_line( mLastChar, lineNum ) ) {
+ Fl::error("Fl_Text_Display::position_to_line(): Consistency check ptvl failed");
+ return 0;
+ }
+ return ++( *lineNum ) <= mNVisibleLines - 1;
+ } else {
+ position_to_line( mLastChar - 1, lineNum );
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ for ( i = mNVisibleLines - 1; i >= 0; i-- ) {
+ if ( mLineStarts[ i ] != -1 && pos >= mLineStarts[ i ] ) {
+ *lineNum = i;
+ return 1;
+ }
+ }
+ return 0; /* probably never be reached */
+}
+
+/*
+** Draw the text on a single line represented by "visLineNum" (the
+** number of lines down from the top of the display), limited by
+** "leftClip" and "rightClip" window coordinates and "leftCharIndex" and
+** "rightCharIndex" character positions (not including the character at
+** position "rightCharIndex").
+*/
+void Fl_Text_Display::draw_vline(int visLineNum, int leftClip, int rightClip,
+ int leftCharIndex, int rightCharIndex) {
+ Fl_Text_Buffer * buf = mBuffer;
+ int i, X, Y, startX, charIndex, lineStartPos, lineLen, fontHeight;
+ int stdCharWidth, charWidth, startIndex, charStyle, style;
+ int charLen, outStartIndex, outIndex;
+ int dispIndexOffset;
+ char expandedChar[ FL_TEXT_MAX_EXP_CHAR_LEN ], outStr[ MAX_DISP_LINE_LEN ];
+ char *outPtr;
+ const char *lineStr;
+
+// printf("draw_vline(visLineNum=%d, leftClip=%d, rightClip=%d, leftCharIndex=%d, rightCharIndex=%d)\n",
+// visLineNum, leftClip, rightClip, leftCharIndex, rightCharIndex);
+// printf("nNVisibleLines=%d\n", mNVisibleLines);
+
+ /* If line is not displayed, skip it */
+ if ( visLineNum < 0 || visLineNum >= mNVisibleLines )
+ return;
+
+ /* Calculate Y coordinate of the string to draw */
+ fontHeight = mMaxsize;
+ Y = text_area.y + visLineNum * fontHeight;
+
+ /* Get the text, length, and buffer position of the line to display */
+ lineStartPos = mLineStarts[ visLineNum ];
+// printf("lineStartPos=%d\n", lineStartPos);
+ if ( lineStartPos == -1 ) {
+ lineLen = 0;
+ lineStr = NULL;
+ } else {
+ lineLen = vline_length( visLineNum );
+ lineStr = buf->text_range( lineStartPos, lineStartPos + lineLen );
+ }
+
+ /* Space beyond the end of the line is still counted in units of characters
+ of a standardized character width (this is done mostly because style
+ changes based on character position can still occur in this region due
+ to rectangular Fl_Text_Selections). stdCharWidth must be non-zero to
+ prevent a potential infinite loop if X does not advance */
+ stdCharWidth = TMPFONTWIDTH; //mFontStruct->max_bounds.width;
+ if ( stdCharWidth <= 0 ) {
+ Fl::error("Fl_Text_Display::draw_vline(): bad font measurement");
+ free((void *)lineStr);
+ return;
+ }
+
+ /* Shrink the clipping range to the active display area */
+ leftClip = max( text_area.x, leftClip );
+ rightClip = min( rightClip, text_area.x + text_area.w );
+
+ /* Rectangular Fl_Text_Selections are based on "real" line starts (after
+ a newline or start of buffer). Calculate the difference between the
+ last newline position and the line start we're using. Since scanning
+ back to find a newline is expensive, only do so if there's actually a
+ rectangular Fl_Text_Selection which needs it */
+ if (mContinuousWrap && (range_touches_selection(buf->primary_selection(),
+ lineStartPos, lineStartPos + lineLen) || range_touches_selection(
+ buf->secondary_selection(), lineStartPos, lineStartPos + lineLen) ||
+ range_touches_selection(buf->highlight_selection(), lineStartPos,
+ lineStartPos + lineLen))) {
+ dispIndexOffset = buf->count_displayed_characters(
+ buf->line_start(lineStartPos), lineStartPos);
+ } else
+ dispIndexOffset = 0;
+
+ /* Step through character positions from the beginning of the line (even if
+ that's off the left edge of the displayed area) to find the first
+ character position that's not clipped, and the X coordinate for drawing
+ that character */
+ X = text_area.x - mHorizOffset;
+ outIndex = 0;
+ for ( charIndex = 0; ; charIndex++ ) {
+ charLen = charIndex >= lineLen ? 1 :
+ Fl_Text_Buffer::expand_character( lineStr[ charIndex ], outIndex,
+ expandedChar, buf->tab_distance(), buf->null_substitution_character() );
+ style = position_style( lineStartPos, lineLen, charIndex,
+ outIndex + dispIndexOffset );
+ charWidth = charIndex >= lineLen ? stdCharWidth :
+ string_width( expandedChar, charLen, style );
+ if ( X + charWidth >= leftClip && charIndex >= leftCharIndex ) {
+ startIndex = charIndex;
+ outStartIndex = outIndex;
+ startX = X;
+ break;
+ }
+ X += charWidth;
+ outIndex += charLen;
+ }
+
+ /* Scan character positions from the beginning of the clipping range, and
+ draw parts whenever the style changes (also note if the cursor is on
+ this line, and where it should be drawn to take advantage of the x
+ position which we've gone to so much trouble to calculate) */
+ /* since characters between style may overlap, we draw the full
+ background first */
+ int sX = startX;
+ outPtr = outStr;
+ outIndex = outStartIndex;
+ X = startX;
+ for ( charIndex = startIndex; charIndex < rightCharIndex; charIndex++ ) {
+ charLen = charIndex >= lineLen ? 1 :
+ Fl_Text_Buffer::expand_character( lineStr[ charIndex ], outIndex, expandedChar,
+ buf->tab_distance(), buf->null_substitution_character() );
+ charStyle = position_style( lineStartPos, lineLen, charIndex,
+ outIndex + dispIndexOffset );
+ for ( i = 0; i < charLen; i++ ) {
+ if ( i != 0 && charIndex < lineLen && lineStr[ charIndex ] == '\t' )
+ charStyle = position_style( lineStartPos, lineLen,
+ charIndex, outIndex + dispIndexOffset );
+ if ( charStyle != style ) {
+ draw_string( style|BG_ONLY_MASK, sX, Y, X, outStr, outPtr - outStr );
+ outPtr = outStr;
+ sX = X;
+ style = charStyle;
+ }
+ if ( charIndex < lineLen ) {
+ *outPtr = expandedChar[ i ];
+ charWidth = string_width( &expandedChar[ i ], 1, charStyle );
+ } else
+ charWidth = stdCharWidth;
+ outPtr++;
+ X += charWidth;
+ outIndex++;
+ }
+ if ( outPtr - outStr + FL_TEXT_MAX_EXP_CHAR_LEN >= MAX_DISP_LINE_LEN || X >= rightClip )
+ break;
+ }
+ draw_string( style|BG_ONLY_MASK, sX, Y, X, outStr, outPtr - outStr );
+
+ /* now draw the text over the previously erased background */
+ outPtr = outStr;
+ outIndex = outStartIndex;
+ X = startX;
+ for ( charIndex = startIndex; charIndex < rightCharIndex; charIndex++ ) {
+ charLen = charIndex >= lineLen ? 1 :
+ Fl_Text_Buffer::expand_character( lineStr[ charIndex ], outIndex, expandedChar,
+ buf->tab_distance(), buf->null_substitution_character() );
+ charStyle = position_style( lineStartPos, lineLen, charIndex,
+ outIndex + dispIndexOffset );
+ for ( i = 0; i < charLen; i++ ) {
+ if ( i != 0 && charIndex < lineLen && lineStr[ charIndex ] == '\t' )
+ charStyle = position_style( lineStartPos, lineLen,
+ charIndex, outIndex + dispIndexOffset );
+ if ( charStyle != style ) {
+ draw_string( style|TEXT_ONLY_MASK, startX, Y, X, outStr, outPtr - outStr );
+ outPtr = outStr;
+ startX = X;
+ style = charStyle;
+ }
+ if ( charIndex < lineLen ) {
+ *outPtr = expandedChar[ i ];
+ charWidth = string_width( &expandedChar[ i ], 1, charStyle );
+ } else
+ charWidth = stdCharWidth;
+ outPtr++;
+ X += charWidth;
+ outIndex++;
+ }
+ if ( outPtr - outStr + FL_TEXT_MAX_EXP_CHAR_LEN >= MAX_DISP_LINE_LEN || X >= rightClip )
+ break;
+ }
+
+ /* Draw the remaining style segment */
+ draw_string( style|TEXT_ONLY_MASK, startX, Y, X, outStr, outPtr - outStr );
+
+ /* Draw the cursor if part of it appeared on the redisplayed part of
+ this line. Also check for the cases which are not caught as the
+ line is scanned above: when the cursor appears at the very end
+ of the redisplayed section. */
+ /* CET - FIXME
+ if ( mCursorOn )
+ {
+ if ( hasCursor )
+ draw_cursor( cursorX, Y );
+ else if ( charIndex < lineLen && ( lineStartPos + charIndex + 1 == cursorPos )
+ && X == rightClip )
+ {
+ if ( cursorPos >= buf->length() )
+ draw_cursor( X - 1, Y );
+ else
+ {
+ draw_cursor( X - 1, Y );
+ }
+ }
+ }
+ */
+ if ( lineStr != NULL )
+ free((void *)lineStr);
+}
+
+/*
+** Draw a string or blank area according to parameter "style", using the
+** appropriate colors and drawing method for that style, with top left
+** corner at X, y. If style says to draw text, use "string" as source of
+** characters, and draw "nChars", if style is FILL, erase
+** rectangle where text would have drawn from X to toX and from Y to
+** the maximum Y extent of the current font(s).
+*/
+void Fl_Text_Display::draw_string( int style, int X, int Y, int toX,
+ const char *string, int nChars ) {
+ const Style_Table_Entry * styleRec;
+
+ /* Draw blank area rather than text, if that was the request */
+ if ( style & FILL_MASK ) {
+ if (style & TEXT_ONLY_MASK) return;
+ clear_rect( style, X, Y, toX - X, mMaxsize );
+ return;
+ }
+
+ /* Set font, color, and gc depending on style. For normal text, GCs
+ for normal drawing, or drawing within a Fl_Text_Selection or highlight are
+ pre-allocated and pre-configured. For syntax highlighting, GCs are
+ configured here, on the fly. */
+
+ Fl_Font font = textfont();
+ int fsize = textsize();
+ Fl_Color foreground;
+ Fl_Color background;
+
+ if ( style & STYLE_LOOKUP_MASK ) {
+ int si = (style & STYLE_LOOKUP_MASK) - 'A';
+ if (si < 0) si = 0;
+ else if (si >= mNStyles) si = mNStyles - 1;
+
+ styleRec = mStyleTable + si;
+ font = styleRec->font;
+ fsize = styleRec->size;
+
+ if (style & PRIMARY_MASK) {
+ if (Fl::focus() == this) background = selection_color();
+ else background = fl_color_average(color(), selection_color(), 0.4f);
+ } else if (style & HIGHLIGHT_MASK) {
+ if (Fl::focus() == this) background = fl_color_average(color(), selection_color(), 0.5f);
+ else background = fl_color_average(color(), selection_color(), 0.6f);
+ } else background = color();
+ foreground = fl_contrast(styleRec->color, background);
+ } else if (style & PRIMARY_MASK) {
+ if (Fl::focus() == this) background = selection_color();
+ else background = fl_color_average(color(), selection_color(), 0.4f);
+ foreground = fl_contrast(textcolor(), background);
+ } else if (style & HIGHLIGHT_MASK) {
+ if (Fl::focus() == this) background = fl_color_average(color(), selection_color(), 0.5f);
+ else background = fl_color_average(color(), selection_color(), 0.6f);
+ foreground = fl_contrast(textcolor(), background);
+ } else {
+ foreground = textcolor();
+ background = color();
+ }
+
+ if (!(style & TEXT_ONLY_MASK)) {
+ fl_color( background );
+ fl_rectf( X, Y, toX - X, mMaxsize );
+ }
+ if (!(style & BG_ONLY_MASK)) {
+ fl_color( foreground );
+ fl_font( font, fsize );
+ fl_draw( string, nChars, X, Y + mMaxsize - fl_descent());
+ }
+
+ // CET - FIXME
+ /* If any space around the character remains unfilled (due to use of
+ different sized fonts for highlighting), fill in above or below
+ to erase previously drawn characters */
+ /*
+ if (fs->ascent < mAscent)
+ clear_rect( style, X, Y, toX - X, mAscent - fs->ascent);
+ if (fs->descent < mDescent)
+ clear_rect( style, X, Y + mAscent + fs->descent, toX - x,
+ mDescent - fs->descent);
+ */
+ /* Underline if style is secondary Fl_Text_Selection */
+
+ /*
+ if (style & SECONDARY_MASK)
+ XDrawLine(XtDisplay(mW), XtWindow(mW), gc, x,
+ y + mAscent, toX - 1, Y + fs->ascent);
+ */
+}
+
+
+/*
+** Clear a rectangle with the appropriate background color for "style"
+*/
+void Fl_Text_Display::clear_rect( int style, int X, int Y,
+ int width, int height ) {
+ /* A width of zero means "clear to end of window" to XClearArea */
+ if ( width == 0 )
+ return;
+
+ if (style & PRIMARY_MASK) {
+ if (Fl::focus()==this) {
+ fl_color(selection_color());
+ } else {
+ fl_color(fl_color_average(color(), selection_color(), 0.4f));
+ }
+ } else if (style & HIGHLIGHT_MASK) {
+ if (Fl::focus()==this) {
+ fl_color(fl_color_average(color(), selection_color(), 0.5f));
+ } else {
+ fl_color(fl_color_average(color(), selection_color(), 0.6f));
+ }
+ } else {
+ fl_color( color() );
+ }
+ fl_rectf( X, Y, width, height );
+}
+
+
+/*
+** Draw a cursor with top center at X, y.
+*/
+void Fl_Text_Display::draw_cursor( int X, int Y ) {
+ typedef struct {
+ int x1, y1, x2, y2;
+ }
+ Segment;
+
+ Segment segs[ 5 ];
+ int left, right, cursorWidth, midY;
+ // int fontWidth = mFontStruct->min_bounds.width, nSegs = 0;
+ int fontWidth = TMPFONTWIDTH; // CET - FIXME
+ int nSegs = 0;
+ int fontHeight = mMaxsize;
+ int bot = Y + fontHeight - 1;
+
+ if ( X < text_area.x - 1 || X > text_area.x + text_area.w )
+ return;
+
+ /* For cursors other than the block, make them around 2/3 of a character
+ width, rounded to an even number of pixels so that X will draw an
+ odd number centered on the stem at x. */
+ cursorWidth = 4; //(fontWidth/3) * 2;
+ left = X - cursorWidth / 2;
+ right = left + cursorWidth;
+
+ /* Create segments and draw cursor */
+ if ( mCursorStyle == CARET_CURSOR ) {
+ midY = bot - fontHeight / 5;
+ segs[ 0 ].x1 = left; segs[ 0 ].y1 = bot; segs[ 0 ].x2 = X; segs[ 0 ].y2 = midY;
+ segs[ 1 ].x1 = X; segs[ 1 ].y1 = midY; segs[ 1 ].x2 = right; segs[ 1 ].y2 = bot;
+ segs[ 2 ].x1 = left; segs[ 2 ].y1 = bot; segs[ 2 ].x2 = X; segs[ 2 ].y2 = midY - 1;
+ segs[ 3 ].x1 = X; segs[ 3 ].y1 = midY - 1; segs[ 3 ].x2 = right; segs[ 3 ].y2 = bot;
+ nSegs = 4;
+ } else if ( mCursorStyle == NORMAL_CURSOR ) {
+ segs[ 0 ].x1 = left; segs[ 0 ].y1 = Y; segs[ 0 ].x2 = right; segs[ 0 ].y2 = Y;
+ segs[ 1 ].x1 = X; segs[ 1 ].y1 = Y; segs[ 1 ].x2 = X; segs[ 1 ].y2 = bot;
+ segs[ 2 ].x1 = left; segs[ 2 ].y1 = bot; segs[ 2 ].x2 = right; segs[ 2 ].y2 = bot;
+ nSegs = 3;
+ } else if ( mCursorStyle == HEAVY_CURSOR ) {
+ segs[ 0 ].x1 = X - 1; segs[ 0 ].y1 = Y; segs[ 0 ].x2 = X - 1; segs[ 0 ].y2 = bot;
+ segs[ 1 ].x1 = X; segs[ 1 ].y1 = Y; segs[ 1 ].x2 = X; segs[ 1 ].y2 = bot;
+ segs[ 2 ].x1 = X + 1; segs[ 2 ].y1 = Y; segs[ 2 ].x2 = X + 1; segs[ 2 ].y2 = bot;
+ segs[ 3 ].x1 = left; segs[ 3 ].y1 = Y; segs[ 3 ].x2 = right; segs[ 3 ].y2 = Y;
+ segs[ 4 ].x1 = left; segs[ 4 ].y1 = bot; segs[ 4 ].x2 = right; segs[ 4 ].y2 = bot;
+ nSegs = 5;
+ } else if ( mCursorStyle == DIM_CURSOR ) {
+ midY = Y + fontHeight / 2;
+ segs[ 0 ].x1 = X; segs[ 0 ].y1 = Y; segs[ 0 ].x2 = X; segs[ 0 ].y2 = Y;
+ segs[ 1 ].x1 = X; segs[ 1 ].y1 = midY; segs[ 1 ].x2 = X; segs[ 1 ].y2 = midY;
+ segs[ 2 ].x1 = X; segs[ 2 ].y1 = bot; segs[ 2 ].x2 = X; segs[ 2 ].y2 = bot;
+ nSegs = 3;
+ } else if ( mCursorStyle == BLOCK_CURSOR ) {
+ right = X + fontWidth;
+ segs[ 0 ].x1 = X; segs[ 0 ].y1 = Y; segs[ 0 ].x2 = right; segs[ 0 ].y2 = Y;
+ segs[ 1 ].x1 = right; segs[ 1 ].y1 = Y; segs[ 1 ].x2 = right; segs[ 1 ].y2 = bot;
+ segs[ 2 ].x1 = right; segs[ 2 ].y1 = bot; segs[ 2 ].x2 = X; segs[ 2 ].y2 = bot;
+ segs[ 3 ].x1 = X; segs[ 3 ].y1 = bot; segs[ 3 ].x2 = X; segs[ 3 ].y2 = Y;
+ nSegs = 4;
+ }
+ fl_color( mCursor_color );
+
+ for ( int k = 0; k < nSegs; k++ ) {
+ fl_line( segs[ k ].x1, segs[ k ].y1, segs[ k ].x2, segs[ k ].y2 );
+ }
+}
+
+/*
+** Determine the drawing method to use to draw a specific character from "buf".
+** "lineStartPos" gives the character index where the line begins, "lineIndex",
+** the number of characters past the beginning of the line, and "dispIndex",
+** the number of displayed characters past the beginning of the line. Passing
+** lineStartPos of -1 returns the drawing style for "no text".
+**
+** Why not just: position_style(pos)? Because style applies to blank areas
+** of the window beyond the text boundaries, and because this routine must also
+** decide whether a position is inside of a rectangular Fl_Text_Selection, and do
+** so efficiently, without re-counting character positions from the start of the
+** line.
+**
+** Note that style is a somewhat incorrect name, drawing method would
+** be more appropriate.
+*/
+int Fl_Text_Display::position_style( int lineStartPos,
+ int lineLen, int lineIndex, int dispIndex ) {
+ Fl_Text_Buffer * buf = mBuffer;
+ Fl_Text_Buffer *styleBuf = mStyleBuffer;
+ int pos, style = 0;
+
+ if ( lineStartPos == -1 || buf == NULL )
+ return FILL_MASK;
+
+ pos = lineStartPos + min( lineIndex, lineLen );
+
+ if ( lineIndex >= lineLen )
+ style = FILL_MASK;
+ else if ( styleBuf != NULL ) {
+ style = ( unsigned char ) styleBuf->character( pos );
+ if (style == mUnfinishedStyle && mUnfinishedHighlightCB) {
+ /* encountered "unfinished" style, trigger parsing */
+ (mUnfinishedHighlightCB)( pos, mHighlightCBArg);
+ style = (unsigned char) styleBuf->character( pos);
+ }
+ }
+ if (buf->primary_selection()->includes(pos, lineStartPos, dispIndex))
+ style |= PRIMARY_MASK;
+ if (buf->highlight_selection()->includes(pos, lineStartPos, dispIndex))
+ style |= HIGHLIGHT_MASK;
+ if (buf->secondary_selection()->includes(pos, lineStartPos, dispIndex))
+ style |= SECONDARY_MASK;
+ return style;
+}
+
+/*
+** Find the width of a string in the font of a particular style
+*/
+int Fl_Text_Display::string_width( const char *string, int length, int style ) {
+ Fl_Font font;
+ int fsize;
+
+ if ( style & STYLE_LOOKUP_MASK ) {
+ int si = (style & STYLE_LOOKUP_MASK) - 'A';
+ if (si < 0) si = 0;
+ else if (si >= mNStyles) si = mNStyles - 1;
+
+ font = mStyleTable[si].font;
+ fsize = mStyleTable[si].size;
+ } else {
+ font = textfont();
+ fsize = textsize();
+ }
+ fl_font( font, fsize );
+
+ return ( int ) ( fl_width( string, length ) );
+}
+
+/*
+** Translate window coordinates to the nearest (insert cursor or character
+** cell) text position. The parameter posType specifies how to interpret the
+** position: CURSOR_POS means translate the coordinates to the nearest cursor
+** position, and CHARACTER_POS means return the position of the character
+** closest to (X, Y).
+*/
+int Fl_Text_Display::xy_to_position( int X, int Y, int posType ) {
+ int charIndex, lineStart, lineLen, fontHeight;
+ int charWidth, charLen, charStyle, visLineNum, xStep, outIndex;
+ char expandedChar[ FL_TEXT_MAX_EXP_CHAR_LEN ];
+ const char *lineStr;
+
+ /* Find the visible line number corresponding to the Y coordinate */
+ fontHeight = mMaxsize;
+ visLineNum = ( Y - text_area.y ) / fontHeight;
+ if ( visLineNum < 0 )
+ return mFirstChar;
+ if ( visLineNum >= mNVisibleLines )
+ visLineNum = mNVisibleLines - 1;
+
+ /* Find the position at the start of the line */
+ lineStart = mLineStarts[ visLineNum ];
+
+ /* If the line start was empty, return the last position in the buffer */
+ if ( lineStart == -1 )
+ return mBuffer->length();
+
+ /* Get the line text and its length */
+ lineLen = vline_length( visLineNum );
+ lineStr = mBuffer->text_range( lineStart, lineStart + lineLen );
+
+ /* Step through character positions from the beginning of the line
+ to find the character position corresponding to the X coordinate */
+ xStep = text_area.x - mHorizOffset;
+ outIndex = 0;
+ for ( charIndex = 0; charIndex < lineLen; charIndex++ ) {
+ charLen = Fl_Text_Buffer::expand_character( lineStr[ charIndex ], outIndex, expandedChar,
+ mBuffer->tab_distance(), mBuffer->null_substitution_character() );
+ charStyle = position_style( lineStart, lineLen, charIndex, outIndex );
+ charWidth = string_width( expandedChar, charLen, charStyle );
+ if ( X < xStep + ( posType == CURSOR_POS ? charWidth / 2 : charWidth ) ) {
+ free((char *)lineStr);
+ return lineStart + charIndex;
+ }
+ xStep += charWidth;
+ outIndex += charLen;
+ }
+
+ /* If the X position was beyond the end of the line, return the position
+ of the newline at the end of the line */
+ free((char *)lineStr);
+ return lineStart + lineLen;
+}
+
+/*
+** Translate window coordinates to the nearest row and column number for
+** positioning the cursor. This, of course, makes no sense when the font is
+** proportional, since there are no absolute columns. The parameter posType
+** specifies how to interpret the position: CURSOR_POS means translate the
+** coordinates to the nearest position between characters, and CHARACTER_POS
+** means translate the position to the nearest character cell.
+*/
+void Fl_Text_Display::xy_to_rowcol( int X, int Y, int *row,
+ int *column, int posType ) {
+ int fontHeight = mMaxsize;
+ int fontWidth = TMPFONTWIDTH; //mFontStruct->max_bounds.width;
+
+ /* Find the visible line number corresponding to the Y coordinate */
+ *row = ( Y - text_area.y ) / fontHeight;
+ if ( *row < 0 ) * row = 0;
+ if ( *row >= mNVisibleLines ) * row = mNVisibleLines - 1;
+ *column = ( ( X - text_area.x ) + mHorizOffset +
+ ( posType == CURSOR_POS ? fontWidth / 2 : 0 ) ) / fontWidth;
+ if ( *column < 0 ) * column = 0;
+}
+
+/*
+** Offset the line starts array, mTopLineNum, mFirstChar and lastChar, for a new
+** vertical scroll position given by newTopLineNum. If any currently displayed
+** lines will still be visible, salvage the line starts values, otherwise,
+** count lines from the nearest known line start (start or end of buffer, or
+** the closest value in the mLineStarts array)
+*/
+void Fl_Text_Display::offset_line_starts( int newTopLineNum ) {
+ int oldTopLineNum = mTopLineNum;
+ int oldFirstChar = mFirstChar;
+ int lineDelta = newTopLineNum - oldTopLineNum;
+ int nVisLines = mNVisibleLines;
+ int *lineStarts = mLineStarts;
+ int i, lastLineNum;
+ Fl_Text_Buffer *buf = mBuffer;
+
+ /* If there was no offset, nothing needs to be changed */
+ if ( lineDelta == 0 )
+ return;
+
+ /* Find the new value for mFirstChar by counting lines from the nearest
+ known line start (start or end of buffer, or the closest value in the
+ lineStarts array) */
+ lastLineNum = oldTopLineNum + nVisLines - 1;
+ if ( newTopLineNum < oldTopLineNum && newTopLineNum < -lineDelta ) {
+ mFirstChar = skip_lines( 0, newTopLineNum - 1, true );
+ } else if ( newTopLineNum < oldTopLineNum ) {
+ mFirstChar = rewind_lines( mFirstChar, -lineDelta );
+ } else if ( newTopLineNum < lastLineNum ) {
+ mFirstChar = lineStarts[ newTopLineNum - oldTopLineNum ];
+ } else if ( newTopLineNum - lastLineNum < mNBufferLines - newTopLineNum ) {
+ mFirstChar = skip_lines( lineStarts[ nVisLines - 1 ],
+ newTopLineNum - lastLineNum, true );
+ } else {
+ mFirstChar = rewind_lines( buf->length(), mNBufferLines - newTopLineNum + 1 );
+ }
+
+ /* Fill in the line starts array */
+ if ( lineDelta < 0 && -lineDelta < nVisLines ) {
+ for ( i = nVisLines - 1; i >= -lineDelta; i-- )
+ lineStarts[ i ] = lineStarts[ i + lineDelta ];
+ calc_line_starts( 0, -lineDelta );
+ } else if ( lineDelta > 0 && lineDelta < nVisLines ) {
+ for ( i = 0; i < nVisLines - lineDelta; i++ )
+ lineStarts[ i ] = lineStarts[ i + lineDelta ];
+ calc_line_starts( nVisLines - lineDelta, nVisLines - 1 );
+ } else
+ calc_line_starts( 0, nVisLines );
+
+ /* Set lastChar and mTopLineNum */
+ calc_last_char();
+ mTopLineNum = newTopLineNum;
+
+ /* If we're numbering lines or being asked to maintain an absolute line
+ number, re-calculate the absolute line number */
+ absolute_top_line_number(oldFirstChar);
+}
+
+/*
+** Update the line starts array, mTopLineNum, mFirstChar and lastChar for text
+** display "textD" after a modification to the text buffer, given by the
+** position where the change began "pos", and the nmubers of characters
+** and lines inserted and deleted.
+*/
+void Fl_Text_Display::update_line_starts( int pos, int charsInserted,
+ int charsDeleted, int linesInserted, int linesDeleted, int *scrolled ) {
+ int * lineStarts = mLineStarts;
+ int i, lineOfPos, lineOfEnd, nVisLines = mNVisibleLines;
+ int charDelta = charsInserted - charsDeleted;
+ int lineDelta = linesInserted - linesDeleted;
+
+ /* If all of the changes were before the displayed text, the display
+ doesn't change, just update the top line num and offset the line
+ start entries and first and last characters */
+ if ( pos + charsDeleted < mFirstChar ) {
+ mTopLineNum += lineDelta;
+ for ( i = 0; i < nVisLines && lineStarts[i] != -1; i++ )
+ lineStarts[ i ] += charDelta;
+ mFirstChar += charDelta;
+ mLastChar += charDelta;
+ *scrolled = 0;
+ return;
+ }
+
+ /* The change began before the beginning of the displayed text, but
+ part or all of the displayed text was deleted */
+ if ( pos < mFirstChar ) {
+ /* If some text remains in the window, anchor on that */
+ if ( position_to_line( pos + charsDeleted, &lineOfEnd ) &&
+ ++lineOfEnd < nVisLines && lineStarts[ lineOfEnd ] != -1 ) {
+ mTopLineNum = max( 1, mTopLineNum + lineDelta );
+ mFirstChar = rewind_lines(
+ lineStarts[ lineOfEnd ] + charDelta, lineOfEnd );
+ /* Otherwise anchor on original line number and recount everything */
+ } else {
+ if ( mTopLineNum > mNBufferLines + lineDelta ) {
+ mTopLineNum = 1;
+ mFirstChar = 0;
+ } else
+ mFirstChar = skip_lines( 0, mTopLineNum - 1, true );
+ }
+ calc_line_starts( 0, nVisLines - 1 );
+ /* calculate lastChar by finding the end of the last displayed line */
+ calc_last_char();
+ *scrolled = 1;
+ return;
+ }
+
+ /* If the change was in the middle of the displayed text (it usually is),
+ salvage as much of the line starts array as possible by moving and
+ offsetting the entries after the changed area, and re-counting the
+ added lines or the lines beyond the salvaged part of the line starts
+ array */
+ if ( pos <= mLastChar ) {
+ /* find line on which the change began */
+ position_to_line( pos, &lineOfPos );
+ /* salvage line starts after the changed area */
+ if ( lineDelta == 0 ) {
+ for ( i = lineOfPos + 1; i < nVisLines && lineStarts[ i ] != -1; i++ )
+ lineStarts[ i ] += charDelta;
+ } else if ( lineDelta > 0 ) {
+ for ( i = nVisLines - 1; i >= lineOfPos + lineDelta + 1; i-- )
+ lineStarts[ i ] = lineStarts[ i - lineDelta ] +
+ ( lineStarts[ i - lineDelta ] == -1 ? 0 : charDelta );
+ } else /* (lineDelta < 0) */ {
+ for ( i = max( 0, lineOfPos + 1 ); i < nVisLines + lineDelta; i++ )
+ lineStarts[ i ] = lineStarts[ i - lineDelta ] +
+ ( lineStarts[ i - lineDelta ] == -1 ? 0 : charDelta );
+ }
+ /* fill in the missing line starts */
+ if ( linesInserted >= 0 )
+ calc_line_starts( lineOfPos + 1, lineOfPos + linesInserted );
+ if ( lineDelta < 0 )
+ calc_line_starts( nVisLines + lineDelta, nVisLines );
+ /* calculate lastChar by finding the end of the last displayed line */
+ calc_last_char();
+ *scrolled = 0;
+ return;
+ }
+
+ /* Change was past the end of the displayed text, but displayable by virtue
+ of being an insert at the end of the buffer into visible blank lines */
+ if ( empty_vlines() ) {
+ position_to_line( pos, &lineOfPos );
+ calc_line_starts( lineOfPos, lineOfPos + linesInserted );
+ calc_last_char();
+ *scrolled = 0;
+ return;
+ }
+
+ /* Change was beyond the end of the buffer and not visible, do nothing */
+ *scrolled = 0;
+}
+
+/*
+** Scan through the text in the "textD"'s buffer and recalculate the line
+** starts array values beginning at index "startLine" and continuing through
+** (including) "endLine". It assumes that the line starts entry preceding
+** "startLine" (or mFirstChar if startLine is 0) is good, and re-counts
+** newlines to fill in the requested entries. Out of range values for
+** "startLine" and "endLine" are acceptable.
+*/
+void Fl_Text_Display::calc_line_starts( int startLine, int endLine ) {
+ int startPos, bufLen = mBuffer->length();
+ int line, lineEnd, nextLineStart, nVis = mNVisibleLines;
+ int *lineStarts = mLineStarts;
+
+ /* Clean up (possibly) messy input parameters */
+ if ( endLine < 0 ) endLine = 0;
+ if ( endLine >= nVis ) endLine = nVis - 1;
+ if ( startLine < 0 ) startLine = 0;
+ if ( startLine >= nVis ) startLine = nVis - 1;
+ if ( startLine > endLine )
+ return;
+
+ /* Find the last known good line number -> position mapping */
+ if ( startLine == 0 ) {
+ lineStarts[ 0 ] = mFirstChar;
+ startLine = 1;
+ }
+ startPos = lineStarts[ startLine - 1 ];
+
+ /* If the starting position is already past the end of the text,
+ fill in -1's (means no text on line) and return */
+ if ( startPos == -1 ) {
+ for ( line = startLine; line <= endLine; line++ )
+ lineStarts[ line ] = -1;
+ return;
+ }
+
+ /* Loop searching for ends of lines and storing the positions of the
+ start of the next line in lineStarts */
+ for ( line = startLine; line <= endLine; line++ ) {
+ find_line_end(startPos, true, &lineEnd, &nextLineStart);
+ startPos = nextLineStart;
+ if ( startPos >= bufLen ) {
+ /* If the buffer ends with a newline or line break, put
+ buf->length() in the next line start position (instead of
+ a -1 which is the normal marker for an empty line) to
+ indicate that the cursor may safely be displayed there */
+ if ( line == 0 || ( lineStarts[ line - 1 ] != bufLen &&
+ lineEnd != nextLineStart ) ) {
+ lineStarts[ line ] = bufLen;
+ line++;
+ }
+ break;
+ }
+ lineStarts[ line ] = startPos;
+ }
+
+ /* Set any entries beyond the end of the text to -1 */
+ for ( ; line <= endLine; line++ )
+ lineStarts[ line ] = -1;
+}
+
+/*
+** Given a Fl_Text_Display with a complete, up-to-date lineStarts array, update
+** the lastChar entry to point to the last buffer position displayed.
+*/
+void Fl_Text_Display::calc_last_char() {
+ int i;
+ for (i = mNVisibleLines - 1; i >= 0 && mLineStarts[i] == -1; i--) ;
+ mLastChar = i < 0 ? 0 : line_end(mLineStarts[i], true);
+}
+
+void Fl_Text_Display::scroll(int topLineNum, int horizOffset) {
+ mTopLineNumHint = topLineNum;
+ mHorizOffsetHint = horizOffset;
+ resize(x(), y(), w(), h());
+}
+
+void Fl_Text_Display::scroll_(int topLineNum, int horizOffset) {
+ /* Limit the requested scroll position to allowable values */
+ if (topLineNum > mNBufferLines + 3 - mNVisibleLines)
+ topLineNum = mNBufferLines + 3 - mNVisibleLines;
+ if (topLineNum < 1) topLineNum = 1;
+
+ if (horizOffset > longest_vline() - text_area.w)
+ horizOffset = longest_vline() - text_area.w;
+ if (horizOffset < 0) horizOffset = 0;
+
+ /* Do nothing if scroll position hasn't actually changed or there's no
+ window to draw in yet */
+ if (mHorizOffset == horizOffset && mTopLineNum == topLineNum)
+ return;
+
+ /* If the vertical scroll position has changed, update the line
+ starts array and related counters in the text display */
+ offset_line_starts(topLineNum);
+
+ /* Just setting mHorizOffset is enough information for redisplay */
+ mHorizOffset = horizOffset;
+
+ // redraw all text
+ damage(FL_DAMAGE_EXPOSE);
+}
+
+/*
+** Update the minimum, maximum, slider size, page increment, and value
+** for vertical scroll bar.
+*/
+void Fl_Text_Display::update_v_scrollbar() {
+ /* The Vert. scroll bar value and slider size directly represent the top
+ line number, and the number of visible lines respectively. The scroll
+ bar maximum value is chosen to generally represent the size of the whole
+ buffer, with minor adjustments to keep the scroll bar widget happy */
+#ifdef DEBUG
+ printf("Fl_Text_Display::update_v_scrollbar():\n"
+ " mTopLineNum=%d, mNVisibleLines=%d, mNBufferLines=%d\n",
+ mTopLineNum, mNVisibleLines, mNBufferLines);
+#endif // DEBUG
+
+ mVScrollBar->value(mTopLineNum, mNVisibleLines, 1, mNBufferLines+2);
+ mVScrollBar->linesize(3);
+}
+
+/*
+** Update the minimum, maximum, slider size, page increment, and value
+** for the horizontal scroll bar.
+*/
+void Fl_Text_Display::update_h_scrollbar() {
+ int sliderMax = max(longest_vline(), text_area.w + mHorizOffset);
+ mHScrollBar->value( mHorizOffset, text_area.w, 0, sliderMax );
+}
+
+/*
+** Callbacks for drag or valueChanged on scroll bars
+*/
+void Fl_Text_Display::v_scrollbar_cb(Fl_Scrollbar* b, Fl_Text_Display* textD) {
+ if (b->value() == textD->mTopLineNum) return;
+ textD->scroll(b->value(), textD->mHorizOffset);
+}
+
+void Fl_Text_Display::h_scrollbar_cb(Fl_Scrollbar* b, Fl_Text_Display* textD) {
+ if (b->value() == textD->mHorizOffset) return;
+ textD->scroll(textD->mTopLineNum, b->value());
+}
+
+/*
+** Refresh the line number area. If clearAll is False, writes only over
+** the character cell areas. Setting clearAll to True will clear out any
+** stray marks outside of the character cell area, which might have been
+** left from before a resize or font change.
+*/
+void Fl_Text_Display::draw_line_numbers(bool /*clearAll*/) {
+#if 0
+ // FIXME: don't want this yet, so will leave for another time
+
+ int y, line, visLine, nCols, lineStart;
+ char lineNumString[12];
+ int lineHeight = mMaxsize ? mMaxsize : textsize_;
+ int charWidth = TMPFONTWIDTH; //mFontStruct->max_bounds.width;
+
+ /* Don't draw if mLineNumWidth == 0 (line numbers are hidden), or widget is
+ not yet realized */
+ if (mLineNumWidth == 0 || visible_r())
+ return;
+
+ /* GC is allocated on demand, since not everyone will use line numbering */
+ if (textD->lineNumGC == NULL) {
+ XGCValues values;
+ values.foreground = textD->lineNumFGPixel;
+ values.background = textD->bgPixel;
+ values.font = textD->fontStruct->fid;
+ textD->lineNumGC = XtGetGC(textD->w,
+ GCFont| GCForeground | GCBackground, &values);
+ }
+
+ /* Erase the previous contents of the line number area, if requested */
+ if (clearAll)
+ XClearArea(XtDisplay(textD->w), XtWindow(textD->w), textD->lineNumLeft,
+ textD->top, textD->lineNumWidth, textD->height, False);
+
+ /* Draw the line numbers, aligned to the text */
+ nCols = min(11, textD->lineNumWidth / charWidth);
+ y = textD->top;
+ line = getAbsTopLineNum(textD);
+ for (visLine=0; visLine < textD->nVisibleLines; visLine++) {
+ lineStart = textD->lineStarts[visLine];
+ if (lineStart != -1 && (lineStart==0 ||
+ BufGetCharacter(textD->buffer, lineStart-1)=='\n')) {
+ sprintf(lineNumString, "%*d", nCols, line);
+ XDrawImageString(XtDisplay(textD->w), XtWindow(textD->w),
+ textD->lineNumGC, textD->lineNumLeft, y + textD->ascent,
+ lineNumString, strlen(lineNumString));
+ line++;
+ } else {
+ XClearArea(XtDisplay(textD->w), XtWindow(textD->w),
+ textD->lineNumLeft, y, textD->lineNumWidth,
+ textD->ascent + textD->descent, False);
+ if (visLine == 0)
+ line++;
+ }
+ y += lineHeight;
+ }
+#endif
+}
+
+static int max( int i1, int i2 ) {
+ return i1 >= i2 ? i1 : i2;
+}
+
+static int min( int i1, int i2 ) {
+ return i1 <= i2 ? i1 : i2;
+}
+
+/*
+** Count the number of newlines in a null-terminated text string;
+*/
+static int countlines( const char *string ) {
+ const char * c;
+ int lineCount = 0;
+
+ if (!string) return 0;
+
+ for ( c = string; *c != '\0'; c++ )
+ if ( *c == '\n' ) lineCount++;
+ return lineCount;
+}
+
+/*
+** Return the width in pixels of the displayed line pointed to by "visLineNum"
+*/
+int Fl_Text_Display::measure_vline( int visLineNum ) {
+ int i, width = 0, len, style, lineLen = vline_length( visLineNum );
+ int charCount = 0, lineStartPos = mLineStarts[ visLineNum ];
+ char expandedChar[ FL_TEXT_MAX_EXP_CHAR_LEN ];
+
+ if (lineStartPos < 0 || lineLen == 0) return 0;
+ if ( mStyleBuffer == NULL ) {
+ for ( i = 0; i < lineLen; i++ ) {
+ len = mBuffer->expand_character( lineStartPos + i,
+ charCount, expandedChar );
+
+ fl_font( textfont(), textsize() );
+
+ width += ( int ) fl_width( expandedChar, len );
+
+ charCount += len;
+ }
+ } else {
+ for ( i = 0; i < lineLen; i++ ) {
+ len = mBuffer->expand_character( lineStartPos + i,
+ charCount, expandedChar );
+ style = ( unsigned char ) mStyleBuffer->character(
+ lineStartPos + i ) - 'A';
+
+ if (style < 0) style = 0;
+ else if (style >= mNStyles) style = mNStyles - 1;
+
+ fl_font( mStyleTable[ style ].font, mStyleTable[ style ].size );
+
+ width += ( int ) fl_width( expandedChar, len );
+
+ charCount += len;
+ }
+ }
+ return width;
+}
+
+/*
+** Return true if there are lines visible with no corresponding buffer text
+*/
+int Fl_Text_Display::empty_vlines() {
+ return mNVisibleLines > 0 &&
+ mLineStarts[ mNVisibleLines - 1 ] == -1;
+}
+
+/*
+** Return the length of a line (number of displayable characters) by examining
+** entries in the line starts array rather than by scanning for newlines
+*/
+int Fl_Text_Display::vline_length( int visLineNum ) {
+ int nextLineStart, lineStartPos;
+
+ if (visLineNum < 0 || visLineNum >= mNVisibleLines)
+ return (0);
+
+ lineStartPos = mLineStarts[ visLineNum ];
+
+ if ( lineStartPos == -1 )
+ return 0;
+ if ( visLineNum + 1 >= mNVisibleLines )
+ return mLastChar - lineStartPos;
+ nextLineStart = mLineStarts[ visLineNum + 1 ];
+ if ( nextLineStart == -1 )
+ return mLastChar - lineStartPos;
+ if (wrap_uses_character(nextLineStart-1))
+ return nextLineStart-1 - lineStartPos;
+ return nextLineStart - lineStartPos;
+}
+
+/*
+** When continuous wrap is on, and the user inserts or deletes characters,
+** wrapping can happen before and beyond the changed position. This routine
+** finds the extent of the changes, and counts the deleted and inserted lines
+** over that range. It also attempts to minimize the size of the range to
+** what has to be counted and re-displayed, so the results can be useful
+** both for delimiting where the line starts need to be recalculated, and
+** for deciding what part of the text to redisplay.
+*/
+void Fl_Text_Display::find_wrap_range(const char *deletedText, int pos,
+ int nInserted, int nDeleted, int *modRangeStart, int *modRangeEnd,
+ int *linesInserted, int *linesDeleted) {
+ int length, retPos, retLines, retLineStart, retLineEnd;
+ Fl_Text_Buffer *deletedTextBuf, *buf = buffer();
+ int nVisLines = mNVisibleLines;
+ int *lineStarts = mLineStarts;
+ int countFrom, countTo, lineStart, adjLineStart, i;
+ int visLineNum = 0, nLines = 0;
+
+ /*
+ ** Determine where to begin searching: either the previous newline, or
+ ** if possible, limit to the start of the (original) previous displayed
+ ** line, using information from the existing line starts array
+ */
+ if (pos >= mFirstChar && pos <= mLastChar) {
+ for (i=nVisLines-1; i>0; i--)
+ if (lineStarts[i] != -1 && pos >= lineStarts[i])
+ break;
+ if (i > 0) {
+ countFrom = lineStarts[i-1];
+ visLineNum = i-1;
+ } else
+ countFrom = buf->line_start(pos);
+ } else
+ countFrom = buf->line_start(pos);
+
+
+ /*
+ ** Move forward through the (new) text one line at a time, counting
+ ** displayed lines, and looking for either a real newline, or for the
+ ** line starts to re-sync with the original line starts array
+ */
+ lineStart = countFrom;
+ *modRangeStart = countFrom;
+ for (;;) {
+
+ /* advance to the next line. If the line ended in a real newline
+ or the end of the buffer, that's far enough */
+ wrapped_line_counter(buf, lineStart, buf->length(), 1, true, 0,
+ &retPos, &retLines, &retLineStart, &retLineEnd);
+ if (retPos >= buf->length()) {
+ countTo = buf->length();
+ *modRangeEnd = countTo;
+ if (retPos != retLineEnd)
+ nLines++;
+ break;
+ } else
+ lineStart = retPos;
+ nLines++;
+ if (lineStart > pos + nInserted &&
+ buf->character(lineStart-1) == '\n') {
+ countTo = lineStart;
+ *modRangeEnd = lineStart;
+ break;
+ }
+
+ /* Don't try to resync in continuous wrap mode with non-fixed font
+ sizes; it would result in a chicken-and-egg dependency between
+ the calculations for the inserted and the deleted lines.
+ If we're in that mode, the number of deleted lines is calculated in
+ advance, without resynchronization, so we shouldn't resynchronize
+ for the inserted lines either. */
+ if (mSuppressResync)
+ continue;
+
+ /* check for synchronization with the original line starts array
+ before pos, if so, the modified range can begin later */
+ if (lineStart <= pos) {
+ while (visLineNum<nVisLines && lineStarts[visLineNum] < lineStart)
+ visLineNum++;
+ if (visLineNum < nVisLines && lineStarts[visLineNum] == lineStart) {
+ countFrom = lineStart;
+ nLines = 0;
+ if (visLineNum+1 < nVisLines && lineStarts[visLineNum+1] != -1)
+ *modRangeStart = min(pos, lineStarts[visLineNum+1]-1);
+ else
+ *modRangeStart = countFrom;
+ } else
+ *modRangeStart = min(*modRangeStart, lineStart-1);
+ }
+
+ /* check for synchronization with the original line starts array
+ after pos, if so, the modified range can end early */
+ else if (lineStart > pos + nInserted) {
+ adjLineStart = lineStart - nInserted + nDeleted;
+ while (visLineNum<nVisLines && lineStarts[visLineNum]<adjLineStart)
+ visLineNum++;
+ if (visLineNum < nVisLines && lineStarts[visLineNum] != -1 &&
+ lineStarts[visLineNum] == adjLineStart) {
+ countTo = line_end(lineStart, true);
+ *modRangeEnd = lineStart;
+ break;
+ }
+ }
+ }
+ *linesInserted = nLines;
+
+
+ /* Count deleted lines between countFrom and countTo as the text existed
+ before the modification (that is, as if the text between pos and
+ pos+nInserted were replaced by "deletedText"). This extra context is
+ necessary because wrapping can occur outside of the modified region
+ as a result of adding or deleting text in the region. This is done by
+ creating a textBuffer containing the deleted text and the necessary
+ additional context, and calling the wrappedLineCounter on it.
+
+ NOTE: This must not be done in continuous wrap mode when the font
+ width is not fixed. In that case, the calculation would try
+ to access style information that is no longer available (deleted
+ text), or out of date (updated highlighting), possibly leading
+ to completely wrong calculations and/or even crashes eventually.
+ (This is not theoretical; it really happened.)
+
+ In that case, the calculation of the number of deleted lines
+ has happened before the buffer was modified (only in that case,
+ because resynchronization of the line starts is impossible
+ in that case, which makes the whole calculation less efficient).
+ */
+ if (mSuppressResync) {
+ *linesDeleted = mNLinesDeleted;
+ mSuppressResync = 0;
+ return;
+ }
+
+ length = (pos-countFrom) + nDeleted +(countTo-(pos+nInserted));
+ deletedTextBuf = new Fl_Text_Buffer(length);
+ deletedTextBuf->copy(buffer(), countFrom, pos, 0);
+ if (nDeleted != 0)
+ deletedTextBuf->insert(pos-countFrom, deletedText);
+ deletedTextBuf->copy(buffer(),
+ pos+nInserted, countTo, pos-countFrom+nDeleted);
+ /* Note that we need to take into account an offset for the style buffer:
+ the deletedTextBuf can be out of sync with the style buffer. */
+ wrapped_line_counter(deletedTextBuf, 0, length, INT_MAX, true,
+ countFrom, &retPos, &retLines, &retLineStart, &retLineEnd, false);
+ delete deletedTextBuf;
+ *linesDeleted = retLines;
+ mSuppressResync = 0;
+}
+
+/*
+** This is a stripped-down version of the findWrapRange() function above,
+** intended to be used to calculate the number of "deleted" lines during
+** a buffer modification. It is called _before_ the modification takes place.
+**
+** This function should only be called in continuous wrap mode with a
+** non-fixed font width. In that case, it is impossible to calculate
+** the number of deleted lines, because the necessary style information
+** is no longer available _after_ the modification. In other cases, we
+** can still perform the calculation afterwards (possibly even more
+** efficiently).
+*/
+void Fl_Text_Display::measure_deleted_lines(int pos, int nDeleted) {
+ int retPos, retLines, retLineStart, retLineEnd;
+ Fl_Text_Buffer *buf = buffer();
+ int nVisLines = mNVisibleLines;
+ int *lineStarts = mLineStarts;
+ int countFrom, lineStart;
+ int nLines = 0, i;
+ /*
+ ** Determine where to begin searching: either the previous newline, or
+ ** if possible, limit to the start of the (original) previous displayed
+ ** line, using information from the existing line starts array
+ */
+ if (pos >= mFirstChar && pos <= mLastChar) {
+ for (i=nVisLines-1; i>0; i--)
+ if (lineStarts[i] != -1 && pos >= lineStarts[i])
+ break;
+ if (i > 0) countFrom = lineStarts[i-1];
+ else countFrom = buf->line_start(pos);
+ } else
+ countFrom = buf->line_start(pos);
+
+ /*
+ ** Move forward through the (new) text one line at a time, counting
+ ** displayed lines, and looking for either a real newline, or for the
+ ** line starts to re-sync with the original line starts array
+ */
+ lineStart = countFrom;
+ for (;;) {
+ /* advance to the next line. If the line ended in a real newline
+ or the end of the buffer, that's far enough */
+ wrapped_line_counter(buf, lineStart, buf->length(), 1, true, 0,
+ &retPos, &retLines, &retLineStart, &retLineEnd);
+ if (retPos >= buf->length()) {
+ if (retPos != retLineEnd)
+ nLines++;
+ break;
+ } else
+ lineStart = retPos;
+ nLines++;
+ if (lineStart > pos + nDeleted &&
+ buf->character(lineStart-1) == '\n') {
+ break;
+ }
+
+ /* Unlike in the findWrapRange() function above, we don't try to
+ resync with the line starts, because we don't know the length
+ of the inserted text yet, nor the updated style information.
+
+ Because of that, we also shouldn't resync with the line starts
+ after the modification either, because we must perform the
+ calculations for the deleted and inserted lines in the same way.
+
+ This can result in some unnecessary recalculation and redrawing
+ overhead, and therefore we should only use this two-phase mode
+ of calculation when it's really needed (continuous wrap + variable
+ font width). */
+ }
+ mNLinesDeleted = nLines;
+ mSuppressResync = 1;
+}
+
+/*
+** Count forward from startPos to either maxPos or maxLines (whichever is
+** reached first), and return all relevant positions and line count.
+** The provided textBuffer may differ from the actual text buffer of the
+** widget. In that case it must be a (partial) copy of the actual text buffer
+** and the styleBufOffset argument must indicate the starting position of the
+** copy, to take into account the correct style information.
+**
+** Returned values:
+**
+** retPos: Position where counting ended. When counting lines, the
+** position returned is the start of the line "maxLines"
+** lines beyond "startPos".
+** retLines: Number of line breaks counted
+** retLineStart: Start of the line where counting ended
+** retLineEnd: End position of the last line traversed
+*/
+void Fl_Text_Display::wrapped_line_counter(Fl_Text_Buffer *buf, int startPos,
+ int maxPos, int maxLines, bool startPosIsLineStart, int styleBufOffset,
+ int *retPos, int *retLines, int *retLineStart, int *retLineEnd,
+ bool countLastLineMissingNewLine) {
+ int lineStart, newLineStart = 0, b, p, colNum, wrapMargin;
+ int maxWidth, i, foundBreak, width;
+ bool countPixels;
+ int nLines = 0, tabDist = buffer()->tab_distance();
+ unsigned char c;
+ char nullSubsChar = buffer()->null_substitution_character();
+
+ /* If the font is fixed, or there's a wrap margin set, it's more efficient
+ to measure in columns, than to count pixels. Determine if we can count
+ in columns (countPixels == False) or must count pixels (countPixels ==
+ True), and set the wrap target for either pixels or columns */
+ if (mFixedFontWidth != -1 || mWrapMargin != 0) {
+ countPixels = false;
+ wrapMargin = mWrapMargin ? mWrapMargin : text_area.w / (mFixedFontWidth + 1);
+ maxWidth = INT_MAX;
+ } else {
+ countPixels = true;
+ wrapMargin = INT_MAX;
+ maxWidth = text_area.w;
+ }
+
+ /* Find the start of the line if the start pos is not marked as a
+ line start. */
+ if (startPosIsLineStart)
+ lineStart = startPos;
+ else
+ lineStart = line_start(startPos);
+
+ /*
+ ** Loop until position exceeds maxPos or line count exceeds maxLines.
+ ** (actually, contines beyond maxPos to end of line containing maxPos,
+ ** in case later characters cause a word wrap back before maxPos)
+ */
+ colNum = 0;
+ width = 0;
+ for (p=lineStart; p<buf->length(); p++) {
+ c = (unsigned char)buf->character(p);
+
+ /* If the character was a newline, count the line and start over,
+ otherwise, add it to the width and column counts */
+ if (c == '\n') {
+ if (p >= maxPos) {
+ *retPos = maxPos;
+ *retLines = nLines;
+ *retLineStart = lineStart;
+ *retLineEnd = maxPos;
+ return;
+ }
+ nLines++;
+ if (nLines >= maxLines) {
+ *retPos = p + 1;
+ *retLines = nLines;
+ *retLineStart = p + 1;
+ *retLineEnd = p;
+ return;
+ }
+ lineStart = p + 1;
+ colNum = 0;
+ width = 0;
+ } else {
+ colNum += Fl_Text_Buffer::character_width(c, colNum, tabDist, nullSubsChar);
+ if (countPixels)
+ width += measure_proportional_character(c, colNum, p+styleBufOffset);
+ }
+
+ /* If character exceeded wrap margin, find the break point
+ and wrap there */
+ if (colNum > wrapMargin || width > maxWidth) {
+ foundBreak = false;
+ for (b=p; b>=lineStart; b--) {
+ c = (unsigned char)buf->character(b);
+ if (c == '\t' || c == ' ') {
+ newLineStart = b + 1;
+ if (countPixels) {
+ colNum = 0;
+ width = 0;
+ for (i=b+1; i<p+1; i++) {
+ width += measure_proportional_character(
+ buf->character(i), colNum,
+ i+styleBufOffset);
+ colNum++;
+ }
+ } else
+ colNum = buf->count_displayed_characters(b+1, p+1);
+ foundBreak = true;
+ break;
+ }
+ }
+ if (!foundBreak) { /* no whitespace, just break at margin */
+ newLineStart = max(p, lineStart+1);
+ colNum = Fl_Text_Buffer::character_width(c, colNum, tabDist, nullSubsChar);
+ if (countPixels)
+ width = measure_proportional_character(c, colNum, p+styleBufOffset);
+ }
+ if (p >= maxPos) {
+ *retPos = maxPos;
+ *retLines = maxPos < newLineStart ? nLines : nLines + 1;
+ *retLineStart = maxPos < newLineStart ? lineStart :
+ newLineStart;
+ *retLineEnd = maxPos;
+ return;
+ }
+ nLines++;
+ if (nLines >= maxLines) {
+ *retPos = foundBreak ? b + 1 : max(p, lineStart+1);
+ *retLines = nLines;
+ *retLineStart = lineStart;
+ *retLineEnd = foundBreak ? b : p;
+ return;
+ }
+ lineStart = newLineStart;
+ }
+ }
+
+ /* reached end of buffer before reaching pos or line target */
+ *retPos = buf->length();
+ *retLines = nLines;
+ if (countLastLineMissingNewLine && colNum > 0)
+ ++(*retLines);
+ *retLineStart = lineStart;
+ *retLineEnd = buf->length();
+}
+
+/*
+** Measure the width in pixels of a character "c" at a particular column
+** "colNum" and buffer position "pos". This is for measuring characters in
+** proportional or mixed-width highlighting fonts.
+**
+** A note about proportional and mixed-width fonts: the mixed width and
+** proportional font code in nedit does not get much use in general editing,
+** because nedit doesn't allow per-language-mode fonts, and editing programs
+** in a proportional font is usually a bad idea, so very few users would
+** choose a proportional font as a default. There are still probably mixed-
+** width syntax highlighting cases where things don't redraw properly for
+** insertion/deletion, though static display and wrapping and resizing
+** should now be solid because they are now used for online help display.
+*/
+int Fl_Text_Display::measure_proportional_character(char c, int colNum, int pos) {
+ int charLen, style;
+ char expChar[ FL_TEXT_MAX_EXP_CHAR_LEN ];
+ Fl_Text_Buffer *styleBuf = mStyleBuffer;
+
+ charLen = Fl_Text_Buffer::expand_character(c, colNum, expChar,
+ buffer()->tab_distance(), buffer()->null_substitution_character());
+ if (styleBuf == 0) {
+ style = 0;
+ } else {
+ style = (unsigned char)styleBuf->character(pos);
+ if (style == mUnfinishedStyle && mUnfinishedHighlightCB) {
+ /* encountered "unfinished" style, trigger parsing */
+ (mUnfinishedHighlightCB)(pos, mHighlightCBArg);
+ style = (unsigned char)styleBuf->character(pos);
+ }
+ }
+ return string_width(expChar, charLen, style);
+}
+
+/*
+** Finds both the end of the current line and the start of the next line. Why?
+** In continuous wrap mode, if you need to know both, figuring out one from the
+** other can be expensive or error prone. The problem comes when there's a
+** trailing space or tab just before the end of the buffer. To translate an
+** end of line value to or from the next lines start value, you need to know
+** whether the trailing space or tab is being used as a line break or just a
+** normal character, and to find that out would otherwise require counting all
+** the way back to the beginning of the line.
+*/
+void Fl_Text_Display::find_line_end(int startPos, bool startPosIsLineStart,
+ int *lineEnd, int *nextLineStart) {
+ int retLines, retLineStart;
+
+ /* if we're not wrapping use more efficient BufEndOfLine */
+ if (!mContinuousWrap) {
+ *lineEnd = buffer()->line_end(startPos);
+ *nextLineStart = min(buffer()->length(), *lineEnd + 1);
+ return;
+ }
+
+ /* use the wrapped line counter routine to count forward one line */
+ wrapped_line_counter(buffer(), startPos, buffer()->length(),
+ 1, startPosIsLineStart, 0, nextLineStart, &retLines,
+ &retLineStart, lineEnd);
+ return;
+}
+
+/*
+** Line breaks in continuous wrap mode usually happen at newlines or
+** whitespace. This line-terminating character is not included in line
+** width measurements and has a special status as a non-visible character.
+** However, lines with no whitespace are wrapped without the benefit of a
+** line terminating character, and this distinction causes endless trouble
+** with all of the text display code which was originally written without
+** continuous wrap mode and always expects to wrap at a newline character.
+**
+** Given the position of the end of the line, as returned by TextDEndOfLine
+** or BufEndOfLine, this returns true if there is a line terminating
+** character, and false if there's not. On the last character in the
+** buffer, this function can't tell for certain whether a trailing space was
+** used as a wrap point, and just guesses that it wasn't. So if an exact
+** accounting is necessary, don't use this function.
+*/
+int Fl_Text_Display::wrap_uses_character(int lineEndPos) {
+ char c;
+
+ if (!mContinuousWrap || lineEndPos == buffer()->length())
+ return 1;
+
+ c = buffer()->character(lineEndPos);
+ return c == '\n' || ((c == '\t' || c == ' ') &&
+ lineEndPos + 1 != buffer()->length());
+}
+
+/*
+** Return true if the selection "sel" is rectangular, and touches a
+** buffer position withing "rangeStart" to "rangeEnd"
+*/
+int Fl_Text_Display::range_touches_selection(Fl_Text_Selection *sel,
+ int rangeStart, int rangeEnd) {
+ return sel->selected() && sel->rectangular() && sel->end() >= rangeStart &&
+ sel->start() <= rangeEnd;
+}
+
+/*
+** Extend the range of a redraw request (from *start to *end) with additional
+** redraw requests resulting from changes to the attached style buffer (which
+** contains auxiliary information for coloring or styling text).
+*/
+void Fl_Text_Display::extend_range_for_styles( int *startpos, int *endpos ) {
+ Fl_Text_Selection * sel = mStyleBuffer->primary_selection();
+ int extended = 0;
+
+ /* The peculiar protocol used here is that modifications to the style
+ buffer are marked by selecting them with the buffer's primary Fl_Text_Selection.
+ The style buffer is usually modified in response to a modify callback on
+ the text buffer BEFORE Fl_Text_Display.c's modify callback, so that it can keep
+ the style buffer in step with the text buffer. The style-update
+ callback can't just call for a redraw, because Fl_Text_Display hasn't processed
+ the original text changes yet. Anyhow, to minimize redrawing and to
+ avoid the complexity of scheduling redraws later, this simple protocol
+ tells the text display's buffer modify callback to extend it's redraw
+ range to show the text color/and font changes as well. */
+ if ( sel->selected() ) {
+ if ( sel->start() < *startpos ) {
+ *startpos = sel->start();
+ extended = 1;
+ }
+ if ( sel->end() > *endpos ) {
+ *endpos = sel->end();
+ extended = 1;
+ }
+ }
+
+ /* If the Fl_Text_Selection was extended due to a style change, and some of the
+ fonts don't match in spacing, extend redraw area to end of line to
+ redraw characters exposed by possible font size changes */
+ if ( mFixedFontWidth == -1 && extended )
+ *endpos = mBuffer->line_end( *endpos ) + 1;
+}
+
+// The draw() method. It tries to minimize what is draw as much as possible.
+void Fl_Text_Display::draw(void) {
+ // don't even try if there is no associated text buffer!
+ if (!buffer()) { draw_box(); return; }
+
+ fl_push_clip(x(),y(),w(),h()); // prevent drawing outside widget area
+
+ // draw the non-text, non-scrollbar areas.
+ if (damage() & FL_DAMAGE_ALL) {
+// printf("drawing all (box = %d)\n", box());
+ // draw the box()
+ int W = w(), H = h();
+ draw_box(box(), x(), y(), W, H, color());
+
+ if (mHScrollBar->visible())
+ W -= scrollbar_width();
+ if (mVScrollBar->visible())
+ H -= scrollbar_width();
+
+ // left margin
+ fl_rectf(text_area.x-LEFT_MARGIN, text_area.y-TOP_MARGIN,
+ LEFT_MARGIN, text_area.h+TOP_MARGIN+BOTTOM_MARGIN,
+ color());
+
+ // right margin
+ fl_rectf(text_area.x+text_area.w, text_area.y-TOP_MARGIN,
+ RIGHT_MARGIN, text_area.h+TOP_MARGIN+BOTTOM_MARGIN,
+ color());
+
+ // top margin
+ fl_rectf(text_area.x, text_area.y-TOP_MARGIN,
+ text_area.w, TOP_MARGIN, color());
+
+ // bottom margin
+ fl_rectf(text_area.x, text_area.y+text_area.h,
+ text_area.w, BOTTOM_MARGIN, color());
+
+ // draw that little box in the corner of the scrollbars
+ if (mVScrollBar->visible() && mHScrollBar->visible())
+ fl_rectf(mVScrollBar->x(), mHScrollBar->y(),
+ mVScrollBar->w(), mHScrollBar->h(),
+ FL_GRAY);
+
+ // blank the previous cursor protrusions
+ }
+ else if (damage() & (FL_DAMAGE_SCROLL | FL_DAMAGE_EXPOSE)) {
+// printf("blanking previous cursor extrusions at Y: %d\n", mCursorOldY);
+ // CET - FIXME - save old cursor position instead and just draw side needed?
+ fl_push_clip(text_area.x-LEFT_MARGIN,
+ text_area.y,
+ text_area.w+LEFT_MARGIN+RIGHT_MARGIN,
+ text_area.h);
+ fl_rectf(text_area.x-LEFT_MARGIN, mCursorOldY,
+ LEFT_MARGIN, mMaxsize, color());
+ fl_rectf(text_area.x+text_area.w, mCursorOldY,
+ RIGHT_MARGIN, mMaxsize, color());
+ fl_pop_clip();
+ }
+
+ // draw the scrollbars
+ if (damage() & (FL_DAMAGE_ALL | FL_DAMAGE_CHILD)) {
+ mVScrollBar->damage(FL_DAMAGE_ALL);
+ mHScrollBar->damage(FL_DAMAGE_ALL);
+ }
+ update_child(*mVScrollBar);
+ update_child(*mHScrollBar);
+
+ // draw all of the text
+ if (damage() & (FL_DAMAGE_ALL | FL_DAMAGE_EXPOSE)) {
+ //printf("drawing all text\n");
+ int X, Y, W, H;
+ if (fl_clip_box(text_area.x, text_area.y, text_area.w, text_area.h,
+ X, Y, W, H)) {
+ // Draw text using the intersected clipping box...
+ // (this sets the clipping internally)
+ draw_text(X, Y, W, H);
+ } else {
+ // Draw the whole area...
+ draw_text(text_area.x, text_area.y, text_area.w, text_area.h);
+ }
+ }
+ else if (damage() & FL_DAMAGE_SCROLL) {
+ // draw some lines of text
+ fl_push_clip(text_area.x, text_area.y,
+ text_area.w, text_area.h);
+ //printf("drawing text from %d to %d\n", damage_range1_start, damage_range1_end);
+ draw_range(damage_range1_start, damage_range1_end);
+ if (damage_range2_end != -1) {
+ //printf("drawing text from %d to %d\n", damage_range2_start, damage_range2_end);
+ draw_range(damage_range2_start, damage_range2_end);
+ }
+ damage_range1_start = damage_range1_end = -1;
+ damage_range2_start = damage_range2_end = -1;
+ fl_pop_clip();
+ }
+
+ // draw the text cursor
+ if (damage() & (FL_DAMAGE_ALL | FL_DAMAGE_SCROLL | FL_DAMAGE_EXPOSE)
+ && !buffer()->primary_selection()->selected() &&
+ mCursorOn && Fl::focus() == this ) {
+ fl_push_clip(text_area.x-LEFT_MARGIN,
+ text_area.y,
+ text_area.w+LEFT_MARGIN+RIGHT_MARGIN,
+ text_area.h);
+
+ int X, Y;
+ if (position_to_xy(mCursorPos, &X, &Y)) draw_cursor(X, Y);
+// else puts("position_to_xy() failed - unable to draw cursor!");
+ //printf("drew cursor at pos: %d (%d,%d)\n", mCursorPos, X, Y);
+ mCursorOldY = Y;
+ fl_pop_clip();
+ }
+ fl_pop_clip();
+}
+
+// this processes drag events due to mouse for Fl_Text_Display and
+// also drags due to cursor movement with shift held down for
+// Fl_Text_Editor
+void fl_text_drag_me(int pos, Fl_Text_Display* d) {
+ if (d->dragType == Fl_Text_Display::DRAG_CHAR) {
+ if (pos >= d->dragPos) {
+ d->buffer()->select(d->dragPos, pos);
+ } else {
+ d->buffer()->select(pos, d->dragPos);
+ }
+ d->insert_position(pos);
+ } else if (d->dragType == Fl_Text_Display::DRAG_WORD) {
+ if (pos >= d->dragPos) {
+ d->insert_position(d->word_end(pos));
+ d->buffer()->select(d->word_start(d->dragPos), d->word_end(pos));
+ } else {
+ d->insert_position(d->word_start(pos));
+ d->buffer()->select(d->word_start(pos), d->word_end(d->dragPos));
+ }
+ } else if (d->dragType == Fl_Text_Display::DRAG_LINE) {
+ if (pos >= d->dragPos) {
+ d->insert_position(d->buffer()->line_end(pos)+1);
+ d->buffer()->select(d->buffer()->line_start(d->dragPos),
+ d->buffer()->line_end(pos)+1);
+ } else {
+ d->insert_position(d->buffer()->line_start(pos));
+ d->buffer()->select(d->buffer()->line_start(pos),
+ d->buffer()->line_end(d->dragPos)+1);
+ }
+ }
+}
+
+// This timer event scrolls the text view proportionally to
+// how far the mouse pointer has left the text area. This
+// allows for smooth scrolling without "wiggeling" the mouse.
+void Fl_Text_Display::scroll_timer_cb(void *user_data) {
+ Fl_Text_Display *w = (Fl_Text_Display*)user_data;
+ int pos;
+ switch (scroll_direction) {
+ case 1: // mouse is to the right, scroll left
+ w->scroll(w->mTopLineNum, w->mHorizOffset + scroll_amount);
+ pos = w->xy_to_position(w->text_area.x + w->text_area.w, scroll_y, CURSOR_POS);
+ break;
+ case 2: // mouse is to the left, scroll right
+ w->scroll(w->mTopLineNum, w->mHorizOffset + scroll_amount);
+ pos = w->xy_to_position(w->text_area.x, scroll_y, CURSOR_POS);
+ break;
+ case 3: // mouse is above, scroll down
+ w->scroll(w->mTopLineNum + scroll_amount, w->mHorizOffset);
+ pos = w->xy_to_position(scroll_x, w->text_area.y, CURSOR_POS);
+ break;
+ case 4: // mouse is below, scroll up
+ w->scroll(w->mTopLineNum + scroll_amount, w->mHorizOffset);
+ pos = w->xy_to_position(scroll_x, w->text_area.y + w->text_area.h, CURSOR_POS);
+ break;
+ default:
+ return;
+ }
+ fl_text_drag_me(pos, w);
+ Fl::repeat_timeout(.1, scroll_timer_cb, user_data);
+}
+
+
+int Fl_Text_Display::handle(int event) {
+ if (!buffer()) return 0;
+ // This isn't very elegant!
+ if (!Fl::event_inside(text_area.x, text_area.y, text_area.w, text_area.h) &&
+ !dragging && event != FL_LEAVE && event != FL_ENTER &&
+ event != FL_MOVE && event != FL_FOCUS && event != FL_UNFOCUS &&
+ event != FL_KEYBOARD && event != FL_KEYUP) {
+ return Fl_Group::handle(event);
+ }
+
+ switch (event) {
+ case FL_ENTER:
+ case FL_MOVE:
+ if (active_r()) {
+ if (Fl::event_inside(text_area.x, text_area.y, text_area.w,
+ text_area.h)) window()->cursor(FL_CURSOR_INSERT);
+ else window()->cursor(FL_CURSOR_DEFAULT);
+ return 1;
+ } else {
+ return 0;
+ }
+
+ case FL_LEAVE:
+ case FL_HIDE:
+ if (active_r() && window()) {
+ window()->cursor(FL_CURSOR_DEFAULT);
+
+ return 1;
+ } else {
+ return 0;
+ }
+
+ case FL_PUSH: {
+ if (active_r() && window()) {
+ if (Fl::event_inside(text_area.x, text_area.y, text_area.w,
+ text_area.h)) window()->cursor(FL_CURSOR_INSERT);
+ else window()->cursor(FL_CURSOR_DEFAULT);
+ }
+
+ if (Fl::focus() != this) {
+ Fl::focus(this);
+ handle(FL_FOCUS);
+ }
+ if (Fl_Group::handle(event)) return 1;
+ if (Fl::event_state()&FL_SHIFT) return handle(FL_DRAG);
+ dragging = 1;
+ int pos = xy_to_position(Fl::event_x(), Fl::event_y(), CURSOR_POS);
+ dragType = Fl::event_clicks();
+ dragPos = pos;
+ if (dragType == DRAG_CHAR)
+ buffer()->unselect();
+ else if (dragType == DRAG_WORD)
+ buffer()->select(word_start(pos), word_end(pos));
+ else if (dragType == DRAG_LINE)
+ buffer()->select(buffer()->line_start(pos), buffer()->line_end(pos)+1);
+
+ if (buffer()->primary_selection()->selected())
+ insert_position(buffer()->primary_selection()->end());
+ else
+ insert_position(pos);
+ show_insert_position();
+ return 1;
+ }
+
+ case FL_DRAG: {
+ if (dragType < 0) return 1;
+ int X = Fl::event_x(), Y = Fl::event_y(), pos;
+ // if we leave the text_area, we start a timer event
+ // that will take care of scrolling and selecting
+ if (Y < text_area.y) {
+ scroll_x = X;
+ scroll_amount = (Y - text_area.y) / 5 - 1;
+ if (!scroll_direction) {
+ Fl::add_timeout(.01, scroll_timer_cb, this);
+ }
+ scroll_direction = 3;
+ } else if (Y >= text_area.y+text_area.h) {
+ scroll_x = X;
+ scroll_amount = (Y - text_area.y - text_area.h) / 5 + 1;
+ if (!scroll_direction) {
+ Fl::add_timeout(.01, scroll_timer_cb, this);
+ }
+ scroll_direction = 4;
+ } else if (X < text_area.x) {
+ scroll_y = Y;
+ scroll_amount = (X - text_area.x) / 2 - 1;
+ if (!scroll_direction) {
+ Fl::add_timeout(.01, scroll_timer_cb, this);
+ }
+ scroll_direction = 2;
+ } else if (X >= text_area.x+text_area.w) {
+ scroll_y = Y;
+ scroll_amount = (X - text_area.x - text_area.w) / 2 + 1;
+ if (!scroll_direction) {
+ Fl::add_timeout(.01, scroll_timer_cb, this);
+ }
+ scroll_direction = 1;
+ } else {
+ if (scroll_direction) {
+ Fl::remove_timeout(scroll_timer_cb, this);
+ scroll_direction = 0;
+ }
+ pos = xy_to_position(X, Y, CURSOR_POS);
+ fl_text_drag_me(pos, this);
+ }
+ return 1;
+ }
+
+ case FL_RELEASE: {
+ dragging = 0;
+ if (scroll_direction) {
+ Fl::remove_timeout(scroll_timer_cb, this);
+ scroll_direction = 0;
+ }
+
+ // convert from WORD or LINE selection to CHAR
+ if (insert_position() >= dragPos)
+ dragPos = buffer()->primary_selection()->start();
+ else
+ dragPos = buffer()->primary_selection()->end();
+ dragType = DRAG_CHAR;
+
+ const char* copy = buffer()->selection_text();
+ if (*copy) Fl::copy(copy, strlen(copy), 0);
+ free((void*)copy);
+ return 1;
+ }
+
+ case FL_MOUSEWHEEL:
+ if (Fl::event_dy()) return mVScrollBar->handle(event);
+ else return mHScrollBar->handle(event);
+
+ case FL_UNFOCUS:
+ if (active_r() && window()) window()->cursor(FL_CURSOR_DEFAULT);
+ case FL_FOCUS:
+ if (buffer()->selected()) {
+ int start, end;
+ if (buffer()->selection_position(&start, &end))
+ redisplay_range(start, end);
+ }
+ if (buffer()->secondary_selected()) {
+ int start, end;
+ if (buffer()->secondary_selection_position(&start, &end))
+ redisplay_range(start, end);
+ }
+ if (buffer()->highlight()) {
+ int start, end;
+ if (buffer()->highlight_position(&start, &end))
+ redisplay_range(start, end);
+ }
+ return 1;
+
+ case FL_KEYBOARD:
+ // Copy?
+ if ((Fl::event_state()&(FL_CTRL|FL_COMMAND)) && Fl::event_key()=='c') {
+ if (!buffer()->selected()) return 1;
+ const char *copy = buffer()->selection_text();
+ if (*copy) Fl::copy(copy, strlen(copy), 1);
+ free((void*)copy);
+ return 1;
+ }
+
+ // Select all ?
+ if ((Fl::event_state()&(FL_CTRL|FL_COMMAND)) && Fl::event_key()=='a') {
+ buffer()->select(0,buffer()->length());
+ return 1;
+ }
+
+ if (mVScrollBar->handle(event)) return 1;
+ if (mHScrollBar->handle(event)) return 1;
+
+ break;
+ }
+
+ return 0;
+}
+
+
+//
+// End of "$Id: Fl_Text_Display.cxx 6105 2008-04-21 21:03:22Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Text_Editor.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Text_Editor.cxx new file mode 100644 index 0000000..4750896 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Text_Editor.cxx @@ -0,0 +1,492 @@ +//
+// "$Id: Fl_Text_Editor.cxx 5671 2007-02-08 07:58:47Z matt $"
+//
+// Copyright 2001-2006 by Bill Spitzak and others.
+// Original code Copyright Mark Edel. Permission to distribute under
+// the LGPL for the FLTK library granted by Mark Edel.
+//
+// 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 <stdio.h>
+#include <stdlib.h>
+#include "flstring.h"
+#include <ctype.h>
+#include <FL/Fl.H>
+#include <FL/Fl_Window.H>
+#include <FL/Fl_Text_Editor.H>
+#include <FL/fl_ask.H>
+
+
+Fl_Text_Editor::Fl_Text_Editor(int X, int Y, int W, int H, const char* l)
+ : Fl_Text_Display(X, Y, W, H, l) {
+ mCursorOn = 1;
+ insert_mode_ = 1;
+ key_bindings = 0;
+
+ // handle the default key bindings
+ add_default_key_bindings(&key_bindings);
+
+ // handle everything else
+ default_key_function(kf_default);
+}
+
+Fl_Text_Editor::Key_Binding* Fl_Text_Editor::global_key_bindings = 0;
+
+// These are the default key bindings every widget should start with
+static struct {
+ int key;
+ int state;
+ Fl_Text_Editor::Key_Func func;
+} default_key_bindings[] = {
+ { FL_Escape, FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor::kf_ignore },
+ { FL_Enter, FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor::kf_enter },
+ { FL_KP_Enter, FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor::kf_enter },
+ { FL_BackSpace, FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor::kf_backspace },
+ { FL_Insert, FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor::kf_insert },
+ { FL_Delete, FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor::kf_delete },
+ { FL_Home, 0, Fl_Text_Editor::kf_move },
+ { FL_End, 0, Fl_Text_Editor::kf_move },
+ { FL_Left, 0, Fl_Text_Editor::kf_move },
+ { FL_Up, 0, Fl_Text_Editor::kf_move },
+ { FL_Right, 0, Fl_Text_Editor::kf_move },
+ { FL_Down, 0, Fl_Text_Editor::kf_move },
+ { FL_Page_Up, 0, Fl_Text_Editor::kf_move },
+ { FL_Page_Down, 0, Fl_Text_Editor::kf_move },
+ { FL_Home, FL_SHIFT, Fl_Text_Editor::kf_shift_move },
+ { FL_End, FL_SHIFT, Fl_Text_Editor::kf_shift_move },
+ { FL_Left, FL_SHIFT, Fl_Text_Editor::kf_shift_move },
+ { FL_Up, FL_SHIFT, Fl_Text_Editor::kf_shift_move },
+ { FL_Right, FL_SHIFT, Fl_Text_Editor::kf_shift_move },
+ { FL_Down, FL_SHIFT, Fl_Text_Editor::kf_shift_move },
+ { FL_Page_Up, FL_SHIFT, Fl_Text_Editor::kf_shift_move },
+ { FL_Page_Down, FL_SHIFT, Fl_Text_Editor::kf_shift_move },
+ { FL_Home, FL_CTRL, Fl_Text_Editor::kf_ctrl_move },
+ { FL_End, FL_CTRL, Fl_Text_Editor::kf_ctrl_move },
+ { FL_Left, FL_CTRL, Fl_Text_Editor::kf_ctrl_move },
+ { FL_Up, FL_CTRL, Fl_Text_Editor::kf_ctrl_move },
+ { FL_Right, FL_CTRL, Fl_Text_Editor::kf_ctrl_move },
+ { FL_Down, FL_CTRL, Fl_Text_Editor::kf_ctrl_move },
+ { FL_Page_Up, FL_CTRL, Fl_Text_Editor::kf_ctrl_move },
+ { FL_Page_Down, FL_CTRL, Fl_Text_Editor::kf_ctrl_move },
+ { FL_Home, FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_c_s_move },
+ { FL_End, FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_c_s_move },
+ { FL_Left, FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_c_s_move },
+ { FL_Up, FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_c_s_move },
+ { FL_Right, FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_c_s_move },
+ { FL_Down, FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_c_s_move },
+ { FL_Page_Up, FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_c_s_move },
+ { FL_Page_Down, FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_c_s_move },
+//{ FL_Clear, 0, Fl_Text_Editor::delete_to_eol },
+ { 'z', FL_CTRL, Fl_Text_Editor::kf_undo },
+ { '/', FL_CTRL, Fl_Text_Editor::kf_undo },
+ { 'x', FL_CTRL, Fl_Text_Editor::kf_cut },
+ { FL_Delete, FL_SHIFT, Fl_Text_Editor::kf_cut },
+ { 'c', FL_CTRL, Fl_Text_Editor::kf_copy },
+ { FL_Insert, FL_CTRL, Fl_Text_Editor::kf_copy },
+ { 'v', FL_CTRL, Fl_Text_Editor::kf_paste },
+ { FL_Insert, FL_SHIFT, Fl_Text_Editor::kf_paste },
+ { 'a', FL_CTRL, Fl_Text_Editor::kf_select_all },
+
+#ifdef __APPLE__
+ // Define CMD+key accelerators...
+ { 'z', FL_COMMAND, Fl_Text_Editor::kf_undo },
+ { 'x', FL_COMMAND, Fl_Text_Editor::kf_cut },
+ { 'c', FL_COMMAND, Fl_Text_Editor::kf_copy },
+ { 'v', FL_COMMAND, Fl_Text_Editor::kf_paste },
+ { 'a', FL_COMMAND, Fl_Text_Editor::kf_select_all },
+#endif // __APPLE__
+
+ { 0, 0, 0 }
+};
+
+void Fl_Text_Editor::add_default_key_bindings(Key_Binding** list) {
+ for (int i = 0; default_key_bindings[i].key; i++) {
+ add_key_binding(default_key_bindings[i].key,
+ default_key_bindings[i].state,
+ default_key_bindings[i].func,
+ list);
+ }
+}
+
+Fl_Text_Editor::Key_Func
+Fl_Text_Editor::bound_key_function(int key, int state, Key_Binding* list) {
+ Key_Binding* cur;
+ for (cur = list; cur; cur = cur->next)
+ if (cur->key == key)
+ if (cur->state == FL_TEXT_EDITOR_ANY_STATE || cur->state == state)
+ break;
+ if (!cur) return 0;
+ return cur->function;
+}
+
+void
+Fl_Text_Editor::remove_all_key_bindings(Key_Binding** list) {
+ Key_Binding *cur, *next;
+ for (cur = *list; cur; cur = next) {
+ next = cur->next;
+ delete cur;
+ }
+ *list = 0;
+}
+
+void
+Fl_Text_Editor::remove_key_binding(int key, int state, Key_Binding** list) {
+ Key_Binding *cur, *last = 0;
+ for (cur = *list; cur; last = cur, cur = cur->next)
+ if (cur->key == key && cur->state == state) break;
+ if (!cur) return;
+ if (last) last->next = cur->next;
+ else *list = cur->next;
+ delete cur;
+}
+
+void
+Fl_Text_Editor::add_key_binding(int key, int state, Key_Func function,
+ Key_Binding** list) {
+ Key_Binding* kb = new Key_Binding;
+ kb->key = key;
+ kb->state = state;
+ kb->function = function;
+ kb->next = *list;
+ *list = kb;
+}
+
+////////////////////////////////////////////////////////////////
+
+#define NORMAL_INPUT_MOVE 0
+
+static void kill_selection(Fl_Text_Editor* e) {
+ if (e->buffer()->selected()) {
+ e->insert_position(e->buffer()->primary_selection()->start());
+ e->buffer()->remove_selection();
+ }
+}
+
+int Fl_Text_Editor::kf_default(int c, Fl_Text_Editor* e) {
+ if (!c || (!isprint(c) && c != '\t')) return 0;
+ char s[2] = "\0";
+ s[0] = (char)c;
+ kill_selection(e);
+ if (e->insert_mode()) e->insert(s);
+ else e->overstrike(s);
+ e->show_insert_position();
+ e->set_changed();
+ if (e->when()&FL_WHEN_CHANGED) e->do_callback();
+ return 1;
+}
+
+int Fl_Text_Editor::kf_ignore(int, Fl_Text_Editor*) {
+ return 0; // don't handle
+}
+
+int Fl_Text_Editor::kf_backspace(int, Fl_Text_Editor* e) {
+ if (!e->buffer()->selected() && e->move_left())
+ e->buffer()->select(e->insert_position(), e->insert_position()+1);
+ kill_selection(e);
+ e->show_insert_position();
+ e->set_changed();
+ if (e->when()&FL_WHEN_CHANGED) e->do_callback();
+ return 1;
+}
+
+int Fl_Text_Editor::kf_enter(int, Fl_Text_Editor* e) {
+ kill_selection(e);
+ e->insert("\n");
+ e->show_insert_position();
+ e->set_changed();
+ if (e->when()&FL_WHEN_CHANGED) e->do_callback();
+ return 1;
+}
+
+extern void fl_text_drag_me(int pos, Fl_Text_Display* d);
+
+int Fl_Text_Editor::kf_move(int c, Fl_Text_Editor* e) {
+ int i;
+ int selected = e->buffer()->selected();
+ if (!selected)
+ e->dragPos = e->insert_position();
+ e->buffer()->unselect();
+ switch (c) {
+ case FL_Home:
+ e->insert_position(e->buffer()->line_start(e->insert_position()));
+ break;
+ case FL_End:
+ e->insert_position(e->buffer()->line_end(e->insert_position()));
+ break;
+ case FL_Left:
+ e->move_left();
+ break;
+ case FL_Right:
+ e->move_right();
+ break;
+ case FL_Up:
+ e->move_up();
+ break;
+ case FL_Down:
+ e->move_down();
+ break;
+ case FL_Page_Up:
+ for (i = 0; i < e->mNVisibleLines - 1; i++) e->move_up();
+ break;
+ case FL_Page_Down:
+ for (i = 0; i < e->mNVisibleLines - 1; i++) e->move_down();
+ break;
+ }
+ e->show_insert_position();
+ return 1;
+}
+
+int Fl_Text_Editor::kf_shift_move(int c, Fl_Text_Editor* e) {
+ kf_move(c, e);
+ fl_text_drag_me(e->insert_position(), e);
+ return 1;
+}
+
+int Fl_Text_Editor::kf_ctrl_move(int c, Fl_Text_Editor* e) {
+ if (!e->buffer()->selected())
+ e->dragPos = e->insert_position();
+ if (c != FL_Up && c != FL_Down) {
+ e->buffer()->unselect();
+ e->show_insert_position();
+ }
+ switch (c) {
+ case FL_Home:
+ e->insert_position(0);
+ e->scroll(0, 0);
+ break;
+ case FL_End:
+ e->insert_position(e->buffer()->length());
+ e->scroll(e->count_lines(0, e->buffer()->length(), 1), 0);
+ break;
+ case FL_Left:
+ e->previous_word();
+ break;
+ case FL_Right:
+ e->next_word();
+ break;
+ case FL_Up:
+ e->scroll(e->mTopLineNum-1, e->mHorizOffset);
+ break;
+ case FL_Down:
+ e->scroll(e->mTopLineNum+1, e->mHorizOffset);
+ break;
+ case FL_Page_Up:
+ e->insert_position(e->mLineStarts[0]);
+ break;
+ case FL_Page_Down:
+ e->insert_position(e->mLineStarts[e->mNVisibleLines-2]);
+ break;
+ }
+ return 1;
+}
+
+int Fl_Text_Editor::kf_c_s_move(int c, Fl_Text_Editor* e) {
+ kf_ctrl_move(c, e);
+ fl_text_drag_me(e->insert_position(), e);
+ return 1;
+}
+
+int Fl_Text_Editor::kf_home(int, Fl_Text_Editor* e) {
+ return kf_move(FL_Home, e);
+}
+
+int Fl_Text_Editor::kf_end(int, Fl_Text_Editor* e) {
+ return kf_move(FL_End, e);
+}
+
+int Fl_Text_Editor::kf_left(int, Fl_Text_Editor* e) {
+ return kf_move(FL_Left, e);
+}
+
+int Fl_Text_Editor::kf_up(int, Fl_Text_Editor* e) {
+ return kf_move(FL_Up, e);
+}
+
+int Fl_Text_Editor::kf_right(int, Fl_Text_Editor* e) {
+ return kf_move(FL_Right, e);
+}
+
+int Fl_Text_Editor::kf_down(int, Fl_Text_Editor* e) {
+ return kf_move(FL_Down, e);
+}
+
+int Fl_Text_Editor::kf_page_up(int, Fl_Text_Editor* e) {
+ return kf_move(FL_Page_Up, e);
+}
+
+int Fl_Text_Editor::kf_page_down(int, Fl_Text_Editor* e) {
+ return kf_move(FL_Page_Down, e);
+}
+
+
+int Fl_Text_Editor::kf_insert(int, Fl_Text_Editor* e) {
+ e->insert_mode(e->insert_mode() ? 0 : 1);
+ return 1;
+}
+
+int Fl_Text_Editor::kf_delete(int, Fl_Text_Editor* e) {
+ if (!e->buffer()->selected())
+ e->buffer()->select(e->insert_position(), e->insert_position()+1);
+ kill_selection(e);
+ e->show_insert_position();
+ e->set_changed();
+ if (e->when()&FL_WHEN_CHANGED) e->do_callback();
+ return 1;
+}
+
+int Fl_Text_Editor::kf_copy(int, Fl_Text_Editor* e) {
+ if (!e->buffer()->selected()) return 1;
+ const char *copy = e->buffer()->selection_text();
+ if (*copy) Fl::copy(copy, strlen(copy), 1);
+ free((void*)copy);
+ e->show_insert_position();
+ return 1;
+}
+
+int Fl_Text_Editor::kf_cut(int c, Fl_Text_Editor* e) {
+ kf_copy(c, e);
+ kill_selection(e);
+ e->set_changed();
+ if (e->when()&FL_WHEN_CHANGED) e->do_callback();
+ return 1;
+}
+
+int Fl_Text_Editor::kf_paste(int, Fl_Text_Editor* e) {
+ kill_selection(e);
+ Fl::paste(*e, 1);
+ e->show_insert_position();
+ e->set_changed();
+ if (e->when()&FL_WHEN_CHANGED) e->do_callback();
+ return 1;
+}
+
+int Fl_Text_Editor::kf_select_all(int, Fl_Text_Editor* e) {
+ e->buffer()->select(0, e->buffer()->length());
+ return 1;
+}
+
+int Fl_Text_Editor::kf_undo(int , Fl_Text_Editor* e) {
+ e->buffer()->unselect();
+ int crsr;
+ int ret = e->buffer()->undo(&crsr);
+ e->insert_position(crsr);
+ e->show_insert_position();
+ e->set_changed();
+ if (e->when()&FL_WHEN_CHANGED) e->do_callback();
+ return ret;
+}
+
+int Fl_Text_Editor::handle_key() {
+ // Call FLTK's rules to try to turn this into a printing character.
+ // This uses the right-hand ctrl key as a "compose prefix" and returns
+ // the changes that should be made to the text, as a number of
+ // bytes to delete and a string to insert:
+ int del;
+ if (Fl::compose(del)) {
+ if (del) buffer()->select(insert_position()-del, insert_position());
+ kill_selection(this);
+ if (Fl::event_length()) {
+ if (insert_mode()) insert(Fl::event_text());
+ else overstrike(Fl::event_text());
+ }
+ show_insert_position();
+ set_changed();
+ if (when()&FL_WHEN_CHANGED) do_callback();
+ return 1;
+ }
+
+ int key = Fl::event_key(), state = Fl::event_state(), c = Fl::event_text()[0];
+ state &= FL_SHIFT|FL_CTRL|FL_ALT|FL_META; // only care about these states
+ Key_Func f;
+ f = bound_key_function(key, state, global_key_bindings);
+ if (!f) f = bound_key_function(key, state, key_bindings);
+ if (f) return f(key, this);
+ if (default_key_function_ && !state) return default_key_function_(c, this);
+ return 0;
+}
+
+void Fl_Text_Editor::maybe_do_callback() {
+// printf("Fl_Text_Editor::maybe_do_callback()\n");
+// printf("changed()=%d, when()=%x\n", changed(), when());
+ if (changed() || (when()&FL_WHEN_NOT_CHANGED)) do_callback();
+}
+
+int Fl_Text_Editor::handle(int event) {
+ if (!buffer()) return 0;
+
+ switch (event) {
+ case FL_FOCUS:
+ show_cursor(mCursorOn); // redraws the cursor
+ if (buffer()->selected()) redraw(); // Redraw selections...
+ Fl::focus(this);
+ return 1;
+
+ case FL_UNFOCUS:
+ show_cursor(mCursorOn); // redraws the cursor
+ if (buffer()->selected()) redraw(); // Redraw selections...
+ case FL_HIDE:
+ if (when() & FL_WHEN_RELEASE) maybe_do_callback();
+ return 1;
+
+ case FL_KEYBOARD:
+ if (active_r() && window() && this == Fl::belowmouse())
+ window()->cursor(FL_CURSOR_NONE);
+ return handle_key();
+
+ case FL_PASTE:
+ if (!Fl::event_text()) {
+ fl_beep();
+ return 1;
+ }
+ buffer()->remove_selection();
+ if (insert_mode()) insert(Fl::event_text());
+ else overstrike(Fl::event_text());
+ show_insert_position();
+ set_changed();
+ if (when()&FL_WHEN_CHANGED) do_callback();
+ return 1;
+
+ case FL_ENTER:
+// MRS: WIN32 only? Need to test!
+// case FL_MOVE:
+ show_cursor(mCursorOn);
+ return 1;
+
+ case FL_PUSH:
+ if (Fl::event_button() == 2) {
+ // don't let the text_display see this event
+ if (Fl_Group::handle(event)) return 1;
+ dragType = -1;
+ Fl::paste(*this, 0);
+ Fl::focus(this);
+ set_changed();
+ if (when()&FL_WHEN_CHANGED) do_callback();
+ return 1;
+ }
+ break;
+ }
+
+ return Fl_Text_Display::handle(event);
+}
+
+//
+// End of "$Id: Fl_Text_Editor.cxx 5671 2007-02-08 07:58:47Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Tile.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Tile.cxx new file mode 100644 index 0000000..97590f4 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Tile.cxx @@ -0,0 +1,207 @@ +//
+// "$Id: Fl_Tile.cxx 5606 2007-01-18 10:01:24Z matt $"
+//
+// Tile widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Group of 2 or 4 "tiles" that can be resized by dragging border
+// The size of the first child determines where the resize border is.
+// The resizebox is used to limit where the border can be dragged to.
+
+#include <FL/Fl.H>
+#include <FL/Fl_Tile.H>
+#include <FL/Fl_Window.H>
+#include <stdlib.h>
+
+// Drag the edges that were initially at oldx,oldy to newx,newy:
+// pass zero as oldx or oldy to disable drag in that direction:
+
+void Fl_Tile::position(int oix, int oiy, int newx, int newy) {
+ Fl_Widget*const* a = array();
+ short* p = sizes();
+ p += 8; // skip group & resizable's saved size
+ for (int i=children(); i--; p += 4) {
+ Fl_Widget* o = *a++;
+ if (o == resizable()) continue;
+ int X = o->x();
+ int R = X+o->w();
+ if (oix) {
+ int t = p[0];
+ if (t == oix || t>oix && X<newx || t<oix && X>newx) X = newx;
+ t = p[1];
+ if (t == oix || t>oix && R<newx || t<oix && R>newx) R = newx;
+ }
+ int Y = o->y();
+ int B = Y+o->h();
+ if (oiy) {
+ int t = p[2];
+ if (t == oiy || t>oiy && Y<newy || t<oiy && Y>newy) Y = newy;
+ t = p[3];
+ if (t == oiy || t>oiy && B<newy || t<oiy && B>newy) B = newy;
+ }
+ o->damage_resize(X,Y,R-X,B-Y);
+ }
+}
+
+// move the lower-right corner (sort of):
+void Fl_Tile::resize(int X,int Y,int W,int H) {
+ //Fl_Group::resize(X, Y, W, H);
+ //return;
+ // remember how much to move the child widgets:
+ int dx = X-x();
+ int dy = Y-y();
+ int dw = W-w();
+ int dh = H-h();
+ short* p = sizes();
+ // resize this (skip the Fl_Group resize):
+ Fl_Widget::resize(X,Y,W,H);
+ // find bottom-right of resiable:
+ int OR = p[5];
+ int NR = X+W-(p[1]-OR);
+ int OB = p[7];
+ int NB = Y+H-(p[3]-OB);
+ // move everything to be on correct side of new resizable:
+ Fl_Widget*const* a = array();
+ p += 8;
+ for (int i=children(); i--;) {
+ Fl_Widget* o = *a++;
+ int xx = o->x()+dx;
+ int R = xx+o->w();
+ if (*p++ >= OR) xx += dw; else if (xx > NR) xx = NR;
+ if (*p++ >= OR) R += dw; else if (R > NR) R = NR;
+ int yy = o->y()+dy;
+ int B = yy+o->h();
+ if (*p++ >= OB) yy += dh; else if (yy > NB) yy = NB;
+ if (*p++ >= OB) B += dh; else if (B > NB) B = NB;
+ o->resize(xx,yy,R-xx,B-yy);
+ // do *not* call o->redraw() here! If you do, and the tile is inside a
+ // scroll, it'll set the damage areas wrong for all children!
+ }
+}
+
+static void set_cursor(Fl_Tile*t, Fl_Cursor c) {
+ static Fl_Cursor cursor;
+ if (cursor == c || !t->window()) return;
+ cursor = c;
+#ifdef __sgi
+ t->window()->cursor(c,FL_RED,FL_WHITE);
+#else
+ t->window()->cursor(c);
+#endif
+}
+
+static Fl_Cursor cursors[4] = {
+ FL_CURSOR_DEFAULT,
+ FL_CURSOR_WE,
+ FL_CURSOR_NS,
+ FL_CURSOR_MOVE};
+
+int Fl_Tile::handle(int event) {
+ static int sdrag;
+ static int sdx, sdy;
+ static int sx, sy;
+#define DRAGH 1
+#define DRAGV 2
+#define GRABAREA 4
+
+ int mx = Fl::event_x();
+ int my = Fl::event_y();
+
+ switch (event) {
+
+ case FL_MOVE:
+ case FL_ENTER:
+ case FL_PUSH: {
+ int mindx = 100;
+ int mindy = 100;
+ int oldx = 0;
+ int oldy = 0;
+ Fl_Widget*const* a = array();
+ short* q = sizes();
+ short* p = q+8;
+ for (int i=children(); i--; p += 4) {
+ Fl_Widget* o = *a++;
+ if (o == resizable()) continue;
+ if (p[1]<q[1] && o->y()<=my+GRABAREA && o->y()+o->h()>=my-GRABAREA) {
+ int t = mx - (o->x()+o->w());
+ if (abs(t) < mindx) {
+ sdx = t;
+ mindx = abs(t);
+ oldx = p[1];
+ }
+ }
+ if (p[3]<q[3] && o->x()<=mx+GRABAREA && o->x()+o->w()>=mx-GRABAREA) {
+ int t = my - (o->y()+o->h());
+ if (abs(t) < mindy) {
+ sdy = t;
+ mindy = abs(t);
+ oldy = p[3];
+ }
+ }
+ }
+ sdrag = 0; sx = sy = 0;
+ if (mindx <= GRABAREA) {sdrag = DRAGH; sx = oldx;}
+ if (mindy <= GRABAREA) {sdrag |= DRAGV; sy = oldy;}
+ set_cursor(this, cursors[sdrag]);
+ if (sdrag) return 1;
+ return Fl_Group::handle(event);
+ }
+
+ case FL_LEAVE:
+ set_cursor(this, FL_CURSOR_DEFAULT);
+ break;
+
+ case FL_DRAG:
+ // This is necessary if CONSOLIDATE_MOTION in Fl_x.cxx is turned off:
+ // if (damage()) return 1; // don't fall behind
+ case FL_RELEASE: {
+ if (!sdrag) return 0; // should not happen
+ Fl_Widget* r = resizable(); if (!r) r = this;
+ int newx;
+ if (sdrag&DRAGH) {
+ newx = Fl::event_x()-sdx;
+ if (newx < r->x()) newx = r->x();
+ else if (newx > r->x()+r->w()) newx = r->x()+r->w();
+ } else
+ newx = sx;
+ int newy;
+ if (sdrag&DRAGV) {
+ newy = Fl::event_y()-sdy;
+ if (newy < r->y()) newy = r->y();
+ else if (newy > r->y()+r->h()) newy = r->y()+r->h();
+ } else
+ newy = sy;
+ position(sx,sy,newx,newy);
+ if (event == FL_DRAG) set_changed();
+ do_callback();
+ return 1;}
+
+ }
+
+ return Fl_Group::handle(event);
+}
+
+//
+// End of "$Id: Fl_Tile.cxx 5606 2007-01-18 10:01:24Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Tiled_Image.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Tiled_Image.cxx new file mode 100644 index 0000000..289bcab --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Tiled_Image.cxx @@ -0,0 +1,139 @@ +//
+// "$Id: Fl_Tiled_Image.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Tiled image code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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_Tiled_Image.H>
+#include <FL/fl_draw.H>
+
+
+//
+// 'Fl_Tiled_Image::Fl_Tiled_Image()' - Constructor.
+//
+// Use a width and height of 0 to tile the whole window/widget.
+//
+
+Fl_Tiled_Image::Fl_Tiled_Image(Fl_Image *i, // I - Image to tile
+ int W, // I - Width of tiled area
+ int H) : // I - Height of tiled area
+ Fl_Image(W,H,0) {
+ image_ = i;
+ alloc_image_ = 0;
+
+ if (W == 0) w(Fl::w());
+ if (H == 0) h(Fl::h());
+}
+
+
+//
+// 'Fl_Tiled_Image::~Fl_Tiled_Image()' - Destructor.
+//
+
+Fl_Tiled_Image::~Fl_Tiled_Image() {
+ if (alloc_image_) delete image_;
+}
+
+
+//
+// 'Fl_Tiled_Image::copy()' - Copy and resize a tiled image...
+//
+
+Fl_Image * // O - New image
+Fl_Tiled_Image::copy(int W, // I - New width
+ int H) { // I - New height
+ if (W == w() && H == h()) return this;
+ else return new Fl_Tiled_Image(image_, W, H);
+}
+
+
+//
+// 'Fl_Tiled_Image::color_average()' - Blend colors...
+//
+
+void
+Fl_Tiled_Image::color_average(Fl_Color c, // I - Color to blend with
+ float i) { // I - Blend fraction
+ if (!alloc_image_) {
+ image_ = image_->copy();
+ alloc_image_ = 1;
+ }
+
+ image_->color_average(c, i);
+}
+
+
+//
+// 'Fl_Tiled_Image::desaturate()' - Convert the image to grayscale...
+//
+
+void
+Fl_Tiled_Image::desaturate() {
+ if (!alloc_image_) {
+ image_ = image_->copy();
+ alloc_image_ = 1;
+ }
+
+ image_->desaturate();
+}
+
+
+//
+// 'Fl_Tiled_Image::draw()' - Draw a shared image...
+//
+
+void
+Fl_Tiled_Image::draw(int X, // I - Starting X position
+ int Y, // I - Starting Y position
+ int W, // I - Width of area to be filled
+ int H, // I - Height of area to be filled
+ int cx, // I - "Source" X position
+ int cy) { // I - "Source" Y position
+ if (!image_->w() || !image_->h()) return;
+ if (W == 0) W = Fl::w();
+ if (H == 0) H = Fl::h();
+
+ fl_clip(X, Y, W, H);
+
+ X += cx;
+ Y += cy;
+
+ X = X - (X % image_->w());
+ Y = Y - (Y % image_->h());
+
+ W += X;
+ H += Y;
+
+ for (int yy = Y; yy < H; yy += image_->h())
+ for (int xx = X; xx < W; xx += image_->w())
+ image_->draw(xx, yy);
+
+ fl_pop_clip();
+}
+
+
+//
+// End of "$Id: Fl_Tiled_Image.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Tooltip.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Tooltip.cxx new file mode 100644 index 0000000..4eb99b6 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Tooltip.cxx @@ -0,0 +1,263 @@ +//
+// "$Id: Fl_Tooltip.cxx 5848 2007-05-20 16:18:31Z mike $"
+//
+// Tooltip source file for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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>
+
+float Fl_Tooltip::delay_ = 1.0f;
+float Fl_Tooltip::hoverdelay_ = 0.2f;
+int Fl_Tooltip::enabled_ = 1;
+unsigned Fl_Tooltip::color_ = fl_color_cube(FL_NUM_RED - 1,
+ FL_NUM_GREEN - 1,
+ FL_NUM_BLUE - 2);
+unsigned Fl_Tooltip::textcolor_ = FL_BLACK;
+int Fl_Tooltip::font_ = FL_HELVETICA;
+int Fl_Tooltip::size_ = FL_NORMAL_SIZE;
+
+#define MAX_WIDTH 400
+
+static const char* tip;
+
+class Fl_TooltipBox : public Fl_Menu_Window {
+public:
+ Fl_TooltipBox() : Fl_Menu_Window(0, 0) {
+ set_override();
+ end();
+ }
+ void draw();
+ void layout();
+ void show() {
+ if (tip) Fl_Menu_Window::show();
+ }
+};
+
+Fl_Widget* Fl_Tooltip::widget_ = 0;
+static Fl_TooltipBox *window = 0;
+static int Y,H;
+
+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 {
+ //if (Fl::grab()) return;
+ 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;
+}
+
+// If this widget or one of it's 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());
+}
+
+// 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.
+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 == 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 assummed to point
+// inside or near the box).
+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_Widget::tooltip(const char *tt) {
+ static char beenhere = 0;
+ if (!beenhere) {
+ beenhere = 1;
+ Fl_Tooltip::enter = Fl_Tooltip::enter_;
+ Fl_Tooltip::exit = Fl_Tooltip::exit_;
+ }
+ tooltip_ = tt;
+}
+
+//
+// End of "$Id: Fl_Tooltip.cxx 5848 2007-05-20 16:18:31Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Valuator.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Valuator.cxx new file mode 100644 index 0000000..bdb829a --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Valuator.cxx @@ -0,0 +1,149 @@ +//
+// "$Id: Fl_Valuator.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Valuator widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Base class for sliders and all other one-value "knobs"
+
+#include <FL/Fl.H>
+#include <FL/Fl_Valuator.H>
+#include <FL/math.h>
+#include <stdio.h>
+#include "flstring.h"
+
+Fl_Valuator::Fl_Valuator(int X, int Y, int W, int H, const char* L)
+ : Fl_Widget(X,Y,W,H,L) {
+ align(FL_ALIGN_BOTTOM);
+ when(FL_WHEN_CHANGED);
+ value_ = 0;
+ previous_value_ = 1;
+ min = 0;
+ max = 1;
+ A = 0.0;
+ B = 1;
+}
+
+const double epsilon = 4.66e-10;
+
+void Fl_Valuator::step(double s) {
+ if (s < 0) s = -s;
+ A = rint(s);
+ B = 1;
+ while (fabs(s-A/B) > epsilon && B<=(0x7fffffff/10)) {B *= 10; A = rint(s*B);}
+}
+
+void Fl_Valuator::precision(int p) {
+ A = 1.0;
+ for (B = 1; p--;) B *= 10;
+}
+
+void Fl_Valuator::value_damage() {damage(FL_DAMAGE_EXPOSE);} // by default do partial-redraw
+
+int Fl_Valuator::value(double v) {
+ clear_changed();
+ if (v == value_) return 0;
+ value_ = v;
+ value_damage();
+ return 1;
+}
+
+double Fl_Valuator::softclamp(double v) {
+ int which = (min<=max);
+ double p = previous_value_;
+ if ((v<min)==which && p!=min && (p<min)!=which) return min;
+ else if ((v>max)==which && p!=max && (p>max)!=which) return max;
+ else return v;
+}
+
+// inline void Fl_Valuator::handle_push() {previous_value_ = value_;}
+
+void Fl_Valuator::handle_drag(double v) {
+ if (v != value_) {
+ value_ = v;
+ value_damage();
+ set_changed();
+ if (when() & FL_WHEN_CHANGED) do_callback();
+ }
+}
+
+void Fl_Valuator::handle_release() {
+ if (when()&FL_WHEN_RELEASE) {
+ // insure changed() is off even if no callback is done. It may have
+ // been turned on by the drag, and then the slider returned to it's
+ // initial position:
+ clear_changed();
+ // now do the callback only if slider in new position or always is on:
+ if (value_ != previous_value_ || when() & FL_WHEN_NOT_CHANGED) {
+ do_callback();
+ }
+ }
+}
+
+double Fl_Valuator::round(double v) {
+ if (A) return rint(v*B/A)*A/B;
+ else return v;
+}
+
+double Fl_Valuator::clamp(double v) {
+ if ((v<min)==(min<=max)) return min;
+ else if ((v>max)==(min<=max)) return max;
+ else return v;
+}
+
+double Fl_Valuator::increment(double v, int n) {
+ if (!A) return v+n*(max-min)/100;
+ if (min > max) n = -n;
+ return (rint(v*B/A)+n)*A/B;
+}
+
+int Fl_Valuator::format(char* buffer) {
+ double v = value();
+ // MRS: THIS IS A HACK - RECOMMEND ADDING BUFFER SIZE ARGUMENT
+ if (!A || !B) return snprintf(buffer, 128, "%g", v);
+
+ // Figure out how many digits are required to correctly format the
+ // value.
+ int i, c = 0;
+ char temp[32];
+ // output a number with many digits after the decimal point. This
+ // seems to be needed to get high precission
+ snprintf(temp, sizeof(temp), "%.12f", A/B);
+ // strip all trailing 0's
+ for (i=strlen(temp)-1; i>0; i--) {
+ if (temp[i]!='0') break;
+ }
+ // count digits until we find the decimal point (or comma or whatever
+ // letter is set in the current locale)
+ for (; i>0; i--, c++) {
+ if (!isdigit(temp[i])) break;
+ }
+
+ // MRS: THIS IS A HACK - RECOMMEND ADDING BUFFER SIZE ARGUMENT
+ return snprintf(buffer, 128, "%.*f", c, v);
+}
+
+//
+// End of "$Id: Fl_Valuator.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Value_Input.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Value_Input.cxx new file mode 100644 index 0000000..5d1fae4 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Value_Input.cxx @@ -0,0 +1,133 @@ +//
+// "$Id: Fl_Value_Input.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Value input widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// FLTK widget for drag-adjusting a floating point value.
+// Warning: this works by making a child Fl_Input object, even
+// though this object is *not* an Fl_Group. May be a kludge?
+
+#include <FL/Fl.H>
+#include <FL/Fl_Value_Input.H>
+#include <FL/Fl_Group.H>
+#include <stdlib.h>
+#include <FL/math.h>
+
+
+void Fl_Value_Input::input_cb(Fl_Widget*, void* v) {
+ Fl_Value_Input& t = *(Fl_Value_Input*)v;
+ double nv;
+ if ((t.step() - floor(t.step()))>0.0 || t.step() == 0.0) nv = strtod(t.input.value(), 0);
+ else nv = strtol(t.input.value(), 0, 0);
+ if (nv != t.value() || t.when() & FL_WHEN_NOT_CHANGED) {
+ t.set_value(nv);
+ t.set_changed();
+ if (t.when()) t.do_callback();
+ }
+}
+
+void Fl_Value_Input::draw() {
+ if (damage()&~FL_DAMAGE_CHILD) input.clear_damage(FL_DAMAGE_ALL);
+ input.box(box());
+ input.color(color(), selection_color());
+ input.draw();
+ input.clear_damage();
+}
+
+void Fl_Value_Input::resize(int X, int Y, int W, int H) {
+ Fl_Valuator::resize(X, Y, W, H);
+ input.resize(X, Y, W, H);
+}
+
+void Fl_Value_Input::value_damage() {
+ char buf[128];
+ format(buf);
+ input.value(buf);
+ input.mark(input.position()); // turn off selection highlight
+}
+
+int Fl_Value_Input::handle(int event) {
+ double v;
+ int delta;
+ int mx = Fl::event_x_root();
+ static int ix, drag;
+ input.when(when());
+ switch (event) {
+ case FL_PUSH:
+ if (!step()) goto DEFAULT;
+ ix = mx;
+ drag = Fl::event_button();
+ handle_push();
+ return 1;
+ case FL_DRAG:
+ if (!step()) goto DEFAULT;
+ delta = mx-ix;
+ if (delta > 5) delta -= 5;
+ else if (delta < -5) delta += 5;
+ else delta = 0;
+ switch (drag) {
+ case 3: v = increment(previous_value(), delta*100); break;
+ case 2: v = increment(previous_value(), delta*10); break;
+ default:v = increment(previous_value(), delta); break;
+ }
+ v = round(v);
+ handle_drag(soft()?softclamp(v):clamp(v));;
+ return 1;
+ case FL_RELEASE:
+ if (!step()) goto DEFAULT;
+ if (value() != previous_value() || !Fl::event_is_click())
+ handle_release();
+ else {
+ input.handle(FL_PUSH);
+ input.handle(FL_RELEASE);
+ }
+ return 1;
+ case FL_FOCUS:
+ return input.take_focus();
+ default:
+ DEFAULT:
+ input.type(((step() - floor(step()))>0.0 || step() == 0.0) ? FL_FLOAT_INPUT : FL_INT_INPUT);
+ return input.handle(event);
+ }
+}
+
+Fl_Value_Input::Fl_Value_Input(int X, int Y, int W, int H, const char* l)
+: Fl_Valuator(X, Y, W, H, l), input(X, Y, W, H, 0) {
+ soft_ = 0;
+ if (input.parent()) // defeat automatic-add
+ ((Fl_Group*)input.parent())->remove(input);
+ input.parent((Fl_Group *)this); // kludge!
+ input.callback(input_cb, this);
+ input.when(FL_WHEN_CHANGED);
+ box(input.box());
+ color(input.color());
+ selection_color(input.selection_color());
+ align(FL_ALIGN_LEFT);
+ value_damage();
+}
+
+//
+// End of "$Id: Fl_Value_Input.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Value_Output.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Value_Output.cxx new file mode 100644 index 0000000..bb9a8f8 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Value_Output.cxx @@ -0,0 +1,103 @@ +//
+// "$Id: Fl_Value_Output.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Value output widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Fltk widget for drag-adjusting a floating point value.
+// This is much lighter than Fl_Value_Input because it has no text editor
+// If step() is zero then it can be used to display a floating-point value
+
+#include <FL/Fl.H>
+#include <FL/Fl_Value_Output.H>
+#include <FL/fl_draw.H>
+
+void Fl_Value_Output::draw() {
+ Fl_Boxtype b = box() ? box() : FL_DOWN_BOX;
+ int X = x()+Fl::box_dx(b);
+ int Y = y()+Fl::box_dy(b);
+ int W = w()-Fl::box_dw(b);
+ int H = h()-Fl::box_dh(b);
+ if (damage()&~FL_DAMAGE_CHILD)
+ draw_box(b, color());
+ else {
+ fl_color(color());
+ fl_rectf(X, Y, W, H);
+ }
+ char buf[128];
+ format(buf);
+ fl_color(active_r() ? textcolor() : fl_inactive(textcolor()));
+ fl_font(textfont(), textsize());
+ fl_draw(buf,X,Y,W,H,FL_ALIGN_LEFT);
+}
+
+int Fl_Value_Output::handle(int event) {
+ if (!step()) return 0;
+ double v;
+ int delta;
+ int mx = Fl::event_x();
+ static int ix, drag;
+ switch (event) {
+ case FL_PUSH:
+ ix = mx;
+ drag = Fl::event_button();
+ handle_push();
+ return 1;
+ case FL_DRAG:
+ delta = Fl::event_x()-ix;
+ if (delta > 5) delta -= 5;
+ else if (delta < -5) delta += 5;
+ else delta = 0;
+ switch (drag) {
+ case 3: v = increment(previous_value(),delta*100); break;
+ case 2: v = increment(previous_value(),delta*10); break;
+ default:v = increment(previous_value(),delta); break;
+ }
+ v = round(v);
+ handle_drag(soft()?softclamp(v):clamp(v));;
+ return 1;
+ case FL_RELEASE:
+ handle_release();
+ return 1;
+ case FL_ENTER :
+ case FL_LEAVE :
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+Fl_Value_Output::Fl_Value_Output(int X, int Y, int W, int H,const char *l)
+: Fl_Valuator(X,Y,W,H,l) {
+ box(FL_NO_BOX);
+ align(FL_ALIGN_LEFT);
+ textfont_ = FL_HELVETICA;
+ textsize_ = (uchar)FL_NORMAL_SIZE;
+ textcolor_ = FL_FOREGROUND_COLOR;
+ soft_ = 0;
+}
+
+//
+// End of "$Id: Fl_Value_Output.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Value_Slider.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Value_Slider.cxx new file mode 100644 index 0000000..e26d1ea --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Value_Slider.cxx @@ -0,0 +1,82 @@ +//
+// "$Id: Fl_Value_Slider.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Value slider widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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_Value_Slider.H>
+#include <FL/fl_draw.H>
+#include <math.h>
+
+Fl_Value_Slider::Fl_Value_Slider(int X, int Y, int W, int H, const char*l)
+: Fl_Slider(X,Y,W,H,l) {
+ step(1,100);
+ textfont_ = FL_HELVETICA;
+ textsize_ = 10;
+ textcolor_ = FL_FOREGROUND_COLOR;
+}
+
+void Fl_Value_Slider::draw() {
+ int sxx = x(), syy = y(), sww = w(), shh = h();
+ int bxx = x(), byy = y(), bww = w(), bhh = h();
+ if (horizontal()) {
+ bww = 35; sxx += 35; sww -= 35;
+ } else {
+ syy += 25; bhh = 25; shh -= 25;
+ }
+ if (damage()&FL_DAMAGE_ALL) draw_box(box(),sxx,syy,sww,shh,color());
+ Fl_Slider::draw(sxx+Fl::box_dx(box()),
+ syy+Fl::box_dy(box()),
+ sww-Fl::box_dw(box()),
+ shh-Fl::box_dh(box()));
+ draw_box(box(),bxx,byy,bww,bhh,color());
+ char buf[128];
+ format(buf);
+ fl_font(textfont(), textsize());
+ fl_color(active_r() ? textcolor() : fl_inactive(textcolor()));
+ fl_draw(buf, bxx, byy, bww, bhh, FL_ALIGN_CLIP);
+}
+
+int Fl_Value_Slider::handle(int event) {
+ if (event == FL_PUSH && Fl::visible_focus()) {
+ Fl::focus(this);
+ redraw();
+ }
+ int sxx = x(), syy = y(), sww = w(), shh = h();
+ if (horizontal()) {
+ sxx += 35; sww -= 35;
+ } else {
+ syy += 25; shh -= 25;
+ }
+ return Fl_Slider::handle(event,
+ sxx+Fl::box_dx(box()),
+ syy+Fl::box_dy(box()),
+ sww-Fl::box_dw(box()),
+ shh-Fl::box_dh(box()));
+}
+
+//
+// End of "$Id: Fl_Value_Slider.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Widget.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Widget.cxx new file mode 100644 index 0000000..f3713a9 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Widget.cxx @@ -0,0 +1,318 @@ +//
+// "$Id: Fl_Widget.cxx 6978 2009-12-23 12:54:41Z AlbrechtS $"
+//
+// Base widget class for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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 compatability with Forms, all widgets without callbacks are
+// inserted into a "queue" when they are activated, and the forms
+// compatability 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;
+}
+
+int 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 = (uchar)FL_NORMAL_SIZE;
+ label_.color = FL_FOREGROUND_COLOR;
+ 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;
+ align_ = FL_ALIGN_CENTER;
+ 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
+
+// Destruction does not remove from any parent group! And groups when
+// destroyed destroy all their children. This is convienent and fast.
+// However, it is only legal to destroy a "root" such as an Fl_Window,
+// and automatic destructors may be called.
+Fl_Widget::~Fl_Widget() {
+ Fl::clear_widget_pointer(this);
+ if (flags() & COPIED_LABEL) free((void *)(label_.value));
+ 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);
+}
+
+// draw a focus box for the widget...
+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(WIN32) || defined(__APPLE_QD__)
+ // 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
+ 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);
+#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();
+}
+
+
+//
+// End of "$Id: Fl_Widget.cxx 6978 2009-12-23 12:54:41Z AlbrechtS $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Window.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Window.cxx new file mode 100644 index 0000000..e224c1f --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Window.cxx @@ -0,0 +1,179 @@ +//
+// "$Id: Fl_Window.cxx 5251 2006-06-28 10:23:33Z matt $"
+//
+// Window widget class for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// The Fl_Window is a window in the fltk library.
+// This is the system-independent portions. The huge amount of
+// crap you need to do to communicate with X is in Fl_x.cxx, the
+// equivalent (but totally different) crap for MSWindows is in Fl_win32.cxx
+
+#include <FL/Fl.H>
+#include <FL/Fl_Window.H>
+#include <stdlib.h>
+#include "flstring.h"
+
+#ifdef __APPLE_QUARTZ__
+#include <FL/fl_draw.H>
+#endif
+
+void Fl_Window::_Fl_Window() {
+ type(FL_WINDOW);
+ box(FL_FLAT_BOX);
+ if (Fl::scheme_bg_) {
+ labeltype(FL_NORMAL_LABEL);
+ align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE | FL_ALIGN_CLIP);
+ image(Fl::scheme_bg_);
+ } else {
+ labeltype(FL_NO_LABEL);
+ }
+ i = 0;
+ xclass_ = 0;
+ icon_ = 0;
+ iconlabel_ = 0;
+ resizable(0);
+ size_range_set = 0;
+ minw = maxw = minh = maxh = 0;
+ callback((Fl_Callback*)default_callback);
+}
+
+Fl_Window::Fl_Window(int X,int Y,int W, int H, const char *l)
+: Fl_Group(X, Y, W, H, l) {
+ cursor_default = FL_CURSOR_DEFAULT;
+ cursor_fg = FL_BLACK;
+ cursor_bg = FL_WHITE;
+
+ _Fl_Window();
+ set_flag(FL_FORCE_POSITION);
+}
+
+Fl_Window::Fl_Window(int W, int H, const char *l)
+// fix common user error of a missing end() with current(0):
+ : Fl_Group((Fl_Group::current(0),0), 0, W, H, l) {
+ cursor_default = FL_CURSOR_DEFAULT;
+ cursor_fg = FL_BLACK;
+ cursor_bg = FL_WHITE;
+
+ _Fl_Window();
+ clear_visible();
+}
+
+Fl_Window *Fl_Widget::window() const {
+ for (Fl_Widget *o = parent(); o; o = o->parent())
+ if (o->type() >= FL_WINDOW) return (Fl_Window*)o;
+ return 0;
+}
+
+int Fl_Window::x_root() const {
+ Fl_Window *p = window();
+ if (p) return p->x_root() + x();
+ return x();
+}
+
+int Fl_Window::y_root() const {
+ Fl_Window *p = window();
+ if (p) return p->y_root() + y();
+ return y();
+}
+
+void Fl_Window::draw() {
+ const char *savelabel = label();
+ int saveflags = flags();
+ int savex = x(); x(0);
+ int savey = y(); y(0);
+ // Make sure we don't draw the window title in the window background...
+ clear_flag(COPIED_LABEL); // do not free copied labels!
+ Fl_Widget::label(0);
+ Fl_Group::draw();
+#ifdef __APPLE_QUARTZ__
+ if (!parent() && resizable() && (!size_range_set || minh!=maxh || minw!=maxw)) {
+ int dx = Fl::box_dw(box())-Fl::box_dx(box());
+ int dy = Fl::box_dh(box())-Fl::box_dy(box());
+ if (dx<=0) dx = 1;
+ if (dy<=0) dy = 1;
+ int x1 = w()-dx-1, x2 = x1, y1 = h()-dx-1, y2 = y1;
+ Fl_Color c[4] = {
+ color(),
+ fl_color_average(color(), FL_WHITE, 0.7f),
+ fl_color_average(color(), FL_BLACK, 0.6f),
+ fl_color_average(color(), FL_BLACK, 0.8f),
+ };
+ int i;
+ for (i=dx; i<12; i++) {
+ fl_color(c[i&3]);
+ fl_line(x1--, y1, x2, y2--);
+ }
+ }
+#endif
+ // Restore the label...
+ Fl_Widget::label(savelabel);
+ set_flag(saveflags);
+ y(savey);
+ x(savex);
+}
+
+void Fl_Window::label(const char *name) {
+ label(name, iconlabel());
+}
+
+void Fl_Window::copy_label(const char *a) {
+ if (flags() & COPIED_LABEL) {
+ free((void *)label());
+ clear_flag(COPIED_LABEL);
+ }
+ if (a) a = strdup(a);
+ label(a, iconlabel());
+ set_flag(COPIED_LABEL);
+}
+
+
+void Fl_Window::iconlabel(const char *iname) {
+ uchar saveflags = flags();
+ label(label(), iname);
+ set_flag(saveflags);
+}
+
+// the Fl::atclose pointer is provided for back compatability. You
+// can now just change the callback for the window instead.
+
+void Fl::default_atclose(Fl_Window* window, void* v) {
+ window->hide();
+ Fl_Widget::default_callback(window, v); // put on Fl::read_queue()
+}
+
+void (*Fl::atclose)(Fl_Window*, void*) = default_atclose;
+
+void Fl_Window::default_callback(Fl_Window* win, void* v) {
+ Fl::atclose(win, v);
+}
+
+Fl_Window *Fl_Window::current() {
+ return current_;
+}
+
+
+//
+// End of "$Id: Fl_Window.cxx 5251 2006-06-28 10:23:33Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Window_fullscreen.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Window_fullscreen.cxx new file mode 100644 index 0000000..fc36dc2 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Window_fullscreen.cxx @@ -0,0 +1,97 @@ +//
+// "$Id: Fl_Window_fullscreen.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Fullscreen window support for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Turning the border on/off by changing the motif_wm_hints property
+// works on Irix 4DWM. Does not appear to work for any other window
+// manager. Fullscreen still works on some window managers (fvwm is one)
+// because they allow the border to be placed off-screen.
+
+// Unfortunatly most X window managers ignore changes to the border
+// and refuse to position the border off-screen, so attempting to make
+// the window full screen will lose the size of the border off the
+// bottom and right.
+
+#include <FL/Fl.H>
+#include <FL/x.H>
+
+#ifdef __APPLE__
+#include <config.h>
+#endif
+
+void Fl_Window::border(int b) {
+ if (b) {
+ if (border()) return;
+ clear_flag(FL_NOBORDER);
+ } else {
+ if (!border()) return;
+ set_flag(FL_NOBORDER);
+ }
+#ifdef WIN32
+ // not yet implemented, but it's possible
+ // for full fullscreen we have to make the window topmost as well
+#elif defined(__APPLE_QD__)
+ // warning: not implemented in Quickdraw/Carbon
+#elif defined(__APPLE_QUARTZ__)
+ // warning: not implemented in Quartz/Carbon
+#else
+ if (shown()) Fl_X::i(this)->sendxjunk();
+#endif
+}
+
+void Fl_Window::fullscreen() {
+#ifndef WIN32
+ //this would clobber the fake wm, since it relies on the border flags to
+ //determine its thickness
+ border(0);
+#endif
+#if defined(__APPLE__) || defined(WIN32)
+ int sx, sy, sw, sh;
+ Fl::screen_xywh(sx, sy, sw, sh, x()+w()/2, y()+h()/2);
+ // if we are on the main screen, we will leave the system menu bar unobstructed
+ if (Fl::x()>=sx && Fl::y()>=sy && Fl::x()+Fl::w()<=sx+sw && Fl::y()+Fl::h()<=sy+sh) {
+ sx = Fl::x(); sy = Fl::y();
+ sw = Fl::w(); sh = Fl::h();
+ }
+ if (x()==sx) x(sx+1); // make sure that we actually execute the resize
+ resize(sx, sy, sw, sh);
+#else
+ if (!x()) x(1); // force it to call XResizeWindow()
+ resize(0,0,Fl::w(),Fl::h());
+#endif
+}
+
+void Fl_Window::fullscreen_off(int X,int Y,int W,int H) {
+ // this order produces less blinking on IRIX:
+ resize(X,Y,W,H);
+#ifndef WIN32
+ border(1);
+#endif
+}
+
+//
+// End of "$Id: Fl_Window_fullscreen.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Window_hotspot.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Window_hotspot.cxx new file mode 100644 index 0000000..493370d --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Window_hotspot.cxx @@ -0,0 +1,100 @@ +//
+// "$Id: Fl_Window_hotspot.cxx 5697 2007-02-13 14:38:43Z matt $"
+//
+// Common hotspot routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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_Window.H>
+#include <FL/x.H>
+#include <stdio.h>
+
+void Fl_Window::hotspot(int X, int Y, int offscreen) {
+ int mx,my;
+
+ // Update the screen position based on the mouse position.
+ Fl::get_mouse(mx,my);
+ X = mx-X; Y = my-Y;
+
+ // If offscreen is 0 (the default), make sure that the window
+ // stays on the screen, if possible.
+ if (!offscreen) {
+ int scr_x, scr_y, scr_w, scr_h;
+ Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h);
+
+ int top = 0;
+ int left = 0;
+ int right = 0;
+ int bottom = 0;
+
+ if (border()) {
+#ifdef WIN32
+ if (size_range_set && (maxw != minw || maxh != minh)) {
+ left = right = GetSystemMetrics(SM_CXSIZEFRAME);
+ top = bottom = GetSystemMetrics(SM_CYSIZEFRAME);
+ } else {
+ left = right = GetSystemMetrics(SM_CXFIXEDFRAME);
+ top = bottom = GetSystemMetrics(SM_CYFIXEDFRAME);
+ }
+ top += GetSystemMetrics(SM_CYCAPTION);
+#elif defined(__APPLE__)
+ top = 24;
+ left = 2;
+ right = 2;
+ bottom = 2;
+#else
+ // Ensure border is on screen; these values are generic enough
+ // to work with many window managers, and are based on KDE defaults.
+ top = 20;
+ left = 4;
+ right = 4;
+ bottom = 8;
+#endif
+ }
+ // now insure contents are on-screen (more important than border):
+ if (X+w()+right > scr_w-scr_x) X = scr_w-scr_x-right-w();
+ if (X-left < scr_x) X = left;
+ if (Y+h()+bottom > scr_h-scr_y) Y = scr_h-scr_y-bottom-h();
+ if (Y-top < scr_y) Y = top;
+ // make sure that we will force this position
+ if (X==x()) x(X-1);
+ }
+
+ position(X,Y);
+}
+
+void Fl_Window::hotspot(const Fl_Widget *o, int offscreen) {
+ int X = o->w()/2;
+ int Y = o->h()/2;
+ while (o != this && o) {
+ X += o->x(); Y += o->y();
+ o = o->window();
+ }
+ hotspot(X,Y,offscreen);
+}
+
+
+//
+// End of "$Id: Fl_Window_hotspot.cxx 5697 2007-02-13 14:38:43Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Window_iconize.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Window_iconize.cxx new file mode 100644 index 0000000..9996b84 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Window_iconize.cxx @@ -0,0 +1,49 @@ +//
+// "$Id: Fl_Window_iconize.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Window minification code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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/x.H>
+
+extern char fl_show_iconic; // in Fl_x.cxx
+
+void Fl_Window::iconize() {
+ if (!shown()) {
+ fl_show_iconic = 1;
+ show();
+ } else {
+#ifdef WIN32
+ ShowWindow(i->xid, SW_SHOWMINNOACTIVE);
+#elif defined(__APPLE__)
+ CollapseWindow( i->xid, true );
+#else
+ XIconifyWindow(fl_display, i->xid, fl_screen);
+#endif
+ }
+}
+
+//
+// End of "$Id: Fl_Window_iconize.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Wizard.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Wizard.cxx new file mode 100644 index 0000000..f5c2d60 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Wizard.cxx @@ -0,0 +1,210 @@ +//
+// "$Id: Fl_Wizard.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Fl_Wizard widget routines.
+//
+// Copyright 1997-2005 by Easy Software Products.
+//
+// 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
+//
+// Contents:
+//
+// Fl_Wizard::Fl_Wizard() - Create an Fl_Wizard widget.
+// Fl_Wizard::draw() - Draw the wizard border and visible child.
+// Fl_Wizard::next() - Show the next child.
+// Fl_Wizard::prev() - Show the previous child.
+// Fl_Wizard::value() - Return the current visible child.
+// Fl_Wizard::value() - Set the visible child.
+//
+
+//
+// Include necessary header files...
+//
+
+#include <FL/Fl_Wizard.H>
+#include <FL/Fl_Window.H>
+#include <FL/fl_draw.H>
+
+
+//
+// 'Fl_Wizard::Fl_Wizard()' - Create an Fl_Wizard widget.
+//
+
+Fl_Wizard::Fl_Wizard(int xx, // I - Lefthand position
+ int yy, // I - Upper position
+ int ww, // I - Width
+ int hh, // I - Height
+ const char *l) : // I - Label
+ Fl_Group(xx, yy, ww, hh, l)
+{
+ box(FL_THIN_UP_BOX);
+
+ value_ = (Fl_Widget *)0;
+}
+
+
+//
+// 'Fl_Wizard::draw()' - Draw the wizard border and visible child.
+//
+
+void
+Fl_Wizard::draw()
+{
+ Fl_Widget *kid; // Visible child
+
+
+ kid = value();
+
+ if (damage() & FL_DAMAGE_ALL)
+ {
+ // Redraw everything...
+ if (kid)
+ {
+ draw_box(box(), x(), y(), w(), h(), kid->color());
+ draw_child(*kid);
+ }
+ else
+ draw_box(box(), x(), y(), w(), h(), color());
+
+ }
+ else if (kid)
+ update_child(*kid);
+}
+
+
+//
+// 'Fl_Wizard::next()' - Show the next child.
+//
+
+void
+Fl_Wizard::next()
+{
+ int num_kids;
+ Fl_Widget * const *kids;
+
+
+ if ((num_kids = children()) == 0)
+ return;
+
+ for (kids = array(); num_kids > 0; kids ++, num_kids --)
+ if ((*kids)->visible())
+ break;
+
+ if (num_kids > 1)
+ value(kids[1]);
+}
+
+
+//
+// 'Fl_Wizard::prev()' - Show the previous child.
+//
+
+
+void
+Fl_Wizard::prev()
+{
+ int num_kids;
+ Fl_Widget * const *kids;
+
+
+ if ((num_kids = children()) == 0)
+ return;
+
+ for (kids = array(); num_kids > 0; kids ++, num_kids --)
+ if ((*kids)->visible())
+ break;
+
+ if (num_kids > 0 && num_kids < children())
+ value(kids[-1]);
+}
+
+
+//
+// 'Fl_Wizard::value()' - Return the current visible child.
+//
+
+Fl_Widget *
+Fl_Wizard::value()
+{
+ int num_kids;
+ Fl_Widget * const *kids;
+ Fl_Widget *kid;
+
+
+ if ((num_kids = children()) == 0)
+ return ((Fl_Widget *)0);
+
+ for (kids = array(), kid = (Fl_Widget *)0; num_kids > 0; kids ++, num_kids --)
+ {
+ if ((*kids)->visible())
+ {
+ if (kid)
+ (*kids)->hide();
+ else
+ kid = *kids;
+ }
+ }
+
+ if (!kid)
+ {
+ kids --;
+ kid = *kids;
+ kid->show();
+ }
+
+ return (kid);
+}
+
+
+//
+// 'Fl_Wizard::value()' - Set the visible child.
+//
+
+void
+Fl_Wizard::value(Fl_Widget *kid)
+{
+ int num_kids;
+ Fl_Widget * const *kids;
+
+
+ if ((num_kids = children()) == 0)
+ return;
+
+ for (kids = array(); num_kids > 0; kids ++, num_kids --)
+ {
+ if (*kids == kid)
+ {
+ if (!kid->visible())
+ kid->show();
+ }
+ else
+ (*kids)->hide();
+ }
+
+ // This will restore the mouse pointer to the window's default cursor
+ // whenever the wizard pane is changed. Otherwise text widgets that
+ // show the next pane may leave the cursor set to the I beam, etc...
+ if (window()) window()->cursor(FL_CURSOR_DEFAULT);
+}
+
+
+//
+// End of "$Id: Fl_Wizard.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_XBM_Image.cxx b/third_party/windows/fltk-1.1.10/src/Fl_XBM_Image.cxx new file mode 100644 index 0000000..0254195 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_XBM_Image.cxx @@ -0,0 +1,106 @@ +//
+// "$Id: Fl_XBM_Image.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Fl_XBM_Image routines.
+//
+// Copyright 1997-2005 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
+//
+// Contents:
+//
+// Fl_XBM_Image::Fl_XBM_Image() - Load an XBM file.
+//
+
+//
+// Include necessary header files...
+//
+
+#include <FL/Fl.H>
+#include <FL/Fl_XBM_Image.H>
+#include <stdio.h>
+#include <stdlib.h>
+#include "flstring.h"
+
+//
+// 'Fl_XBM_Image::Fl_XBM_Image()' - Load an XBM file.
+//
+
+Fl_XBM_Image::Fl_XBM_Image(const char *name) : Fl_Bitmap((const char *)0,0,0) {
+ FILE *f;
+ uchar *ptr;
+
+ if ((f = fopen(name, "rb")) == NULL) return;
+
+ char buffer[1024];
+ char junk[1024];
+ int wh[2]; // width and height
+ int i;
+ for (i = 0; i<2; i++) {
+ for (;;) {
+ if (!fgets(buffer,1024,f)) {
+ fclose(f);
+ return;
+ }
+ int r = sscanf(buffer,"#define %s %d",junk,&wh[i]);
+ if (r >= 2) break;
+ }
+ }
+
+ // skip to data array:
+ for (;;) {
+ if (!fgets(buffer,1024,f)) {
+ fclose(f);
+ return;
+ }
+ if (!strncmp(buffer,"static ",7)) break;
+ }
+
+ // Allocate memory...
+ w(wh[0]);
+ h(wh[1]);
+
+ int n = ((wh[0]+7)/8)*wh[1];
+ array = new uchar[n];
+
+ // read the data:
+ for (i = 0, ptr = (uchar *)array; i < n;) {
+ if (!fgets(buffer,1024,f)) {
+ fclose(f);
+ return;
+ }
+ const char *a = buffer;
+ while (*a && i<n) {
+ unsigned int t;
+ if (sscanf(a," 0x%x",&t)>0) {
+ *ptr++ = (uchar)t;
+ i ++;
+ }
+ while (*a && *a++ != ',');
+ }
+ }
+
+ fclose(f);
+}
+
+
+//
+// End of "$Id: Fl_XBM_Image.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_XColor.H b/third_party/windows/fltk-1.1.10/src/Fl_XColor.H new file mode 100644 index 0000000..cd14ef8 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_XColor.H @@ -0,0 +1,46 @@ +//
+// "$Id: Fl_XColor.H 4288 2005-04-16 00:13:17Z mike $"
+//
+// X-specific color definitions for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2001 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 <config.h>
+#include <FL/Enumerations.H>
+
+// one of these for each color in fltk's "colormap":
+// if overlays are enabled, another one for the overlay
+struct Fl_XColor {
+ unsigned char r,g,b; // actual color used by X
+ unsigned char mapped; // true when XAllocColor done
+ unsigned long pixel; // the X pixel to use
+};
+extern Fl_XColor fl_xmap[/*overlay*/][256];
+
+// mask & shifts to produce xcolor for truecolor visuals:
+extern unsigned char fl_redmask, fl_greenmask, fl_bluemask;
+extern int fl_redshift, fl_greenshift, fl_blueshift, fl_extrashift;
+
+//
+// End of "$Id: Fl_XColor.H 4288 2005-04-16 00:13:17Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_XPM_Image.cxx b/third_party/windows/fltk-1.1.10/src/Fl_XPM_Image.cxx new file mode 100644 index 0000000..a09e479 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_XPM_Image.cxx @@ -0,0 +1,131 @@ +//
+// "$Id: Fl_XPM_Image.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Fl_XPM_Image routines.
+//
+// Copyright 1997-2005 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
+//
+// Contents:
+//
+//
+
+//
+// Include necessary header files...
+//
+
+#include <FL/Fl.H>
+#include <FL/Fl_XPM_Image.H>
+#include <stdio.h>
+#include <stdlib.h>
+#include "flstring.h"
+
+
+//
+// 'hexdigit()' - Convert a hex digit to an integer.
+//
+
+static int hexdigit(int x) { // I - Hex digit...
+ if (isdigit(x)) return x-'0';
+ if (isupper(x)) return x-'A'+10;
+ if (islower(x)) return x-'a'+10;
+ return 20;
+}
+
+#define MAXSIZE 2048
+#define INITIALLINES 256
+
+Fl_XPM_Image::Fl_XPM_Image(const char *name) : Fl_Pixmap((char *const*)0) {
+ FILE *f;
+
+ if ((f = fopen(name, "rb")) == NULL) return;
+
+ // read all the c-strings out of the file:
+ char** new_data = new char *[INITIALLINES];
+ char** temp_data;
+ int malloc_size = INITIALLINES;
+ char buffer[MAXSIZE+20];
+ int i = 0;
+ while (fgets(buffer,MAXSIZE+20,f)) {
+ if (buffer[0] != '\"') continue;
+ char *myp = buffer;
+ char *q = buffer+1;
+ while (*q != '\"' && myp < buffer+MAXSIZE) {
+ if (*q == '\\') switch (*++q) {
+ case '\r':
+ case '\n':
+ fgets(q,(buffer+MAXSIZE+20)-q,f); break;
+ case 0:
+ break;
+ case 'x': {
+ q++;
+ int n = 0;
+ for (int x = 0; x < 3; x++) {
+ int xd = hexdigit(*q);
+ if (xd > 15) break;
+ n = (n<<4)+xd;
+ q++;
+ }
+ *myp++ = n;
+ } break;
+ default: {
+ int c = *q++;
+ if (c>='0' && c<='7') {
+ c -= '0';
+ for (int x=0; x<2; x++) {
+ int xd = hexdigit(*q);
+ if (xd>7) break;
+ c = (c<<3)+xd;
+ q++;
+ }
+ }
+ *myp++ = c;
+ } break;
+ } else {
+ *myp++ = *q++;
+ }
+ }
+ *myp++ = 0;
+ if (i >= malloc_size) {
+ temp_data = new char *[malloc_size + INITIALLINES];
+ memcpy(temp_data, new_data, sizeof(char *) * malloc_size);
+ delete[] new_data;
+ new_data = temp_data;
+ malloc_size += INITIALLINES;
+ }
+ new_data[i] = new char[myp-buffer+1];
+ memcpy(new_data[i], buffer,myp-buffer);
+ new_data[i][myp-buffer] = 0;
+ i++;
+ }
+
+ fclose(f);
+
+ data((const char **)new_data, i);
+ alloc_data = 1;
+
+ measure();
+}
+
+
+//
+// End of "$Id: Fl_XPM_Image.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_abort.cxx b/third_party/windows/fltk-1.1.10/src/Fl_abort.cxx new file mode 100644 index 0000000..db9a7bc --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_abort.cxx @@ -0,0 +1,102 @@ +//
+// "$Id: Fl_abort.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Warning/error message code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// This method is in it's own source file so that stdlib and stdio
+// do not need to be included in Fl.cxx:
+// You can also override this by redefining all of these.
+
+#include <FL/Fl.H>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include "flstring.h"
+
+#ifdef WIN32
+# include <windows.h>
+
+static void warning(const char *, ...) {
+ // Show nothing for warnings under WIN32...
+}
+
+static void error(const char *format, ...) {
+ va_list args;
+ char buf[1024];
+ va_start(args, format);
+ vsnprintf(buf, 1024, format, args);
+ va_end(args);
+ MessageBox(0,buf,"Error",MB_ICONEXCLAMATION|MB_SYSTEMMODAL);
+}
+
+static void fatal(const char *format, ...) {
+ va_list args;
+ char buf[1024];
+ va_start(args, format);
+ vsnprintf(buf, 1024, format, args);
+ va_end(args);
+ MessageBox(0,buf,"Error",MB_ICONSTOP|MB_SYSTEMMODAL);
+ ::exit(1);
+}
+
+#else
+
+static void warning(const char *format, ...) {
+ va_list args;
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fputc('\n', stderr);
+ fflush(stderr);
+}
+
+static void error(const char *format, ...) {
+ va_list args;
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fputc('\n', stderr);
+ fflush(stderr);
+}
+
+static void fatal(const char *format, ...) {
+ va_list args;
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fputc('\n', stderr);
+ fflush(stderr);
+ ::exit(1);
+}
+
+#endif
+
+void (*Fl::warning)(const char* format, ...) = ::warning;
+void (*Fl::error)(const char* format, ...) = ::error;
+void (*Fl::fatal)(const char* format, ...) = ::fatal;
+
+//
+// End of "$Id: Fl_abort.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_add_idle.cxx b/third_party/windows/fltk-1.1.10/src/Fl_add_idle.cxx new file mode 100644 index 0000000..495bb89 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_add_idle.cxx @@ -0,0 +1,100 @@ +//
+// "$Id: Fl_add_idle.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Idle routine support for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Allows you to manage an arbitrary set of idle() callbacks.
+// Replaces the older set_idle() call (which is used to implement this)
+
+#include <FL/Fl.H>
+
+struct idle_cb {
+ void (*cb)(void*);
+ void* data;
+ idle_cb *next;
+};
+
+// the callbacks are stored linked in a ring. last points at the one
+// just called, first at the next to call. last->next == first.
+
+static idle_cb* first;
+static idle_cb* last;
+static idle_cb* freelist;
+
+static void call_idle() {
+ idle_cb* p = first;
+ last = p; first = p->next;
+ p->cb(p->data); // this may call add_idle() or remove_idle()!
+}
+
+void Fl::add_idle(void (*cb)(void*), void* data) {
+ idle_cb* p = freelist;
+ if (p) freelist = p->next;
+ else p = new idle_cb;
+ p->cb = cb;
+ p->data = data;
+ if (first) {
+ last->next = p;
+ last = p;
+ p->next = first;
+ } else {
+ first = last = p;
+ p->next = p;
+ set_idle(call_idle);
+ }
+}
+
+int Fl::has_idle(void (*cb)(void*), void* data) {
+ idle_cb* p = first;
+ if (!p) return 0;
+ for (;; p = p->next) {
+ if (p->cb == cb && p->data == data) return 1;
+ if (p==last) return 0;
+ }
+}
+
+void Fl::remove_idle(void (*cb)(void*), void* data) {
+ idle_cb* p = first;
+ if (!p) return;
+ idle_cb* l = last;
+ for (;; p = p->next) {
+ if (p->cb == cb && p->data == data) break;
+ if (p==last) return; // not found
+ l = p;
+ }
+ if (l == p) { // only one
+ first = last = 0;
+ set_idle(0);
+ } else {
+ last = l;
+ first = l->next = p->next;
+ }
+ p->next = freelist;
+ freelist = p;
+}
+
+//
+// End of "$Id: Fl_add_idle.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_arg.cxx b/third_party/windows/fltk-1.1.10/src/Fl_arg.cxx new file mode 100644 index 0000000..1733c8f --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_arg.cxx @@ -0,0 +1,424 @@ +//
+// "$Id: Fl_arg.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Optional argument initialization code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// OPTIONAL initialization code for a program using fltk.
+// You do not need to call this! Feel free to make up your own switches.
+
+#include <FL/Fl.H>
+#include <FL/x.H>
+#include <FL/Fl_Window.H>
+#include <FL/Fl_Tooltip.H>
+#include <FL/filename.H>
+#include <FL/fl_draw.H>
+#include <ctype.h>
+#include "flstring.h"
+
+#if defined(WIN32) || defined(__APPLE__)
+int XParseGeometry(const char*, int*, int*, unsigned int*, unsigned int*);
+# define NoValue 0x0000
+# define XValue 0x0001
+# define YValue 0x0002
+# define WidthValue 0x0004
+# define HeightValue 0x0008
+# define AllValues 0x000F
+# define XNegative 0x0010
+# define YNegative 0x0020
+#endif
+
+static int fl_match(const char *a, const char *s, int atleast = 1) {
+ const char *b = s;
+ while (*a && (*a == *b || tolower(*a) == *b)) {a++; b++;}
+ return !*a && b >= s+atleast;
+}
+
+// flags set by previously parsed arguments:
+extern char fl_show_iconic; // in Fl_x.cxx
+static char arg_called;
+static char return_i;
+static const char *name;
+static const char *geometry;
+static const char *title;
+// these are in Fl_get_system_colors and are set by the switches:
+extern const char *fl_fg;
+extern const char *fl_bg;
+extern const char *fl_bg2;
+
+// consume a switch from argv. Returns number of words eaten, 0 on error:
+int Fl::arg(int argc, char **argv, int &i) {
+ arg_called = 1;
+ const char *s = argv[i];
+
+ if (!s) {i++; return 1;} // something removed by calling program?
+
+ // a word that does not start with '-', or a word after a '--', or
+ // the word '-' by itself all start the "non-switch arguments" to
+ // a program. Return 0 to indicate that we don't understand the
+ // word, but set a flag (return_i) so that args() will return at
+ // that point:
+ if (s[0] != '-' || s[1] == '-' || !s[1]) {return_i = 1; return 0;}
+ s++; // point after the dash
+
+ if (fl_match(s, "iconic")) {
+ fl_show_iconic = 1;
+ i++;
+ return 1;
+ } else if (fl_match(s, "kbd")) {
+ Fl::visible_focus(1);
+ i++;
+ return 1;
+ } else if (fl_match(s, "nokbd", 3)) {
+ Fl::visible_focus(0);
+ i++;
+ return 1;
+ } else if (fl_match(s, "dnd", 2)) {
+ Fl::dnd_text_ops(1);
+ i++;
+ return 1;
+ } else if (fl_match(s, "nodnd", 3)) {
+ Fl::dnd_text_ops(0);
+ i++;
+ return 1;
+ } else if (fl_match(s, "tooltips", 2)) {
+ Fl_Tooltip::enable();
+ i++;
+ return 1;
+ } else if (fl_match(s, "notooltips", 3)) {
+ Fl_Tooltip::disable();
+ i++;
+ return 1;
+ }
+#ifdef __APPLE__
+ // The Finder application in MacOS X passes the "-psn_N_NNNNN" option
+ // to all apps...
+ else if (strncmp(s, "psn_", 4) == 0) {
+ i++;
+ return 1;
+ }
+#endif // __APPLE__
+
+ const char *v = argv[i+1];
+ if (i >= argc-1 || !v)
+ return 0; // all the rest need an argument, so if missing it is an error
+
+ if (fl_match(s, "geometry")) {
+
+ int flags, gx, gy; unsigned int gw, gh;
+ flags = XParseGeometry(v, &gx, &gy, &gw, &gh);
+ if (!flags) return 0;
+ geometry = v;
+
+#if !defined(WIN32) && !defined(__APPLE__)
+ } else if (fl_match(s, "display", 2)) {
+ Fl::display(v);
+#endif
+
+ } else if (fl_match(s, "title", 2)) {
+ title = v;
+
+ } else if (fl_match(s, "name", 2)) {
+ name = v;
+
+ } else if (fl_match(s, "bg2", 3) || fl_match(s, "background2", 11)) {
+ fl_bg2 = v;
+
+ } else if (fl_match(s, "bg", 2) || fl_match(s, "background", 10)) {
+ fl_bg = v;
+
+ } else if (fl_match(s, "fg", 2) || fl_match(s, "foreground", 10)) {
+ fl_fg = v;
+
+ } else if (fl_match(s, "scheme", 1)) {
+ Fl::scheme(v);
+
+ } else return 0; // unrecognized
+
+ i += 2;
+ return 2;
+}
+
+// consume all switches from argv. Returns number of words eaten.
+// Returns zero on error. 'i' will either point at first word that
+// does not start with '-', at the error word, or after a '--', or at
+// argc. If your program does not take any word arguments you can
+// report an error if i < argc.
+
+int Fl::args(int argc, char** argv, int& i, int (*cb)(int,char**,int&)) {
+ arg_called = 1;
+ i = 1; // skip argv[0]
+ while (i < argc) {
+ if (cb && cb(argc,argv,i)) continue;
+ if (!arg(argc,argv,i)) return return_i ? i : 0;
+ }
+ return i;
+}
+
+// show a main window, use any parsed arguments
+void Fl_Window::show(int argc, char **argv) {
+ if (argc && !arg_called) Fl::args(argc,argv);
+
+ Fl::get_system_colors();
+
+#if !defined(WIN32) && !defined(__APPLE__)
+ // Get defaults for drag-n-drop and focus...
+ const char *key = 0, *val;
+
+ if (Fl::first_window()) key = Fl::first_window()->xclass();
+ if (!key) key = "fltk";
+
+ val = XGetDefault(fl_display, key, "dndTextOps");
+ if (val) Fl::dnd_text_ops(strcasecmp(val, "true") == 0 ||
+ strcasecmp(val, "on") == 0 ||
+ strcasecmp(val, "yes") == 0);
+
+ val = XGetDefault(fl_display, key, "tooltips");
+ if (val) Fl_Tooltip::enable(strcasecmp(val, "true") == 0 ||
+ strcasecmp(val, "on") == 0 ||
+ strcasecmp(val, "yes") == 0);
+
+ val = XGetDefault(fl_display, key, "visibleFocus");
+ if (val) Fl::visible_focus(strcasecmp(val, "true") == 0 ||
+ strcasecmp(val, "on") == 0 ||
+ strcasecmp(val, "yes") == 0);
+#endif // !WIN32 && !__APPLE__
+
+ // set colors first, so background_pixel is correct:
+ static char beenhere;
+ if (!beenhere) {
+ if (geometry) {
+ int fl = 0, gx = x(), gy = y(); unsigned int gw = w(), gh = h();
+ fl = XParseGeometry(geometry, &gx, &gy, &gw, &gh);
+ if (fl & XNegative) gx = Fl::w()-w()+gx;
+ if (fl & YNegative) gy = Fl::h()-h()+gy;
+ // int mw,mh; minsize(mw,mh);
+ // if (mw > gw) gw = mw;
+ // if (mh > gh) gh = mh;
+ Fl_Widget *r = resizable();
+ if (!r) resizable(this);
+ // for WIN32 we assumme window is not mapped yet:
+ if (fl & (XValue | YValue))
+ x(-1), resize(gx,gy,gw,gh);
+ else
+ size(gw,gh);
+ resizable(r);
+ }
+ }
+
+ // set the class, which is used by X version of get_system_colors:
+ if (name) {xclass(name); name = 0;}
+ else if (!xclass()) xclass(fl_filename_name(argv[0]));
+
+ if (title) {label(title); title = 0;}
+ else if (!label()) label(xclass());
+
+ if (!beenhere) {
+ beenhere = 1;
+ Fl::scheme(Fl::scheme()); // opens display! May call Fl::fatal()
+ }
+
+ // Show the window AFTER we have set the colors and scheme.
+ show();
+
+#if !defined(WIN32) && !defined(__APPLE__)
+ // set the command string, used by state-saving window managers:
+ int j;
+ int n=0; for (j=0; j<argc; j++) n += strlen(argv[j])+1;
+ char *buffer = new char[n];
+ char *p = buffer;
+ for (j=0; j<argc; j++) for (const char *q = argv[j]; (*p++ = *q++););
+ XChangeProperty(fl_display, fl_xid(this), XA_WM_COMMAND, XA_STRING, 8, 0,
+ (unsigned char *)buffer, p-buffer-1);
+ delete[] buffer;
+#endif // !WIN32 && !__APPLE__
+}
+
+// Calls useful for simple demo programs, with automatic help message:
+
+static const char * const helpmsg =
+"options are:\n"
+" -bg2 color\n"
+" -bg color\n"
+" -di[splay] host:n.n\n"
+" -dn[d]\n"
+" -fg color\n"
+" -g[eometry] WxH+X+Y\n"
+" -i[conic]\n"
+" -k[bd]\n"
+" -na[me] classname\n"
+" -nod[nd]\n"
+" -nok[bd]\n"
+" -not[ooltips]\n"
+" -s[cheme] scheme\n"
+" -ti[tle] windowtitle\n"
+" -to[oltips]";
+
+const char * const Fl::help = helpmsg+13;
+
+void Fl::args(int argc, char **argv) {
+ int i; if (Fl::args(argc,argv,i) < argc) Fl::error(helpmsg);
+}
+
+#if defined(WIN32) || defined(__APPLE__)
+
+/* the following function was stolen from the X sources as indicated. */
+
+/* Copyright Massachusetts Institute of Technology 1985, 1986, 1987 */
+/* $XConsortium: XParseGeom.c,v 11.18 91/02/21 17:23:05 rws Exp $ */
+
+/*
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in advertising or
+publicity pertaining to distribution of the software without specific,
+written prior permission. M.I.T. makes no representations about the
+suitability of this software for any purpose. It is provided "as is"
+without express or implied warranty.
+*/
+
+/*
+ * XParseGeometry parses strings of the form
+ * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
+ * width, height, xoffset, and yoffset are unsigned integers.
+ * Example: "=80x24+300-49"
+ * The equal sign is optional.
+ * It returns a bitmask that indicates which of the four values
+ * were actually found in the string. For each value found,
+ * the corresponding argument is updated; for each value
+ * not found, the corresponding argument is left unchanged.
+ */
+
+static int ReadInteger(char* string, char** NextString)
+{
+ register int Result = 0;
+ int Sign = 1;
+
+ if (*string == '+')
+ string++;
+ else if (*string == '-') {
+ string++;
+ Sign = -1;
+ }
+ for (; (*string >= '0') && (*string <= '9'); string++) {
+ Result = (Result * 10) + (*string - '0');
+ }
+ *NextString = string;
+ if (Sign >= 0)
+ return (Result);
+ else
+ return (-Result);
+}
+
+int XParseGeometry(const char* string, int* x, int* y,
+ unsigned int* width, unsigned int* height)
+{
+ int mask = NoValue;
+ register char *strind;
+ unsigned int tempWidth = 0, tempHeight = 0;
+ int tempX = 0, tempY = 0;
+ char *nextCharacter;
+
+ if ( (string == NULL) || (*string == '\0')) return(mask);
+ if (*string == '=')
+ string++; /* ignore possible '=' at beg of geometry spec */
+
+ strind = (char *)string;
+ if (*strind != '+' && *strind != '-' && *strind != 'x') {
+ tempWidth = ReadInteger(strind, &nextCharacter);
+ if (strind == nextCharacter)
+ return (0);
+ strind = nextCharacter;
+ mask |= WidthValue;
+ }
+
+ if (*strind == 'x' || *strind == 'X') {
+ strind++;
+ tempHeight = ReadInteger(strind, &nextCharacter);
+ if (strind == nextCharacter)
+ return (0);
+ strind = nextCharacter;
+ mask |= HeightValue;
+ }
+
+ if ((*strind == '+') || (*strind == '-')) {
+ if (*strind == '-') {
+ strind++;
+ tempX = -ReadInteger(strind, &nextCharacter);
+ if (strind == nextCharacter)
+ return (0);
+ strind = nextCharacter;
+ mask |= XNegative;
+
+ } else {
+ strind++;
+ tempX = ReadInteger(strind, &nextCharacter);
+ if (strind == nextCharacter)
+ return(0);
+ strind = nextCharacter;
+ }
+ mask |= XValue;
+ if ((*strind == '+') || (*strind == '-')) {
+ if (*strind == '-') {
+ strind++;
+ tempY = -ReadInteger(strind, &nextCharacter);
+ if (strind == nextCharacter)
+ return(0);
+ strind = nextCharacter;
+ mask |= YNegative;
+
+ } else {
+ strind++;
+ tempY = ReadInteger(strind, &nextCharacter);
+ if (strind == nextCharacter)
+ return(0);
+ strind = nextCharacter;
+ }
+ mask |= YValue;
+ }
+ }
+
+ /* If strind isn't at the end of the string the it's an invalid
+ geometry specification. */
+
+ if (*strind != '\0') return (0);
+
+ if (mask & XValue)
+ *x = tempX;
+ if (mask & YValue)
+ *y = tempY;
+ if (mask & WidthValue)
+ *width = tempWidth;
+ if (mask & HeightValue)
+ *height = tempHeight;
+ return (mask);
+}
+
+#endif // ifdef WIN32
+
+//
+// End of "$Id: Fl_arg.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_compose.cxx b/third_party/windows/fltk-1.1.10/src/Fl_compose.cxx new file mode 100644 index 0000000..b884b8f --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_compose.cxx @@ -0,0 +1,223 @@ +//
+// "$Id: Fl_compose.cxx 5211 2006-06-19 07:43:39Z matt $"
+//
+// Character compose processing for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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>
+
+//
+// MRS: Uncomment the following define to get the original (pre-1.1.2)
+// dead key support code. The original code apparently did not
+// work on Belgian keyboards.
+//
+
+//#define OLD_DEAD_KEY_CODE
+
+
+#ifdef __APPLE__
+
+static const char* const compose_pairs =
+":A*A,C'E~N:O:U'a`a^a:a~a*a,c'e`e"
+"^e:e'i`i^i:i~n'o`o^o:o~o'u`u^u:u"
+"+ o /c# SS* P|ssrOcOTM' : !=AE/O"
+"oo+-<=>=Y=mudtSgPipiS a dgOmaeo/"
+"? ! !!v-f ~~Dt<<>>.. `A~A~OOEoe"
+"- --''``\"'\"`:-^V:y:Y//E=< > fifl"
+"++..,,_\"%%^A^E'A:E`E'I^I:I`I'O^O"
+"mc`O'U^U`U||^ ~^_ u . * , ~-; v ";
+
+#else
+
+static const char* const compose_pairs =
+"=E _'f _\"..+ ++^ %%^S< OE ^Z ^''^^\"\"^-*- --~ TM^s> oe ^z:Y"
+" ! % # $ y=| & : c a <<~ - r _ * +-2 3 ' u p . , 1 o >>141234? "
+"`A'A^A~A:A*AAE,C`E'E^E:E`I'I^I:I-D~N`O'O^O~O:Ox O/`U'U^U:U'YTHss"
+"`a'a^a~a:a*aae,c`e'e^e:e`i'i^i:i-d~n`o'o^o~o:o-:o/`u'u^u:u'yth:y";
+
+#endif
+
+#if !defined(WIN32) && defined(OLD_DEAD_KEY_CODE) // X only
+// X dead-key lookup table. This turns a dead-key keysym into the
+// first of two characters for one of the compose sequences. These
+// keysyms start at 0xFE50.
+// Win32 handles the dead keys before FLTK can see them. This is
+// unfortunate, because you don't get the preview effect.
+static char dead_keys[] = {
+ '`', // XK_dead_grave
+ '\'', // XK_dead_acute
+ '^', // XK_dead_circumflex
+ '~', // XK_dead_tilde
+ '_', // XK_dead_macron
+ 0, // XK_dead_breve
+ '.', // XK_dead_abovedot
+ ':', // XK_dead_diaeresis
+ '*', // XK_dead_abovering
+ 0, // XK_dead_doubleacute
+ 'v', // XK_dead_caron
+ ',' // XK_dead_cedilla
+// 0, // XK_dead_ogonek
+// 0, // XK_dead_iota
+// 0, // XK_dead_voiced_sound
+// 0, // XK_dead_semivoiced_sound
+// 0 // XK_dead_belowdot
+};
+#endif // !WIN32 && OLD_DEAD_KEY_CODE
+
+int Fl::compose_state = 0;
+
+int Fl::compose(int& del) {
+
+ del = 0;
+ unsigned char ascii = (unsigned)e_text[0];
+
+ // Alt+letters are reserved for shortcuts. But alt+foreign letters
+ // has to be allowed, because some key layouts require alt to be held
+ // down in order to type them...
+ //
+ // OSX users sometimes need to hold down ALT for keys, so we only check
+ // for META on OSX...
+#ifdef __APPLE__
+ if ((e_state & FL_META) && !(ascii & 128)) return 0;
+#else
+ if ((e_state & (FL_ALT|FL_META)) && !(ascii & 128)) return 0;
+#endif // __APPLE__
+
+ if (compose_state == 1) { // after the compose key
+ if ( // do not get distracted by any modifier keys
+ e_keysym==FL_Shift_L||
+ e_keysym==FL_Shift_R ||
+ e_keysym==FL_Alt_L ||
+ e_keysym==FL_Alt_R ||
+ e_keysym==FL_Meta_L ||
+ e_keysym==FL_Meta_R ||
+ e_keysym==FL_Control_R ||
+ e_keysym==FL_Control_L ||
+ e_keysym==FL_Menu
+ ) return 0;
+
+ if (ascii == ' ') { // space turns into nbsp
+#ifdef __APPLE__
+ e_text[0] = char(0xCA);
+#else
+ e_text[0] = char(0xA0);
+#endif
+ compose_state = 0;
+ return 1;
+ } else if (ascii < ' ' || ascii == 127) {
+ compose_state = 0;
+ return 0;
+ }
+
+ // see if it is either character of any pair:
+ for (const char *p = compose_pairs; *p; p += 2)
+ if (p[0] == ascii || p[1] == ascii) {
+ if (p[1] == ' ') e_text[0] = (p-compose_pairs)/2+0x80;
+ compose_state = ascii;
+ return 1;
+ }
+
+ if (e_length) { // compose key also "quotes" control characters
+ compose_state = 0;
+ return 1;
+ }
+
+ } else if (compose_state) { // second character of compose
+
+ char c1 = char(compose_state); // retrieve first character
+#ifdef __APPLE__
+ if ( (c1==0x60 && ascii==0xab) || (c1==0x27 && ascii==0x60)) {
+ del = 1;
+ compose_state = '^';
+ e_text[0] = 0xf6;
+ return 1;
+ }
+ if (ascii==' ') {
+ del = 0;
+ compose_state = 0;
+ return 0;
+ }
+#endif
+ // now search for the pair in either order:
+ for (const char *p = compose_pairs; *p; p += 2) {
+ if (p[0] == ascii && p[1] == c1 || p[1] == ascii && p[0] == c1) {
+ e_text[0] = (p-compose_pairs)/2+0x80;
+ del = 1; // delete the old character and insert new one
+ compose_state = 0;
+ return 1;
+ }
+ }
+
+ }
+
+ int i = e_keysym;
+
+ // See if they type the compose prefix key:
+ if (i == FL_Control_R || i == 0xff20/* Multi-Key */) {
+ compose_state = 1;
+ return 1;
+ }
+
+#ifdef WIN32
+#elif (defined __APPLE__)
+ if (e_state & 0x40000000) {
+ if (ascii<0x80)
+ compose_state = ascii;
+ else
+ compose_state = compose_pairs[(ascii-0x80)*2];
+ return 1;
+ }
+#else
+ // See if they typed a dead key. This gets it into the same state as
+ // typing prefix+accent:
+ if (i >= 0xfe50 && i <= 0xfe5b) {
+# ifdef OLD_DEAD_KEY_CODE
+ ascii = dead_keys[i-0xfe50];
+ for (const char *p = compose_pairs; *p; p += 2)
+ if (p[0] == ascii) {
+ compose_state = ascii;
+ return 1;
+ }
+# else
+ ascii = e_text[0];
+ for (const char *p = compose_pairs; *p; p += 2)
+ if (p[0] == ascii ||
+ (p[1] == ' ' && (p - compose_pairs) / 2 + 0x80 == ascii)) {
+ compose_state = p[0];
+ return 1;
+ }
+# endif // OLD_DEAD_KEY_CODE
+ compose_state = 0;
+ return 1;
+ }
+#endif
+
+ // Only insert non-control characters:
+ if (e_length && (ascii & ~31 && ascii!=127)) {compose_state = 0; return 1;}
+
+ return 0;
+}
+
+
+
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_display.cxx b/third_party/windows/fltk-1.1.10/src/Fl_display.cxx new file mode 100644 index 0000000..d0db51e --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_display.cxx @@ -0,0 +1,54 @@ +//
+// "$Id: Fl_display.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Display function for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Startup method to set what display to use.
+// Using setenv makes programs that are exec'd use the same display.
+
+#include <FL/Fl.H>
+#include <stdlib.h>
+#include "flstring.h"
+
+void Fl::display(const char *d) {
+#if defined(__APPLE__) || defined(WIN32)
+ (void)d;
+#else
+ static char e[1024];
+ strcpy(e,"DISPLAY=");
+ strlcat(e,d,sizeof(e));
+ for (char *c = e+8; *c!=':'; c++) {
+ if (!*c) {
+ strlcat(e,":0.0",sizeof(e));
+ break;
+ }
+ }
+ putenv(e);
+#endif // __APPLE__
+}
+
+//
+// End of "$Id: Fl_display.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_get_key.cxx b/third_party/windows/fltk-1.1.10/src/Fl_get_key.cxx new file mode 100644 index 0000000..3536ce2 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_get_key.cxx @@ -0,0 +1,69 @@ +//
+// "$Id: Fl_get_key.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Keyboard state routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+#ifdef WIN32
+# include "Fl_get_key_win32.cxx"
+#elif defined(__APPLE__)
+# include "Fl_get_key_mac.cxx"
+#else
+
+// Return the current state of a key. This is the X version. I identify
+// keys (mostly) by the X keysym. So this turns the keysym into a keycode
+// and looks it up in the X key bit vector, which Fl_x.cxx keeps track of.
+
+# include <FL/Fl.H>
+# include <FL/x.H>
+
+extern char fl_key_vector[32]; // in Fl_x.cxx
+
+int Fl::event_key(int k) {
+ if (k > FL_Button && k <= FL_Button+8)
+ return Fl::event_state(8<<(k-FL_Button));
+ int i;
+# ifdef __sgi
+ // get some missing PC keyboard keys:
+ if (k == FL_Meta_L) i = 147;
+ else if (k == FL_Meta_R) i = 148;
+ else if (k == FL_Menu) i = 149;
+ else
+# endif
+ i = XKeysymToKeycode(fl_display, k);
+ if (i==0) return 0;
+ return fl_key_vector[i/8] & (1 << (i%8));
+}
+
+int Fl::get_key(int k) {
+ fl_open_display();
+ XQueryKeymap(fl_display, fl_key_vector);
+ return event_key(k);
+}
+
+#endif
+
+//
+// End of "$Id: Fl_get_key.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_get_key_mac.cxx b/third_party/windows/fltk-1.1.10/src/Fl_get_key_mac.cxx new file mode 100644 index 0000000..02dd22b --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_get_key_mac.cxx @@ -0,0 +1,110 @@ +//
+// "$Id: Fl_get_key_mac.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// MacOS keyboard state routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Return the current state of a key. Keys are named by fltk symbols,
+// which are actually X keysyms. So this has to translate to macOS
+// symbols.
+
+#include <FL/Fl.H>
+#include <FL/x.H>
+#include <config.h>
+
+// convert an FLTK (X) keysym to a MacOS symbol:
+// See also the inverse converter in Fl_mac.cxx
+// This table is in numeric order by FLTK symbol order for binary search:
+
+static const struct {unsigned short vk, fltk;} vktab[] = {
+ { 49, ' ' }, { 39, '\'' }, { 43, ',' }, { 27, '-' }, { 47, '.' }, { 44, '/' },
+ { 29, '0' }, { 18, '1' }, { 19, '2' }, { 20, '3' },
+ { 21, '4' }, { 23, '5' }, { 22, '6' }, { 26, '7' },
+ { 28, '8' }, { 25, '9' }, { 41, ';' }, { 24, '=' },
+ { 0, 'A' }, { 11, 'B' }, { 8, 'C' }, { 2, 'D' },
+ { 14, 'E' }, { 3, 'F' }, { 5, 'G' }, { 4, 'H' },
+ { 34, 'I' }, { 38, 'J' }, { 40, 'K' }, { 37, 'L' },
+ { 46, 'M' }, { 45, 'N' }, { 31, 'O' }, { 35, 'P' },
+ { 12, 'Q' }, { 15, 'R' }, { 1, 'S' }, { 17, 'T' },
+ { 32, 'U' }, { 9, 'V' }, { 13, 'W' }, { 7, 'X' },
+ { 16, 'Y' }, { 6, 'Z' },
+ { 33, '[' }, { 30, ']' }, { 50, '`' }, { 42, '|' },
+ { 51, FL_BackSpace }, { 48, FL_Tab }, { 36, FL_Enter }, { 127, FL_Pause },
+ { 107, FL_Scroll_Lock }, { 53, FL_Escape }, { 0x73, FL_Home }, { 123, FL_Left },
+ { 126, FL_Up }, { 124, FL_Right }, { 125, FL_Down }, { 0x74, FL_Page_Up },
+ { 0x79, FL_Page_Down }, { 119, FL_End }, { 0x71, FL_Print }, { 127, FL_Insert },
+ { 0x6e, FL_Menu }, { 114, FL_Help }, { 0x47, FL_Num_Lock },
+ { 76, FL_KP_Enter }, { 67, FL_KP+'*' }, { 69, FL_KP+'+'}, { 78, FL_KP+'-' }, { 65, FL_KP+'.' }, { 75, FL_KP+'/' },
+ { 82, FL_KP+'0' }, { 83, FL_KP+'1' }, { 84, FL_KP+'2' }, { 85, FL_KP+'3' },
+ { 86, FL_KP+'4' }, { 87, FL_KP+'5' }, { 88, FL_KP+'6' }, { 89, FL_KP+'7' },
+ { 91, FL_KP+'8' }, { 92, FL_KP+'9' }, { 81, FL_KP+'=' },
+ { 0x7a, FL_F+1 }, { 0x78, FL_F+2 }, { 0x63, FL_F+3 }, { 0x76, FL_F+4 },
+ { 0x60, FL_F+5 }, { 0x61, FL_F+6 }, { 0x62, FL_F+7 }, { 0x64, FL_F+8 },
+ { 0x65, FL_F+9 }, { 0x6D, FL_F+10 }, { 0x67, FL_F+11 }, { 0x6f, FL_F+12 },
+ { 56, FL_Shift_L }, { 56, FL_Shift_R }, { 59, FL_Control_L }, { 59, FL_Control_R },
+ { 57, FL_Caps_Lock }, { 55, FL_Meta_L }, { 55, FL_Meta_R },
+ { 58, FL_Alt_L }, { 58, FL_Alt_R }, { 0x75, FL_Delete },
+};
+
+static int fltk2mac(int fltk) {
+ int a = 0;
+ int b = sizeof(vktab)/sizeof(*vktab);
+ while (a < b) {
+ int c = (a+b)/2;
+ if (vktab[c].fltk == fltk) return vktab[c].vk;
+ if (vktab[c].fltk < fltk) a = c+1; else b = c;
+ }
+ return 127;
+}
+
+//: returns true, if that key was pressed during the last event
+int Fl::event_key(int k) {
+ return get_key(k);
+}
+
+#include <stdio.h>
+
+//: returns true, if that key is pressed right now
+int Fl::get_key(int k) {
+ KeyMap foo;
+ GetKeys(foo);
+#ifdef MAC_TEST_FOR_KEYCODES
+ static int cnt = 0;
+ if (cnt++>1024) {
+ cnt = 0;
+ printf("%08x %08x %08x %08x\n", (ulong*)(foo)[3], (ulong*)(foo)[2], (ulong*)(foo)[1], (ulong*)(foo)[0]);
+ }
+#endif
+ unsigned char *b = (unsigned char*)foo;
+ // KP_Enter can be at different locations for Powerbooks vs. desktop Macs
+ if (k==FL_KP_Enter) {
+ return (((b[0x34>>3]>>(0x34&7))&1)||((b[0x4c>>3]>>(0x4c&7))&1));
+ }
+ int i = fltk2mac(k);
+ return (b[i>>3]>>(i&7))&1;
+}
+
+//
+// End of "$Id: Fl_get_key_mac.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_get_key_win32.cxx b/third_party/windows/fltk-1.1.10/src/Fl_get_key_win32.cxx new file mode 100644 index 0000000..0970848 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_get_key_win32.cxx @@ -0,0 +1,138 @@ +//
+// "$Id: Fl_get_key_win32.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// WIN32 keyboard state routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Return the current state of a key. Keys are named by fltk symbols,
+// which are actually X keysyms. So this has to translate to MSWindows
+// VK_x symbols.
+
+#include <FL/Fl.H>
+#include <FL/x.H>
+
+// convert an Fltk (X) keysym to a MSWindows VK symbol:
+// See also the inverse converter in Fl_win32.cxx
+// This table is in numeric order by Fltk symbol order for binary search:
+
+static const struct {unsigned short vk, fltk;} vktab[] = {
+ {VK_SPACE, ' '},
+ {'1', '!'},
+ {0xde, '\"'},
+ {'3', '#'},
+ {'4', '$'},
+ {'5', '%'},
+ {'7', '&'},
+ {0xde, '\''},
+ {'9', '('},
+ {'0', ')'},
+ {'8', '*'},
+ {0xbb, '+'},
+ {0xbc, ','},
+ {0xbd, '-'},
+ {0xbe, '.'},
+ {0xbf, '/'},
+ {0xba, ':'},
+ {0xba, ';'},
+ {0xbc, '<'},
+ {0xbb, '='},
+ {0xbe, '>'},
+ {0xbf, '?'},
+ {'2', '@'},
+ {0xdb, '['},
+ {0xdc, '\\'},
+ {0xdd, ']'},
+ {'6', '^'},
+ {0xbd, '_'},
+ {0xc0, '`'},
+ {0xdb, '{'},
+ {0xdc, '|'},
+ {0xdd, '}'},
+ {0xc0, '~'},
+ {VK_BACK, FL_BackSpace},
+ {VK_TAB, FL_Tab},
+ {VK_CLEAR, 0xff0b/*XK_Clear*/},
+ {VK_RETURN, FL_Enter},
+ {VK_PAUSE, FL_Pause},
+ {VK_SCROLL, FL_Scroll_Lock},
+ {VK_ESCAPE, FL_Escape},
+ {VK_HOME, FL_Home},
+ {VK_LEFT, FL_Left},
+ {VK_UP, FL_Up},
+ {VK_RIGHT, FL_Right},
+ {VK_DOWN, FL_Down},
+ {VK_PRIOR, FL_Page_Up},
+ {VK_NEXT, FL_Page_Down},
+ {VK_END, FL_End},
+ {VK_SNAPSHOT, FL_Print},
+ {VK_INSERT, FL_Insert},
+ {VK_APPS, FL_Menu},
+ {VK_NUMLOCK, FL_Num_Lock},
+//{VK_???, FL_KP_Enter},
+ {VK_MULTIPLY, FL_KP+'*'},
+ {VK_ADD, FL_KP+'+'},
+ {VK_SUBTRACT, FL_KP+'-'},
+ {VK_DECIMAL, FL_KP+'.'},
+ {VK_DIVIDE, FL_KP+'/'},
+ {VK_LSHIFT, FL_Shift_L},
+ {VK_RSHIFT, FL_Shift_R},
+ {VK_LCONTROL, FL_Control_L},
+ {VK_RCONTROL, FL_Control_R},
+ {VK_CAPITAL, FL_Caps_Lock},
+ {VK_LWIN, FL_Meta_L},
+ {VK_RWIN, FL_Meta_R},
+ {VK_LMENU, FL_Alt_L},
+ {VK_RMENU, FL_Alt_R},
+ {VK_DELETE, FL_Delete}
+};
+
+static int fltk2ms(int fltk) {
+ if (fltk >= '0' && fltk <= '9') return fltk;
+ if (fltk >= 'A' && fltk <= 'Z') return fltk;
+ if (fltk >= 'a' && fltk <= 'z') return fltk-('a'-'A');
+ if (fltk > FL_F && fltk <= FL_F+16) return fltk-(FL_F-(VK_F1-1));
+ if (fltk >= FL_KP+'0' && fltk<=FL_KP+'9') return fltk-(FL_KP+'0'-VK_NUMPAD0);
+ int a = 0;
+ int b = sizeof(vktab)/sizeof(*vktab);
+ while (a < b) {
+ int c = (a+b)/2;
+ if (vktab[c].fltk == fltk) return vktab[c].vk;
+ if (vktab[c].fltk < fltk) a = c+1; else b = c;
+ }
+ return 0;
+}
+
+int Fl::event_key(int k) {
+ return GetKeyState(fltk2ms(k))&~1;
+}
+
+int Fl::get_key(int k) {
+ uchar foo[256];
+ GetKeyboardState(foo);
+ return foo[fltk2ms(k)]&~1;
+}
+
+//
+// End of "$Id: Fl_get_key_win32.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_get_system_colors.cxx b/third_party/windows/fltk-1.1.10/src/Fl_get_system_colors.cxx new file mode 100644 index 0000000..2c8b46e --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_get_system_colors.cxx @@ -0,0 +1,386 @@ +//
+// "$Id: Fl_get_system_colors.cxx 5699 2007-02-20 17:02:41Z matt $"
+//
+// System color support for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2006 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_draw.H>
+#include <FL/x.H>
+#include <FL/math.h>
+#include "flstring.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <FL/Fl_Pixmap.H>
+#include <FL/Fl_Tiled_Image.H>
+#include "tile.xpm"
+
+#if defined(__APPLE__) && defined(__MWERKS__)
+extern "C" int putenv(const char*);
+#endif // __APPLE__ && __MWERKS__
+
+#if defined(WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
+// Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs
+// on Windows, which is supposed to be POSIX compliant...
+# define putenv _putenv
+#endif // WIN32 && !__CYGWIN__
+
+static char fl_bg_set = 0;
+static char fl_bg2_set = 0;
+static char fl_fg_set = 0;
+
+
+void Fl::background(uchar r, uchar g, uchar b) {
+ fl_bg_set = 1;
+
+ // replace the gray ramp so that FL_GRAY is this color
+ if (!r) r = 1; else if (r==255) r = 254;
+ double powr = log(r/255.0)/log((FL_GRAY-FL_GRAY_RAMP)/(FL_NUM_GRAY-1.0));
+ if (!g) g = 1; else if (g==255) g = 254;
+ double powg = log(g/255.0)/log((FL_GRAY-FL_GRAY_RAMP)/(FL_NUM_GRAY-1.0));
+ if (!b) b = 1; else if (b==255) b = 254;
+ double powb = log(b/255.0)/log((FL_GRAY-FL_GRAY_RAMP)/(FL_NUM_GRAY-1.0));
+ for (int i = 0; i < FL_NUM_GRAY; i++) {
+ double gray = i/(FL_NUM_GRAY-1.0);
+ Fl::set_color(fl_gray_ramp(i),
+ uchar(pow(gray,powr)*255+.5),
+ uchar(pow(gray,powg)*255+.5),
+ uchar(pow(gray,powb)*255+.5));
+ }
+}
+
+void Fl::foreground(uchar r, uchar g, uchar b) {
+ fl_fg_set = 1;
+
+ Fl::set_color(FL_FOREGROUND_COLOR,r,g,b);
+}
+
+void Fl::background2(uchar r, uchar g, uchar b) {
+ fl_bg2_set = 1;
+
+ Fl::set_color(FL_BACKGROUND2_COLOR,r,g,b);
+ Fl::set_color(FL_FOREGROUND_COLOR,
+ get_color(fl_contrast(FL_FOREGROUND_COLOR,FL_BACKGROUND2_COLOR)));
+}
+
+// these are set by Fl::args() and override any system colors:
+const char *fl_fg = NULL;
+const char *fl_bg = NULL;
+const char *fl_bg2 = NULL;
+
+static void set_selection_color(uchar r, uchar g, uchar b) {
+ Fl::set_color(FL_SELECTION_COLOR,r,g,b);
+}
+
+#if defined(WIN32) || defined(__APPLE__)
+
+# include <stdio.h>
+// simulation of XParseColor:
+int fl_parse_color(const char* p, uchar& r, uchar& g, uchar& b) {
+ if (*p == '#') p++;
+ int n = strlen(p);
+ int m = n/3;
+ const char *pattern = 0;
+ switch(m) {
+ case 1: pattern = "%1x%1x%1x"; break;
+ case 2: pattern = "%2x%2x%2x"; break;
+ case 3: pattern = "%3x%3x%3x"; break;
+ case 4: pattern = "%4x%4x%4x"; break;
+ default: return 0;
+ }
+ int R,G,B; if (sscanf(p,pattern,&R,&G,&B) != 3) return 0;
+ switch(m) {
+ case 1: R *= 0x11; G *= 0x11; B *= 0x11; break;
+ case 3: R >>= 4; G >>= 4; B >>= 4; break;
+ case 4: R >>= 8; G >>= 8; B >>= 8; break;
+ }
+ r = (uchar)R; g = (uchar)G; b = (uchar)B;
+ return 1;
+}
+#else
+// Wrapper around XParseColor...
+int fl_parse_color(const char* p, uchar& r, uchar& g, uchar& b) {
+ XColor x;
+ if (!fl_display) fl_open_display();
+ if (XParseColor(fl_display, fl_colormap, p, &x)) {
+ r = (uchar)(x.red>>8);
+ g = (uchar)(x.green>>8);
+ b = (uchar)(x.blue>>8);
+ return 1;
+ } else return 0;
+}
+#endif // WIN32 || __APPLE__
+
+#if defined(WIN32)
+static void
+getsyscolor(int what, const char* arg, void (*func)(uchar,uchar,uchar))
+{
+ if (arg) {
+ uchar r,g,b;
+ if (!fl_parse_color(arg, r,g,b))
+ Fl::error("Unknown color: %s", arg);
+ else
+ func(r,g,b);
+ } else {
+ DWORD x = GetSysColor(what);
+ func(uchar(x&255), uchar(x>>8), uchar(x>>16));
+ }
+}
+
+void Fl::get_system_colors() {
+ if (!fl_bg2_set) getsyscolor(COLOR_WINDOW, fl_bg2,Fl::background2);
+ if (!fl_fg_set) getsyscolor(COLOR_WINDOWTEXT, fl_fg, Fl::foreground);
+ if (!fl_bg_set) getsyscolor(COLOR_BTNFACE, fl_bg, Fl::background);
+ getsyscolor(COLOR_HIGHLIGHT, 0, set_selection_color);
+}
+
+#elif defined(__APPLE__)
+// MacOS X currently supports two color schemes - Blue and Graphite.
+// Since we aren't emulating the Aqua interface (even if Apple would
+// let us), we use some defaults that are similar to both. The
+// Fl::scheme("plastic") color/box scheme provides a usable Aqua-like
+// look-n-feel...
+void Fl::get_system_colors()
+{
+ fl_open_display();
+
+ if (!fl_bg2_set) background2(0xff, 0xff, 0xff);
+ if (!fl_fg_set) foreground(0, 0, 0);
+ if (!fl_bg_set) background(0xd8, 0xd8, 0xd8);
+
+#if 0
+ // this would be the correct code, but it does not run on all versions
+ // of OS X. Also, setting a bright selection color would require
+ // some updates in Fl_Adjuster and Fl_Help_Browser
+ OSStatus err;
+ RGBColor c;
+ err = GetThemeBrushAsColor(kThemeBrushPrimaryHighlightColor, 24, true, &c);
+ if (err)
+ set_selection_color(0x00, 0x00, 0x80);
+ else
+ set_selection_color(c.red, c.green, c.blue);
+#else
+ set_selection_color(0x00, 0x00, 0x80);
+#endif
+}
+#else
+
+// Read colors that KDE writes to the xrdb database.
+
+// XGetDefault does not do the expected thing: it does not like
+// periods in either word. Therefore it cannot match class.Text.background.
+// However *.Text.background is matched by pretending the program is "Text".
+// But this will also match *.background if there is no *.Text.background
+// entry, requiring users to put in both (unless they want the text fields
+// the same color as the windows).
+
+static void
+getsyscolor(const char *key1, const char* key2, const char *arg, const char *defarg, void (*func)(uchar,uchar,uchar))
+{
+ if (!arg) {
+ arg = XGetDefault(fl_display, key1, key2);
+ if (!arg) arg = defarg;
+ }
+ XColor x;
+ if (!XParseColor(fl_display, fl_colormap, arg, &x))
+ Fl::error("Unknown color: %s", arg);
+ else
+ func(x.red>>8, x.green>>8, x.blue>>8);
+}
+
+void Fl::get_system_colors()
+{
+ fl_open_display();
+ const char* key1 = 0;
+ if (Fl::first_window()) key1 = Fl::first_window()->xclass();
+ if (!key1) key1 = "fltk";
+ if (!fl_bg2_set) getsyscolor("Text","background", fl_bg2, "#ffffff", Fl::background2);
+ if (!fl_fg_set) getsyscolor(key1, "foreground", fl_fg, "#000000", Fl::foreground);
+ if (!fl_bg_set) getsyscolor(key1, "background", fl_bg, "#c0c0c0", Fl::background);
+ getsyscolor("Text", "selectBackground", 0, "#000080", set_selection_color);
+}
+
+#endif
+
+
+//// Simple implementation of 2.0 Fl::scheme() interface...
+#define D1 BORDER_WIDTH
+#define D2 (BORDER_WIDTH+BORDER_WIDTH)
+
+extern void fl_up_box(int, int, int, int, Fl_Color);
+extern void fl_down_box(int, int, int, int, Fl_Color);
+extern void fl_thin_up_box(int, int, int, int, Fl_Color);
+extern void fl_thin_down_box(int, int, int, int, Fl_Color);
+extern void fl_round_up_box(int, int, int, int, Fl_Color);
+extern void fl_round_down_box(int, int, int, int, Fl_Color);
+
+extern void fl_up_frame(int, int, int, int, Fl_Color);
+extern void fl_down_frame(int, int, int, int, Fl_Color);
+extern void fl_thin_up_frame(int, int, int, int, Fl_Color);
+extern void fl_thin_down_frame(int, int, int, int, Fl_Color);
+
+const char *Fl::scheme_ = (const char *)0;
+Fl_Image *Fl::scheme_bg_ = (Fl_Image *)0;
+
+static Fl_Pixmap tile(tile_xpm);
+
+int Fl::scheme(const char *s) {
+ if (!s) {
+ if ((s = getenv("FLTK_SCHEME")) == NULL) {
+#if !defined(WIN32) && !defined(__APPLE__)
+ const char* key = 0;
+ if (Fl::first_window()) key = Fl::first_window()->xclass();
+ if (!key) key = "fltk";
+ fl_open_display();
+ s = XGetDefault(fl_display, key, "scheme");
+#endif // !WIN32 && !__APPLE__
+ }
+ }
+
+ if (s) {
+ if (!strcasecmp(s, "none") || !strcasecmp(s, "base") || !*s) s = 0;
+ else s = strdup(s);
+ }
+ if (scheme_) free((void*)scheme_);
+ scheme_ = s;
+
+ // Save the new scheme in the FLTK_SCHEME env var so that child processes
+ // inherit it...
+ static char e[1024];
+ strcpy(e,"FLTK_SCHEME=");
+ if (s) strlcat(e,s,sizeof(e));
+ putenv(e);
+
+ // Load the scheme...
+ return reload_scheme();
+}
+
+int Fl::reload_scheme() {
+ Fl_Window *win;
+
+ if (scheme_ && !strcasecmp(scheme_, "plastic")) {
+ // Update the tile image to match the background color...
+ uchar r, g, b;
+ int nr, ng, nb;
+ int i;
+// static uchar levels[3] = { 0xff, 0xef, 0xe8 };
+ // OSX 10.3 and higher use a background with less contrast...
+ static uchar levels[3] = { 0xff, 0xf8, 0xf4 };
+
+ get_color(FL_GRAY, r, g, b);
+
+// printf("FL_GRAY = 0x%02x 0x%02x 0x%02x\n", r, g, b);
+
+ for (i = 0; i < 3; i ++) {
+ nr = levels[i] * r / 0xe8;
+ if (nr > 255) nr = 255;
+
+ ng = levels[i] * g / 0xe8;
+ if (ng > 255) ng = 255;
+
+ nb = levels[i] * b / 0xe8;
+ if (nb > 255) nb = 255;
+
+ sprintf(tile_cmap[i], "%c c #%02x%02x%02x", "Oo."[i], nr, ng, nb);
+// puts(tile_cmap[i]);
+ }
+
+ tile.uncache();
+
+ if (!scheme_bg_) scheme_bg_ = new Fl_Tiled_Image(&tile, w(), h());
+
+ // Load plastic buttons, etc...
+ set_boxtype(FL_UP_FRAME, FL_PLASTIC_UP_FRAME);
+ set_boxtype(FL_DOWN_FRAME, FL_PLASTIC_DOWN_FRAME);
+ set_boxtype(FL_THIN_UP_FRAME, FL_PLASTIC_UP_FRAME);
+ set_boxtype(FL_THIN_DOWN_FRAME, FL_PLASTIC_DOWN_FRAME);
+
+ set_boxtype(FL_UP_BOX, FL_PLASTIC_UP_BOX);
+ set_boxtype(FL_DOWN_BOX, FL_PLASTIC_DOWN_BOX);
+ set_boxtype(FL_THIN_UP_BOX, FL_PLASTIC_THIN_UP_BOX);
+ set_boxtype(FL_THIN_DOWN_BOX, FL_PLASTIC_THIN_DOWN_BOX);
+ set_boxtype(_FL_ROUND_UP_BOX, FL_PLASTIC_ROUND_UP_BOX);
+ set_boxtype(_FL_ROUND_DOWN_BOX, FL_PLASTIC_ROUND_DOWN_BOX);
+
+ // Use standard size scrollbars...
+ Fl::scrollbar_size(16);
+ } else if (scheme_ && !strcasecmp(scheme_, "gtk+")) {
+ // Use a GTK+ inspired look-n-feel...
+ if (scheme_bg_) {
+ delete scheme_bg_;
+ scheme_bg_ = (Fl_Image *)0;
+ }
+
+ set_boxtype(FL_UP_FRAME, FL_GTK_UP_FRAME);
+ set_boxtype(FL_DOWN_FRAME, FL_GTK_DOWN_FRAME);
+ set_boxtype(FL_THIN_UP_FRAME, FL_GTK_THIN_UP_FRAME);
+ set_boxtype(FL_THIN_DOWN_FRAME, FL_GTK_THIN_DOWN_FRAME);
+
+ set_boxtype(FL_UP_BOX, FL_GTK_UP_BOX);
+ set_boxtype(FL_DOWN_BOX, FL_GTK_DOWN_BOX);
+ set_boxtype(FL_THIN_UP_BOX, FL_GTK_THIN_UP_BOX);
+ set_boxtype(FL_THIN_DOWN_BOX, FL_GTK_THIN_DOWN_BOX);
+ set_boxtype(_FL_ROUND_UP_BOX, FL_GTK_ROUND_UP_BOX);
+ set_boxtype(_FL_ROUND_DOWN_BOX, FL_GTK_ROUND_DOWN_BOX);
+
+ // Use slightly thinner scrollbars...
+ Fl::scrollbar_size(15);
+ } else {
+ // Use the standard FLTK look-n-feel...
+ if (scheme_bg_) {
+ delete scheme_bg_;
+ scheme_bg_ = (Fl_Image *)0;
+ }
+
+ set_boxtype(FL_UP_FRAME, fl_up_frame, D1, D1, D2, D2);
+ set_boxtype(FL_DOWN_FRAME, fl_down_frame, D1, D1, D2, D2);
+ set_boxtype(FL_THIN_UP_FRAME, fl_thin_up_frame, 1, 1, 2, 2);
+ set_boxtype(FL_THIN_DOWN_FRAME, fl_thin_down_frame, 1, 1, 2, 2);
+
+ set_boxtype(FL_UP_BOX, fl_up_box, D1, D1, D2, D2);
+ set_boxtype(FL_DOWN_BOX, fl_down_box, D1, D1, D2, D2);
+ set_boxtype(FL_THIN_UP_BOX, fl_thin_up_box, 1, 1, 2, 2);
+ set_boxtype(FL_THIN_DOWN_BOX, fl_thin_down_box, 1, 1, 2, 2);
+ set_boxtype(_FL_ROUND_UP_BOX, fl_round_up_box, 3, 3, 6, 6);
+ set_boxtype(_FL_ROUND_DOWN_BOX, fl_round_down_box, 3, 3, 6, 6);
+
+ // Use standard size scrollbars...
+ Fl::scrollbar_size(16);
+ }
+
+ // Set (or clear) the background tile for all windows...
+ for (win = first_window(); win; win = next_window(win)) {
+ win->labeltype(scheme_bg_ ? FL_NORMAL_LABEL : FL_NO_LABEL);
+ win->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE | FL_ALIGN_CLIP);
+ win->image(scheme_bg_);
+ win->redraw();
+ }
+
+ return 1;
+}
+
+
+//
+// End of "$Id: Fl_get_system_colors.cxx 5699 2007-02-20 17:02:41Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_grab.cxx b/third_party/windows/fltk-1.1.10/src/Fl_grab.cxx new file mode 100644 index 0000000..fe7e5e7 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_grab.cxx @@ -0,0 +1,106 @@ +//
+// "$Id: Fl_grab.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Grab/release code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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 <config.h>
+#include <FL/Fl.H>
+#include <FL/x.H>
+
+////////////////////////////////////////////////////////////////
+// "Grab" is done while menu systems are up. This has several effects:
+// Events are all sent to the "grab window", which does not even
+// have to be displayed (and in the case of Fl_Menu.cxx it isn't).
+// The system is also told to "grab" events and send them to this app.
+// This also modifies how Fl_Window::show() works, on X it turns on
+// override_redirect, it does similar things on WIN32.
+
+extern void fl_fix_focus(); // in Fl.cxx
+
+#ifdef WIN32
+// We have to keep track of whether we have captured the mouse, since
+// MSWindows shows little respect for this... Grep for fl_capture to
+// see where and how this is used.
+extern HWND fl_capture;
+#endif
+
+#ifdef __APPLE__
+// MacOS Carbon does not seem to have a mechanism to grab the mouse pointer
+extern WindowRef fl_capture;
+#endif
+
+void Fl::grab(Fl_Window* win) {
+ if (win) {
+ if (!grab_) {
+#ifdef WIN32
+ SetActiveWindow(fl_capture = fl_xid(first_window()));
+ SetCapture(fl_capture);
+#elif defined(__APPLE__)
+ fl_capture = fl_xid( first_window() );
+ SetUserFocusWindow( fl_capture );
+#else
+ XGrabPointer(fl_display,
+ fl_xid(first_window()),
+ 1,
+ ButtonPressMask|ButtonReleaseMask|
+ ButtonMotionMask|PointerMotionMask,
+ GrabModeAsync,
+ GrabModeAsync,
+ None,
+ 0,
+ fl_event_time);
+ XGrabKeyboard(fl_display,
+ fl_xid(first_window()),
+ 1,
+ GrabModeAsync,
+ GrabModeAsync,
+ fl_event_time);
+#endif
+ }
+ grab_ = win;
+ } else {
+ if (grab_) {
+#ifdef WIN32
+ fl_capture = 0;
+ ReleaseCapture();
+#elif defined(__APPLE__)
+ fl_capture = 0;
+ SetUserFocusWindow( (WindowRef)kUserFocusAuto );
+#else
+ XUngrabKeyboard(fl_display, fl_event_time);
+ XUngrabPointer(fl_display, fl_event_time);
+ // this flush is done in case the picked menu item goes into
+ // an infinite loop, so we don't leave the X server locked up:
+ XFlush(fl_display);
+#endif
+ grab_ = 0;
+ fl_fix_focus();
+ }
+ }
+}
+
+//
+// End of "$Id: Fl_grab.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_lock.cxx b/third_party/windows/fltk-1.1.10/src/Fl_lock.cxx new file mode 100644 index 0000000..ced5259 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_lock.cxx @@ -0,0 +1,358 @@ +//
+// "$Id: Fl_lock.cxx 5950 2007-10-07 10:44:28Z matt $"
+//
+// Multi-threading support code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2007 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 <config.h>
+
+#include <stdlib.h>
+
+/*
+ From Bill:
+
+ I would prefer that FLTK contain the minimal amount of extra
+ stuff for doing threads. There are other portable thread
+ wrapper libraries out there and FLTK should not be providing
+ another. This file is an attempt to make minimal additions
+ and make them self-contained in this source file.
+
+ From Mike:
+
+ Starting with 1.1.8, we now have a callback so that you can
+ process awake() messages as they come in.
+
+
+ The API:
+
+ Fl::lock() - recursive lock. You must call this before the
+ first call to Fl::wait()/run() to initialize the thread
+ system. The lock is locked all the time except when
+ Fl::wait() is waiting for events.
+
+ Fl::unlock() - release the recursive lock.
+
+ Fl::awake(void*) - Causes Fl::wait() to return (with the lock
+ locked) even if there are no events ready.
+
+ Fl::awake(void (*cb)(void *), void*) - Call a function
+ in the main thread from within another thread of execution.
+
+ Fl::thread_message() - returns an argument sent to an
+ Fl::awake() call, or returns NULL if none. WARNING: the
+ current implementation only has a one-entry queue and only
+ returns the most recent value!
+*/
+
+Fl_Awake_Handler *Fl::awake_ring_;
+void **Fl::awake_data_;
+int Fl::awake_ring_size_;
+int Fl::awake_ring_head_;
+int Fl::awake_ring_tail_;
+static const int AWAKE_RING_SIZE = 1024;
+
+static void lock_ring();
+static void unlock_ring();
+
+
+int Fl::add_awake_handler_(Fl_Awake_Handler func, void *data)
+{
+ int ret = 0;
+ lock_ring();
+ if (!awake_ring_) {
+ awake_ring_size_ = AWAKE_RING_SIZE;
+ awake_ring_ = (Fl_Awake_Handler*)malloc(awake_ring_size_*sizeof(Fl_Awake_Handler));
+ awake_data_ = (void**)malloc(awake_ring_size_*sizeof(void*));
+ }
+ if (awake_ring_head_==awake_ring_tail_-1 || awake_ring_head_+1==awake_ring_tail_) {
+ // ring is full. Return -1 as an error indicator.
+ ret = -1;
+ } else {
+ awake_ring_[awake_ring_head_] = func;
+ awake_data_[awake_ring_head_] = data;
+ ++awake_ring_head_;
+ if (awake_ring_head_ == awake_ring_size_)
+ awake_ring_head_ = 0;
+ }
+ unlock_ring();
+ return ret;
+}
+
+int Fl::get_awake_handler_(Fl_Awake_Handler &func, void *&data)
+{
+ int ret = 0;
+ lock_ring();
+ if (!awake_ring_ || awake_ring_head_ == awake_ring_tail_) {
+ ret = -1;
+ } else {
+ func = awake_ring_[awake_ring_tail_];
+ data = awake_data_[awake_ring_tail_];
+ ++awake_ring_tail_;
+ if (awake_ring_tail_ == awake_ring_size_)
+ awake_ring_tail_ = 0;
+ }
+ unlock_ring();
+ return ret;
+}
+
+//
+// 'Fl::awake()' - Let the main thread know an update is pending
+// and have it cal a specific function
+//
+int Fl::awake(Fl_Awake_Handler func, void *data) {
+ int ret = add_awake_handler_(func, data);
+ Fl::awake();
+ return ret;
+}
+
+////////////////////////////////////////////////////////////////
+// Windows threading...
+#ifdef WIN32
+# include <windows.h>
+# include <process.h>
+# include <FL/x.H>
+
+// These pointers are in Fl_win32.cxx:
+extern void (*fl_lock_function)();
+extern void (*fl_unlock_function)();
+
+// The main thread's ID
+static DWORD main_thread;
+
+// Microsoft's version of a MUTEX...
+CRITICAL_SECTION cs;
+CRITICAL_SECTION *cs_ring;
+
+void unlock_ring() {
+ LeaveCriticalSection(cs_ring);
+}
+
+void lock_ring() {
+ if (!cs_ring) {
+ cs_ring = (CRITICAL_SECTION*)malloc(sizeof(CRITICAL_SECTION));
+ InitializeCriticalSection(cs_ring);
+ }
+ EnterCriticalSection(cs_ring);
+}
+
+//
+// 'unlock_function()' - Release the lock.
+//
+
+static void unlock_function() {
+ LeaveCriticalSection(&cs);
+}
+
+//
+// 'lock_function()' - Get the lock.
+//
+
+static void lock_function() {
+ EnterCriticalSection(&cs);
+}
+
+//
+// 'Fl::lock()' - Lock access to FLTK data structures...
+//
+
+void Fl::lock() {
+ if (!main_thread) InitializeCriticalSection(&cs);
+
+ lock_function();
+
+ if (!main_thread) {
+ fl_lock_function = lock_function;
+ fl_unlock_function = unlock_function;
+ main_thread = GetCurrentThreadId();
+ }
+}
+
+//
+// 'Fl::unlock()' - Unlock access to FLTK data structures...
+//
+
+void Fl::unlock() {
+ unlock_function();
+}
+
+
+//
+// 'Fl::awake()' - Let the main thread know an update is pending.
+//
+// When called from a thread, it causes FLTK to awake from Fl::wait()...
+//
+
+void Fl::awake(void* msg) {
+ PostThreadMessage( main_thread, fl_wake_msg, (WPARAM)msg, 0);
+}
+
+////////////////////////////////////////////////////////////////
+// POSIX threading...
+#elif HAVE_PTHREAD
+# include <unistd.h>
+# include <fcntl.h>
+# include <pthread.h>
+
+// Pipe for thread messaging via Fl::awake()...
+static int thread_filedes[2];
+
+// Mutex and state information for Fl::lock() and Fl::unlock()...
+static pthread_mutex_t fltk_mutex;
+static pthread_t owner;
+static int counter;
+
+static void lock_function_init_std() {
+ pthread_mutex_init(&fltk_mutex, NULL);
+}
+
+static void lock_function_std() {
+ if (!counter || owner != pthread_self()) {
+ pthread_mutex_lock(&fltk_mutex);
+ owner = pthread_self();
+ }
+ counter++;
+}
+
+static void unlock_function_std() {
+ if (!--counter) pthread_mutex_unlock(&fltk_mutex);
+}
+
+# ifdef PTHREAD_MUTEX_RECURSIVE
+static bool lock_function_init_rec() {
+ pthread_mutexattr_t attrib;
+ pthread_mutexattr_init(&attrib);
+ if (pthread_mutexattr_settype(&attrib, PTHREAD_MUTEX_RECURSIVE)) {
+ pthread_mutexattr_destroy(&attrib);
+ return true;
+ }
+
+ pthread_mutex_init(&fltk_mutex, &attrib);
+ return false;
+}
+
+static void lock_function_rec() {
+ pthread_mutex_lock(&fltk_mutex);
+}
+
+static void unlock_function_rec() {
+ pthread_mutex_unlock(&fltk_mutex);
+}
+# endif // PTHREAD_MUTEX_RECURSIVE
+
+void Fl::awake(void* msg) {
+ write(thread_filedes[1], &msg, sizeof(void*));
+}
+
+static void* thread_message_;
+void* Fl::thread_message() {
+ void* r = thread_message_;
+ thread_message_ = 0;
+ return r;
+}
+
+static void thread_awake_cb(int fd, void*) {
+ read(fd, &thread_message_, sizeof(void*));
+ Fl_Awake_Handler func;
+ void *data;
+ while (Fl::get_awake_handler_(func, data)==0) {
+ (*func)(data);
+ }
+}
+
+// These pointers are in Fl_x.cxx:
+extern void (*fl_lock_function)();
+extern void (*fl_unlock_function)();
+
+void Fl::lock() {
+ if (!thread_filedes[1]) {
+ // Initialize thread communication pipe to let threads awake FLTK
+ // from Fl::wait()
+ pipe(thread_filedes);
+
+ // Make the write side of the pipe non-blocking to avoid deadlock
+ // conditions (STR #1537)
+ fcntl(thread_filedes[1], F_SETFL,
+ fcntl(thread_filedes[1], F_GETFL) | O_NONBLOCK);
+
+ // Monitor the read side of the pipe so that messages sent via
+ // Fl::awake() from a thread will "wake up" the main thread in
+ // Fl::wait().
+ Fl::add_fd(thread_filedes[0], FL_READ, thread_awake_cb);
+
+ // Set lock/unlock functions for this system, using a system-supplied
+ // recursive mutex if supported...
+# ifdef PTHREAD_MUTEX_RECURSIVE
+ if (!lock_function_init_rec()) {
+ fl_lock_function = lock_function_rec;
+ fl_unlock_function = unlock_function_rec;
+ } else {
+# endif // PTHREAD_MUTEX_RECURSIVE
+ lock_function_init_std();
+ fl_lock_function = lock_function_std;
+ fl_unlock_function = unlock_function_std;
+# ifdef PTHREAD_MUTEX_RECURSIVE
+ }
+# endif // PTHREAD_MUTEX_RECURSIVE
+ }
+
+ fl_lock_function();
+}
+
+void Fl::unlock() {
+ fl_unlock_function();
+}
+
+// Mutex code for the awake ring buffer
+static pthread_mutex_t *ring_mutex;
+
+void unlock_ring() {
+ pthread_mutex_unlock(ring_mutex);
+}
+
+void lock_ring() {
+ if (!ring_mutex) {
+ ring_mutex = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
+ pthread_mutex_init(ring_mutex, NULL);
+ }
+ pthread_mutex_lock(ring_mutex);
+}
+
+#else
+
+void unlock_ring() {
+}
+
+void lock_ring() {
+}
+
+void Fl::awake(void*) {
+}
+
+#endif // WIN32
+
+//
+// End of "$Id: Fl_lock.cxx 5950 2007-10-07 10:44:28Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_mac.cxx b/third_party/windows/fltk-1.1.10/src/Fl_mac.cxx new file mode 100644 index 0000000..6a8fbf5 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_mac.cxx @@ -0,0 +1,2475 @@ +//
+// "$Id: Fl_mac.cxx 6800 2009-06-28 21:54:59Z matt $"
+//
+// MacOS specific code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2007 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
+//
+
+//// From the inner edge of a MetroWerks CodeWarrior CD:
+// (without permission)
+//
+// "Three Compiles for 68Ks under the sky,
+// Seven Compiles for PPCs in their fragments of code,
+// Nine Compiles for Mortal Carbon doomed to die,
+// One Compile for Mach-O Cocoa on its Mach-O throne,
+// in the Land of MacOS X where the Drop-Shadows lie.
+//
+// One Compile to link them all, One Compile to merge them,
+// One Compile to copy them all and in the bundle bind them,
+// in the Land of MacOS X where the Drop-Shadows lie."
+
+// warning: the Apple Quartz version still uses some Quickdraw calls,
+// mostly to get around the single active context in QD and
+// to implement clipping. This should be changed into pure
+// Quartz calls in the near future.
+
+// we don't need the following definition because we deliver only
+// true mouse moves. On very slow systems however, this flag may
+// still be useful.
+#define CONSOLIDATE_MOTION 0
+extern "C" {
+#include <pthread.h>
+}
+
+#include <config.h>
+#include <FL/Fl.H>
+#include <FL/x.H>
+#include <FL/Fl_Window.H>
+#include <FL/Fl_Tooltip.H>
+#include <FL/Fl_Sys_Menu_Bar.H>
+#include <stdio.h>
+#include <stdlib.h>
+#include "flstring.h"
+#include <unistd.h>
+
+// #define DEBUG_SELECT // UNCOMMENT FOR SELECT()/THREAD DEBUGGING
+#ifdef DEBUG_SELECT
+#include <stdio.h> // testing
+#define DEBUGMSG(msg) if ( msg ) fprintf(stderr, msg);
+#define DEBUGPERRORMSG(msg) if ( msg ) perror(msg)
+#define DEBUGTEXT(txt) txt
+#else
+#define DEBUGMSG(msg)
+#define DEBUGPERRORMSG(msg)
+#define DEBUGTEXT(txt) NULL
+#endif /*DEBUG_SELECT*/
+
+// external functions
+extern Fl_Window* fl_find(Window);
+extern void fl_fix_focus();
+
+// forward definition of functions in this file
+static void handleUpdateEvent( WindowPtr xid );
+//+ int fl_handle(const EventRecord &event);
+static int FSSpec2UnixPath( FSSpec *fs, char *dst );
+
+// public variables
+int fl_screen;
+CGContextRef fl_gc = 0;
+Handle fl_system_menu;
+Fl_Sys_Menu_Bar *fl_sys_menu_bar = 0;
+CursHandle fl_default_cursor;
+WindowRef fl_capture = 0; // we need this to compensate for a missing(?) mouse capture
+ulong fl_event_time; // the last timestamp from an x event
+char fl_key_vector[32]; // used by Fl::get_key()
+bool fl_show_iconic; // true if called from iconize() - shows the next created window in collapsed state
+int fl_disable_transient_for; // secret method of removing TRANSIENT_FOR
+const Fl_Window* fl_modal_for; // parent of modal() window
+Fl_Region fl_window_region = 0;
+Window fl_window;
+Fl_Window *Fl_Window::current_;
+EventRef fl_os_event; // last (mouse) event
+
+// forward declarations of variables in this file
+static int got_events = 0;
+static Fl_Window* resize_from_system;
+static CursPtr default_cursor_ptr;
+static Cursor default_cursor;
+static WindowRef fl_os_capture = 0; // the dispatch handler will redirect mose move and drag events to these windows
+
+#if CONSOLIDATE_MOTION
+static Fl_Window* send_motion;
+extern Fl_Window* fl_xmousewin;
+#endif
+
+enum { kEventClassFLTK = 'fltk' };
+enum { kEventFLTKBreakLoop = 1, kEventFLTKDataReady };
+
+/**
+* Mac keyboard lookup table
+ */
+static unsigned short macKeyLookUp[128] =
+{
+ 'a', 's', 'd', 'f', 'h', 'g', 'z', 'x',
+ 'c', 'v', '^', 'b', 'q', 'w', 'e', 'r',
+
+ 'y', 't', '1', '2', '3', '4', '6', '5',
+ '=', '9', '7', '-', '8', '0', ']', 'o',
+
+ 'u', '[', 'i', 'p', FL_Enter, 'l', 'j', '\'',
+ 'k', ';', '\\', ',', '/', 'n', 'm', '.',
+
+ FL_Tab, ' ', '`', FL_BackSpace,
+ FL_KP_Enter, FL_Escape, 0, 0/*FL_Meta_L*/,
+ 0/*FL_Shift_L*/, 0/*FL_Caps_Lock*/, 0/*FL_Alt_L*/, 0/*FL_Control_L*/,
+ 0/*FL_Shift_R*/, 0/*FL_Alt_R*/, 0/*FL_Control_R*/, 0,
+
+ 0, FL_KP+'.', FL_Right, FL_KP+'*', 0, FL_KP+'+', FL_Left, FL_Num_Lock,
+ FL_Down, 0, 0, FL_KP+'/', FL_KP_Enter, FL_Up, FL_KP+'-', 0,
+
+ 0, FL_KP+'=', FL_KP+'0', FL_KP+'1', FL_KP+'2', FL_KP+'3', FL_KP+'4', FL_KP+'5',
+ FL_KP+'6', FL_KP+'7', 0, FL_KP+'8', FL_KP+'9', 0, 0, 0,
+
+ FL_F+5, FL_F+6, FL_F+7, FL_F+3, FL_F+8, FL_F+9, 0, FL_F+11,
+ 0, 0/*FL_F+13*/, FL_Print, FL_Scroll_Lock, 0, FL_F+10, FL_Menu, FL_F+12,
+
+ 0, FL_Pause, FL_Help, FL_Home, FL_Page_Up, FL_Delete, FL_F+4, FL_End,
+ FL_F+2, FL_Page_Down, FL_F+1, FL_Left, FL_Right, FL_Down, FL_Up, 0/*FL_Power*/,
+};
+
+/**
+ * convert the current mouse chord into the FLTK modifier state
+ */
+static unsigned int mods_to_e_state( UInt32 mods )
+{
+ long state = 0;
+ if ( mods & kEventKeyModifierNumLockMask ) state |= FL_NUM_LOCK;
+ if ( mods & cmdKey ) state |= FL_META;
+ if ( mods & (optionKey|rightOptionKey) ) state |= FL_ALT;
+ if ( mods & (controlKey|rightControlKey) ) state |= FL_CTRL;
+ if ( mods & (shiftKey|rightShiftKey) ) state |= FL_SHIFT;
+ if ( mods & alphaLock ) state |= FL_CAPS_LOCK;
+ unsigned int ret = ( Fl::e_state & 0xff000000 ) | state;
+ Fl::e_state = ret;
+ //printf( "State 0x%08x (%04x)\n", ret, mods );
+ return ret;
+}
+
+
+/**
+ * convert the current mouse chord into the FLTK keysym
+ */
+static void mods_to_e_keysym( UInt32 mods )
+{
+ if ( mods & cmdKey ) Fl::e_keysym = FL_Meta_L;
+ else if ( mods & kEventKeyModifierNumLockMask ) Fl::e_keysym = FL_Num_Lock;
+ else if ( mods & optionKey ) Fl::e_keysym = FL_Alt_L;
+ else if ( mods & rightOptionKey ) Fl::e_keysym = FL_Alt_R;
+ else if ( mods & controlKey ) Fl::e_keysym = FL_Control_L;
+ else if ( mods & rightControlKey ) Fl::e_keysym = FL_Control_R;
+ else if ( mods & shiftKey ) Fl::e_keysym = FL_Shift_L;
+ else if ( mods & rightShiftKey ) Fl::e_keysym = FL_Shift_R;
+ else if ( mods & alphaLock ) Fl::e_keysym = FL_Caps_Lock;
+ else Fl::e_keysym = 0;
+ //printf( "to sym 0x%08x (%04x)\n", Fl::e_keysym, mods );
+}
+// these pointers are set by the Fl::lock() function:
+static void nothing() {}
+void (*fl_lock_function)() = nothing;
+void (*fl_unlock_function)() = nothing;
+
+//
+// Select interface -- how it's implemented:
+// When the user app configures one or more file descriptors to monitor
+// with Fl::add_fd(), we start a separate thread to select() the data,
+// sending a custom OSX 'FLTK data ready event' to the parent thread's
+// RunApplicationLoop(), so that it triggers the data ready callbacks
+// in the parent thread. -erco 04/04/04
+//
+#define POLLIN 1
+#define POLLOUT 4
+#define POLLERR 8
+
+// Class to handle select() 'data ready'
+class DataReady
+{
+ struct FD
+ {
+ int fd;
+ short events;
+ void (*cb)(int, void*);
+ void* arg;
+ };
+ int nfds, fd_array_size;
+ FD *fds;
+ pthread_t tid; // select()'s thread id
+
+ // Data that needs to be locked (all start with '_')
+ pthread_mutex_t _datalock; // data lock
+ fd_set _fdsets[3]; // r/w/x sets user wants to monitor
+ int _maxfd; // max fd count to monitor
+ int _cancelpipe[2]; // pipe used to help cancel thread
+ void *_userdata; // thread's userdata
+
+public:
+ DataReady()
+ {
+ nfds = 0;
+ fd_array_size = 0;
+ fds = 0;
+ tid = 0;
+
+ pthread_mutex_init(&_datalock, NULL);
+ FD_ZERO(&_fdsets[0]); FD_ZERO(&_fdsets[1]); FD_ZERO(&_fdsets[2]);
+ _cancelpipe[0] = _cancelpipe[1] = 0;
+ _userdata = 0;
+ _maxfd = 0;
+ }
+
+ ~DataReady()
+ {
+ CancelThread(DEBUGTEXT("DESTRUCTOR\n"));
+ if (fds) { free(fds); fds = 0; }
+ nfds = 0;
+ }
+
+ // Locks
+ // The convention for locks: volatile vars start with '_',
+ // and must be locked before use. Locked code is prefixed
+ // with /*LOCK*/ to make painfully obvious esp. in debuggers. -erco
+ //
+ void DataLock() { pthread_mutex_lock(&_datalock); }
+ void DataUnlock() { pthread_mutex_unlock(&_datalock); }
+
+ // Accessors
+ int IsThreadRunning() { return(tid ? 1 : 0); }
+ int GetNfds() { return(nfds); }
+ int GetCancelPipe(int ix) { return(_cancelpipe[ix]); }
+ fd_set GetFdset(int ix) { return(_fdsets[ix]); }
+
+ // Methods
+ void AddFD(int n, int events, void (*cb)(int, void*), void *v);
+ void RemoveFD(int n, int events);
+ int CheckData(fd_set& r, fd_set& w, fd_set& x);
+ void HandleData(fd_set& r, fd_set& w, fd_set& x);
+ static void* DataReadyThread(void *self);
+ void StartThread(void *userdata);
+ void CancelThread(const char *reason);
+};
+
+static DataReady dataready;
+
+void DataReady::AddFD(int n, int events, void (*cb)(int, void*), void *v)
+{
+ RemoveFD(n, events);
+ int i = nfds++;
+ if (i >= fd_array_size)
+ {
+ FD *temp;
+ fd_array_size = 2*fd_array_size+1;
+ if (!fds) { temp = (FD*)malloc(fd_array_size*sizeof(FD)); }
+ else { temp = (FD*)realloc(fds, fd_array_size*sizeof(FD)); }
+ if (!temp) return;
+ fds = temp;
+ }
+ fds[i].cb = cb;
+ fds[i].arg = v;
+ fds[i].fd = n;
+ fds[i].events = events;
+ DataLock();
+ /*LOCK*/ if (events & POLLIN) FD_SET(n, &_fdsets[0]);
+ /*LOCK*/ if (events & POLLOUT) FD_SET(n, &_fdsets[1]);
+ /*LOCK*/ if (events & POLLERR) FD_SET(n, &_fdsets[2]);
+ /*LOCK*/ if (n > _maxfd) _maxfd = n;
+ DataUnlock();
+}
+
+// Remove an FD from the array
+void DataReady::RemoveFD(int n, int events)
+{
+ int i,j;
+ for (i=j=0; i<nfds; i++)
+ {
+ if (fds[i].fd == n)
+ {
+ int e = fds[i].events & ~events;
+ if (!e) continue; // if no events left, delete this fd
+ fds[i].events = e;
+ }
+ // move it down in the array if necessary:
+ if (j<i)
+ { fds[j] = fds[i]; }
+ j++;
+ }
+ nfds = j;
+ DataLock();
+ /*LOCK*/ if (events & POLLIN) FD_CLR(n, &_fdsets[0]);
+ /*LOCK*/ if (events & POLLOUT) FD_CLR(n, &_fdsets[1]);
+ /*LOCK*/ if (events & POLLERR) FD_CLR(n, &_fdsets[2]);
+ /*LOCK*/ if (n == _maxfd) _maxfd--;
+ DataUnlock();
+}
+
+// CHECK IF USER DATA READY, RETURNS r/w/x INDICATING WHICH IF ANY
+int DataReady::CheckData(fd_set& r, fd_set& w, fd_set& x)
+{
+ int ret;
+ DataLock();
+ /*LOCK*/ timeval t = { 0, 1 }; // quick check
+ /*LOCK*/ r = _fdsets[0], w = _fdsets[1], x = _fdsets[2];
+ /*LOCK*/ ret = ::select(_maxfd+1, &r, &w, &x, &t);
+ DataUnlock();
+ if ( ret == -1 )
+ { DEBUGPERRORMSG("CheckData(): select()"); }
+ return(ret);
+}
+
+// HANDLE DATA READY CALLBACKS
+void DataReady::HandleData(fd_set& r, fd_set& w, fd_set& x)
+{
+ for (int i=0; i<nfds; i++)
+ {
+ int f = fds[i].fd;
+ short revents = 0;
+ if (FD_ISSET(f, &r)) revents |= POLLIN;
+ if (FD_ISSET(f, &w)) revents |= POLLOUT;
+ if (FD_ISSET(f, &x)) revents |= POLLERR;
+ if (fds[i].events & revents)
+ {
+ DEBUGMSG("DOING CALLBACK: ");
+ fds[i].cb(f, fds[i].arg);
+ DEBUGMSG("DONE\n");
+ }
+ }
+}
+
+// DATA READY THREAD
+// This thread watches for changes in user's file descriptors.
+// Sends a 'data ready event' to the main thread if any change.
+//
+void* DataReady::DataReadyThread(void *o)
+{
+ DataReady *self = (DataReady*)o;
+ while ( 1 ) // loop until thread cancel or error
+ {
+ // Thread safe local copies of data before each select()
+ self->DataLock();
+ /*LOCK*/ int maxfd = self->_maxfd;
+ /*LOCK*/ fd_set r = self->GetFdset(0);
+ /*LOCK*/ fd_set w = self->GetFdset(1);
+ /*LOCK*/ fd_set x = self->GetFdset(2);
+ /*LOCK*/ void *userdata = self->_userdata;
+ /*LOCK*/ int cancelpipe = self->GetCancelPipe(0);
+ /*LOCK*/ if ( cancelpipe > maxfd ) maxfd = cancelpipe;
+ /*LOCK*/ FD_SET(cancelpipe, &r); // add cancelpipe to fd's to watch
+ /*LOCK*/ FD_SET(cancelpipe, &x);
+ self->DataUnlock();
+ // timeval t = { 1000, 0 }; // 1000 seconds;
+ timeval t = { 2, 0 }; // HACK: 2 secs prevents 'hanging' problem
+ int ret = ::select(maxfd+1, &r, &w, &x, &t);
+ pthread_testcancel(); // OSX 10.0.4 and older: needed for parent to cancel
+ switch ( ret )
+ {
+ case 0: // NO DATA
+ continue;
+ case -1: // ERROR
+ {
+ DEBUGPERRORMSG("CHILD THREAD: select() failed");
+ return(NULL); // error? exit thread
+ }
+ default: // DATA READY
+ {
+ if (FD_ISSET(cancelpipe, &r) || FD_ISSET(cancelpipe, &x)) // cancel?
+ { return(NULL); } // just exit
+ DEBUGMSG("CHILD THREAD: DATA IS READY\n");
+ EventRef drEvent;
+ CreateEvent( 0, kEventClassFLTK, kEventFLTKDataReady,
+ 0, kEventAttributeUserEvent, &drEvent);
+ EventQueueRef eventqueue = (EventQueueRef)userdata;
+ PostEventToQueue(eventqueue, drEvent, kEventPriorityStandard );
+ ReleaseEvent( drEvent );
+ return(NULL); // done with thread
+ }
+ }
+ }
+}
+
+// START 'DATA READY' THREAD RUNNING, CREATE INTER-THREAD PIPE
+void DataReady::StartThread(void *new_userdata)
+{
+ CancelThread(DEBUGTEXT("STARTING NEW THREAD\n"));
+ DataLock();
+ /*LOCK*/ pipe(_cancelpipe); // pipe for sending cancel msg to thread
+ /*LOCK*/ _userdata = new_userdata;
+ DataUnlock();
+ DEBUGMSG("*** START THREAD\n");
+ pthread_create(&tid, NULL, DataReadyThread, (void*)this);
+}
+
+// CANCEL 'DATA READY' THREAD, CLOSE PIPE
+void DataReady::CancelThread(const char *reason)
+{
+ if ( tid )
+ {
+ DEBUGMSG("*** CANCEL THREAD: ");
+ DEBUGMSG(reason);
+ if ( pthread_cancel(tid) == 0 ) // cancel first
+ {
+ DataLock();
+ /*LOCK*/ write(_cancelpipe[1], "x", 1); // wake thread from select
+ DataUnlock();
+ pthread_join(tid, NULL); // wait for thread to finish
+ }
+ tid = 0;
+ DEBUGMSG("(JOINED) OK\n");
+ }
+ // Close pipe if open
+ DataLock();
+ /*LOCK*/ if ( _cancelpipe[0] ) { close(_cancelpipe[0]); _cancelpipe[0] = 0; }
+ /*LOCK*/ if ( _cancelpipe[1] ) { close(_cancelpipe[1]); _cancelpipe[1] = 0; }
+ DataUnlock();
+}
+
+void Fl::add_fd( int n, int events, void (*cb)(int, void*), void *v )
+ { dataready.AddFD(n, events, cb, v); }
+
+void Fl::add_fd(int fd, void (*cb)(int, void*), void* v)
+ { dataready.AddFD(fd, POLLIN, cb, v); }
+
+void Fl::remove_fd(int n, int events)
+ { dataready.RemoveFD(n, events); }
+
+void Fl::remove_fd(int n)
+ { dataready.RemoveFD(n, -1); }
+
+/**
+ * Check if there is actually a message pending!
+ */
+int fl_ready()
+{
+ EventRef event;
+ return !ReceiveNextEvent(0, NULL, 0.0, false, &event);
+}
+
+/**
+ * handle Apple Menu items (can be created using the Fl_Sys_Menu_Bar
+ * returns eventNotHandledErr if the menu item could not be handled
+ */
+OSStatus HandleMenu( HICommand *cmd )
+{
+ OSStatus ret = eventNotHandledErr;
+ // attributes, commandIDm menu.menuRef, menu.menuItemIndex
+ UInt32 ref;
+ OSErr rrc = GetMenuItemRefCon( cmd->menu.menuRef, cmd->menu.menuItemIndex, &ref );
+ //printf( "%d, %08x, %08x, %d, %d, %8x\n", rrc, cmd->attributes, cmd->commandID, cmd->menu.menuRef, cmd->menu.menuItemIndex, rrc );
+ if ( rrc==noErr && ref )
+ {
+ Fl_Menu_Item *m = (Fl_Menu_Item*)ref;
+ //printf( "Menu: %s\n", m->label() );
+ fl_sys_menu_bar->picked( m );
+ if ( m->flags & FL_MENU_TOGGLE ) // update the menu toggle symbol
+ SetItemMark( cmd->menu.menuRef, cmd->menu.menuItemIndex, (m->flags & FL_MENU_VALUE ) ? 0x12 : 0 );
+ if ( m->flags & FL_MENU_RADIO ) // update all radio buttons in this menu
+ {
+ Fl_Menu_Item *j = m;
+ int i = cmd->menu.menuItemIndex;
+ for (;;)
+ {
+ if ( j->flags & FL_MENU_DIVIDER )
+ break;
+ j++; i++;
+ if ( !j->text || !j->radio() )
+ break;
+ SetItemMark( cmd->menu.menuRef, i, ( j->flags & FL_MENU_VALUE ) ? 0x13 : 0 );
+ }
+ j = m-1; i = cmd->menu.menuItemIndex-1;
+ for ( ; i>0; j--, i-- )
+ {
+ if ( !j->text || j->flags&FL_MENU_DIVIDER || !j->radio() )
+ break;
+ SetItemMark( cmd->menu.menuRef, i, ( j->flags & FL_MENU_VALUE ) ? 0x13 : 0 );
+ }
+ SetItemMark( cmd->menu.menuRef, cmd->menu.menuItemIndex, ( m->flags & FL_MENU_VALUE ) ? 0x13 : 0 );
+ }
+ ret = noErr; // done handling this event
+ }
+ HiliteMenu(0);
+ return ret;
+}
+
+
+/**
+ * We can make every event pass through this function
+ * - mouse events need to be manipulated to use a mouse focus window
+ * - keyboard, mouse and some window events need to quit the Apple Event Loop
+ * so FLTK can continue its own management
+ */
+static pascal OSStatus carbonDispatchHandler( EventHandlerCallRef nextHandler, EventRef event, void *userData )
+{
+ OSStatus ret = eventNotHandledErr;
+ HICommand cmd;
+
+ fl_lock_function();
+
+ got_events = 1;
+
+ switch ( GetEventClass( event ) )
+ {
+ case kEventClassMouse:
+ switch ( GetEventKind( event ) )
+ {
+ case kEventMouseUp:
+ case kEventMouseMoved:
+ case kEventMouseDragged:
+ if ( fl_capture )
+ ret = SendEventToEventTarget( event, GetWindowEventTarget( fl_capture ) );
+ else if ( fl_os_capture ){
+ ret = SendEventToEventTarget( event, GetWindowEventTarget( fl_os_capture ) );
+ fl_os_capture = 0;
+ }
+ break;
+ }
+ break;
+ case kEventClassCommand:
+ switch (GetEventKind( event ) )
+ {
+ case kEventCommandProcess:
+ ret = GetEventParameter( event, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &cmd );
+ if (ret == noErr && (cmd.attributes & kHICommandFromMenu) != 0)
+ ret = HandleMenu( &cmd );
+ else
+ ret = eventNotHandledErr;
+ break;
+ }
+ break;
+ case kEventClassFLTK:
+ switch ( GetEventKind( event ) )
+ {
+ case kEventFLTKBreakLoop:
+ ret = noErr;
+ break;
+ case kEventFLTKDataReady:
+ {
+ dataready.CancelThread(DEBUGTEXT("DATA READY EVENT\n"));
+
+ // CHILD THREAD TELLS US DATA READY
+ // Check to see what's ready, and invoke user's cb's
+ //
+ fd_set r,w,x;
+ switch(dataready.CheckData(r,w,x))
+ {
+ case 0: // NO DATA
+ break;
+ case -1: // ERROR
+ break;
+ default: // DATA READY
+ dataready.HandleData(r,w,x);
+ break;
+ }
+ }
+ ret = noErr;
+ break;
+ }
+ }
+ if ( ret == eventNotHandledErr )
+ ret = CallNextEventHandler( nextHandler, event ); // let the OS handle the activation, but continue to get a click-through effect
+
+ fl_unlock_function();
+
+ return ret;
+}
+
+
+/**
+ * break the current event loop
+ */
+static void breakMacEventLoop()
+{
+ EventRef breakEvent;
+
+ fl_lock_function();
+
+ CreateEvent( 0, kEventClassFLTK, kEventFLTKBreakLoop, 0, kEventAttributeUserEvent, &breakEvent );
+ PostEventToQueue( GetCurrentEventQueue(), breakEvent, kEventPriorityStandard );
+ ReleaseEvent( breakEvent );
+
+ fl_unlock_function();
+}
+
+//
+// MacOS X timers
+//
+
+struct MacTimeout {
+ Fl_Timeout_Handler callback;
+ void* data;
+ EventLoopTimerRef timer;
+ EventLoopTimerUPP upp;
+ char pending;
+};
+static MacTimeout* mac_timers;
+static int mac_timer_alloc;
+static int mac_timer_used;
+
+
+static void realloc_timers()
+{
+ if (mac_timer_alloc == 0) {
+ mac_timer_alloc = 8;
+ }
+ mac_timer_alloc *= 2;
+ MacTimeout* new_timers = new MacTimeout[mac_timer_alloc];
+ memset(new_timers, 0, sizeof(MacTimeout)*mac_timer_alloc);
+ memcpy(new_timers, mac_timers, sizeof(MacTimeout) * mac_timer_used);
+ MacTimeout* delete_me = mac_timers;
+ mac_timers = new_timers;
+ delete [] delete_me;
+}
+
+static void delete_timer(MacTimeout& t)
+{
+ if (t.timer) {
+ RemoveEventLoopTimer(t.timer);
+ DisposeEventLoopTimerUPP(t.upp);
+ memset(&t, 0, sizeof(MacTimeout));
+ }
+}
+
+
+static pascal void do_timer(EventLoopTimerRef timer, void* data)
+{
+ for (int i = 0; i < mac_timer_used; ++i) {
+ MacTimeout& t = mac_timers[i];
+ if (t.timer == timer && t.data == data) {
+ t.pending = 0;
+ (*t.callback)(data);
+ if (t.pending==0)
+ delete_timer(t);
+ break;
+ }
+ }
+ breakMacEventLoop();
+}
+
+/**
+ * This function is the central event handler.
+ * It reads events from the event queue using the given maximum time
+ * Funny enough, it returns the same time that it got as the argument.
+ */
+static double do_queued_events( double time = 0.0 )
+{
+ static bool been_here = 0;
+ static RgnHandle rgn;
+
+ // initialize events and a region that enables mouse move events
+ if (!been_here) {
+ rgn = NewRgn();
+ Point mp;
+ GetMouse(&mp);
+ SetRectRgn(rgn, mp.h, mp.v, mp.h, mp.v);
+ SetEventMask(everyEvent);
+ been_here = 1;
+ }
+ OSStatus ret;
+ static EventTargetRef target = 0;
+ if ( !target )
+ {
+ target = GetEventDispatcherTarget();
+
+ EventHandlerUPP dispatchHandler = NewEventHandlerUPP( carbonDispatchHandler ); // will not be disposed by Carbon...
+ static EventTypeSpec dispatchEvents[] = {
+ { kEventClassWindow, kEventWindowShown },
+ { kEventClassWindow, kEventWindowHidden },
+ { kEventClassWindow, kEventWindowActivated },
+ { kEventClassWindow, kEventWindowDeactivated },
+ { kEventClassWindow, kEventWindowClose },
+ { kEventClassKeyboard, kEventRawKeyDown },
+ { kEventClassKeyboard, kEventRawKeyRepeat },
+ { kEventClassKeyboard, kEventRawKeyUp },
+ { kEventClassKeyboard, kEventRawKeyModifiersChanged },
+ { kEventClassMouse, kEventMouseDown },
+ { kEventClassMouse, kEventMouseUp },
+ { kEventClassMouse, kEventMouseMoved },
+ { kEventClassMouse, 11 }, // MightyMouse wheels
+ { kEventClassMouse, kEventMouseWheelMoved },
+ { kEventClassMouse, kEventMouseDragged },
+ { kEventClassFLTK, kEventFLTKBreakLoop },
+ { kEventClassFLTK, kEventFLTKDataReady } };
+ ret = InstallEventHandler( target, dispatchHandler, GetEventTypeCount(dispatchEvents), dispatchEvents, 0, 0L );
+ static EventTypeSpec appEvents[] = {
+ { kEventClassCommand, kEventCommandProcess } };
+ ret = InstallApplicationEventHandler( dispatchHandler, GetEventTypeCount(appEvents), appEvents, 0, 0L );
+ }
+
+ got_events = 0;
+
+ // Check for re-entrant condition
+ if ( dataready.IsThreadRunning() )
+ { dataready.CancelThread(DEBUGTEXT("AVOID REENTRY\n")); }
+
+ // Start thread to watch for data ready
+ if ( dataready.GetNfds() )
+ { dataready.StartThread((void*)GetCurrentEventQueue()); }
+
+ fl_unlock_function();
+
+ EventRef event;
+ EventTimeout timeout = time;
+ if (!ReceiveNextEvent(0, NULL, timeout, true, &event)) {
+ got_events = 1;
+ OSErr ret = SendEventToEventTarget( event, target );
+ if (ret!=noErr) {
+ EventRecord clevent;
+ ConvertEventRefToEventRecord(event, &clevent);
+ if (clevent.what==kHighLevelEvent) {
+ ret = AEProcessAppleEvent(&clevent);
+ }
+ }
+ if ( ret==eventNotHandledErr
+ && GetEventClass(event)==kEventClassMouse
+ && GetEventKind(event)==kEventMouseDown ) {
+ WindowRef win; Point pos;
+ GetEventParameter(event, kEventParamMouseLocation, typeQDPoint,
+ NULL, sizeof(pos), NULL, &pos);
+ if (MacFindWindow(pos, &win)==inMenuBar) {
+ MenuSelect(pos);
+ }
+ }
+ ReleaseEvent( event );
+ }
+
+ fl_lock_function();
+
+#if CONSOLIDATE_MOTION
+ if (send_motion && send_motion == fl_xmousewin) {
+ send_motion = 0;
+ Fl::handle(FL_MOVE, fl_xmousewin);
+ }
+#endif
+
+ return time;
+}
+
+
+/**
+ * This public function handles all events. It wait a maximum of
+ * 'time' secods for an event. This version returns 1 if events
+ * other than the timeout timer were processed.
+ *
+ * \todo there is no socket handling in this code whatsoever
+ */
+int fl_wait( double time )
+{
+ do_queued_events( time );
+ return (got_events);
+}
+
+
+/**
+ * event handler for Apple-Q key combination
+ * this is also called from the Carbon Window handler after all windows were closed
+ */
+static OSErr QuitAppleEventHandler( const AppleEvent *appleEvt, AppleEvent* reply, UInt32 refcon )
+{
+ fl_lock_function();
+
+ while ( Fl_X::first ) {
+ Fl_X *x = Fl_X::first;
+ Fl::handle( FL_CLOSE, x->w );
+ if ( Fl_X::first == x ) {
+ fl_unlock_function();
+ return noErr; // FLTK has not close all windows, so we return to the main program now
+ }
+ }
+
+ fl_unlock_function();
+
+ return noErr;
+}
+
+
+/**
+ * Carbon Window handler
+ * This needs to be linked into all new window event handlers
+ */
+static pascal OSStatus carbonWindowHandler( EventHandlerCallRef nextHandler, EventRef event, void *userData )
+{
+ UInt32 kind = GetEventKind( event );
+ OSStatus ret = eventNotHandledErr;
+ Fl_Window *window = (Fl_Window*)userData;
+ Fl::first_window(window);
+
+ Rect currentBounds, originalBounds;
+ WindowClass winClass;
+ static Fl_Window *activeWindow = 0;
+
+ fl_lock_function();
+
+ switch ( kind )
+ {
+ case kEventWindowBoundsChanging:
+ GetEventParameter( event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, ¤tBounds );
+ GetEventParameter( event, kEventParamOriginalBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &originalBounds );
+ break;
+ case kEventWindowDrawContent:
+ handleUpdateEvent( fl_xid( window ) );
+ ret = noErr;
+ break;
+ case kEventWindowBoundsChanged: {
+ GetEventParameter( event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, ¤tBounds );
+ GetEventParameter( event, kEventParamOriginalBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &originalBounds );
+ int X = currentBounds.left, W = currentBounds.right-X;
+ int Y = currentBounds.top, H = currentBounds.bottom-Y;
+ resize_from_system = window;
+ window->resize( X, Y, W, H );
+ if ( ( originalBounds.right - originalBounds.left != W )
+ || ( originalBounds.bottom - originalBounds.top != H ) )
+ {
+ if ( window->shown() )
+ handleUpdateEvent( fl_xid( window ) );
+ }
+ break; }
+ case kEventWindowShown:
+ if ( !window->parent() )
+ {
+ GetWindowClass( fl_xid( window ), &winClass );
+ if ( winClass != kHelpWindowClass ) { // help windows can't get the focus!
+ Fl::handle( FL_FOCUS, window);
+ activeWindow = window;
+ }
+ Fl::handle( FL_SHOW, window);
+ mods_to_e_state(GetCurrentKeyModifiers());
+ }
+ break;
+ case kEventWindowHidden:
+ if ( !window->parent() ) Fl::handle( FL_HIDE, window);
+ break;
+ case kEventWindowActivated:
+ if ( window->shown() && window!=activeWindow )
+ {
+ GetWindowClass( fl_xid( window ), &winClass );
+ if ( winClass != kHelpWindowClass ) { // help windows can't get the focus!
+ Fl::handle( FL_FOCUS, window);
+ activeWindow = window;
+ }
+ }
+ break;
+ case kEventWindowDeactivated:
+ if ( window==activeWindow )
+ {
+ Fl::handle( FL_UNFOCUS, window);
+ activeWindow = 0;
+ }
+ break;
+ case kEventWindowClose:
+ Fl::handle( FL_CLOSE, window ); // this might or might not close the window
+ // if there are no more windows, send a high-level quit event
+ if (!Fl_X::first) QuitAppleEventHandler( 0, 0, 0 );
+ ret = noErr; // returning noErr tells Carbon to stop following up on this event
+ break;
+ case kEventWindowCollapsed:
+ window->clear_visible();
+ break;
+ case kEventWindowExpanded:
+ window->set_visible();
+ break;
+ }
+
+ fl_unlock_function();
+
+ return ret;
+}
+
+
+/**
+ * Carbon Mousewheel handler
+ * This needs to be linked into all new window event handlers
+ */
+static pascal OSStatus carbonMousewheelHandler( EventHandlerCallRef nextHandler, EventRef event, void *userData )
+{
+ // Handle the new "MightyMouse" mouse wheel events. Please, someone explain
+ // to me why Apple changed the API on this even though the current API
+ // supports two wheels just fine. Matthias,
+ fl_lock_function();
+
+ fl_os_event = event;
+ Fl_Window *window = (Fl_Window*)userData;
+ if ( !window->shown() )
+ {
+ fl_unlock_function();
+ return noErr;
+ }
+ Fl::first_window(window);
+
+ EventMouseWheelAxis axis;
+ GetEventParameter( event, kEventParamMouseWheelAxis, typeMouseWheelAxis, NULL, sizeof(EventMouseWheelAxis), NULL, &axis );
+ long delta;
+ GetEventParameter( event, kEventParamMouseWheelDelta, typeLongInteger, NULL, sizeof(long), NULL, &delta );
+// fprintf(stderr, "axis=%d, delta=%d\n", axis, delta);
+ if ( axis == kEventMouseWheelAxisX ) {
+ Fl::e_dx = -delta;
+ Fl::e_dy = 0;
+ if ( Fl::e_dx) Fl::handle( FL_MOUSEWHEEL, window );
+ } else if ( axis == kEventMouseWheelAxisY ) {
+ Fl::e_dx = 0;
+ Fl::e_dy = -delta;
+ if ( Fl::e_dy) Fl::handle( FL_MOUSEWHEEL, window );
+ } else {
+ fl_unlock_function();
+
+ return eventNotHandledErr;
+ }
+
+ fl_unlock_function();
+
+ return noErr;
+}
+
+
+/**
+ * convert the current mouse chord into the FLTK modifier state
+ */
+static void chord_to_e_state( UInt32 chord )
+{
+ static ulong state[] =
+ {
+ 0, FL_BUTTON1, FL_BUTTON3, FL_BUTTON1|FL_BUTTON3, FL_BUTTON2,
+ FL_BUTTON2|FL_BUTTON1, FL_BUTTON2|FL_BUTTON3,
+ FL_BUTTON2|FL_BUTTON1|FL_BUTTON3
+ };
+ Fl::e_state = ( Fl::e_state & 0xff0000 ) | state[ chord & 0x07 ];
+}
+
+
+/**
+ * Carbon Mouse Button Handler
+ */
+static pascal OSStatus carbonMouseHandler( EventHandlerCallRef nextHandler, EventRef event, void *userData )
+{
+ static int keysym[] = { 0, FL_Button+1, FL_Button+3, FL_Button+2 };
+ static int px, py;
+ static char suppressed = 0;
+
+ fl_lock_function();
+
+ fl_os_event = event;
+ Fl_Window *window = (Fl_Window*)userData;
+ if ( !window->shown() )
+ {
+ fl_unlock_function();
+ return noErr;
+ }
+ Fl::first_window(window);
+ Point pos;
+ GetEventParameter( event, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &pos );
+ EventMouseButton btn;
+ GetEventParameter( event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(EventMouseButton), NULL, &btn );
+ UInt32 clickCount;
+ GetEventParameter( event, kEventParamClickCount, typeUInt32, NULL, sizeof(UInt32), NULL, &clickCount );
+ UInt32 chord;
+ GetEventParameter( event, kEventParamMouseChord, typeUInt32, NULL, sizeof(UInt32), NULL, &chord );
+ WindowRef xid = fl_xid(window), tempXid;
+ int sendEvent = 0, part = 0;
+ switch ( GetEventKind( event ) )
+ {
+ case kEventMouseDown:
+ part = FindWindow( pos, &tempXid );
+ if (!(Fl::grab() && window!=Fl::grab())) {
+ if ( part == inGrow ) {
+ fl_unlock_function();
+ suppressed = 1;
+ Fl_Tooltip::current(0L);
+ return CallNextEventHandler( nextHandler, event ); // let the OS handle this for us
+ }
+ if ( part != inContent ) {
+ fl_unlock_function();
+ suppressed = 1;
+ Fl_Tooltip::current(0L);
+ // anything else to here?
+ return CallNextEventHandler( nextHandler, event ); // let the OS handle this for us
+ }
+ }
+ suppressed = 0;
+ if (part==inContent && !IsWindowActive( xid ) ) {
+ CallNextEventHandler( nextHandler, event ); // let the OS handle the activation, but continue to get a click-through effect
+ }
+ // normal handling of mouse-down follows
+ fl_os_capture = xid;
+ sendEvent = FL_PUSH;
+ Fl::e_is_click = 1; px = pos.h; py = pos.v;
+ if (clickCount>1)
+ Fl::e_clicks++;
+ else
+ Fl::e_clicks = 0;
+ // fall through
+ case kEventMouseUp:
+ if (suppressed) {
+ suppressed = 0;
+ break;
+ }
+ if ( !window ) break;
+ if ( !sendEvent ) {
+ sendEvent = FL_RELEASE;
+ }
+ Fl::e_keysym = keysym[ btn ];
+ // fall through
+ case kEventMouseMoved:
+ suppressed = 0;
+ if ( !sendEvent ) {
+ sendEvent = FL_MOVE; chord = 0;
+ }
+ // fall through
+ case kEventMouseDragged:
+ if (suppressed) break;
+ if ( !sendEvent ) {
+ sendEvent = FL_MOVE; // Fl::handle will convert into FL_DRAG
+ if (abs(pos.h-px)>5 || abs(pos.v-py)>5)
+ Fl::e_is_click = 0;
+ }
+ chord_to_e_state( chord );
+ GrafPtr oldPort;
+ GetPort( &oldPort );
+ SetPort( GetWindowPort(xid) ); // \todo replace this! There must be some GlobalToLocal call that has a port as an argument
+ SetOrigin(0, 0);
+ Fl::e_x_root = pos.h;
+ Fl::e_y_root = pos.v;
+ GlobalToLocal( &pos );
+ Fl::e_x = pos.h;
+ Fl::e_y = pos.v;
+ SetPort( oldPort );
+ if (GetEventKind(event)==kEventMouseDown && part!=inContent) {
+ int used = Fl::handle( sendEvent, window );
+ CallNextEventHandler( nextHandler, event ); // let the OS handle this for us
+ if (!used)
+ suppressed = 1;
+ } else {
+ Fl::handle( sendEvent, window );
+ }
+ break;
+ }
+
+ fl_unlock_function();
+
+ return noErr;
+}
+
+
+/**
+ * convert the keyboard return code into the symbol on the keycaps
+ */
+static unsigned short keycode_to_sym( UInt32 keyCode, UInt32 mods, unsigned short deflt )
+{
+ static Ptr map = 0;
+ UInt32 state = 0;
+ if (!map) {
+ map = (Ptr)GetScriptManagerVariable(smKCHRCache);
+ if (!map) {
+ long kbID = GetScriptManagerVariable(smKeyScript);
+ map = *GetResource('KCHR', kbID);
+ }
+ }
+ if (map)
+ return KeyTranslate(map, keyCode|mods, &state );
+ return deflt;
+}
+
+/**
+ * handle carbon keyboard events
+ */
+pascal OSStatus carbonKeyboardHandler(
+ EventHandlerCallRef nextHandler, EventRef event, void *userData )
+{
+ static char buffer[5];
+ int sendEvent = 0;
+ Fl_Window *window = (Fl_Window*)userData;
+ Fl::first_window(window);
+ UInt32 mods;
+ static UInt32 prevMods = mods_to_e_state( GetCurrentKeyModifiers() );
+
+ fl_lock_function();
+
+ int kind = GetEventKind(event);
+
+ // get the modifiers for any of the events
+ GetEventParameter( event, kEventParamKeyModifiers, typeUInt32,
+ NULL, sizeof(UInt32), NULL, &mods );
+
+ // get the key code only for key events
+ UInt32 keyCode = 0, maskedKeyCode = 0;
+ unsigned char key = 0;
+ unsigned short sym = 0;
+ if (kind!=kEventRawKeyModifiersChanged) {
+ GetEventParameter( event, kEventParamKeyCode, typeUInt32,
+ NULL, sizeof(UInt32), NULL, &keyCode );
+ GetEventParameter( event, kEventParamKeyMacCharCodes, typeChar,
+ NULL, sizeof(char), NULL, &key );
+ }
+ maskedKeyCode = keyCode & 0x7f;
+ /* output a human readbale event identifier for debugging
+ const char *ev = "";
+ switch (kind) {
+ case kEventRawKeyDown: ev = "kEventRawKeyDown"; break;
+ case kEventRawKeyRepeat: ev = "kEventRawKeyRepeat"; break;
+ case kEventRawKeyUp: ev = "kEventRawKeyUp"; break;
+ case kEventRawKeyModifiersChanged: ev = "kEventRawKeyModifiersChanged"; break;
+ default: ev = "unknown";
+ }
+ printf("%08x %08x %08x '%c' %s \n", mods, keyCode, key, key, ev);
+ */
+ switch (kind)
+ {
+ case kEventRawKeyDown:
+ case kEventRawKeyRepeat:
+ // When the user presses a "dead key", no information is send about
+ // which dead key symbol was created. So we need to trick Carbon into
+ // giving us the code by sending a "space" after the "dead key".
+ if (key==0) {
+ UInt32 ktState = 0;
+ KeyboardLayoutRef klr;
+ KLGetCurrentKeyboardLayout(&klr);
+ const void *kchar = 0; KLGetKeyboardLayoutProperty(klr, kKLKCHRData, &kchar);
+ KeyTranslate(kchar, (mods&0xff00) | keyCode, &ktState); // send the dead key
+ key = KeyTranslate(kchar, 0x31, &ktState); // fake a space key press
+ Fl::e_state |= 0x40000000; // mark this as a dead key
+ } else {
+ Fl::e_state &= 0xbfffffff; // clear the deadkey flag
+ }
+ sendEvent = FL_KEYBOARD;
+ // fall through
+ case kEventRawKeyUp:
+ if ( !sendEvent ) {
+ sendEvent = FL_KEYUP;
+ Fl::e_state &= 0xbfffffff; // clear the deadkey flag
+ }
+ // if the user pressed alt/option, event_key should have the keycap,
+ // but event_text should generate the international symbol
+ sym = macKeyLookUp[ maskedKeyCode ];
+ if ( isalpha(key) )
+ sym = tolower(key);
+ else if ( Fl::e_state&FL_CTRL && key<32 && sym<0xff00)
+ sym = key+96;
+ else if ( Fl::e_state&FL_ALT && sym<0xff00) // find the keycap of this key
+ sym = keycode_to_sym( maskedKeyCode, 0, macKeyLookUp[ maskedKeyCode ] );
+ Fl::e_keysym = Fl::e_original_keysym = sym;
+ // Handle FL_KP_Enter on regular keyboards and on Powerbooks
+ if ( maskedKeyCode==0x4c || maskedKeyCode==0x34) key=0x0d;
+ // Matt: the Mac has no concept of a NumLock key, or at least not visible
+ // Matt: to Carbon. The kEventKeyModifierNumLockMask is only set when
+ // Matt: a numeric keypad key is pressed and does not correspond with
+ // Matt: the NumLock light in PowerBook keyboards.
+ if ( (sym >= FL_KP && sym <= FL_KP_Last) || !(sym & 0xff00) ||
+ sym == FL_Tab || sym == FL_Enter) {
+ buffer[0] = key;
+ Fl::e_length = 1;
+ } else {
+ buffer[0] = 0;
+ Fl::e_length = 0;
+ }
+ Fl::e_text = buffer;
+ // insert UnicodeHandling here!
+ break;
+ case kEventRawKeyModifiersChanged: {
+ UInt32 tMods = prevMods ^ mods;
+ if ( tMods )
+ {
+ mods_to_e_keysym( tMods );
+ if ( Fl::e_keysym )
+ sendEvent = ( prevMods<mods ) ? FL_KEYBOARD : FL_KEYUP;
+ Fl::e_length = 0;
+ buffer[0] = 0;
+ prevMods = mods;
+ }
+ mods_to_e_state( mods );
+ break; }
+ }
+ while (window->parent()) window = window->window();
+ if (sendEvent && Fl::handle(sendEvent,window)) {
+ fl_unlock_function();
+ return noErr; // return noErr if FLTK handled the event
+ } else {
+ fl_unlock_function();
+ //return CallNextEventHandler( nextHandler, event );;
+ // Matt: I had better results (no duplicate events) always returning
+ // Matt: 'noErr'. System keyboard events still seem to work just fine.
+ return noErr;
+ }
+}
+
+
+
+/**
+ * Open callback function to call...
+ */
+
+static void (*open_cb)(const char *) = 0;
+
+
+/**
+ * Event handler for Apple-O key combination and also for file opens
+ * via the finder...
+ */
+
+static OSErr OpenAppleEventHandler(const AppleEvent *appleEvt,
+ AppleEvent *reply,
+ UInt32 refcon) {
+ OSErr err;
+ AEDescList documents;
+ long i, n;
+ FSSpec fileSpec;
+ AEKeyword keyWd;
+ DescType typeCd;
+ Size actSz;
+ char filename[1024];
+
+ if (!open_cb) return noErr;
+
+ // Initialize the document list...
+ AECreateDesc(typeNull, NULL, 0, &documents);
+
+ // Get the open parameter(s)...
+ err = AEGetParamDesc(appleEvt, keyDirectObject, typeAEList, &documents);
+ if (err != noErr) {
+ AEDisposeDesc(&documents);
+ return err;
+ }
+
+ // Lock access to FLTK in this thread...
+ fl_lock_function();
+
+ // Open the documents via the callback...
+ if (AECountItems(&documents, &n) == noErr) {
+ for (i = 1; i <= n; i ++) {
+ // Get the next FSSpec record...
+ AEGetNthPtr(&documents, i, typeFSS, &keyWd, &typeCd,
+ (Ptr)&fileSpec, sizeof(fileSpec),
+ (actSz = sizeof(fileSpec), &actSz));
+
+ // Convert to a UNIX path...
+ FSSpec2UnixPath(&fileSpec, filename);
+
+ // Call the callback with the filename...
+ (*open_cb)(filename);
+ }
+ }
+
+ // Unlock access to FLTK for all threads...
+ fl_unlock_function();
+
+ // Get rid of the document list...
+ AEDisposeDesc(&documents);
+
+ return noErr;
+}
+
+
+/**
+ * Install an open documents event handler...
+ */
+
+void fl_open_callback(void (*cb)(const char *)) {
+ open_cb = cb;
+ if (cb) {
+ AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
+ NewAEEventHandlerUPP((AEEventHandlerProcPtr)
+ OpenAppleEventHandler), 0, false);
+ } else {
+ AERemoveEventHandler(kCoreEventClass, kAEOpenDocuments,
+ NewAEEventHandlerUPP((AEEventHandlerProcPtr)
+ OpenAppleEventHandler), false);
+ }
+}
+
+
+/**
+ * initialize the Mac toolboxes, dock status, and set the default menubar
+ */
+
+extern "C" {
+ extern OSErr CPSEnableForegroundOperation(ProcessSerialNumber *psn, UInt32 _arg2,
+ UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
+}
+
+void fl_open_display() {
+ static char beenHereDoneThat = 0;
+ if ( !beenHereDoneThat ) {
+ beenHereDoneThat = 1;
+
+ FlushEvents(everyEvent,0);
+
+ MoreMasters(); // \todo Carbon suggests MoreMasterPointers()
+ AEInstallEventHandler( kCoreEventClass, kAEQuitApplication, NewAEEventHandlerUPP((AEEventHandlerProcPtr)QuitAppleEventHandler), 0, false );
+
+ // create the Mac Handle for the default cursor (a pointer to a pointer)
+ GetQDGlobalsArrow(&default_cursor);
+ default_cursor_ptr = &default_cursor;
+ fl_default_cursor = &default_cursor_ptr;
+
+ ClearMenuBar();
+ AppendResMenu( GetMenuHandle( 1 ), 'DRVR' );
+ DrawMenuBar();
+
+ // bring the application into foreground without a 'CARB' resource
+ Boolean same_psn;
+ ProcessSerialNumber cur_psn, front_psn;
+ if( !GetCurrentProcess( &cur_psn ) && !GetFrontProcess( &front_psn ) &&
+ !SameProcess( &front_psn, &cur_psn, &same_psn ) && !same_psn )
+ {
+ // only transform the application type for unbundled apps
+ CFBundleRef bundle = CFBundleGetMainBundle();
+ if( bundle )
+ {
+ FSRef execFs;
+ CFURLRef execUrl = CFBundleCopyExecutableURL( bundle );
+ CFURLGetFSRef( execUrl, &execFs );
+
+ FSRef bundleFs;
+ GetProcessBundleLocation( &cur_psn, &bundleFs );
+
+ if( !FSCompareFSRefs( &execFs, &bundleFs ) )
+ bundle = NULL;
+
+ CFRelease(execUrl);
+ }
+
+ if( !bundle )
+ {
+ // Earlier versions of this code tried to use weak linking, however it
+ // appears that this does not work on 10.2. Since 10.3 and higher provide
+ // both TransformProcessType and CPSEnableForegroundOperation, the following
+ // conditional code compiled on 10.2 will still work on newer releases...
+ OSErr err;
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
+ if (TransformProcessType != NULL) {
+ err = TransformProcessType(&cur_psn, kProcessTransformToForegroundApplication);
+ } else
+#endif // MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
+ err = CPSEnableForegroundOperation(&cur_psn, 0x03, 0x3C, 0x2C, 0x1103);
+
+ if (err == noErr) {
+ SetFrontProcess( &cur_psn );
+ }
+ }
+ }
+ }
+}
+
+
+/**
+ * get rid of allocated resources
+ */
+void fl_close_display() {
+}
+
+
+/**
+ * smallest x ccordinate in screen space
+ */
+int Fl::x() {
+ BitMap r;
+ GetQDGlobalsScreenBits(&r);
+ return r.bounds.left;
+}
+
+
+/**
+ * smallest y ccordinate in screen space
+ */
+int Fl::y() {
+ BitMap r;
+ GetQDGlobalsScreenBits(&r);
+ return r.bounds.top + 20; // \todo 20 pixel menu bar?
+}
+
+
+/**
+ * screen width (single monitor!?)
+ */
+int Fl::w() {
+ BitMap r;
+ GetQDGlobalsScreenBits(&r);
+ return r.bounds.right - r.bounds.left;
+}
+
+
+/**
+ * screen height (single monitor!?)
+ */
+int Fl::h() {
+ BitMap r;
+ GetQDGlobalsScreenBits(&r);
+ return r.bounds.bottom - r.bounds.top - 20;
+}
+
+
+/**
+ * get the current mouse pointer world coordinates
+ */
+void Fl::get_mouse(int &x, int &y)
+{
+ fl_open_display();
+ Point loc;
+ GetMouse( &loc );
+ LocalToGlobal( &loc );
+ x = loc.h;
+ y = loc.v;
+}
+
+
+/**
+ * convert Mac keystrokes to FLTK
+ */
+unsigned short mac2fltk(ulong macKey)
+{
+ unsigned short cc = macKeyLookUp[(macKey>>8)&0x7f];
+ if (cc) return cc;
+ return macKey&0xff;
+}
+
+
+/**
+ * Initialize the given port for redraw and call the windw's flush() to actually draw the content
+ */
+void Fl_X::flush()
+{
+ w->flush();
+#ifdef __APPLE_QD__
+ GrafPtr port;
+ GetPort( &port );
+ if ( port )
+ QDFlushPortBuffer( port, 0 );
+#elif defined (__APPLE_QUARTZ__)
+ if (fl_gc)
+ CGContextFlush(fl_gc);
+#endif
+ SetOrigin( 0, 0 );
+}
+
+
+/**
+ * Handle all clipping and redraw for the given port
+ * There are two different callers for this event:
+ * 1: the OS can request a redraw and provides all clipping itself
+ * 2: Fl::flush() wants all redraws now
+ */
+void handleUpdateEvent( WindowPtr xid )
+{
+ Fl_Window *window = fl_find( xid );
+ if ( !window ) return;
+ GrafPtr oldPort;
+ GetPort( &oldPort );
+ SetPort( GetWindowPort(xid) );
+ Fl_X *i = Fl_X::i( window );
+ i->wait_for_expose = 0;
+ if ( window->damage() ) {
+ if ( i->region ) {
+ InvalWindowRgn( xid, i->region );
+ }
+ }
+ if ( i->region ) { // no region, so the sytem will take the update region from the OS
+ DisposeRgn( i->region );
+ i->region = 0;
+ }
+ for ( Fl_X *cx = i->xidChildren; cx; cx = cx->xidNext )
+ {
+ cx->w->clear_damage(window->damage()|FL_DAMAGE_EXPOSE);
+ cx->flush();
+ cx->w->clear_damage();
+ }
+ window->clear_damage(window->damage()|FL_DAMAGE_EXPOSE);
+ i->flush();
+ window->clear_damage();
+ SetPort( oldPort );
+}
+
+
+/**
+ * \todo this is a leftover from OS9 times. Please check how much applies to Carbon!
+ */
+int Fl_X::fake_X_wm(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, int &by) {
+ int W, H, xoff, yoff, dx, dy;
+ int ret = bx = by = bt = 0;
+ if (w->border() && !w->parent()) {
+ if (w->maxw != w->minw || w->maxh != w->minh) {
+ ret = 2;
+ bx = 6; // \todo Mac : GetSystemMetrics(SM_CXSIZEFRAME);
+ by = 6; // \todo Mac : get Mac window frame size GetSystemMetrics(SM_CYSIZEFRAME);
+ } else {
+ ret = 1;
+ bx = 6; // \todo Mac : GetSystemMetrics(SM_CXFIXEDFRAME);
+ by = 6; // \todo Mac : GetSystemMetrics(SM_CYFIXEDFRAME);
+ }
+ bt = 22; // \todo Mac : GetSystemMetrics(SM_CYCAPTION);
+ }
+ //The coordinates of the whole window, including non-client area
+ xoff = bx;
+ yoff = by + bt;
+ dx = 2*bx;
+ dy = 2*by + bt;
+ X = w->x()-xoff;
+ Y = w->y()-yoff;
+ W = w->w()+dx;
+ H = w->h()+dy;
+
+ //Proceed to positioning the window fully inside the screen, if possible
+
+ // let's get a little elaborate here. Mac OS X puts a lot of stuff on the desk
+ // that we want to avoid when positioning our window, namely the Dock and the
+ // top menu bar (and even more stuff in 10.4 Tiger). So we will go through the
+ // list of all available screens and find the one that this window is most
+ // likely to go to, and then reposition it to fit withing the 'good' area.
+ Rect r;
+ // find the screen, that the center of this window will fall into
+ int R = X+W, B = Y+H; // right and bottom
+ int cx = (X+R)/2, cy = (Y+B)/2; // center of window;
+ GDHandle gd = 0L;
+ for (gd = GetDeviceList(); gd; gd = GetNextDevice(gd)) {
+ GDPtr gp = *gd;
+ if ( cx >= gp->gdRect.left && cx <= gp->gdRect.right
+ && cy >= gp->gdRect.top && cy <= gp->gdRect.bottom)
+ break;
+ }
+ // if the center doesn't fall on a screen, try the top left
+ if (!gd) {
+ for (gd = GetDeviceList(); gd; gd = GetNextDevice(gd)) {
+ GDPtr gp = *gd;
+ if ( X >= gp->gdRect.left && X <= gp->gdRect.right
+ && Y >= gp->gdRect.top && Y <= gp->gdRect.bottom)
+ break;
+ }
+ }
+ // if that doesn't fall on a screen, try the top right
+ if (!gd) {
+ for (gd = GetDeviceList(); gd; gd = GetNextDevice(gd)) {
+ GDPtr gp = *gd;
+ if ( R >= gp->gdRect.left && R <= gp->gdRect.right
+ && Y >= gp->gdRect.top && Y <= gp->gdRect.bottom)
+ break;
+ }
+ }
+ // if that doesn't fall on a screen, try the bottom left
+ if (!gd) {
+ for (gd = GetDeviceList(); gd; gd = GetNextDevice(gd)) {
+ GDPtr gp = *gd;
+ if ( X >= gp->gdRect.left && X <= gp->gdRect.right
+ && B >= gp->gdRect.top && B <= gp->gdRect.bottom)
+ break;
+ }
+ }
+ // last resort, try the bottom right
+ if (!gd) {
+ for (gd = GetDeviceList(); gd; gd = GetNextDevice(gd)) {
+ GDPtr gp = *gd;
+ if ( R >= gp->gdRect.left && R <= gp->gdRect.right
+ && B >= gp->gdRect.top && B <= gp->gdRect.bottom)
+ break;
+ }
+ }
+ // if we still have not found a screen, we will use the main
+ // screen, the one that has the application menu bar.
+ if (!gd) gd = GetMainDevice();
+ if (gd) {
+ GetAvailableWindowPositioningBounds(gd, &r);
+ if ( R > r.right ) X -= R - r.right;
+ if ( B > r.bottom ) Y -= B - r.bottom;
+ if ( X < r.left ) X = r.left;
+ if ( Y < r.top ) Y = r.top;
+ }
+
+ //Return the client area's top left corner in (X,Y)
+ X+=xoff;
+ Y+=yoff;
+
+ return ret;
+}
+
+/**
+ * convert a Mac FSSpec structure into a Unix filename
+ */
+static int FSSpec2UnixPath( FSSpec *fs, char *dst )
+{
+ FSRef fsRef;
+ FSpMakeFSRef( fs, &fsRef );
+ FSRefMakePath( &fsRef, (UInt8*)dst, 1024 );
+ return strlen(dst);
+}
+
+static DragReference currDragRef = 0;
+static char *currDragData = 0L;
+static int currDragSize = 0;
+static OSErr currDragErr = noErr;
+Fl_Window *fl_dnd_target_window = 0;
+#include <FL/fl_draw.H>
+
+/**
+ * Fill the currDrag* variables with the current DnD ASCII text.
+ */
+static OSErr fillCurrentDragData(DragReference dragRef)
+{
+ OSErr ret = noErr;
+ char *dst = 0L;
+
+ // shortcut through this whole procedure if this is still the same drag event
+ if (dragRef==currDragRef)
+ return currDragErr;
+
+ // clear currDrag* for a new drag event
+ currDragRef = dragRef;
+ if (currDragData) free(currDragData);
+ currDragData = 0;
+ currDragSize = 0;
+
+ // fill currDRag* with ASCII data, if available
+ UInt16 i, nItem;
+ ItemReference itemRef;
+ FlavorFlags flags;
+ Size itemSize, size = 0;
+ CountDragItems( dragRef, &nItem );
+ for ( i = 1; i <= nItem; i++ )
+ {
+ GetDragItemReferenceNumber( dragRef, i, &itemRef );
+ ret = GetFlavorFlags( dragRef, itemRef, 'TEXT', &flags );
+ if ( ret == noErr )
+ {
+ GetFlavorDataSize( dragRef, itemRef, 'TEXT', &itemSize );
+ size += itemSize;
+ }
+ ret = GetFlavorFlags( dragRef, itemRef, 'hfs ', &flags );
+ if ( ret == noErr )
+ {
+ size += 1024; //++ ouch! We should create the full pathname and figure out its length
+ }
+ }
+
+ if ( !size )
+ {
+ currDragErr = userCanceledErr;
+ return currDragErr;
+ }
+
+ currDragSize = size + nItem - 1;
+ currDragData = dst = (char*)malloc( size+nItem );;
+
+ for ( i = 1; i <= nItem; i++ )
+ {
+ GetDragItemReferenceNumber( dragRef, i, &itemRef );
+ ret = GetFlavorFlags( dragRef, itemRef, 'TEXT', &flags );
+ if ( ret == noErr )
+ {
+ GetFlavorDataSize( dragRef, itemRef, 'TEXT', &itemSize );
+ GetFlavorData( dragRef, itemRef, 'TEXT', dst, &itemSize, 0L );
+ dst += itemSize;
+ *dst++ = '\n'; // add our element seperator
+ }
+ ret = GetFlavorFlags( dragRef, itemRef, 'hfs ', &flags );
+ if ( ret == noErr )
+ {
+ HFSFlavor hfs; itemSize = sizeof( hfs );
+ GetFlavorData( dragRef, itemRef, 'hfs ', &hfs, &itemSize, 0L );
+ itemSize = FSSpec2UnixPath( &hfs.fileSpec, dst );
+ dst += itemSize;
+ if ( itemSize>1 && ( hfs.fileType=='fold' || hfs.fileType=='disk' ) )
+ *dst++ = '/';
+ *dst++ = '\n'; // add our element seperator
+ }
+ }
+
+ dst[-1] = 0;
+ currDragSize = dst - currDragData - 1;
+ currDragErr = ret;
+ return ret;
+}
+
+/**
+ * Drag'n'drop tracking handler
+ */
+static pascal OSErr dndTrackingHandler( DragTrackingMessage msg, WindowPtr w, void *userData, DragReference dragRef )
+{
+ Fl_Window *target = (Fl_Window*)userData;
+ Fl::first_window(target);
+ Point mp;
+ static int px, py;
+
+ fillCurrentDragData(dragRef);
+ Fl::e_length = currDragSize;
+ Fl::e_text = currDragData;
+
+ switch ( msg )
+ {
+ case kDragTrackingEnterWindow:
+ // check if 'TEXT' is available
+ GetDragMouse( dragRef, &mp, 0 );
+ Fl::e_x_root = px = mp.h;
+ Fl::e_y_root = py = mp.v;
+ Fl::e_x = px - target->x();
+ Fl::e_y = py - target->y();
+ fl_dnd_target_window = target;
+ if ( Fl::handle( FL_DND_ENTER, target ) )
+ fl_cursor( FL_CURSOR_HAND ); //ShowDragHilite( ); // modify the mouse cursor?!
+ else
+ fl_cursor( FL_CURSOR_DEFAULT ); //HideDragHilite( dragRef );
+ breakMacEventLoop();
+ return noErr;
+ case kDragTrackingInWindow:
+ GetDragMouse( dragRef, &mp, 0 );
+ if ( mp.h==px && mp.v==py )
+ break; //+ return previous condition for dnd hiliting
+ Fl::e_x_root = px = mp.h;
+ Fl::e_y_root = py = mp.v;
+ Fl::e_x = px - target->x();
+ Fl::e_y = py - target->y();
+ fl_dnd_target_window = target;
+ if ( Fl::handle( FL_DND_DRAG, target ) )
+ fl_cursor( FL_CURSOR_HAND ); //ShowDragHilite( ); // modify the mouse cursor?!
+ else
+ fl_cursor( FL_CURSOR_DEFAULT ); //HideDragHilite( dragRef );
+ breakMacEventLoop();
+ return noErr;
+ break;
+ case kDragTrackingLeaveWindow:
+ // HideDragHilite()
+ fl_cursor( FL_CURSOR_DEFAULT ); //HideDragHilite( dragRef );
+ if ( fl_dnd_target_window )
+ {
+ Fl::handle( FL_DND_LEAVE, fl_dnd_target_window );
+ fl_dnd_target_window = 0;
+ }
+ breakMacEventLoop();
+ return noErr;
+ }
+ return noErr;
+}
+
+
+/**
+ * Drag'n'drop receive handler
+ */
+static pascal OSErr dndReceiveHandler( WindowPtr w, void *userData, DragReference dragRef )
+{
+ Point mp;
+ OSErr ret;
+
+ Fl_Window *target = fl_dnd_target_window = (Fl_Window*)userData;
+ Fl::first_window(target);
+ GetDragMouse( dragRef, &mp, 0 );
+ Fl::e_x_root = mp.h;
+ Fl::e_y_root = mp.v;
+ Fl::e_x = Fl::e_x_root - target->x();
+ Fl::e_y = Fl::e_y_root - target->y();
+ if ( !Fl::handle( FL_DND_RELEASE, target ) )
+ return userCanceledErr;
+
+ ret = fillCurrentDragData(dragRef);
+ if (ret==userCanceledErr)
+ return userCanceledErr;
+
+ Fl::e_length = currDragSize;
+ Fl::e_text = currDragData;
+// printf("Sending following text to widget %p:\n%s\n", Fl::belowmouse(), Fl::e_text);
+ int old_event = Fl::e_number;
+ Fl::belowmouse()->handle(Fl::e_number = FL_PASTE);
+ Fl::e_number = old_event;
+
+ if (currDragData) {
+ free(currDragData);
+ }
+ currDragData = 0L;
+ currDragRef = 0;
+ Fl::e_text = 0L;
+ Fl::e_length = 0;
+ fl_dnd_target_window = 0L;
+
+ breakMacEventLoop();
+ return noErr;
+}
+
+
+/**
+ * go ahead, create that (sub)window
+ * \todo we should make menu windows slightly transparent for the new Mac look
+ */
+void Fl_X::make(Fl_Window* w)
+{
+ static int xyPos = 100;
+ if ( w->parent() ) // create a subwindow
+ {
+ Fl_Group::current(0);
+ Rect wRect;
+ wRect.top = w->y();
+ wRect.left = w->x();
+ wRect.bottom = w->y() + w->h(); if (wRect.bottom<=wRect.top) wRect.bottom = wRect.top+1;
+ wRect.right = w->x() + w->w(); if (wRect.right<=wRect.left) wRect.right = wRect.left+1;
+ // our subwindow needs this structure to know about its clipping.
+ Fl_X* x = new Fl_X;
+ x->other_xid = 0;
+ x->region = 0;
+ x->subRegion = 0;
+ x->cursor = fl_default_cursor;
+ x->gc = 0; // stay 0 for Quickdraw; fill with CGContext for Quartz
+ Fl_Window *win = w->window();
+ Fl_X *xo = Fl_X::i(win);
+ if (xo) {
+ x->xidNext = xo->xidChildren;
+ x->xidChildren = 0L;
+ xo->xidChildren = x;
+ x->xid = fl_xid(win);
+ x->w = w; w->i = x;
+ x->wait_for_expose = 0;
+ x->next = Fl_X::first; // must be in the list for ::flush()
+ Fl_X::first = x;
+ int old_event = Fl::e_number;
+ w->handle(Fl::e_number = FL_SHOW);
+ Fl::e_number = old_event;
+ w->redraw(); // force draw to happen
+ }
+ fl_show_iconic = 0;
+ }
+ else // create a desktop window
+ {
+ Fl_Group::current(0);
+ fl_open_display();
+ int winclass = kDocumentWindowClass;
+ int winattr = kWindowStandardHandlerAttribute | kWindowCloseBoxAttribute | kWindowCollapseBoxAttribute;
+ int xp = w->x();
+ int yp = w->y();
+ int wp = w->w();
+ int hp = w->h();
+ if (w->size_range_set) {
+ if ( w->minh != w->maxh || w->minw != w->maxw)
+ winattr |= kWindowFullZoomAttribute | kWindowResizableAttribute | kWindowLiveResizeAttribute;
+ } else {
+ if (w->resizable()) {
+ Fl_Widget *o = w->resizable();
+ int minw = o->w(); if (minw > 100) minw = 100;
+ int minh = o->h(); if (minh > 100) minh = 100;
+ w->size_range(w->w() - o->w() + minw, w->h() - o->h() + minh, 0, 0);
+ winattr |= kWindowFullZoomAttribute | kWindowResizableAttribute | kWindowLiveResizeAttribute;
+ } else {
+ w->size_range(w->w(), w->h(), w->w(), w->h());
+ }
+ }
+ int xwm = xp, ywm = yp, bt, bx, by;
+
+ if (!fake_X_wm(w, xwm, ywm, bt, bx, by)) {
+ // menu windows and tooltips
+ if (w->modal()||w->override()) {
+ winclass = kHelpWindowClass;
+ winattr = 0;
+ } else {
+ winattr = 512; // kWindowNoTitleBarAttribute;
+ }
+ } else if (w->modal()) {
+ winclass = kMovableModalWindowClass;
+ }
+
+ if (by+bt) {
+ wp += 2*bx;
+ hp += 2*by+bt;
+ }
+ if (!(w->flags() & Fl_Window::FL_FORCE_POSITION)) {
+ // use the Carbon functions below for default window positioning
+ w->x(xyPos+Fl::x());
+ w->y(xyPos+Fl::y());
+ xyPos += 25;
+ if (xyPos>200) xyPos = 100;
+ } else {
+ if (!Fl::grab()) {
+ xp = xwm; yp = ywm;
+ w->x(xp);w->y(yp);
+ }
+ xp -= bx;
+ yp -= by+bt;
+ }
+
+ if (w->non_modal() && Fl_X::first && !fl_disable_transient_for) {
+ // find some other window to be "transient for":
+ Fl_Window* w = Fl_X::first->w;
+ while (w->parent()) w = w->window(); // todo: this code does not make any sense! (w!=w??)
+ }
+
+ Rect wRect;
+ wRect.top = w->y();
+ wRect.left = w->x();
+ wRect.bottom = w->y() + w->h(); if (wRect.bottom<=wRect.top) wRect.bottom = wRect.top+1;
+ wRect.right = w->x() + w->w(); if (wRect.right<=wRect.left) wRect.right = wRect.left+1;
+
+ const char *name = w->label();
+ Str255 pTitle;
+ if (name) {
+ if (strlen(name) > 255) pTitle[0] = 255;
+ else pTitle[0] = strlen(name);
+
+ memcpy(pTitle+1, name, pTitle[0]);
+ } else pTitle[0] = 0;
+
+ Fl_X* x = new Fl_X;
+ x->other_xid = 0; // room for doublebuffering image map. On OS X this is only used by overlay windows
+ x->region = 0;
+ x->subRegion = 0;
+ x->cursor = fl_default_cursor;
+ x->xidChildren = 0;
+ x->xidNext = 0;
+ x->gc = 0;
+
+ winattr &= GetAvailableWindowAttributes( winclass ); // make sure that the window will open
+ CreateNewWindow( winclass, winattr, &wRect, &(x->xid) );
+ SetWTitle(x->xid, pTitle);
+ MoveWindow(x->xid, wRect.left, wRect.top, 1); // avoid Carbon Bug on old OS
+ if (w->non_modal() && !w->modal()) {
+ // Major kludge: this is to have the regular look, but stay above the document windows
+ SetWindowClass(x->xid, kFloatingWindowClass);
+ SetWindowActivationScope(x->xid, kWindowActivationScopeAll);
+ }
+ if (!(w->flags() & Fl_Window::FL_FORCE_POSITION))
+ {
+ WindowRef pw = Fl_X::first ? Fl_X::first->xid : 0 ;
+ if (w->modal()) {
+ RepositionWindow(x->xid, pw, kWindowAlertPositionOnParentWindowScreen);
+ } else if (w->non_modal()) {
+ RepositionWindow(x->xid, pw, kWindowCenterOnParentWindowScreen);
+ } else {
+ RepositionWindow(x->xid, pw, kWindowCascadeOnParentWindowScreen);
+ }
+ }
+ x->w = w; w->i = x;
+ x->wait_for_expose = 1;
+ x->next = Fl_X::first;
+ Fl_X::first = x;
+ { // Install Carbon Event handlers
+ OSStatus ret;
+ EventHandlerUPP mousewheelHandler = NewEventHandlerUPP( carbonMousewheelHandler ); // will not be disposed by Carbon...
+ static EventTypeSpec mousewheelEvents[] = {
+ { kEventClassMouse, kEventMouseWheelMoved } };
+ ret = InstallWindowEventHandler( x->xid, mousewheelHandler,
+ (int)(sizeof(mousewheelEvents)/sizeof(mousewheelEvents[0])),
+ mousewheelEvents, w, 0L );
+ EventHandlerUPP mouseHandler = NewEventHandlerUPP( carbonMouseHandler ); // will not be disposed by Carbon...
+ static EventTypeSpec mouseEvents[] = {
+ { kEventClassMouse, kEventMouseDown },
+ { kEventClassMouse, kEventMouseUp },
+ { kEventClassMouse, kEventMouseMoved },
+ { kEventClassMouse, kEventMouseDragged } };
+ ret = InstallWindowEventHandler( x->xid, mouseHandler, 4, mouseEvents, w, 0L );
+ EventHandlerUPP keyboardHandler = NewEventHandlerUPP( carbonKeyboardHandler ); // will not be disposed by Carbon...
+ static EventTypeSpec keyboardEvents[] = {
+ { kEventClassKeyboard, kEventRawKeyDown },
+ { kEventClassKeyboard, kEventRawKeyRepeat },
+ { kEventClassKeyboard, kEventRawKeyUp },
+ { kEventClassKeyboard, kEventRawKeyModifiersChanged } };
+ ret = InstallWindowEventHandler( x->xid, keyboardHandler, 4, keyboardEvents, w, 0L );
+ EventHandlerUPP windowHandler = NewEventHandlerUPP( carbonWindowHandler ); // will not be disposed by Carbon...
+ static EventTypeSpec windowEvents[] = {
+ { kEventClassWindow, kEventWindowDrawContent },
+ { kEventClassWindow, kEventWindowShown },
+ { kEventClassWindow, kEventWindowHidden },
+ { kEventClassWindow, kEventWindowActivated },
+ { kEventClassWindow, kEventWindowDeactivated },
+ { kEventClassWindow, kEventWindowClose },
+ { kEventClassWindow, kEventWindowCollapsed },
+ { kEventClassWindow, kEventWindowExpanded },
+ { kEventClassWindow, kEventWindowBoundsChanging },
+ { kEventClassWindow, kEventWindowBoundsChanged } };
+ ret = InstallWindowEventHandler( x->xid, windowHandler, 10, windowEvents, w, 0L );
+ ret = InstallTrackingHandler( dndTrackingHandler, x->xid, w );
+ ret = InstallReceiveHandler( dndReceiveHandler, x->xid, w );
+ }
+
+ if ( ! Fl_X::first->next ) // if this is the first window, we need to bring the application to the front
+ {
+ ProcessSerialNumber psn;
+ OSErr err = GetCurrentProcess( &psn );
+ if ( err==noErr ) SetFrontProcess( &psn );
+ }
+
+ if (w->size_range_set) w->size_range_();
+
+ if (winclass != kHelpWindowClass) {
+ Fl_Tooltip::enter(0);
+ }
+ if (w->size_range_set) w->size_range_();
+ ShowWindow(x->xid);
+ if (fl_show_iconic) {
+ fl_show_iconic = 0;
+ CollapseWindow( x->xid, true ); // \todo Mac ; untested
+ } else {
+ w->set_visible();
+ }
+
+ Rect rect;
+ GetWindowBounds(x->xid, kWindowContentRgn, &rect);
+ w->x(rect.left); w->y(rect.top);
+ w->w(rect.right-rect.left); w->h(rect.bottom-rect.top);
+
+ int old_event = Fl::e_number;
+ w->handle(Fl::e_number = FL_SHOW);
+ Fl::e_number = old_event;
+ w->redraw(); // force draw to happen
+
+ if (w->modal()) { Fl::modal_ = w; fl_fix_focus(); }
+ }
+}
+
+
+/**
+ * Tell the OS what window sizes we want to allow
+ */
+void Fl_Window::size_range_() {
+ size_range_set = 1;
+ HISize minSize = { minw, minh };
+ HISize maxSize = { maxw?maxw:32000, maxh?maxh:32000 };
+ if (i && i->xid)
+ SetWindowResizeLimits(i->xid, &minSize, &maxSize);
+}
+
+
+/**
+ * returns pointer to the filename, or null if name ends with ':'
+ */
+const char *fl_filename_name( const char *name )
+{
+ const char *p, *q;
+ if (!name) return (0);
+ for ( p = q = name ; *p ; )
+ {
+ if ( ( p[0] == ':' ) && ( p[1] == ':' ) )
+ {
+ q = p+2;
+ p++;
+ }
+ else if (p[0] == '/')
+ q = p + 1;
+ p++;
+ }
+ return q;
+}
+
+
+/**
+ * set the window title bar
+ * \todo make the titlebar icon work!
+ */
+void Fl_Window::label(const char *name,const char */*iname*/) {
+ Fl_Widget::label(name);
+ Str255 pTitle;
+
+ if (name) { pTitle[0] = strlen(name); memcpy(pTitle+1, name, pTitle[0]); }
+ else pTitle[0] = 0;
+
+ if (shown() || i) SetWTitle(fl_xid(this), pTitle);
+}
+
+
+/**
+ * make a window visible
+ */
+void Fl_Window::show() {
+ image(Fl::scheme_bg_);
+ if (Fl::scheme_bg_) {
+ labeltype(FL_NORMAL_LABEL);
+ align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE | FL_ALIGN_CLIP);
+ } else {
+ labeltype(FL_NO_LABEL);
+ }
+ Fl_Tooltip::exit(this);
+ if (!shown() || !i) {
+ Fl_X::make(this);
+ } else {
+ if ( !parent() )
+ {
+ if ( IsWindowCollapsed( i->xid ) ) CollapseWindow( i->xid, false );
+ if (!fl_capture) {
+ BringToFront(i->xid);
+ SelectWindow(i->xid);
+ }
+ }
+ }
+}
+
+
+/**
+ * resize a window
+ */
+void Fl_Window::resize(int X,int Y,int W,int H) {
+ if (W<=0) W = 1; // OS X does not like zero width windows
+ if (H<=0) H = 1;
+ int is_a_resize = (W != w() || H != h());
+// printf("Fl_Winodw::resize(X=%d, Y=%d, W=%d, H=%d), is_a_resize=%d, resize_from_system=%p, this=%p\n",
+// X, Y, W, H, is_a_resize, resize_from_system, this);
+ if (X != x() || Y != y()) set_flag(FL_FORCE_POSITION);
+ else if (!is_a_resize) return;
+ if ( (resize_from_system!=this) && (!parent()) && shown()) {
+ if (is_a_resize) {
+ if (resizable()) {
+ if (W<minw) minw = W; // user request for resize takes priority
+ if (W>maxw) maxw = W; // over a previously set size_range
+ if (H<minh) minh = H;
+ if (H>maxh) maxh = H;
+ size_range(minw, minh, maxw, maxh);
+ } else {
+ size_range(W, H, W, H);
+ }
+ Rect dim; dim.left=X; dim.top=Y; dim.right=X+W; dim.bottom=Y+H;
+ SetWindowBounds(i->xid, kWindowContentRgn, &dim);
+ Rect all; all.top=-32000; all.bottom=32000; all.left=-32000; all.right=32000;
+ InvalWindowRect( i->xid, &all );
+ } else {
+ MoveWindow(i->xid, X, Y, 0);
+ }
+ }
+ resize_from_system = 0;
+ if (is_a_resize) {
+ Fl_Group::resize(X,Y,W,H);
+ if (shown()) {
+ redraw();
+ }
+ } else {
+ x(X); y(Y);
+ }
+}
+
+
+/**
+ * make all drawing go into this window (called by subclass flush() impl.)
+ */
+void Fl_Window::make_current()
+{
+#ifdef __APPLE_QUARTZ__
+ OSStatus err;
+ Fl_X::q_release_context();
+#endif
+ if ( !fl_window_region )
+ fl_window_region = NewRgn();
+ fl_window = i->xid;
+ current_ = this;
+
+ SetPort( GetWindowPort(i->xid) ); // \todo check for the handling of doublebuffered windows
+
+ int xp = 0, yp = 0;
+ Fl_Window *win = this;
+ while ( win )
+ {
+ if ( !win->window() )
+ break;
+ xp += win->x();
+ yp += win->y();
+ win = (Fl_Window*)win->window();
+ }
+ SetOrigin( -xp, -yp );
+
+ SetRectRgn( fl_window_region, 0, 0, w(), h() );
+
+ // \todo for performance reasons: we don't have to create this unless the child windows moved
+ for ( Fl_X *cx = i->xidChildren; cx; cx = cx->xidNext )
+ {
+ Fl_Window *cw = cx->w;
+ if (!cw->visible_r()) continue;
+ Fl_Region r = NewRgn();
+ SetRectRgn( r, cw->x() - xp, cw->y() - yp,
+ cw->x() + cw->w() - xp, cw->y() + cw->h() - yp );
+ DiffRgn( fl_window_region, r, fl_window_region );
+ DisposeRgn( r );
+ }
+
+#ifdef __APPLE_QUARTZ__
+ err = QDBeginCGContext(GetWindowPort(i->xid), &i->gc);
+ if (err!=noErr)
+ fprintf(stderr, "Error %d in QDBeginCGContext\n", (int)err);
+ fl_gc = i->gc;
+ CGContextSaveGState(fl_gc);
+ Fl_X::q_fill_context();
+#endif
+ fl_clip_region( 0 );
+ SetPortClipRegion( GetWindowPort(i->xid), fl_window_region );
+ return;
+}
+
+// helper function to manage the current CGContext fl_gc
+#ifdef __APPLE_QUARTZ__
+extern Fl_Color fl_color_;
+extern class Fl_FontSize *fl_fontsize;
+extern void fl_font(class Fl_FontSize*);
+extern void fl_quartz_restore_line_style_();
+
+// FLTK has only one global graphics state. This function copies the FLTK state into the
+// current Quartz context
+void Fl_X::q_fill_context() {
+ if (!fl_gc) return;
+ int hgt = 0;
+ if (fl_window) {
+ Rect portRect;
+ GetPortBounds(GetWindowPort( fl_window ), &portRect);
+ hgt = portRect.bottom-portRect.top;
+ } else {
+ hgt = CGBitmapContextGetHeight(fl_gc);
+ }
+ CGContextTranslateCTM(fl_gc, 0.5, hgt-0.5f);
+ CGContextScaleCTM(fl_gc, 1.0f, -1.0f);
+ fl_font(fl_fontsize);
+ fl_color(fl_color_);
+ fl_quartz_restore_line_style_();
+}
+
+// The only way to reset clipping to its original state is to pop the current graphics
+// state and restore the global state.
+void Fl_X::q_clear_clipping() {
+ if (!fl_gc) return;
+ CGContextRestoreGState(fl_gc);
+ CGContextSaveGState(fl_gc);
+}
+
+// Give the Quartz context back to the system
+void Fl_X::q_release_context(Fl_X *x) {
+ if (x && x->gc!=fl_gc) return;
+ if (!fl_gc) return;
+ CGContextRestoreGState(fl_gc);
+ if (fl_window) {
+ OSStatus err = QDEndCGContext(GetWindowPort(fl_window), &fl_gc);
+ if (err!=noErr)
+ fprintf(stderr, "Error %d in QDEndCGContext\n", (int)err);
+ }
+ fl_gc = 0;
+}
+
+void Fl_X::q_begin_image(CGRect &rect, int cx, int cy, int w, int h) {
+ CGContextSaveGState(fl_gc);
+ CGAffineTransform mx = CGContextGetCTM(fl_gc);
+ CGRect r2 = rect;
+ r2.origin.x -= 0.5f;
+ r2.origin.y -= 0.5f;
+ CGContextClipToRect(fl_gc, r2);
+ mx.d = -1.0; mx.tx = -mx.tx;
+ CGContextConcatCTM(fl_gc, mx);
+ rect.origin.x = -(mx.tx+0.5f) + rect.origin.x - cx;
+ rect.origin.y = (mx.ty+0.5f) - rect.origin.y - h + cy;
+ rect.size.width = w;
+ rect.size.height = h;
+}
+
+void Fl_X::q_end_image() {
+ CGContextRestoreGState(fl_gc);
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////
+// Cut & paste.
+
+Fl_Widget *fl_selection_requestor = 0;
+char *fl_selection_buffer[2];
+int fl_selection_length[2];
+int fl_selection_buffer_length[2];
+static ScrapRef myScrap = 0;
+
+/**
+ * create a selection
+ * owner: widget that created the selection
+ * stuff: pointer to selected data
+ * size of selected data
+ */
+void Fl::copy(const char *stuff, int len, int clipboard) {
+ if (!stuff || len<0) return;
+ if (len+1 > fl_selection_buffer_length[clipboard]) {
+ delete[] fl_selection_buffer[clipboard];
+ fl_selection_buffer[clipboard] = new char[len+100];
+ fl_selection_buffer_length[clipboard] = len+100;
+ }
+ memcpy(fl_selection_buffer[clipboard], stuff, len);
+ fl_selection_buffer[clipboard][len] = 0; // needed for direct paste
+ fl_selection_length[clipboard] = len;
+ if (clipboard) {
+ ClearCurrentScrap();
+ OSStatus ret = GetCurrentScrap( &myScrap );
+ if ( ret != noErr ) {
+ myScrap = 0;
+ return;
+ }
+ // Previous version changed \n to \r before sending the text, but I would
+ // prefer to leave the local buffer alone, so a copied buffer may be
+ // needed. Check to see if this is necessary on OS/X.
+ PutScrapFlavor( myScrap, kScrapFlavorTypeText, 0,
+ len, fl_selection_buffer[1] );
+ }
+}
+
+// Call this when a "paste" operation happens:
+void Fl::paste(Fl_Widget &receiver, int clipboard) {
+ if (clipboard) {
+ // see if we own the selection, if not go get it:
+ ScrapRef scrap = 0;
+ Size len = 0;
+ if (GetCurrentScrap(&scrap) == noErr && scrap != myScrap &&
+ GetScrapFlavorSize(scrap, kScrapFlavorTypeText, &len) == noErr) {
+ if ( len >= fl_selection_buffer_length[1] ) {
+ fl_selection_buffer_length[1] = len + 32;
+ delete[] fl_selection_buffer[1];
+ fl_selection_buffer[1] = new char[len + 32];
+ }
+ fl_selection_length[1] = len; len++;
+ GetScrapFlavorData( scrap, kScrapFlavorTypeText, &len,
+ fl_selection_buffer[1] );
+ fl_selection_buffer[1][fl_selection_length[1]] = 0;
+ // turn all \r characters into \n:
+ for (int x = 0; x < len; x++) {
+ if (fl_selection_buffer[1][x] == '\r')
+ fl_selection_buffer[1][x] = '\n';
+ }
+ }
+ }
+ Fl::e_text = fl_selection_buffer[clipboard];
+ Fl::e_length = fl_selection_length[clipboard];
+ if (!Fl::e_text) Fl::e_text = (char *)"";
+ receiver.handle(FL_PASTE);
+ return;
+}
+
+void Fl::add_timeout(double time, Fl_Timeout_Handler cb, void* data)
+{
+ // check, if this timer slot exists already
+ for (int i = 0; i < mac_timer_used; ++i) {
+ MacTimeout& t = mac_timers[i];
+ // if so, simply change the fire interval
+ if (t.callback == cb && t.data == data) {
+ SetEventLoopTimerNextFireTime(t.timer, (EventTimerInterval)time);
+ t.pending = 1;
+ return;
+ }
+ }
+ // no existing timer to use. Create a new one:
+ int timer_id = -1;
+ // find an empty slot in the timer array
+ for (int i = 0; i < mac_timer_used; ++i) {
+ if ( !mac_timers[i].timer ) {
+ timer_id = i;
+ break;
+ }
+ }
+ // if there was no empty slot, append a new timer
+ if (timer_id == -1) {
+ // make space if needed
+ if (mac_timer_used == mac_timer_alloc) {
+ realloc_timers();
+ }
+ timer_id = mac_timer_used++;
+ }
+ // now install a brand new timer
+ MacTimeout& t = mac_timers[timer_id];
+ EventTimerInterval fireDelay = (EventTimerInterval)time;
+ EventLoopTimerUPP timerUPP = NewEventLoopTimerUPP(do_timer);
+ EventLoopTimerRef timerRef = 0;
+ OSStatus err = InstallEventLoopTimer(GetMainEventLoop(), fireDelay, 0, timerUPP, data, &timerRef);
+ if (err == noErr) {
+ t.callback = cb;
+ t.data = data;
+ t.timer = timerRef;
+ t.upp = timerUPP;
+ t.pending = 1;
+ } else {
+ if (timerRef)
+ RemoveEventLoopTimer(timerRef);
+ if (timerUPP)
+ DisposeEventLoopTimerUPP(timerUPP);
+ }
+}
+
+void Fl::repeat_timeout(double time, Fl_Timeout_Handler cb, void* data)
+{
+ // currently, repeat_timeout does not subtract the trigger time of the previous timer event as it should.
+ add_timeout(time, cb, data);
+}
+
+int Fl::has_timeout(Fl_Timeout_Handler cb, void* data)
+{
+ for (int i = 0; i < mac_timer_used; ++i) {
+ MacTimeout& t = mac_timers[i];
+ if (t.callback == cb && t.data == data && t.pending) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void Fl::remove_timeout(Fl_Timeout_Handler cb, void* data)
+{
+ for (int i = 0; i < mac_timer_used; ++i) {
+ MacTimeout& t = mac_timers[i];
+ if (t.callback == cb && ( t.data == data || data == NULL)) {
+ delete_timer(t);
+ }
+ }
+}
+
+int MacUnlinkWindow(Fl_X *ip, Fl_X *start) {
+ if (!ip) return 0;
+ if (start) {
+ Fl_X *pc = start;
+ while (pc) {
+ if (pc->xidNext == ip) {
+ pc->xidNext = ip->xidNext;
+ return 1;
+ }
+ if (pc->xidChildren) {
+ if (pc->xidChildren == ip) {
+ pc->xidChildren = ip->xidNext;
+ return 1;
+ }
+ if (MacUnlinkWindow(ip, pc->xidChildren))
+ return 1;
+ }
+ pc = pc->xidNext;
+ }
+ } else {
+ for ( Fl_X *pc = Fl_X::first; pc; pc = pc->next ) {
+ if (MacUnlinkWindow(ip, pc))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static void MacRelinkWindow(Fl_X *x, Fl_X *p) {
+ if (!x || !p) return;
+ // first, check if 'x' is already registered as a child of 'p'
+ for (Fl_X *i = p->xidChildren; i; i=i->xidNext) {
+ if (i == x) return;
+ }
+ // now add 'x' as the first child of 'p'
+ x->xidNext = p->xidChildren;
+ p->xidChildren = x;
+}
+
+void MacDestroyWindow(Fl_Window *w, WindowPtr p) {
+ MacUnmapWindow(w, p);
+ if (w && !w->parent() && p)
+ DisposeWindow(p);
+}
+
+void MacMapWindow(Fl_Window *w, WindowPtr p) {
+ if (w && p)
+ ShowWindow(p);
+ //+ link to window list
+ if (w && w->parent()) {
+ MacRelinkWindow(Fl_X::i(w), Fl_X::i(w->window()));
+ w->redraw();
+ }
+}
+
+void MacUnmapWindow(Fl_Window *w, WindowPtr p) {
+ if (w && !w->parent() && p)
+ HideWindow(p);
+ if (w && Fl_X::i(w))
+ MacUnlinkWindow(Fl_X::i(w));
+}
+
+//
+// End of "$Id: Fl_mac.cxx 6800 2009-06-28 21:54:59Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_own_colormap.cxx b/third_party/windows/fltk-1.1.10/src/Fl_own_colormap.cxx new file mode 100644 index 0000000..d7fdaec --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_own_colormap.cxx @@ -0,0 +1,83 @@ +//
+// "$Id: Fl_own_colormap.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Private colormap support for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Using the default system colormap can be a bad idea on PseudoColor
+// visuals, since typically every application uses the default colormap and
+// you can run out of colormap entries easily.
+//
+// The solution is to always create a new colormap on PseudoColor displays
+// and copy the first 16 colors from the default colormap so that we won't
+// get huge color changes when switching windows.
+
+#include <config.h>
+#include <FL/Fl.H>
+#include <FL/x.H>
+
+#ifdef WIN32
+// There is probably something relevant to do on MSWindows 8-bit displays
+// but I don't know what it is
+
+void Fl::own_colormap() {}
+
+#elif defined(__APPLE__)
+// MacOS X always provides a TrueColor interface...
+
+void Fl::own_colormap() {}
+#else
+// X version
+
+void Fl::own_colormap() {
+ fl_open_display();
+#if USE_COLORMAP
+ switch (fl_visual->c_class) {
+ case GrayScale :
+ case PseudoColor :
+ case DirectColor :
+ break;
+ default:
+ return; // don't do anything for non-colormapped visuals
+ }
+ int i;
+ XColor colors[16];
+ // Get the first 16 colors from the default colormap...
+ for (i = 0; i < 16; i ++) colors[i].pixel = i;
+ XQueryColors(fl_display, fl_colormap, colors, 16);
+ // Create a new colormap...
+ fl_colormap = XCreateColormap(fl_display,
+ RootWindow(fl_display,fl_screen),
+ fl_visual->visual, AllocNone);
+ // Copy those first 16 colors to our own colormap:
+ for (i = 0; i < 16; i ++)
+ XAllocColor(fl_display, fl_colormap, colors + i);
+#endif
+}
+
+#endif
+
+//
+// End of "$Id: Fl_own_colormap.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_visual.cxx b/third_party/windows/fltk-1.1.10/src/Fl_visual.cxx new file mode 100644 index 0000000..6a9ee85 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_visual.cxx @@ -0,0 +1,121 @@ +//
+// "$Id: Fl_visual.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Visual support for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Set the default visual according to passed switches:
+
+#include <config.h>
+#include <FL/Fl.H>
+#include <FL/x.H>
+
+#ifdef WIN32
+int Fl::visual(int flags) {
+ fl_GetDC(0);
+ if (flags & FL_DOUBLE) return 0;
+ if (!(flags & FL_INDEX) &&
+ GetDeviceCaps(fl_gc,BITSPIXEL) <= 8) return 0;
+ if ((flags & FL_RGB8) && GetDeviceCaps(fl_gc,BITSPIXEL)<24) return 0;
+ return 1;
+}
+#elif defined(__APPLE__)
+
+// \todo Mac : need to implement Visual flags
+int Fl::visual(int flags) {
+ (void)flags;
+ return 1;
+}
+
+#else
+
+#if USE_XDBE
+#include <X11/extensions/Xdbe.h>
+#endif
+
+static int test_visual(XVisualInfo& v, int flags) {
+ if (v.screen != fl_screen) return 0;
+#if USE_COLORMAP
+ if (!(flags & FL_INDEX)) {
+ if (v.c_class != StaticColor && v.c_class != TrueColor) return 0;
+ if (v.depth <= 8) return 0; // fltk will work better in colormap mode
+ }
+ if (flags & FL_RGB8) {
+ if (v.depth < 24) return 0;
+ }
+ // for now, fltk does not like colormaps of more than 8 bits:
+ if ((v.c_class&1) && v.depth > 8) return 0;
+#else
+ // simpler if we can't use colormapped visuals at all:
+ if (v.c_class != StaticColor && v.c_class != TrueColor) return 0;
+#endif
+#if USE_XDBE
+ if (flags & FL_DOUBLE) {
+ static XdbeScreenVisualInfo *xdbejunk;
+ if (!xdbejunk) {
+ int event_base, error_base;
+ if (!XdbeQueryExtension(fl_display, &event_base, &error_base)) return 0;
+ Drawable root = RootWindow(fl_display,fl_screen);
+ int numscreens = 1;
+ xdbejunk = XdbeGetVisualInfo(fl_display,&root,&numscreens);
+ if (!xdbejunk) return 0;
+ }
+ for (int j = 0; ; j++) {
+ if (j >= xdbejunk->count) return 0;
+ if (xdbejunk->visinfo[j].visual == v.visualid) break;
+ }
+ }
+#endif
+ return 1;
+}
+
+int Fl::visual(int flags) {
+#if USE_XDBE == 0
+ if (flags & FL_DOUBLE) return 0;
+#endif
+ fl_open_display();
+ // always use default if possible:
+ if (test_visual(*fl_visual, flags)) return 1;
+ // get all the visuals:
+ XVisualInfo vTemplate;
+ int num;
+ XVisualInfo *visualList = XGetVisualInfo(fl_display, 0, &vTemplate, &num);
+ // find all matches, use the one with greatest depth:
+ XVisualInfo *found = 0;
+ for (int i=0; i<num; i++) if (test_visual(visualList[i], flags)) {
+ if (!found || found->depth < visualList[i].depth)
+ found = &visualList[i];
+ }
+ if (!found) {XFree((void*)visualList); return 0;}
+ fl_visual = found;
+ fl_colormap = XCreateColormap(fl_display, RootWindow(fl_display,fl_screen),
+ fl_visual->visual, AllocNone);
+ return 1;
+}
+
+#endif
+
+//
+// End of "$Id: Fl_visual.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_win32.cxx b/third_party/windows/fltk-1.1.10/src/Fl_win32.cxx new file mode 100644 index 0000000..1df2671 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_win32.cxx @@ -0,0 +1,1728 @@ +//
+// "$Id: Fl_win32.cxx 6553 2008-12-07 11:05:41Z AlbrechtS $"
+//
+// WIN32-specific code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2007 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
+//
+
+// This file contains win32-specific code for fltk which is always linked
+// in. Search other files for "WIN32" or filenames ending in _win32.cxx
+// for other system-specific code.
+
+#include <FL/Fl.H>
+#include <FL/x.H>
+#include <FL/Fl_Window.H>
+#include <FL/Enumerations.H>
+#include <FL/Fl_Tooltip.H>
+#include "flstring.h"
+#include "Fl_Font.H"
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <time.h>
+#ifdef __CYGWIN__
+# include <sys/time.h>
+# include <unistd.h>
+#else
+# include <winsock.h>
+#endif
+#include <winuser.h>
+#include <commctrl.h>
+
+// The following include files require GCC 3.x or a non-GNU compiler...
+#if !defined(__GNUC__) || __GNUC__ >= 3
+# include <ole2.h>
+# include <shellapi.h>
+#endif // !__GNUC__ || __GNUC__ >= 3
+
+
+//
+// USE_ASYNC_SELECT - define it if you have WSAAsyncSelect()...
+//
+// This currently doesn't appear to work; needs to be fixed!
+//
+
+//#define USE_ASYNC_SELECT
+
+// USE_TRACK_MOUSE - define NO_TRACK_MOUSE if you don't have
+// TrackMouseEvent()...
+//
+// Now (Dec. 2008) we can assume that current Cygwin/MinGW versions
+// support the TrackMouseEvent() function, but WinCE obviously doesn't
+// support it (STR 2095). Therefore, USE_TRACK_MOUSE is enabled by
+// default, but you can disable it by defining NO_TRACK_MOUSE.
+//
+// TrackMouseEvent is only used to support window leave notifications
+// under Windows. It can be used to get FL_LEAVE events, when the
+// mouse leaves the _main_ application window (FLTK detects subwindow
+// leave events by using normal move events).
+//
+// Implementation note: If the mouse cursor leaves one subwindow and
+// enters another window, then Windows sends a WM_MOUSEMOVE message to
+// the new window before it sends a WM_MOUSELEAVE message to the old
+// (just left) window. We save the current mouse window in a static variable,
+// and if we get a WM_MOUSELEAVE event for the current mouse window, this
+// means that the top level window has been left (otherwise we would have
+// got another WM_MOUSEMOVE message before).
+
+// #define NO_TRACK_MOUSE
+
+#if !defined(NO_TRACK_MOUSE)
+# define USE_TRACK_MOUSE
+#endif // NO_TRACK_MOUSE
+
+static Fl_Window *track_mouse_win=0; // current TrackMouseEvent() window
+
+// USE_CAPTURE_MOUSE_WIN - this must be defined for TrackMouseEvent to work
+// correctly with subwindows - otherwise a single mouse click and release
+// (without a move) would generate phantom leave events.
+// This defines, if the current mouse window (maybe a subwindow) or the
+// main window should get mouse events after pushing (and holding) a mouse
+// button, i.e. when dragging the mouse. This is done by calling SetCapture
+// (see below).
+
+#ifdef USE_TRACK_MOUSE
+#define USE_CAPTURE_MOUSE_WIN
+#endif // USE_TRACK_MOUSE
+
+//
+// WM_SYNCPAINT is an "undocumented" message, which is finally defined in
+// VC++ 6.0.
+//
+
+#ifndef WM_SYNCPAINT
+# define WM_SYNCPAINT 0x0088
+#endif
+
+#ifndef WM_MOUSELEAVE
+# define WM_MOUSELEAVE 0x02a3
+#endif
+
+#ifndef WM_MOUSEWHEEL
+# define WM_MOUSEWHEEL 0x020a
+#endif
+
+#ifndef WHEEL_DELTA
+# define WHEEL_DELTA 120 // according to MSDN.
+#endif
+
+
+//
+// WM_FLSELECT is the user-defined message that we get when one of
+// the sockets has pending data, etc.
+//
+
+#define WM_FLSELECT (WM_APP+1) // WM_APP is used for hide-window
+
+
+////////////////////////////////////////////////////////////////
+// interface to poll/select call:
+
+// fd's are only implemented for sockets. Microsoft Windows does not
+// have a unified IO system, so it doesn't support select() on files,
+// devices, or pipes...
+//
+// Microsoft provides the Berkeley select() call and an asynchronous
+// select function that sends a WIN32 message when the select condition
+// exists...
+static int maxfd = 0;
+#ifndef USE_ASYNC_SELECT
+static fd_set fdsets[3];
+#endif // !USE_ASYNC_SELECT
+
+#define POLLIN 1
+#define POLLOUT 4
+#define POLLERR 8
+
+#if !defined(__GNUC__) || __GNUC__ >= 3
+extern IDropTarget *flIDropTarget;
+#endif // !__GNUC__ || __GNUC__ >= 3
+
+static int nfds = 0;
+static int fd_array_size = 0;
+static struct FD {
+ int fd;
+ short events;
+ void (*cb)(int, void*);
+ void* arg;
+} *fd = 0;
+
+void Fl::add_fd(int n, int events, void (*cb)(int, void*), void *v) {
+ remove_fd(n,events);
+ int i = nfds++;
+ if (i >= fd_array_size) {
+ fd_array_size = 2*fd_array_size+1;
+ fd = (FD*)realloc(fd, fd_array_size*sizeof(FD));
+ }
+ fd[i].fd = n;
+ fd[i].events = (short)events;
+ fd[i].cb = cb;
+ fd[i].arg = v;
+
+#ifdef USE_ASYNC_SELECT
+ int mask = 0;
+ if (events & POLLIN) mask |= FD_READ;
+ if (events & POLLOUT) mask |= FD_WRITE;
+ if (events & POLLERR) mask |= FD_CLOSE;
+ WSAAsyncSelect(n, fl_window, WM_FLSELECT, mask);
+#else
+ if (events & POLLIN) FD_SET((unsigned)n, &fdsets[0]);
+ if (events & POLLOUT) FD_SET((unsigned)n, &fdsets[1]);
+ if (events & POLLERR) FD_SET((unsigned)n, &fdsets[2]);
+ if (n > maxfd) maxfd = n;
+#endif // USE_ASYNC_SELECT
+}
+
+void Fl::add_fd(int fd, void (*cb)(int, void*), void* v) {
+ Fl::add_fd(fd, POLLIN, cb, v);
+}
+
+void Fl::remove_fd(int n, int events) {
+ int i,j;
+ for (i=j=0; i<nfds; i++) {
+ if (fd[i].fd == n) {
+ short e = fd[i].events & ~events;
+ if (!e) continue; // if no events left, delete this fd
+ fd[i].events = e;
+ }
+ // move it down in the array if necessary:
+ if (j<i) {
+ fd[j]=fd[i];
+ }
+ j++;
+ }
+ nfds = j;
+
+#ifdef USE_ASYNC_SELECT
+ WSAAsyncSelect(n, 0, 0, 0);
+#else
+ if (events & POLLIN) FD_CLR(unsigned(n), &fdsets[0]);
+ if (events & POLLOUT) FD_CLR(unsigned(n), &fdsets[1]);
+ if (events & POLLERR) FD_CLR(unsigned(n), &fdsets[2]);
+#endif // USE_ASYNC_SELECT
+}
+
+void Fl::remove_fd(int n) {
+ remove_fd(n, -1);
+}
+
+// these pointers are set by the Fl::lock() function:
+static void nothing() {}
+void (*fl_lock_function)() = nothing;
+void (*fl_unlock_function)() = nothing;
+
+static void* thread_message_;
+void* Fl::thread_message() {
+ void* r = thread_message_;
+ thread_message_ = 0;
+ return r;
+}
+
+MSG fl_msg;
+
+// This is never called with time_to_wait < 0.0.
+// It *should* return negative on error, 0 if nothing happens before
+// timeout, and >0 if any callbacks were done. This version only
+// returns zero if nothing happens during a 0.0 timeout, otherwise
+// it returns 1.
+int fl_wait(double time_to_wait) {
+ int have_message = 0;
+
+ run_checks();
+
+ // idle processing
+ static char in_idle;
+ if (Fl::idle && !in_idle) {
+ in_idle = 1;
+ Fl::idle();
+ in_idle = 0;
+ }
+
+#ifndef USE_ASYNC_SELECT
+ if (nfds) {
+ // For WIN32 we need to poll for socket input FIRST, since
+ // the event queue is not something we can select() on...
+ timeval t;
+ t.tv_sec = 0;
+ t.tv_usec = 0;
+
+ fd_set fdt[3];
+ fdt[0] = fdsets[0];
+ fdt[1] = fdsets[1];
+ fdt[2] = fdsets[2];
+ if (::select(maxfd+1,&fdt[0],&fdt[1],&fdt[2],&t)) {
+ // We got something - do the callback!
+ for (int i = 0; i < nfds; i ++) {
+ int f = fd[i].fd;
+ short revents = 0;
+ if (FD_ISSET(f,&fdt[0])) revents |= POLLIN;
+ if (FD_ISSET(f,&fdt[1])) revents |= POLLOUT;
+ if (FD_ISSET(f,&fdt[2])) revents |= POLLERR;
+ if (fd[i].events & revents) fd[i].cb(f, fd[i].arg);
+ }
+ time_to_wait = 0.0; // just peek for any messages
+ } else {
+ // we need to check them periodically, so set a short timeout:
+ if (time_to_wait > .001) time_to_wait = .001;
+ }
+ }
+#endif // USE_ASYNC_SELECT
+
+ if (Fl::idle || Fl::damage())
+ time_to_wait = 0.0;
+
+ // if there are no more windows and this timer is set
+ // to FOREVER, continue through or look up indefinetely
+ if (!Fl::first_window() && time_to_wait==1e20)
+ time_to_wait = 0.0;
+
+ fl_unlock_function();
+
+ time_to_wait = (time_to_wait > 10000 ? 10000 : time_to_wait);
+ int t_msec = (int) (time_to_wait * 1000.0 + 0.5);
+ MsgWaitForMultipleObjects(0, NULL, FALSE, t_msec, QS_ALLINPUT);
+
+ fl_lock_function();
+
+ // Execute the message we got, and all other pending messages:
+ have_message = PeekMessage(&fl_msg, NULL, 0, 0, PM_REMOVE);
+ if (have_message > 0) {
+ while (have_message != 0 && have_message != -1) {
+#ifdef USE_ASYNC_SELECT
+ if (fl_msg.message == WM_FLSELECT) {
+ // Got notification for socket
+ for (int i = 0; i < nfds; i ++)
+ if (fd[i].fd == (int)fl_msg.wParam) {
+ (fd[i].cb)(fd[i].fd, fd[i].arg);
+ break;
+ }
+ // looks like it is best to do the dispatch-message anyway:
+ }
+#endif
+
+ if (fl_msg.message == fl_wake_msg) {
+ // Used for awaking wait() from another thread
+ thread_message_ = (void*)fl_msg.wParam;
+ Fl_Awake_Handler func;
+ void *data;
+ while (Fl::get_awake_handler_(func, data)==0) {
+ func(data);
+ }
+ }
+
+ TranslateMessage(&fl_msg);
+ DispatchMessage(&fl_msg);
+ have_message = PeekMessage(&fl_msg, NULL, 0, 0, PM_REMOVE);
+ }
+ }
+ Fl::flush();
+
+ // This should return 0 if only timer events were handled:
+ return 1;
+}
+
+// fl_ready() is just like fl_wait(0.0) except no callbacks are done:
+int fl_ready() {
+ if (PeekMessage(&fl_msg, NULL, 0, 0, PM_NOREMOVE)) return 1;
+#ifdef USE_ASYNC_SELECT
+ return 0;
+#else
+ timeval t;
+ t.tv_sec = 0;
+ t.tv_usec = 0;
+ fd_set fdt[3];
+ fdt[0] = fdsets[0];
+ fdt[1] = fdsets[1];
+ fdt[2] = fdsets[2];
+ return ::select(0,&fdt[0],&fdt[1],&fdt[2],&t);
+#endif // USE_ASYNC_SELECT
+}
+
+////////////////////////////////////////////////////////////////
+
+int Fl::x()
+{
+ RECT r;
+
+ SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
+ return r.left;
+}
+
+int Fl::y()
+{
+ RECT r;
+
+ SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
+ return r.top;
+}
+
+int Fl::h()
+{
+ RECT r;
+
+ SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
+ return r.bottom - r.top;
+}
+
+int Fl::w()
+{
+ RECT r;
+
+ SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
+ return r.right - r.left;
+}
+
+void Fl::get_mouse(int &x, int &y) {
+ POINT p;
+ GetCursorPos(&p);
+ x = p.x;
+ y = p.y;
+}
+
+////////////////////////////////////////////////////////////////
+// code used for selections:
+
+char *fl_selection_buffer[2];
+int fl_selection_length[2];
+int fl_selection_buffer_length[2];
+char fl_i_own_selection[2];
+
+// Convert \n -> \r\n
+class Lf2CrlfConvert {
+ char *out;
+ int outlen;
+public:
+ Lf2CrlfConvert(const char *in, int inlen) {
+ outlen = 0;
+ const char *i;
+ char *o;
+ int lencount;
+ // Predict size of \r\n conversion buffer
+ for ( i=in, lencount = inlen; lencount--; ) {
+ if ( *i == '\r' && *(i+1) == '\n' ) // leave \r\n untranslated
+ { i+=2; outlen+=2; }
+ else if ( *i == '\n' ) // \n by itself? leave room to insert \r
+ { i++; outlen+=2; }
+ else
+ { ++i; ++outlen; }
+ }
+ // Alloc conversion buffer + NULL
+ out = new char[outlen+1];
+ // Handle \n -> \r\n conversion
+ for ( i=in, o=out, lencount = inlen; lencount--; ) {
+ if ( *i == '\r' && *(i+1) == '\n' ) // leave \r\n untranslated
+ { *o++ = *i++; *o++ = *i++; }
+ else if ( *i == '\n' ) // \n by itself? insert \r
+ { *o++ = '\r'; *o++ = *i++; }
+ else
+ { *o++ = *i++; }
+ }
+ *o++ = 0;
+ }
+ ~Lf2CrlfConvert() {
+ delete[] out;
+ }
+ int GetLength() const { return(outlen); }
+ const char* GetValue() const { return(out); }
+};
+
+// call this when you create a selection:
+void Fl::copy(const char *stuff, int len, int clipboard) {
+ if (!stuff || len<0) return;
+
+ // Convert \n -> \r\n (for old apps like Notepad, DOS)
+ Lf2CrlfConvert buf(stuff, len);
+ len = buf.GetLength();
+ stuff = buf.GetValue();
+
+ if (len+1 > fl_selection_buffer_length[clipboard]) {
+ delete[] fl_selection_buffer[clipboard];
+ fl_selection_buffer[clipboard] = new char[len+100];
+ fl_selection_buffer_length[clipboard] = len+100;
+ }
+ memcpy(fl_selection_buffer[clipboard], stuff, len);
+ fl_selection_buffer[clipboard][len] = 0; // needed for direct paste
+ fl_selection_length[clipboard] = len;
+ if (clipboard) {
+ // set up for "delayed rendering":
+ if (OpenClipboard(fl_xid(Fl::first_window()))) {
+ // if the system clipboard works, use it
+ EmptyClipboard();
+ SetClipboardData(CF_TEXT, NULL);
+ CloseClipboard();
+ fl_i_own_selection[clipboard] = 0;
+ } else {
+ // only if it fails, instruct paste() to use the internal buffers
+ fl_i_own_selection[clipboard] = 1;
+ }
+ }
+}
+
+// Call this when a "paste" operation happens:
+void Fl::paste(Fl_Widget &receiver, int clipboard) {
+ if (!clipboard || fl_i_own_selection[clipboard]) {
+ // We already have it, do it quickly without window server.
+ // Notice that the text is clobbered if set_selection is
+ // called in response to FL_PASTE!
+
+ // Convert \r\n -> \n
+ char *i = fl_selection_buffer[clipboard];
+ if (i==0L) {
+ Fl::e_text = 0;
+ return;
+ }
+ Fl::e_text = new char[fl_selection_length[clipboard]+1];
+ char *o = Fl::e_text;
+ while (*i) {
+ if ( *i == '\r' && *(i+1) == '\n') i++;
+ else *o++ = *i++;
+ }
+ *o = 0;
+ Fl::e_length = o - Fl::e_text;
+ receiver.handle(FL_PASTE);
+ delete [] Fl::e_text;
+ Fl::e_text = 0;
+ } else {
+ if (!OpenClipboard(NULL)) return;
+ HANDLE h = GetClipboardData(CF_TEXT);
+ if (h) {
+ Fl::e_text = (LPSTR)GlobalLock(h);
+ LPSTR a,b;
+ a = b = Fl::e_text;
+ while (*a) { // strip the CRLF pairs ($%$#@^)
+ if (*a == '\r' && a[1] == '\n') a++;
+ else *b++ = *a++;
+ }
+ *b = 0;
+ Fl::e_length = b - Fl::e_text;
+ receiver.handle(FL_PASTE);
+ GlobalUnlock(h);
+ }
+ CloseClipboard();
+ }
+}
+
+////////////////////////////////////////////////////////////////
+
+HWND fl_capture;
+
+static int mouse_event(Fl_Window *window, int what, int button,
+ WPARAM wParam, LPARAM lParam)
+{
+ static int px, py, pmx, pmy;
+ POINT pt;
+ Fl::e_x = pt.x = (signed short)LOWORD(lParam);
+ Fl::e_y = pt.y = (signed short)HIWORD(lParam);
+ ClientToScreen(fl_xid(window), &pt);
+ Fl::e_x_root = pt.x;
+ Fl::e_y_root = pt.y;
+#ifdef USE_CAPTURE_MOUSE_WIN
+ Fl_Window *mouse_window = window; // save "mouse window"
+#endif
+ while (window->parent()) {
+ Fl::e_x += window->x();
+ Fl::e_y += window->y();
+ window = window->window();
+ }
+
+ ulong state = Fl::e_state & 0xff0000; // keep shift key states
+#if 0
+ // mouse event reports some shift flags, perhaps save them?
+ if (wParam & MK_SHIFT) state |= FL_SHIFT;
+ if (wParam & MK_CONTROL) state |= FL_CTRL;
+#endif
+ if (wParam & MK_LBUTTON) state |= FL_BUTTON1;
+ if (wParam & MK_MBUTTON) state |= FL_BUTTON2;
+ if (wParam & MK_RBUTTON) state |= FL_BUTTON3;
+ Fl::e_state = state;
+
+ switch (what) {
+ case 1: // double-click
+ if (Fl::e_is_click) {Fl::e_clicks++; goto J1;}
+ case 0: // single-click
+ Fl::e_clicks = 0;
+ J1:
+#ifdef USE_CAPTURE_MOUSE_WIN
+ if (!fl_capture) SetCapture(fl_xid(mouse_window)); // use mouse window
+#else
+ if (!fl_capture) SetCapture(fl_xid(window)); // use main window
+#endif
+ Fl::e_keysym = FL_Button + button;
+ Fl::e_is_click = 1;
+ px = pmx = Fl::e_x_root; py = pmy = Fl::e_y_root;
+ return Fl::handle(FL_PUSH,window);
+
+ case 2: // release:
+ if (!fl_capture) ReleaseCapture();
+ Fl::e_keysym = FL_Button + button;
+ return Fl::handle(FL_RELEASE,window);
+
+ case 3: // move:
+ default: // avoid compiler warning
+ // MSWindows produces extra events even if mouse does not move, ignore em:
+ if (Fl::e_x_root == pmx && Fl::e_y_root == pmy) return 1;
+ pmx = Fl::e_x_root; pmy = Fl::e_y_root;
+ if (abs(Fl::e_x_root-px)>5 || abs(Fl::e_y_root-py)>5) Fl::e_is_click = 0;
+ return Fl::handle(FL_MOVE,window);
+
+ }
+}
+
+// convert a MSWindows VK_x to an Fltk (X) Keysym:
+// See also the inverse converter in Fl_get_key_win32.cxx
+// This table is in numeric order by VK:
+static const struct {unsigned short vk, fltk, extended;} vktab[] = {
+ {VK_BACK, FL_BackSpace},
+ {VK_TAB, FL_Tab},
+ {VK_CLEAR, FL_KP+'5', 0xff0b/*XK_Clear*/},
+ {VK_RETURN, FL_Enter, FL_KP_Enter},
+ {VK_SHIFT, FL_Shift_L, FL_Shift_R},
+ {VK_CONTROL, FL_Control_L, FL_Control_R},
+ {VK_MENU, FL_Alt_L, FL_Alt_R},
+ {VK_PAUSE, FL_Pause},
+ {VK_CAPITAL, FL_Caps_Lock},
+ {VK_ESCAPE, FL_Escape},
+ {VK_SPACE, ' '},
+ {VK_PRIOR, FL_KP+'9', FL_Page_Up},
+ {VK_NEXT, FL_KP+'3', FL_Page_Down},
+ {VK_END, FL_KP+'1', FL_End},
+ {VK_HOME, FL_KP+'7', FL_Home},
+ {VK_LEFT, FL_KP+'4', FL_Left},
+ {VK_UP, FL_KP+'8', FL_Up},
+ {VK_RIGHT, FL_KP+'6', FL_Right},
+ {VK_DOWN, FL_KP+'2', FL_Down},
+ {VK_SNAPSHOT, FL_Print}, // does not work on NT
+ {VK_INSERT, FL_KP+'0', FL_Insert},
+ {VK_DELETE, FL_KP+'.', FL_Delete},
+ {VK_LWIN, FL_Meta_L},
+ {VK_RWIN, FL_Meta_R},
+ {VK_APPS, FL_Menu},
+ {VK_MULTIPLY, FL_KP+'*'},
+ {VK_ADD, FL_KP+'+'},
+ {VK_SUBTRACT, FL_KP+'-'},
+ {VK_DECIMAL, FL_KP+'.'},
+ {VK_DIVIDE, FL_KP+'/'},
+ {VK_NUMLOCK, FL_Num_Lock},
+ {VK_SCROLL, FL_Scroll_Lock},
+ {0xba, ';'},
+ {0xbb, '='},
+ {0xbc, ','},
+ {0xbd, '-'},
+ {0xbe, '.'},
+ {0xbf, '/'},
+ {0xc0, '`'},
+ {0xdb, '['},
+ {0xdc, '\\'},
+ {0xdd, ']'},
+ {0xde, '\''}
+};
+static int ms2fltk(int vk, int extended) {
+ static unsigned short vklut[256];
+ static unsigned short extendedlut[256];
+ if (!vklut[1]) { // init the table
+ unsigned int i;
+ for (i = 0; i < 256; i++) vklut[i] = tolower(i);
+ for (i=VK_F1; i<=VK_F16; i++) vklut[i] = i+(FL_F-(VK_F1-1));
+ for (i=VK_NUMPAD0; i<=VK_NUMPAD9; i++) vklut[i] = i+(FL_KP+'0'-VK_NUMPAD0);
+ for (i = 0; i < sizeof(vktab)/sizeof(*vktab); i++) {
+ vklut[vktab[i].vk] = vktab[i].fltk;
+ extendedlut[vktab[i].vk] = vktab[i].extended;
+ }
+ for (i = 0; i < 256; i++) if (!extendedlut[i]) extendedlut[i] = vklut[i];
+ }
+ return extended ? extendedlut[vk] : vklut[vk];
+}
+
+#if USE_COLORMAP
+extern HPALETTE fl_select_palette(void); // in fl_color_win32.cxx
+#endif
+
+
+/////////////////////////////////////////////////////////////////////////////
+/// Win32 timers
+///
+
+struct Win32Timer
+{
+ UINT_PTR handle;
+ Fl_Timeout_Handler callback;
+ void *data;
+};
+static Win32Timer* win32_timers;
+static int win32_timer_alloc;
+static int win32_timer_used;
+static HWND s_TimerWnd;
+
+static void realloc_timers()
+{
+ if (win32_timer_alloc == 0) {
+ win32_timer_alloc = 8;
+ }
+ win32_timer_alloc *= 2;
+ Win32Timer* new_timers = new Win32Timer[win32_timer_alloc];
+ memset(new_timers, 0, sizeof(Win32Timer) * win32_timer_used);
+ memcpy(new_timers, win32_timers, sizeof(Win32Timer) * win32_timer_used);
+ Win32Timer* delete_me = win32_timers;
+ win32_timers = new_timers;
+ delete [] delete_me;
+}
+
+static void delete_timer(Win32Timer& t)
+{
+ KillTimer(s_TimerWnd, t.handle);
+ memset(&t, 0, sizeof(Win32Timer));
+}
+
+/// END TIMERS
+/////////////////////////////////////////////////////////////////////////////
+
+static Fl_Window* resize_bug_fix;
+
+extern void fl_save_pen(void);
+extern void fl_restore_pen(void);
+
+static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ // Copy the message to fl_msg so add_handler code can see it, it is
+ // already there if this is called by DispatchMessage, but not if
+ // Windows calls this directly.
+ fl_msg.hwnd = hWnd;
+ fl_msg.message = uMsg;
+ fl_msg.wParam = wParam;
+ fl_msg.lParam = lParam;
+ //fl_msg.time = ???
+ //fl_msg.pt = ???
+ //fl_msg.lPrivate = ???
+
+ Fl_Window *window = fl_find(hWnd);
+
+ if (window) switch (uMsg) {
+
+ case WM_QUIT: // this should not happen?
+ Fl::fatal("WM_QUIT message");
+
+ case WM_CLOSE: // user clicked close box
+ Fl::handle(FL_CLOSE, window);
+ PostQuitMessage(0);
+ return 0;
+
+ case WM_SYNCPAINT :
+ case WM_NCPAINT :
+ case WM_ERASEBKGND :
+ // Andreas Weitl - WM_SYNCPAINT needs to be passed to DefWindowProc
+ // so that Windows can generate the proper paint messages...
+ // Similarly, WM_NCPAINT and WM_ERASEBKGND need this, too...
+ break;
+
+ case WM_PAINT: {
+ Fl_Region R;
+ Fl_X *i = Fl_X::i(window);
+ i->wait_for_expose = 0;
+ char redraw_whole_window = false;
+ if (!i->region && window->damage()) {
+ // Redraw the whole window...
+ i->region = CreateRectRgn(0, 0, window->w(), window->h());
+ redraw_whole_window = true;
+ }
+
+ // We need to merge WIN32's damage into FLTK's damage.
+ R = CreateRectRgn(0,0,0,0);
+ int r = GetUpdateRgn(hWnd,R,0);
+ if (r==NULLREGION && !redraw_whole_window) {
+ break;
+ }
+
+ if (i->region) {
+ // Also tell WIN32 that we are drawing someplace else as well...
+ CombineRgn(i->region, i->region, R, RGN_OR);
+ XDestroyRegion(R);
+ } else {
+ i->region = R;
+ }
+ if (window->type() == FL_DOUBLE_WINDOW) ValidateRgn(hWnd,0);
+ else ValidateRgn(hWnd,i->region);
+
+ window->clear_damage((uchar)(window->damage()|FL_DAMAGE_EXPOSE));
+ // These next two statements should not be here, so that all update
+ // is deferred until Fl::flush() is called during idle. However WIN32
+ // apparently is very unhappy if we don't obey it and draw right now.
+ // Very annoying!
+ fl_GetDC(hWnd); // Make sure we have a DC for this window...
+ fl_save_pen();
+ i->flush();
+ fl_restore_pen();
+ window->clear_damage();
+ } return 0;
+
+ case WM_LBUTTONDOWN: mouse_event(window, 0, 1, wParam, lParam); return 0;
+ case WM_LBUTTONDBLCLK:mouse_event(window, 1, 1, wParam, lParam); return 0;
+ case WM_LBUTTONUP: mouse_event(window, 2, 1, wParam, lParam); return 0;
+ case WM_MBUTTONDOWN: mouse_event(window, 0, 2, wParam, lParam); return 0;
+ case WM_MBUTTONDBLCLK:mouse_event(window, 1, 2, wParam, lParam); return 0;
+ case WM_MBUTTONUP: mouse_event(window, 2, 2, wParam, lParam); return 0;
+ case WM_RBUTTONDOWN: mouse_event(window, 0, 3, wParam, lParam); return 0;
+ case WM_RBUTTONDBLCLK:mouse_event(window, 1, 3, wParam, lParam); return 0;
+ case WM_RBUTTONUP: mouse_event(window, 2, 3, wParam, lParam); return 0;
+
+ case WM_MOUSEMOVE:
+#ifdef USE_TRACK_MOUSE
+ if (track_mouse_win != window) {
+ TRACKMOUSEEVENT tme;
+ tme.cbSize = sizeof(TRACKMOUSEEVENT);
+ tme.dwFlags = TME_LEAVE;
+ tme.hwndTrack = hWnd;
+ _TrackMouseEvent(&tme);
+ track_mouse_win = window;
+ }
+#endif // USE_TRACK_MOUSE
+ mouse_event(window, 3, 0, wParam, lParam);
+ return 0;
+
+ case WM_MOUSELEAVE:
+ if (track_mouse_win == window) { // we left the top level window !
+ Fl_Window *tw = window;
+ while (tw->parent()) tw = tw->window(); // find top level window
+ Fl::belowmouse(0);
+ Fl::handle(FL_LEAVE, tw);
+ }
+ track_mouse_win = 0; // force TrackMouseEvent() restart
+ break;
+
+ case WM_SETFOCUS:
+ Fl::handle(FL_FOCUS, window);
+ break;
+
+ case WM_KILLFOCUS:
+ Fl::handle(FL_UNFOCUS, window);
+ Fl::flush(); // it never returns to main loop when deactivated...
+ break;
+
+ case WM_SHOWWINDOW:
+ if (!window->parent()) {
+ Fl::handle(wParam ? FL_SHOW : FL_HIDE, window);
+ }
+ break;
+
+ case WM_ACTIVATEAPP:
+ // From eric@vfx.sel.sony.com, we should process WM_ACTIVATEAPP
+ // messages to restore the correct state of the shift/ctrl/alt/lock
+ // keys... Added control, shift, alt, and meta keys, and changed
+ // to use GetAsyncKeyState and do it when wParam is 1
+ // (that means we have focus...)
+ if (wParam)
+ {
+ ulong state = 0;
+ if (GetAsyncKeyState(VK_CAPITAL)) state |= FL_CAPS_LOCK;
+ if (GetAsyncKeyState(VK_NUMLOCK)) state |= FL_NUM_LOCK;
+ if (GetAsyncKeyState(VK_SCROLL)) state |= FL_SCROLL_LOCK;
+ if (GetAsyncKeyState(VK_CONTROL)&~1) state |= FL_CTRL;
+ if (GetAsyncKeyState(VK_SHIFT)&~1) state |= FL_SHIFT;
+ if (GetAsyncKeyState(VK_MENU)) state |= FL_ALT;
+ if ((GetAsyncKeyState(VK_LWIN)|GetAsyncKeyState(VK_RWIN))&~1) state |= FL_META;
+ Fl::e_state = state;
+ return 0;
+ }
+ break;
+
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ case WM_KEYUP:
+ case WM_SYSKEYUP:
+ // save the keysym until we figure out the characters:
+ Fl::e_keysym = Fl::e_original_keysym = ms2fltk(wParam,lParam&(1<<24));
+ // See if TranslateMessage turned it into a WM_*CHAR message:
+ if (PeekMessage(&fl_msg, hWnd, WM_CHAR, WM_SYSDEADCHAR, PM_REMOVE)) {
+ uMsg = fl_msg.message;
+ wParam = fl_msg.wParam;
+ lParam = fl_msg.lParam;
+ }
+ case WM_DEADCHAR:
+ case WM_SYSDEADCHAR:
+ case WM_CHAR:
+ case WM_SYSCHAR: {
+ ulong state = Fl::e_state & 0xff000000; // keep the mouse button state
+ // if GetKeyState is expensive we might want to comment some of these out:
+ if (GetKeyState(VK_SHIFT)&~1) state |= FL_SHIFT;
+ if (GetKeyState(VK_CAPITAL)) state |= FL_CAPS_LOCK;
+ if (GetKeyState(VK_CONTROL)&~1) state |= FL_CTRL;
+ // Alt gets reported for the Alt-GR switch on foreign keyboards.
+ // so we need to check the event as well to get it right:
+ if ((lParam&(1<<29)) //same as GetKeyState(VK_MENU)
+ && uMsg != WM_CHAR) state |= FL_ALT;
+ if (GetKeyState(VK_NUMLOCK)) state |= FL_NUM_LOCK;
+ if ((GetKeyState(VK_LWIN)|GetKeyState(VK_RWIN))&~1) {
+ // WIN32 bug? GetKeyState returns garbage if the user hit the
+ // meta key to pop up start menu. Sigh.
+ if ((GetAsyncKeyState(VK_LWIN)|GetAsyncKeyState(VK_RWIN))&~1)
+ state |= FL_META;
+ }
+ if (GetKeyState(VK_SCROLL)) state |= FL_SCROLL_LOCK;
+ Fl::e_state = state;
+ static char buffer[2];
+ if (uMsg == WM_CHAR || uMsg == WM_SYSCHAR) {
+ buffer[0] = char(wParam);
+ Fl::e_length = 1;
+ } else if (Fl::e_keysym >= FL_KP && Fl::e_keysym <= FL_KP_Last) {
+ if (state & FL_NUM_LOCK) {
+ // Convert to regular keypress...
+ buffer[0] = Fl::e_keysym-FL_KP;
+ Fl::e_length = 1;
+ } else {
+ // Convert to special keypress...
+ buffer[0] = 0;
+ Fl::e_length = 0;
+ switch (Fl::e_keysym) {
+ case FL_KP + '0' :
+ Fl::e_keysym = FL_Insert;
+ break;
+ case FL_KP + '1' :
+ Fl::e_keysym = FL_End;
+ break;
+ case FL_KP + '2' :
+ Fl::e_keysym = FL_Down;
+ break;
+ case FL_KP + '3' :
+ Fl::e_keysym = FL_Page_Down;
+ break;
+ case FL_KP + '4' :
+ Fl::e_keysym = FL_Left;
+ break;
+ case FL_KP + '6' :
+ Fl::e_keysym = FL_Right;
+ break;
+ case FL_KP + '7' :
+ Fl::e_keysym = FL_Home;
+ break;
+ case FL_KP + '8' :
+ Fl::e_keysym = FL_Up;
+ break;
+ case FL_KP + '9' :
+ Fl::e_keysym = FL_Page_Up;
+ break;
+ case FL_KP + '.' :
+ Fl::e_keysym = FL_Delete;
+ break;
+ case FL_KP + '/' :
+ case FL_KP + '*' :
+ case FL_KP + '-' :
+ case FL_KP + '+' :
+ buffer[0] = Fl::e_keysym-FL_KP;
+ Fl::e_length = 1;
+ break;
+ }
+ }
+ } else if ((lParam & (1<<31))==0){
+ buffer[0] = 0;
+ Fl::e_length = 0;
+ }
+ Fl::e_text = buffer;
+ if (lParam & (1<<31)) { // key up events.
+ if (Fl::handle(FL_KEYUP, window)) return 0;
+ break;
+ }
+ // for (int i = lParam&0xff; i--;)
+ while (window->parent()) window = window->window();
+ if (Fl::handle(FL_KEYBOARD,window)) return 0;
+ break;}
+
+ case WM_MOUSEWHEEL: {
+ static int delta = 0; // running total of all motion
+ delta += (SHORT)(HIWORD(wParam));
+ Fl::e_dy = -delta / WHEEL_DELTA;
+ delta += Fl::e_dy * WHEEL_DELTA;
+ if (Fl::e_dy) Fl::handle(FL_MOUSEWHEEL, window);
+ return 0;
+ }
+
+ case WM_GETMINMAXINFO:
+ Fl_X::i(window)->set_minmax((LPMINMAXINFO)lParam);
+ break;
+
+ case WM_SIZE:
+ if (!window->parent()) {
+ if (wParam == SIZE_MINIMIZED || wParam == SIZE_MAXHIDE) {
+ Fl::handle(FL_HIDE, window);
+ } else {
+ Fl::handle(FL_SHOW, window);
+ resize_bug_fix = window;
+ window->size(LOWORD(lParam), HIWORD(lParam));
+ }
+ }
+ break;
+
+ case WM_MOVE: {
+ resize_bug_fix = window;
+ int nx = LOWORD(lParam);
+ int ny = HIWORD(lParam);
+ if (nx & 0x8000) nx -= 65536;
+ if (ny & 0x8000) ny -= 65536;
+ window->position(nx, ny); }
+ break;
+
+ case WM_SETCURSOR:
+ if (LOWORD(lParam) == HTCLIENT) {
+ while (window->parent()) window = window->window();
+ SetCursor(Fl_X::i(window)->cursor);
+ return 0;
+ }
+ break;
+
+#if USE_COLORMAP
+ case WM_QUERYNEWPALETTE :
+ fl_GetDC(hWnd);
+ if (fl_select_palette()) InvalidateRect(hWnd, NULL, FALSE);
+ break;
+
+ case WM_PALETTECHANGED:
+ fl_GetDC(hWnd);
+ if ((HWND)wParam != hWnd && fl_select_palette()) UpdateColors(fl_gc);
+ break;
+
+ case WM_CREATE :
+ fl_GetDC(hWnd);
+ fl_select_palette();
+ break;
+#endif
+
+ case WM_DESTROYCLIPBOARD:
+ fl_i_own_selection[1] = 0;
+ return 1;
+
+ case WM_RENDERALLFORMATS:
+ fl_i_own_selection[1] = 0;
+ // Windoze seems unhappy unless I do these two steps. Documentation
+ // seems to vary on whether opening the clipboard is necessary or
+ // is in fact wrong:
+ CloseClipboard();
+ OpenClipboard(NULL);
+ // fall through...
+ case WM_RENDERFORMAT: {
+ HANDLE h = GlobalAlloc(GHND, fl_selection_length[1]+1);
+ if (h) {
+ LPSTR p = (LPSTR)GlobalLock(h);
+ memcpy(p, fl_selection_buffer[1], fl_selection_length[1]);
+ p[fl_selection_length[1]] = 0;
+ GlobalUnlock(h);
+ SetClipboardData(CF_TEXT, h);
+ }
+ // Windoze also seems unhappy if I don't do this. Documentation very
+ // unclear on what is correct:
+ if (fl_msg.message == WM_RENDERALLFORMATS) CloseClipboard();
+ return 1;}
+
+ default:
+ if (Fl::handle(0,0)) return 0;
+ break;
+ }
+
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+////////////////////////////////////////////////////////////////
+// This function gets the dimensions of the top/left borders and
+// the title bar, if there is one, based on the FL_BORDER, FL_MODAL
+// and FL_NONMODAL flags, and on the window's size range.
+// It returns the following values:
+//
+// value | border | title bar
+// 0 | none | no
+// 1 | fix | yes
+// 2 | size | yes
+
+int Fl_X::fake_X_wm(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, int &by) {
+ int W, H, xoff, yoff, dx, dy;
+ int ret = bx = by = bt = 0;
+
+ int fallback = 1;
+ if (!w->parent()) {
+ HWND hwnd = fl_xid(w);
+ if (hwnd) {
+ // The block below calculates the window borders by requesting the
+ // required decorated window rectangle for a desired client rectangle.
+ // If any part of the function above fails, we will drop to a
+ // fallback to get the best guess which is always available.
+ HWND hwnd = fl_xid(w);
+ // request the style flags of this window, as WIN32 sees them
+ LONG style = GetWindowLong(hwnd, GWL_STYLE);
+ LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
+ RECT r;
+ r.left = w->x();
+ r.top = w->y();
+ r.right = w->x()+w->w();
+ r.bottom = w->y()+w->h();
+ // get the decoration rectangle for the desired client rectangle
+ BOOL ok = AdjustWindowRectEx(&r, style, FALSE, exstyle);
+ if (ok) {
+ X = r.left;
+ Y = r.top;
+ W = r.right - r.left;
+ H = r.bottom - r.top;
+ bx = w->x() - r.left;
+ by = r.bottom - w->y() - w->h(); // height of the bootm frame
+ bt = w->y() - r.top - by; // height of top caption bar
+ xoff = bx;
+ yoff = by + bt;
+ dx = W - w->w();
+ dy = H - w->h();
+ if (w->size_range_set && (w->maxw != w->minw || w->maxh != w->minh))
+ ret = 2;
+ else
+ ret = 1;
+ fallback = 0;
+ }
+ }
+ }
+ // This is the original (pre 1.1.7) routine to calculate window border sizes.
+ if (fallback) {
+ if (w->border() && !w->parent()) {
+ if (w->size_range_set && (w->maxw != w->minw || w->maxh != w->minh)) {
+ ret = 2;
+ bx = GetSystemMetrics(SM_CXSIZEFRAME);
+ by = GetSystemMetrics(SM_CYSIZEFRAME);
+ } else {
+ ret = 1;
+ bx = GetSystemMetrics(SM_CXFIXEDFRAME);
+ by = GetSystemMetrics(SM_CYFIXEDFRAME);
+ }
+ bt = GetSystemMetrics(SM_CYCAPTION);
+ }
+ //The coordinates of the whole window, including non-client area
+ xoff = bx;
+ yoff = by + bt;
+ dx = 2*bx;
+ dy = 2*by + bt;
+ X = w->x()-xoff;
+ Y = w->y()-yoff;
+ W = w->w()+dx;
+ H = w->h()+dy;
+ }
+
+ //Proceed to positioning the window fully inside the screen, if possible
+ //Make border's lower right corner visible
+ int scr_x, scr_y, scr_w, scr_h;
+ Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h, X, Y);
+ if (scr_x+scr_w < X+W) X = scr_x+scr_w - W;
+ if (scr_y+scr_h < Y+H) Y = scr_y+scr_h - H;
+ //Make border's upper left corner visible
+ if (X<scr_x) X = scr_x;
+ if (Y<scr_y) Y = scr_y;
+ //Make client area's lower right corner visible
+ if (scr_x+scr_w < X+dx+ w->w()) X = scr_x+scr_w - w->w() - dx;
+ if (scr_y+scr_h < Y+dy+ w->h()) Y = scr_y+scr_h - w->h() - dy;
+ //Make client area's upper left corner visible
+ if (X+xoff < scr_x) X = scr_x-xoff;
+ if (Y+yoff < scr_y) Y = scr_y-yoff;
+ //Return the client area's top left corner in (X,Y)
+ X+=xoff;
+ Y+=yoff;
+
+ return ret;
+}
+
+////////////////////////////////////////////////////////////////
+
+void Fl_Window::resize(int X,int Y,int W,int H) {
+ UINT flags = SWP_NOSENDCHANGING | SWP_NOZORDER
+ | SWP_NOACTIVATE | SWP_NOOWNERZORDER;
+ int is_a_resize = (W != w() || H != h());
+ int resize_from_program = (this != resize_bug_fix);
+ if (!resize_from_program) resize_bug_fix = 0;
+ if (X != x() || Y != y()) {
+ set_flag(FL_FORCE_POSITION);
+ } else {
+ if (!is_a_resize) return;
+ flags |= SWP_NOMOVE;
+ }
+ if (is_a_resize) {
+ Fl_Group::resize(X,Y,W,H);
+ if (visible_r()) {
+ redraw();
+ // only wait for exposure if this window has a size - a window
+ // with no width or height will never get an exposure event
+ if (i && W>0 && H>0)
+ i->wait_for_expose = 1;
+ }
+ } else {
+ x(X); y(Y);
+ flags |= SWP_NOSIZE;
+ }
+ if (!border()) flags |= SWP_NOACTIVATE;
+ if (resize_from_program && shown()) {
+ if (!resizable()) size_range(w(),h(),w(),h());
+ int dummy_x, dummy_y, bt, bx, by;
+ //Ignore window managing when resizing, so that windows (and more
+ //specifically menus) can be moved offscreen.
+ if (Fl_X::fake_X_wm(this, dummy_x, dummy_y, bt, bx, by)) {
+ X -= bx;
+ Y -= by+bt;
+ W += 2*bx;
+ H += 2*by+bt;
+ }
+ // avoid zero size windows. A zero sized window on Win32
+ // will cause continouly new redraw events.
+ if (W<=0) W = 1;
+ if (H<=0) H = 1;
+ SetWindowPos(i->xid, 0, X, Y, W, H, flags);
+ }
+}
+
+////////////////////////////////////////////////////////////////
+
+/*
+ * This silly little class remembers the name of all window classes
+ * we register to avoid double registration. It has the added bonus
+ * of freeing everything on application colse as well.
+ */
+class NameList {
+public:
+ NameList() { name = (char**)malloc(sizeof(char**)); NName = 1; nName = 0; }
+ ~NameList() {
+ int i;
+ for (i=0; i<nName; i++) free(name[i]);
+ if (name) free(name);
+ }
+ void add_name(const char *n) {
+ if (NName==nName) {
+ NName += 5;
+ name = (char**)realloc(name, NName * sizeof(char*));
+ }
+ name[nName++] = strdup(n);
+ }
+ char has_name(const char *n) {
+ int i;
+ for (i=0; i<nName; i++) {
+ if (strcmp(name[i], n)==0) return 1;
+ }
+ return 0;
+ }
+private:
+ char **name;
+ int nName, NName;
+};
+
+void fl_fix_focus(); // in Fl.cxx
+
+char fl_show_iconic; // hack for Fl_Window::iconic()
+// int fl_background_pixel = -1; // color to use for background
+HCURSOR fl_default_cursor;
+UINT fl_wake_msg = 0;
+int fl_disable_transient_for; // secret method of removing TRANSIENT_FOR
+
+Fl_X* Fl_X::make(Fl_Window* w) {
+ Fl_Group::current(0); // get rid of very common user bug: forgot end()
+
+ // if the window is a subwindow and our parent is not mapped yet, we
+ // mark this window visible, so that mapping the parent at a later
+ // point in time will call this function again to finally map the subwindow.
+ if (w->parent() && !Fl_X::i(w->window())) {
+ w->set_visible();
+ return 0L;
+ }
+
+ static NameList class_name_list;
+ static const char *first_class_name = 0L;
+ const char *class_name = w->xclass();
+ if (!class_name) class_name = first_class_name; // reuse first class name used
+ if (!class_name) class_name = "FLTK"; // default to create a "FLTK" WNDCLASS
+ if (!first_class_name) {
+ first_class_name = class_name;
+ }
+
+ if (!class_name_list.has_name(class_name)) {
+ WNDCLASSEX wc;
+ memset(&wc, 0, sizeof(wc));
+ wc.cbSize = sizeof(WNDCLASSEX);
+ // Documentation states a device context consumes about 800 bytes
+ // of memory... so who cares? If 800 bytes per window is what it
+ // takes to speed things up, I'm game.
+ //wc.style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC | CS_DBLCLKS;
+ wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
+ wc.lpfnWndProc = (WNDPROC)WndProc;
+ wc.hInstance = fl_display;
+ if (!w->icon())
+ w->icon((void *)LoadIcon(NULL, IDI_APPLICATION));
+ wc.hIcon = wc.hIconSm = (HICON)w->icon();
+ wc.hCursor = fl_default_cursor = LoadCursor(NULL, IDC_ARROW);
+ //uchar r,g,b; Fl::get_color(FL_GRAY,r,g,b);
+ //wc.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(r,g,b));
+ wc.lpszClassName = class_name;
+ RegisterClassEx(&wc);
+ class_name_list.add_name(class_name);
+ }
+
+ const char* message_name = "FLTK::ThreadWakeup";
+ if (!fl_wake_msg) fl_wake_msg = RegisterWindowMessage(message_name);
+
+ HWND parent;
+ DWORD style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
+ DWORD styleEx = WS_EX_LEFT;
+
+ int xp = w->x();
+ int yp = w->y();
+ int wp = w->w();
+ int hp = w->h();
+
+ int showit = 1;
+
+ if (w->parent()) {
+ style |= WS_CHILD;
+ styleEx |= WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT;
+ parent = fl_xid(w->window());
+ } else {
+ if (!w->size_range_set) {
+ if (w->resizable()) {
+ Fl_Widget *o = w->resizable();
+ int minw = o->w(); if (minw > 100) minw = 100;
+ int minh = o->h(); if (minh > 100) minh = 100;
+ w->size_range(w->w() - o->w() + minw, w->h() - o->h() + minh, 0, 0);
+ } else {
+ w->size_range(w->w(), w->h(), w->w(), w->h());
+ }
+ }
+ styleEx |= WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT;
+ int xwm = xp , ywm = yp , bt, bx, by;
+ switch (fake_X_wm(w, xwm, ywm, bt, bx, by)) {
+ // No border (used for menus)
+ case 0: style |= WS_POPUP;
+ styleEx |= WS_EX_TOOLWINDOW;
+ break;
+
+ // Thin border and title bar
+ case 1: style |= WS_DLGFRAME | WS_CAPTION; break;
+
+ // Thick, resizable border and title bar, with maximize button
+ case 2: style |= WS_THICKFRAME | WS_MAXIMIZEBOX | WS_CAPTION ; break;
+ }
+ if (by+bt) {
+ if (!w->modal()) style |= WS_SYSMENU | WS_MINIMIZEBOX;
+ wp += 2*bx;
+ hp += 2*by+bt;
+ }
+ if (!(w->flags() & Fl_Window::FL_FORCE_POSITION)) {
+ xp = yp = CW_USEDEFAULT;
+ } else {
+ if (!Fl::grab()) {
+ xp = xwm; yp = ywm;
+ w->x(xp);w->y(yp);
+ }
+ xp -= bx;
+ yp -= by+bt;
+ }
+
+ parent = 0;
+ if (w->non_modal() && Fl_X::first && !fl_disable_transient_for) {
+ // find some other window to be "transient for":
+ Fl_Window* w = Fl_X::first->w;
+ while (w->parent()) w = w->window();
+ parent = fl_xid(w);
+ if (!w->visible()) showit = 0;
+ } else if (Fl::grab()) parent = fl_xid(Fl::grab());
+ }
+
+ Fl_X* x = new Fl_X;
+ x->other_xid = 0;
+ x->setwindow(w);
+ x->region = 0;
+ x->private_dc = 0;
+ x->cursor = fl_default_cursor;
+ x->xid = CreateWindowEx(
+ styleEx,
+ class_name, w->label(), style,
+ xp, yp, wp, hp,
+ parent,
+ NULL, // menu
+ fl_display,
+ NULL // creation parameters
+ );
+ x->next = Fl_X::first;
+ Fl_X::first = x;
+
+ x->wait_for_expose = 1;
+ if (fl_show_iconic) {showit = 0; fl_show_iconic = 0;}
+ if (showit) {
+ w->set_visible();
+ int old_event = Fl::e_number;
+ w->handle(Fl::e_number = FL_SHOW); // get child windows to appear
+ Fl::e_number = old_event;
+ w->redraw(); // force draw to happen
+ }
+ // If we've captured the mouse, we dont want to activate any
+ // other windows from the code, or we loose the capture.
+ ShowWindow(x->xid, !showit ? SW_SHOWMINNOACTIVE :
+ (Fl::grab() || (style & WS_POPUP)) ? SW_SHOWNOACTIVATE : SW_SHOWNORMAL);
+
+ // Drag-n-drop requires GCC 3.x or a non-GNU compiler...
+#if !defined(__GNUC__) || __GNUC__ >= 3
+ // Register all windows for potential drag'n'drop operations
+ static char oleInitialized = 0;
+ if (!oleInitialized) { OleInitialize(0L); oleInitialized=1; }
+
+ RegisterDragDrop(x->xid, flIDropTarget);
+#endif // !__GNUC__ || __GNUC__ >= 3
+
+ if (w->modal()) {Fl::modal_ = w; fl_fix_focus();}
+ return x;
+}
+
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+/// Win32 timers
+///
+
+
+static LRESULT CALLBACK s_TimerProc(HWND hwnd, UINT msg,
+ WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_TIMER:
+ {
+ unsigned int id = wParam - 1;
+ if (id < (unsigned int)win32_timer_used && win32_timers[id].handle) {
+ Fl_Timeout_Handler cb = win32_timers[id].callback;
+ void* data = win32_timers[id].data;
+ delete_timer(win32_timers[id]);
+ if (cb) {
+ (*cb)(data);
+ }
+ }
+ }
+ return 0;
+
+ default:
+ break;
+ }
+
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+void Fl::add_timeout(double time, Fl_Timeout_Handler cb, void* data)
+{
+ repeat_timeout(time, cb, data);
+}
+
+void Fl::repeat_timeout(double time, Fl_Timeout_Handler cb, void* data)
+{
+ int timer_id = -1;
+ for (int i = 0; i < win32_timer_used; ++i) {
+ if ( !win32_timers[i].handle ) {
+ timer_id = i;
+ break;
+ }
+ }
+ if (timer_id == -1) {
+ if (win32_timer_used == win32_timer_alloc) {
+ realloc_timers();
+ }
+ timer_id = win32_timer_used++;
+ }
+ unsigned int elapsed = (unsigned int)(time * 1000);
+
+ if ( !s_TimerWnd ) {
+ const char* timer_class = "FLTimer";
+ WNDCLASSEX wc;
+ memset(&wc, 0, sizeof(wc));
+ wc.cbSize = sizeof (wc);
+ wc.style = CS_CLASSDC;
+ wc.lpfnWndProc = (WNDPROC)s_TimerProc;
+ wc.hInstance = fl_display;
+ wc.lpszClassName = timer_class;
+ /*ATOM atom =*/ RegisterClassEx(&wc);
+ // create a zero size window to handle timer events
+ s_TimerWnd = CreateWindowEx(WS_EX_LEFT | WS_EX_TOOLWINDOW,
+ timer_class, "",
+ WS_POPUP,
+ 0, 0, 0, 0,
+ NULL, NULL, fl_display, NULL);
+ // just in case this OS won't let us create a 0x0 size window:
+ if (!s_TimerWnd)
+ s_TimerWnd = CreateWindowEx(WS_EX_LEFT | WS_EX_TOOLWINDOW,
+ timer_class, "",
+ WS_POPUP,
+ 0, 0, 1, 1,
+ NULL, NULL, fl_display, NULL);
+ ShowWindow(s_TimerWnd, SW_SHOWNOACTIVATE);
+ }
+
+ win32_timers[timer_id].callback = cb;
+ win32_timers[timer_id].data = data;
+
+ win32_timers[timer_id].handle =
+ SetTimer(s_TimerWnd, timer_id + 1, elapsed, NULL);
+}
+
+int Fl::has_timeout(Fl_Timeout_Handler cb, void* data)
+{
+ for (int i = 0; i < win32_timer_used; ++i) {
+ Win32Timer& t = win32_timers[i];
+ if (t.handle && t.callback == cb && t.data == data) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void Fl::remove_timeout(Fl_Timeout_Handler cb, void* data)
+{
+ int i;
+ for (i = 0; i < win32_timer_used; ++i) {
+ Win32Timer& t = win32_timers[i];
+ if (t.handle && t.callback == cb &&
+ (t.data == data || data == NULL)) {
+ delete_timer(t);
+ }
+ }
+}
+
+/// END TIMERS
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+////////////////////////////////////////////////////////////////
+
+HINSTANCE fl_display = GetModuleHandle(NULL);
+
+void Fl_Window::size_range_() {
+ size_range_set = 1;
+}
+
+void Fl_X::set_minmax(LPMINMAXINFO minmax)
+{
+ int td, wd, hd, dummy_x, dummy_y;
+
+ fake_X_wm(w, dummy_x, dummy_y, td, wd, hd);
+ wd *= 2;
+ hd *= 2;
+ hd += td;
+
+ minmax->ptMinTrackSize.x = w->minw + wd;
+ minmax->ptMinTrackSize.y = w->minh + hd;
+ if (w->maxw) {
+ minmax->ptMaxTrackSize.x = w->maxw + wd;
+ minmax->ptMaxSize.x = w->maxw + wd;
+ }
+ if (w->maxh) {
+ minmax->ptMaxTrackSize.y = w->maxh + hd;
+ minmax->ptMaxSize.y = w->maxh + hd;
+ }
+}
+
+////////////////////////////////////////////////////////////////
+
+#include <FL/filename.H> // need so FL_EXPORT fl_filename_name works
+
+// returns pointer to the filename, or null if name ends with '/'
+const char *fl_filename_name(const char *name) {
+ const char *p,*q;
+ if (!name) return (0);
+ q = name;
+ if (q[0] && q[1]==':') q += 2; // skip leading drive letter
+ for (p = q; *p; p++) if (*p == '/' || *p == '\\') q = p+1;
+ return q;
+}
+
+void Fl_Window::label(const char *name,const char *iname) {
+ Fl_Widget::label(name);
+ iconlabel_ = iname;
+ if (shown() && !parent()) {
+ if (!name) name = "";
+ SetWindowText(i->xid, name);
+ // if (!iname) iname = fl_filename_name(name);
+ // should do something with iname here...
+ }
+}
+
+////////////////////////////////////////////////////////////////
+// Implement the virtual functions for the base Fl_Window class:
+
+// If the box is a filled rectangle, we can make the redisplay *look*
+// faster by using X's background pixel erasing. We can make it
+// actually *be* faster by drawing the frame only, this is done by
+// setting fl_boxcheat, which is seen by code in fl_drawbox.cxx:
+// For WIN32 it looks like all windows share a background color, so
+// I use FL_GRAY for this and only do this cheat for windows that are
+// that color.
+// Actually it is totally disabled.
+// Fl_Widget *fl_boxcheat;
+//static inline int can_boxcheat(uchar b) {return (b==1 || (b&2) && b<=15);}
+
+void Fl_Window::show() {
+ image(Fl::scheme_bg_);
+ if (Fl::scheme_bg_) {
+ labeltype(FL_NORMAL_LABEL);
+ align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE | FL_ALIGN_CLIP);
+ } else {
+ labeltype(FL_NO_LABEL);
+ }
+ Fl_Tooltip::exit(this);
+ if (!shown()) {
+ // if (can_boxcheat(box())) fl_background_pixel = fl_xpixel(color());
+ Fl_X::make(this);
+ } else {
+ // Once again, we would lose the capture if we activated the window.
+ if (IsIconic(i->xid)) OpenIcon(i->xid);
+ if (!fl_capture) BringWindowToTop(i->xid);
+ //ShowWindow(i->xid,fl_capture?SW_SHOWNOACTIVATE:SW_RESTORE);
+ }
+}
+
+Fl_Window *Fl_Window::current_;
+// the current context
+HDC fl_gc = 0;
+// the current window handle, initially set to -1 so we can correctly
+// allocate fl_GetDC(0)
+HWND fl_window = NULL;
+
+// Here we ensure only one GetDC is ever in place.
+HDC fl_GetDC(HWND w) {
+ if (fl_gc) {
+ if (w == fl_window && fl_window != NULL) return fl_gc;
+ if (fl_window) fl_release_dc(fl_window, fl_gc); // ReleaseDC
+ }
+ fl_gc = GetDC(w);
+ fl_save_dc(w, fl_gc);
+ fl_window = w;
+ // calling GetDC seems to always reset these: (?)
+ SetTextAlign(fl_gc, TA_BASELINE|TA_LEFT);
+ SetBkMode(fl_gc, TRANSPARENT);
+ return fl_gc;
+}
+
+// make X drawing go into this window (called by subclass flush() impl.)
+void Fl_Window::make_current() {
+ fl_GetDC(fl_xid(this));
+
+#if USE_COLORMAP
+ // Windows maintains a hardware and software color palette; the
+ // SelectPalette() call updates the current soft->hard mapping
+ // for all drawing calls, so we must select it here before any
+ // code does any drawing...
+
+ fl_select_palette();
+#endif // USE_COLORMAP
+
+ current_ = this;
+ fl_clip_region(0);
+}
+
+/* Make sure that all allocated fonts are released. This works only if
+ Fl::run() is allowed to exit by closing all windows. Calling 'exit(int)'
+ will not automatically free any fonts. */
+void fl_free_fonts(void)
+{
+// remove the Fl_FontSize chains
+ int i;
+ Fl_Fontdesc * s;
+ Fl_FontSize * f;
+ Fl_FontSize * ff;
+ for (i=0; i<FL_FREE_FONT; i++) {
+ s = fl_fonts + i;
+ for (f=s->first; f; f=ff) {
+ ff = f->next;
+ delete f;
+ s->first = ff;
+ }
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////
+//
+// The following routines help fix a problem with the leaking of Windows
+// Device Context (DC) objects. The 'proper' protocol is for a program to
+// acquire a DC, save its state, do the modifications needed for drawing,
+// perform the drawing, restore the initial state, and release the DC. In
+// FLTK, the save and restore steps have previously been omitted and DCs are
+// not properly released, leading to a great number of DC leaks. As some
+// Windows "OSs" will hang when any process exceeds roughly 10,000 GDI objects,
+// it is important to control GDI leaks, which are much more important than memory
+// leaks. The following struct, global variable, and routines help implement
+// the above protocol for those cases where the GetDC and RestoreDC are not in
+// the same routine. For each GetDC, fl_save_dc is used to create an entry in
+// a linked list that saves the window handle, the DC handle, and the initial
+// state. When the DC is to be released, 'fl_release_dc' is called. It restores
+// the initial state and releases the DC. When the program exits, 'fl_cleanup_dc_list'
+// frees any remaining nodes in the list.
+
+struct Win_DC_List { // linked list
+ HWND window; // window handle
+ HDC dc; // device context handle
+ int saved_dc; // initial state of DC
+ Win_DC_List * next; // pointer to next item
+};
+
+static Win_DC_List * win_DC_list = 0;
+
+void fl_save_dc( HWND w, HDC dc) {
+ Win_DC_List * t;
+ t = new Win_DC_List;
+ t->window = w;
+ t->dc = dc;
+ t->saved_dc = SaveDC(dc);
+ if (win_DC_list)
+ t->next = win_DC_list;
+ else
+ t->next = NULL;
+ win_DC_list = t;
+}
+
+void fl_release_dc(HWND w, HDC dc) {
+ Win_DC_List * t= win_DC_list;
+ Win_DC_List * prev = 0;
+ if (!t)
+ return;
+ do {
+ if (t->dc == dc) {
+ RestoreDC(dc, t->saved_dc);
+ ReleaseDC(w, dc);
+ if (!prev) {
+ win_DC_list = t->next; // delete first item
+ } else {
+ prev->next = t->next; // one in the middle
+ }
+ delete (t);
+ return;
+ }
+ prev = t;
+ t = t->next;
+ } while (t);
+}
+
+void fl_cleanup_dc_list(void) { // clean up the list
+ Win_DC_List * t = win_DC_list;
+ if (!t)return;
+ do {
+ RestoreDC(t->dc, t->saved_dc);
+ ReleaseDC(t->window, t->dc);
+ win_DC_list = t->next;
+ delete (t);
+ t = win_DC_list;
+ } while(t);
+}
+
+
+//
+// End of "$Id: Fl_win32.cxx 6553 2008-12-07 11:05:41Z AlbrechtS $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Fl_x.cxx b/third_party/windows/fltk-1.1.10/src/Fl_x.cxx new file mode 100644 index 0000000..b83ace6 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_x.cxx @@ -0,0 +1,1413 @@ +//
+// "$Id: Fl_x.cxx 5914 2007-06-18 13:08:57Z matt $"
+//
+// X specific code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2007 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
+//
+
+#ifdef WIN32
+//# include "Fl_win32.cxx"
+#elif defined(__APPLE__)
+//# include "Fl_mac.cxx"
+#else
+
+# define CONSOLIDATE_MOTION 1
+/**** Define this if your keyboard lacks a backspace key... ****/
+/* #define BACKSPACE_HACK 1 */
+
+# include <FL/Fl.H>
+# include <FL/x.H>
+# include <FL/Fl_Window.H>
+# include <FL/Fl_Tooltip.H>
+# include <stdio.h>
+# include <stdlib.h>
+# include "flstring.h"
+# include <unistd.h>
+# include <sys/time.h>
+
+////////////////////////////////////////////////////////////////
+// interface to poll/select call:
+
+# if USE_POLL
+
+# include <poll.h>
+static pollfd *pollfds = 0;
+
+# else
+# if HAVE_SYS_SELECT_H
+# include <sys/select.h>
+# endif /* HAVE_SYS_SELECT_H */
+
+// The following #define is only needed for HP-UX 9.x and earlier:
+//#define select(a,b,c,d,e) select((a),(int *)(b),(int *)(c),(int *)(d),(e))
+
+static fd_set fdsets[3];
+static int maxfd;
+# define POLLIN 1
+# define POLLOUT 4
+# define POLLERR 8
+
+# endif /* USE_POLL */
+
+static int nfds = 0;
+static int fd_array_size = 0;
+struct FD {
+# if !USE_POLL
+ int fd;
+ short events;
+# endif
+ void (*cb)(int, void*);
+ void* arg;
+};
+
+static FD *fd = 0;
+
+void Fl::add_fd(int n, int events, void (*cb)(int, void*), void *v) {
+ remove_fd(n,events);
+ int i = nfds++;
+ if (i >= fd_array_size) {
+ FD *temp;
+ fd_array_size = 2*fd_array_size+1;
+
+ if (!fd) temp = (FD*)malloc(fd_array_size*sizeof(FD));
+ else temp = (FD*)realloc(fd, fd_array_size*sizeof(FD));
+
+ if (!temp) return;
+ fd = temp;
+
+# if USE_POLL
+ pollfd *tpoll;
+
+ if (!pollfds) tpoll = (pollfd*)malloc(fd_array_size*sizeof(pollfd));
+ else tpoll = (pollfd*)realloc(pollfds, fd_array_size*sizeof(pollfd));
+
+ if (!tpoll) return;
+ pollfds = tpoll;
+# endif
+ }
+ fd[i].cb = cb;
+ fd[i].arg = v;
+# if USE_POLL
+ pollfds[i].fd = n;
+ pollfds[i].events = events;
+# else
+ fd[i].fd = n;
+ fd[i].events = events;
+ if (events & POLLIN) FD_SET(n, &fdsets[0]);
+ if (events & POLLOUT) FD_SET(n, &fdsets[1]);
+ if (events & POLLERR) FD_SET(n, &fdsets[2]);
+ if (n > maxfd) maxfd = n;
+# endif
+}
+
+void Fl::add_fd(int n, void (*cb)(int, void*), void* v) {
+ Fl::add_fd(n, POLLIN, cb, v);
+}
+
+void Fl::remove_fd(int n, int events) {
+ int i,j;
+ maxfd = -1; // recalculate maxfd on the fly
+ for (i=j=0; i<nfds; i++) {
+# if USE_POLL
+ if (pollfds[i].fd == n) {
+ int e = pollfds[i].events & ~events;
+ if (!e) continue; // if no events left, delete this fd
+ pollfds[j].events = e;
+ }
+# else
+ if (fd[i].fd == n) {
+ int e = fd[i].events & ~events;
+ if (!e) continue; // if no events left, delete this fd
+ fd[i].events = e;
+ }
+# endif
+ if (fd[i].fd > maxfd) maxfd = fd[i].fd;
+ // move it down in the array if necessary:
+ if (j<i) {
+ fd[j] = fd[i];
+# if USE_POLL
+ pollfds[j] = pollfds[i];
+# endif
+ }
+ j++;
+ }
+ nfds = j;
+# if !USE_POLL
+ if (events & POLLIN) FD_CLR(n, &fdsets[0]);
+ if (events & POLLOUT) FD_CLR(n, &fdsets[1]);
+ if (events & POLLERR) FD_CLR(n, &fdsets[2]);
+# endif
+}
+
+void Fl::remove_fd(int n) {
+ remove_fd(n, -1);
+}
+
+#if CONSOLIDATE_MOTION
+static Fl_Window* send_motion;
+extern Fl_Window* fl_xmousewin;
+#endif
+static bool in_a_window; // true if in any of our windows, even destroyed ones
+static void do_queued_events() {
+ in_a_window = true;
+ while (XEventsQueued(fl_display,QueuedAfterReading)) {
+ XEvent xevent;
+ XNextEvent(fl_display, &xevent);
+ fl_handle(xevent);
+ }
+ // we send FL_LEAVE only if the mouse did not enter some other window:
+ if (!in_a_window) Fl::handle(FL_LEAVE, 0);
+#if CONSOLIDATE_MOTION
+ else if (send_motion == fl_xmousewin) {
+ send_motion = 0;
+ Fl::handle(FL_MOVE, fl_xmousewin);
+ }
+#endif
+}
+
+// these pointers are set by the Fl::lock() function:
+static void nothing() {}
+void (*fl_lock_function)() = nothing;
+void (*fl_unlock_function)() = nothing;
+
+// This is never called with time_to_wait < 0.0:
+// It should return negative on error, 0 if nothing happens before
+// timeout, and >0 if any callbacks were done.
+int fl_wait(double time_to_wait) {
+
+ // OpenGL and other broken libraries call XEventsQueued
+ // unnecessarily and thus cause the file descriptor to not be ready,
+ // so we must check for already-read events:
+ if (fl_display && XQLength(fl_display)) {do_queued_events(); return 1;}
+
+# if !USE_POLL
+ fd_set fdt[3];
+ fdt[0] = fdsets[0];
+ fdt[1] = fdsets[1];
+ fdt[2] = fdsets[2];
+# endif
+ int n;
+
+ fl_unlock_function();
+
+ if (time_to_wait < 2147483.648) {
+# if USE_POLL
+ n = ::poll(pollfds, nfds, int(time_to_wait*1000 + .5));
+# else
+ timeval t;
+ t.tv_sec = int(time_to_wait);
+ t.tv_usec = int(1000000 * (time_to_wait-t.tv_sec));
+ n = ::select(maxfd+1,&fdt[0],&fdt[1],&fdt[2],&t);
+# endif
+ } else {
+# if USE_POLL
+ n = ::poll(pollfds, nfds, -1);
+# else
+ n = ::select(maxfd+1,&fdt[0],&fdt[1],&fdt[2],0);
+# endif
+ }
+
+ fl_lock_function();
+
+ if (n > 0) {
+ for (int i=0; i<nfds; i++) {
+# if USE_POLL
+ if (pollfds[i].revents) fd[i].cb(pollfds[i].fd, fd[i].arg);
+# else
+ int f = fd[i].fd;
+ short revents = 0;
+ if (FD_ISSET(f,&fdt[0])) revents |= POLLIN;
+ if (FD_ISSET(f,&fdt[1])) revents |= POLLOUT;
+ if (FD_ISSET(f,&fdt[2])) revents |= POLLERR;
+ if (fd[i].events & revents) fd[i].cb(f, fd[i].arg);
+# endif
+ }
+ }
+ return n;
+}
+
+// fl_ready() is just like fl_wait(0.0) except no callbacks are done:
+int fl_ready() {
+ if (XQLength(fl_display)) return 1;
+# if USE_POLL
+ return ::poll(pollfds, nfds, 0);
+# else
+ timeval t;
+ t.tv_sec = 0;
+ t.tv_usec = 0;
+ fd_set fdt[3];
+ fdt[0] = fdsets[0];
+ fdt[1] = fdsets[1];
+ fdt[2] = fdsets[2];
+ return ::select(maxfd+1,&fdt[0],&fdt[1],&fdt[2],&t);
+# endif
+}
+
+////////////////////////////////////////////////////////////////
+
+Display *fl_display;
+Window fl_message_window;
+int fl_screen;
+XVisualInfo *fl_visual;
+Colormap fl_colormap;
+
+static Atom WM_DELETE_WINDOW;
+static Atom WM_PROTOCOLS;
+static Atom fl_MOTIF_WM_HINTS;
+static Atom TARGETS;
+static Atom CLIPBOARD;
+Atom fl_XdndAware;
+Atom fl_XdndSelection;
+Atom fl_XdndEnter;
+Atom fl_XdndTypeList;
+Atom fl_XdndPosition;
+Atom fl_XdndLeave;
+Atom fl_XdndDrop;
+Atom fl_XdndStatus;
+Atom fl_XdndActionCopy;
+Atom fl_XdndFinished;
+//Atom fl_XdndProxy;
+Atom fl_XdndURIList;
+
+
+static void fd_callback(int,void *) {
+ do_queued_events();
+}
+
+extern "C" {
+ static int io_error_handler(Display*) {
+ Fl::fatal("X I/O error");
+ return 0;
+ }
+
+ static int xerror_handler(Display* d, XErrorEvent* e) {
+ char buf1[128], buf2[128];
+ sprintf(buf1, "XRequest.%d", e->request_code);
+ XGetErrorDatabaseText(d,"",buf1,buf1,buf2,128);
+ XGetErrorText(d, e->error_code, buf1, 128);
+ Fl::warning("%s: %s 0x%lx", buf2, buf1, e->resourceid);
+ return 0;
+ }
+}
+
+void fl_open_display() {
+ if (fl_display) return;
+
+ XSetIOErrorHandler(io_error_handler);
+ XSetErrorHandler(xerror_handler);
+
+ Display *d = XOpenDisplay(0);
+ if (!d) Fl::fatal("Can't open display: %s",XDisplayName(0));
+
+ fl_open_display(d);
+}
+
+void fl_open_display(Display* d) {
+ fl_display = d;
+
+ WM_DELETE_WINDOW = XInternAtom(d, "WM_DELETE_WINDOW", 0);
+ WM_PROTOCOLS = XInternAtom(d, "WM_PROTOCOLS", 0);
+ fl_MOTIF_WM_HINTS = XInternAtom(d, "_MOTIF_WM_HINTS", 0);
+ TARGETS = XInternAtom(d, "TARGETS", 0);
+ CLIPBOARD = XInternAtom(d, "CLIPBOARD", 0);
+ fl_XdndAware = XInternAtom(d, "XdndAware", 0);
+ fl_XdndSelection = XInternAtom(d, "XdndSelection", 0);
+ fl_XdndEnter = XInternAtom(d, "XdndEnter", 0);
+ fl_XdndTypeList = XInternAtom(d, "XdndTypeList", 0);
+ fl_XdndPosition = XInternAtom(d, "XdndPosition", 0);
+ fl_XdndLeave = XInternAtom(d, "XdndLeave", 0);
+ fl_XdndDrop = XInternAtom(d, "XdndDrop", 0);
+ fl_XdndStatus = XInternAtom(d, "XdndStatus", 0);
+ fl_XdndActionCopy = XInternAtom(d, "XdndActionCopy", 0);
+ fl_XdndFinished = XInternAtom(d, "XdndFinished", 0);
+ //fl_XdndProxy = XInternAtom(d, "XdndProxy", 0);
+ fl_XdndEnter = XInternAtom(d, "XdndEnter", 0);
+ fl_XdndURIList = XInternAtom(d, "text/uri-list", 0);
+
+ Fl::add_fd(ConnectionNumber(d), POLLIN, fd_callback);
+
+ fl_screen = DefaultScreen(d);
+
+ fl_message_window =
+ XCreateSimpleWindow(d, RootWindow(d,fl_screen), 0,0,1,1,0, 0, 0);
+
+// construct an XVisualInfo that matches the default Visual:
+ XVisualInfo templt; int num;
+ templt.visualid = XVisualIDFromVisual(DefaultVisual(d, fl_screen));
+ fl_visual = XGetVisualInfo(d, VisualIDMask, &templt, &num);
+ fl_colormap = DefaultColormap(d, fl_screen);
+
+#if !USE_COLORMAP
+ Fl::visual(FL_RGB);
+#endif
+}
+
+void fl_close_display() {
+ Fl::remove_fd(ConnectionNumber(fl_display));
+ XCloseDisplay(fl_display);
+}
+
+static int fl_workarea_xywh[4] = { -1, -1, -1, -1 };
+
+static void fl_init_workarea() {
+ fl_open_display();
+
+ Atom _NET_WORKAREA = XInternAtom(fl_display, "_NET_WORKAREA", 0);
+ Atom actual;
+ unsigned long count, remaining;
+ int format;
+ unsigned *xywh;
+
+ if (XGetWindowProperty(fl_display, RootWindow(fl_display, fl_screen),
+ _NET_WORKAREA, 0, 4 * sizeof(unsigned), False,
+ XA_CARDINAL, &actual, &format, &count, &remaining,
+ (unsigned char **)&xywh) || !xywh || !xywh[2] ||
+ !xywh[3])
+ {
+ fl_workarea_xywh[0] = 0;
+ fl_workarea_xywh[1] = 0;
+ fl_workarea_xywh[2] = DisplayWidth(fl_display, fl_screen);
+ fl_workarea_xywh[3] = DisplayHeight(fl_display, fl_screen);
+ }
+ else
+ {
+ fl_workarea_xywh[0] = (int)xywh[0];
+ fl_workarea_xywh[1] = (int)xywh[1];
+ fl_workarea_xywh[2] = (int)xywh[2];
+ fl_workarea_xywh[3] = (int)xywh[3];
+ XFree(xywh);
+ }
+}
+
+int Fl::x() {
+ if (fl_workarea_xywh[0] < 0) fl_init_workarea();
+ return fl_workarea_xywh[0];
+}
+
+int Fl::y() {
+ if (fl_workarea_xywh[0] < 0) fl_init_workarea();
+ return fl_workarea_xywh[1];
+}
+
+int Fl::w() {
+ if (fl_workarea_xywh[0] < 0) fl_init_workarea();
+ return fl_workarea_xywh[2];
+}
+
+int Fl::h() {
+ if (fl_workarea_xywh[0] < 0) fl_init_workarea();
+ return fl_workarea_xywh[3];
+}
+
+void Fl::get_mouse(int &xx, int &yy) {
+ fl_open_display();
+ Window root = RootWindow(fl_display, fl_screen);
+ Window c; int mx,my,cx,cy; unsigned int mask;
+ XQueryPointer(fl_display,root,&root,&c,&mx,&my,&cx,&cy,&mask);
+ xx = mx;
+ yy = my;
+}
+
+////////////////////////////////////////////////////////////////
+// Code used for paste and DnD into the program:
+
+Fl_Widget *fl_selection_requestor;
+char *fl_selection_buffer[2];
+int fl_selection_length[2];
+int fl_selection_buffer_length[2];
+char fl_i_own_selection[2];
+
+// Call this when a "paste" operation happens:
+void Fl::paste(Fl_Widget &receiver, int clipboard) {
+ if (fl_i_own_selection[clipboard]) {
+ // We already have it, do it quickly without window server.
+ // Notice that the text is clobbered if set_selection is
+ // called in response to FL_PASTE!
+ Fl::e_text = fl_selection_buffer[clipboard];
+ Fl::e_length = fl_selection_length[clipboard];
+ if (!Fl::e_text) Fl::e_text = (char *)"";
+ receiver.handle(FL_PASTE);
+ return;
+ }
+ // otherwise get the window server to return it:
+ fl_selection_requestor = &receiver;
+ Atom property = clipboard ? CLIPBOARD : XA_PRIMARY;
+ XConvertSelection(fl_display, property, XA_STRING, property,
+ fl_xid(Fl::first_window()), fl_event_time);
+}
+
+Window fl_dnd_source_window;
+Atom *fl_dnd_source_types; // null-terminated list of data types being supplied
+Atom fl_dnd_type;
+Atom fl_dnd_source_action;
+Atom fl_dnd_action;
+
+void fl_sendClientMessage(Window window, Atom message,
+ unsigned long d0,
+ unsigned long d1=0,
+ unsigned long d2=0,
+ unsigned long d3=0,
+ unsigned long d4=0)
+{
+ XEvent e;
+ e.xany.type = ClientMessage;
+ e.xany.window = window;
+ e.xclient.message_type = message;
+ e.xclient.format = 32;
+ e.xclient.data.l[0] = (long)d0;
+ e.xclient.data.l[1] = (long)d1;
+ e.xclient.data.l[2] = (long)d2;
+ e.xclient.data.l[3] = (long)d3;
+ e.xclient.data.l[4] = (long)d4;
+ XSendEvent(fl_display, window, 0, 0, &e);
+}
+
+////////////////////////////////////////////////////////////////
+// Code for copying to clipboard and DnD out of the program:
+
+void Fl::copy(const char *stuff, int len, int clipboard) {
+ if (!stuff || len<0) return;
+ if (len+1 > fl_selection_buffer_length[clipboard]) {
+ delete[] fl_selection_buffer[clipboard];
+ fl_selection_buffer[clipboard] = new char[len+100];
+ fl_selection_buffer_length[clipboard] = len+100;
+ }
+ memcpy(fl_selection_buffer[clipboard], stuff, len);
+ fl_selection_buffer[clipboard][len] = 0; // needed for direct paste
+ fl_selection_length[clipboard] = len;
+ fl_i_own_selection[clipboard] = 1;
+ Atom property = clipboard ? CLIPBOARD : XA_PRIMARY;
+ XSetSelectionOwner(fl_display, property, fl_message_window, fl_event_time);
+}
+
+////////////////////////////////////////////////////////////////
+
+const XEvent* fl_xevent; // the current x event
+ulong fl_event_time; // the last timestamp from an x event
+
+char fl_key_vector[32]; // used by Fl::get_key()
+
+// Record event mouse position and state from an XEvent:
+
+static int px, py;
+static ulong ptime;
+
+static void set_event_xy() {
+# if CONSOLIDATE_MOTION
+ send_motion = 0;
+# endif
+ Fl::e_x_root = fl_xevent->xbutton.x_root;
+ Fl::e_x = fl_xevent->xbutton.x;
+ Fl::e_y_root = fl_xevent->xbutton.y_root;
+ Fl::e_y = fl_xevent->xbutton.y;
+ Fl::e_state = fl_xevent->xbutton.state << 16;
+ fl_event_time = fl_xevent->xbutton.time;
+# ifdef __sgi
+ // get the meta key off PC keyboards:
+ if (fl_key_vector[18]&0x18) Fl::e_state |= FL_META;
+# endif
+ // turn off is_click if enough time or mouse movement has passed:
+ if (abs(Fl::e_x_root-px)+abs(Fl::e_y_root-py) > 3 ||
+ fl_event_time >= ptime+1000)
+ Fl::e_is_click = 0;
+}
+
+// if this is same event as last && is_click, increment click count:
+static inline void checkdouble() {
+ if (Fl::e_is_click == Fl::e_keysym)
+ Fl::e_clicks++;
+ else {
+ Fl::e_clicks = 0;
+ Fl::e_is_click = Fl::e_keysym;
+ }
+ px = Fl::e_x_root;
+ py = Fl::e_y_root;
+ ptime = fl_event_time;
+}
+
+static Fl_Window* resize_bug_fix;
+
+extern "C" {
+ static Bool fake_keyup_test(Display*, XEvent* event, char* previous) {
+ return
+ event->type == KeyPress &&
+ event->xkey.keycode == ((XKeyEvent*)previous)->keycode &&
+ event->xkey.time == ((XKeyEvent*)previous)->time;
+ }
+}
+
+////////////////////////////////////////////////////////////////
+
+static char unknown[] = "<unknown>";
+const int unknown_len = 10;
+
+int fl_handle(const XEvent& thisevent)
+{
+ XEvent xevent = thisevent;
+ fl_xevent = &thisevent;
+ Window xid = xevent.xany.window;
+
+ switch (xevent.type) {
+
+ case KeymapNotify:
+ memcpy(fl_key_vector, xevent.xkeymap.key_vector, 32);
+ return 0;
+
+ case MappingNotify:
+ XRefreshKeyboardMapping((XMappingEvent*)&xevent.xmapping);
+ return 0;
+
+ case SelectionNotify: {
+ if (!fl_selection_requestor) return 0;
+ static unsigned char* buffer;
+ if (buffer) {XFree(buffer); buffer = 0;}
+ long bytesread = 0;
+ if (fl_xevent->xselection.property) for (;;) {
+ // The Xdnd code pastes 64K chunks together, possibly to avoid
+ // bugs in X servers, or maybe to avoid an extra round-trip to
+ // get the property length. I copy this here:
+ Atom actual; int format; unsigned long count, remaining;
+ unsigned char* portion;
+ if (XGetWindowProperty(fl_display,
+ fl_xevent->xselection.requestor,
+ fl_xevent->xselection.property,
+ bytesread/4, 65536, 1, 0,
+ &actual, &format, &count, &remaining,
+ &portion)) break; // quit on error
+ if (bytesread) { // append to the accumulated buffer
+ buffer = (unsigned char*)realloc(buffer, bytesread+count*format/8+remaining);
+ memcpy(buffer+bytesread, portion, count*format/8);
+ XFree(portion);
+ } else { // Use the first section without moving the memory:
+ buffer = portion;
+ }
+ bytesread += count*format/8;
+ if (!remaining) break;
+ }
+ Fl::e_text = buffer ? (char*)buffer : (char *)"";
+ Fl::e_length = bytesread;
+ int old_event = Fl::e_number;
+ fl_selection_requestor->handle(Fl::e_number = FL_PASTE);
+ Fl::e_number = old_event;
+ // Detect if this paste is due to Xdnd by the property name (I use
+ // XA_SECONDARY for that) and send an XdndFinished message. It is not
+ // clear if this has to be delayed until now or if it can be done
+ // immediatly after calling XConvertSelection.
+ if (fl_xevent->xselection.property == XA_SECONDARY &&
+ fl_dnd_source_window) {
+ fl_sendClientMessage(fl_dnd_source_window, fl_XdndFinished,
+ fl_xevent->xselection.requestor);
+ fl_dnd_source_window = 0; // don't send a second time
+ }
+ return 1;}
+
+ case SelectionClear: {
+ int clipboard = fl_xevent->xselectionclear.selection == CLIPBOARD;
+ fl_i_own_selection[clipboard] = 0;
+ return 1;}
+
+ case SelectionRequest: {
+ XSelectionEvent e;
+ e.type = SelectionNotify;
+ e.requestor = fl_xevent->xselectionrequest.requestor;
+ e.selection = fl_xevent->xselectionrequest.selection;
+ int clipboard = e.selection == CLIPBOARD;
+ e.target = fl_xevent->xselectionrequest.target;
+ e.time = fl_xevent->xselectionrequest.time;
+ e.property = fl_xevent->xselectionrequest.property;
+ if (e.target == TARGETS) {
+ Atom a = XA_STRING;
+ XChangeProperty(fl_display, e.requestor, e.property,
+ XA_ATOM, sizeof(Atom)*8, 0, (unsigned char*)&a, 1);
+ } else if (/*e.target == XA_STRING &&*/ fl_selection_length[clipboard]) {
+ XChangeProperty(fl_display, e.requestor, e.property,
+ e.target, 8, 0,
+ (unsigned char *)fl_selection_buffer[clipboard],
+ fl_selection_length[clipboard]);
+ } else {
+// char* x = XGetAtomName(fl_display,e.target);
+// fprintf(stderr,"selection request of %s\n",x);
+// XFree(x);
+ e.property = 0;
+ }
+ XSendEvent(fl_display, e.requestor, 0, 0, (XEvent *)&e);}
+ return 1;
+
+ // events where interesting window id is in a different place:
+ case CirculateNotify:
+ case CirculateRequest:
+ case ConfigureNotify:
+ case ConfigureRequest:
+ case CreateNotify:
+ case DestroyNotify:
+ case GravityNotify:
+ case MapNotify:
+ case MapRequest:
+ case ReparentNotify:
+ case UnmapNotify:
+ xid = xevent.xmaprequest.window;
+ break;
+ }
+
+ int event = 0;
+ Fl_Window* window = fl_find(xid);
+
+ if (window) switch (xevent.type) {
+
+ case ClientMessage: {
+ Atom message = fl_xevent->xclient.message_type;
+ const long* data = fl_xevent->xclient.data.l;
+ if ((Atom)(data[0]) == WM_DELETE_WINDOW) {
+ event = FL_CLOSE;
+ } else if (message == fl_XdndEnter) {
+ fl_xmousewin = window;
+ in_a_window = true;
+ fl_dnd_source_window = data[0];
+ // version number is data[1]>>24
+// printf("XdndEnter, version %ld\n", data[1] >> 24);
+ if (data[1]&1) {
+ // get list of data types:
+ Atom actual; int format; unsigned long count, remaining;
+ unsigned char *buffer = 0;
+ XGetWindowProperty(fl_display, fl_dnd_source_window, fl_XdndTypeList,
+ 0, 0x8000000L, False, XA_ATOM, &actual, &format,
+ &count, &remaining, &buffer);
+ if (actual != XA_ATOM || format != 32 || count<4 || !buffer)
+ goto FAILED;
+ delete [] fl_dnd_source_types;
+ fl_dnd_source_types = new Atom[count+1];
+ for (unsigned i = 0; i < count; i++)
+ fl_dnd_source_types[i] = ((Atom*)buffer)[i];
+ fl_dnd_source_types[count] = 0;
+ } else {
+ FAILED:
+ // less than four data types, or if the above messes up:
+ if (!fl_dnd_source_types) fl_dnd_source_types = new Atom[4];
+ fl_dnd_source_types[0] = data[2];
+ fl_dnd_source_types[1] = data[3];
+ fl_dnd_source_types[2] = data[4];
+ fl_dnd_source_types[3] = 0;
+ }
+
+ // Loop through the source types and pick the first text type...
+ int i;
+
+ for (i = 0; fl_dnd_source_types[i]; i ++)
+ {
+// printf("fl_dnd_source_types[%d] = %ld (%s)\n", i,
+// fl_dnd_source_types[i],
+// XGetAtomName(fl_display, fl_dnd_source_types[i]));
+
+ if (!strncmp(XGetAtomName(fl_display, fl_dnd_source_types[i]),
+ "text/", 5))
+ break;
+ }
+
+ if (fl_dnd_source_types[i])
+ fl_dnd_type = fl_dnd_source_types[i];
+ else
+ fl_dnd_type = fl_dnd_source_types[0];
+
+ event = FL_DND_ENTER;
+ Fl::e_text = unknown;
+ Fl::e_length = unknown_len;
+ break;
+
+ } else if (message == fl_XdndPosition) {
+ fl_xmousewin = window;
+ in_a_window = true;
+ fl_dnd_source_window = data[0];
+ Fl::e_x_root = data[2]>>16;
+ Fl::e_y_root = data[2]&0xFFFF;
+ if (window) {
+ Fl::e_x = Fl::e_x_root-window->x();
+ Fl::e_y = Fl::e_y_root-window->y();
+ }
+ fl_event_time = data[3];
+ fl_dnd_source_action = data[4];
+ fl_dnd_action = fl_XdndActionCopy;
+ Fl::e_text = unknown;
+ Fl::e_length = unknown_len;
+ int accept = Fl::handle(FL_DND_DRAG, window);
+ fl_sendClientMessage(data[0], fl_XdndStatus,
+ fl_xevent->xclient.window,
+ accept ? 1 : 0,
+ 0, // used for xy rectangle to not send position inside
+ 0, // used for width+height of rectangle
+ accept ? fl_dnd_action : None);
+ return 1;
+
+ } else if (message == fl_XdndLeave) {
+ fl_dnd_source_window = 0; // don't send a finished message to it
+ event = FL_DND_LEAVE;
+ Fl::e_text = unknown;
+ Fl::e_length = unknown_len;
+ break;
+
+ } else if (message == fl_XdndDrop) {
+ fl_xmousewin = window;
+ in_a_window = true;
+ fl_dnd_source_window = data[0];
+ fl_event_time = data[2];
+ Window to_window = fl_xevent->xclient.window;
+ Fl::e_text = unknown;
+ Fl::e_length = unknown_len;
+ if (Fl::handle(FL_DND_RELEASE, window)) {
+ fl_selection_requestor = Fl::belowmouse();
+ XConvertSelection(fl_display, fl_XdndSelection,
+ fl_dnd_type, XA_SECONDARY,
+ to_window, fl_event_time);
+ } else {
+ // Send the finished message if I refuse the drop.
+ // It is not clear whether I can just send finished always,
+ // or if I have to wait for the SelectionNotify event as the
+ // code is currently doing.
+ fl_sendClientMessage(fl_dnd_source_window, fl_XdndFinished, to_window);
+ fl_dnd_source_window = 0;
+ }
+ return 1;
+
+ }
+ break;}
+
+ case UnmapNotify:
+ event = FL_HIDE;
+ break;
+
+ case Expose:
+ Fl_X::i(window)->wait_for_expose = 0;
+# if 0
+ // try to keep windows on top even if WM_TRANSIENT_FOR does not work:
+ // opaque move/resize window managers do not like this, so I disabled it.
+ if (Fl::first_window()->non_modal() && window != Fl::first_window())
+ Fl::first_window()->show();
+# endif
+
+ case GraphicsExpose:
+ window->damage(FL_DAMAGE_EXPOSE, xevent.xexpose.x, xevent.xexpose.y,
+ xevent.xexpose.width, xevent.xexpose.height);
+ return 1;
+
+ case FocusIn:
+ event = FL_FOCUS;
+ break;
+
+ case FocusOut:
+ event = FL_UNFOCUS;
+ break;
+
+ case KeyPress:
+ case KeyRelease: {
+ KEYPRESS:
+ int keycode = xevent.xkey.keycode;
+ fl_key_vector[keycode/8] |= (1 << (keycode%8));
+ static char buffer[21];
+ int len;
+ KeySym keysym;
+ if (xevent.type == KeyPress) {
+ event = FL_KEYDOWN;
+ //static XComposeStatus compose;
+ len = XLookupString((XKeyEvent*)&(xevent.xkey),
+ buffer, 20, &keysym, 0/*&compose*/);
+ if (keysym && keysym < 0x400) { // a character in latin-1,2,3,4 sets
+ // force it to type a character (not sure if this ever is needed):
+ if (!len) {buffer[0] = char(keysym); len = 1;}
+ // ignore all effects of shift on the keysyms, which makes it a lot
+ // easier to program shortcuts and is Windoze-compatable:
+ keysym = XKeycodeToKeysym(fl_display, keycode, 0);
+ }
+ // MRS: Can't use Fl::event_state(FL_CTRL) since the state is not
+ // set until set_event_xy() is called later...
+ if ((xevent.xkey.state & ControlMask) && keysym == '-') buffer[0] = 0x1f; // ^_
+ buffer[len] = 0;
+ Fl::e_text = buffer;
+ Fl::e_length = len;
+ } else {
+ // Stupid X sends fake key-up events when a repeating key is held
+ // down, probably due to some back compatability problem. Fortunately
+ // we can detect this because the repeating KeyPress event is in
+ // the queue, get it and execute it instead:
+ XEvent temp;
+ if (XCheckIfEvent(fl_display,&temp,fake_keyup_test,(char*)(&xevent))){
+ xevent = temp;
+ goto KEYPRESS;
+ }
+ event = FL_KEYUP;
+ fl_key_vector[keycode/8] &= ~(1 << (keycode%8));
+ // keyup events just get the unshifted keysym:
+ keysym = XKeycodeToKeysym(fl_display, keycode, 0);
+ }
+# ifdef __sgi
+ // You can plug a microsoft keyboard into an sgi but the extra shift
+ // keys are not translated. Make them translate like XFree86 does:
+ if (!keysym) switch(keycode) {
+ case 147: keysym = FL_Meta_L; break;
+ case 148: keysym = FL_Meta_R; break;
+ case 149: keysym = FL_Menu; break;
+ }
+# endif
+# if BACKSPACE_HACK
+ // Attempt to fix keyboards that send "delete" for the key in the
+ // upper-right corner of the main keyboard. But it appears that
+ // very few of these remain?
+ static int got_backspace;
+ if (!got_backspace) {
+ if (keysym == FL_Delete) keysym = FL_BackSpace;
+ else if (keysym == FL_BackSpace) got_backspace = 1;
+ }
+# endif
+ // We have to get rid of the XK_KP_function keys, because they are
+ // not produced on Windoze and thus case statements tend not to check
+ // for them. There are 15 of these in the range 0xff91 ... 0xff9f
+ if (keysym >= 0xff91 && keysym <= 0xff9f) {
+ // Map keypad keysym to character or keysym depending on
+ // numlock state...
+ unsigned long keysym1 = XKeycodeToKeysym(fl_display, keycode, 1);
+ if (keysym1 <= 0x7f || (keysym1 > 0xff9f && keysym1 <= FL_KP_Last))
+ Fl::e_original_keysym = (int)(keysym1 | FL_KP);
+ if ((xevent.xkey.state & Mod2Mask) &&
+ (keysym1 <= 0x7f || (keysym1 > 0xff9f && keysym1 <= FL_KP_Last))) {
+ // Store ASCII numeric keypad value...
+ keysym = keysym1 | FL_KP;
+ buffer[0] = char(keysym1) & 0x7F;
+ len = 1;
+ } else {
+ // Map keypad to special key...
+ static const unsigned short table[15] = {
+ FL_F+1, FL_F+2, FL_F+3, FL_F+4,
+ FL_Home, FL_Left, FL_Up, FL_Right,
+ FL_Down, FL_Page_Up, FL_Page_Down, FL_End,
+ 0xff0b/*XK_Clear*/, FL_Insert, FL_Delete};
+ keysym = table[keysym-0xff91];
+ }
+ } else {
+ // Store this so we can later know if the KP was used
+ Fl::e_original_keysym = (int)keysym;
+ }
+ Fl::e_keysym = int(keysym);
+ set_event_xy();
+ Fl::e_is_click = 0;
+ break;}
+
+ case ButtonPress:
+ Fl::e_keysym = FL_Button + xevent.xbutton.button;
+ set_event_xy();
+ if (xevent.xbutton.button == Button4) {
+ Fl::e_dy = -1; // Up
+ event = FL_MOUSEWHEEL;
+ } else if (xevent.xbutton.button == Button5) {
+ Fl::e_dy = +1; // Down
+ event = FL_MOUSEWHEEL;
+ } else {
+ Fl::e_state |= (FL_BUTTON1 << (xevent.xbutton.button-1));
+ event = FL_PUSH;
+ checkdouble();
+ }
+
+ fl_xmousewin = window;
+ in_a_window = true;
+ break;
+
+ case MotionNotify:
+ set_event_xy();
+# if CONSOLIDATE_MOTION
+ send_motion = fl_xmousewin = window;
+ in_a_window = true;
+ return 0;
+# else
+ event = FL_MOVE;
+ fl_xmousewin = window;
+ in_a_window = true;
+ break;
+# endif
+
+ case ButtonRelease:
+ Fl::e_keysym = FL_Button + xevent.xbutton.button;
+ set_event_xy();
+ Fl::e_state &= ~(FL_BUTTON1 << (xevent.xbutton.button-1));
+ if (xevent.xbutton.button == Button4 ||
+ xevent.xbutton.button == Button5) return 0;
+ event = FL_RELEASE;
+
+ fl_xmousewin = window;
+ in_a_window = true;
+ break;
+
+ case EnterNotify:
+ if (xevent.xcrossing.detail == NotifyInferior) break;
+ // XInstallColormap(fl_display, Fl_X::i(window)->colormap);
+ set_event_xy();
+ Fl::e_state = xevent.xcrossing.state << 16;
+ event = FL_ENTER;
+
+ fl_xmousewin = window;
+ in_a_window = true;
+ break;
+
+ case LeaveNotify:
+ if (xevent.xcrossing.detail == NotifyInferior) break;
+ set_event_xy();
+ Fl::e_state = xevent.xcrossing.state << 16;
+ fl_xmousewin = 0;
+ in_a_window = false; // make do_queued_events produce FL_LEAVE event
+ return 0;
+
+ // We cannot rely on the x,y position in the configure notify event.
+ // I now think this is an unavoidable problem with X: it is impossible
+ // for a window manager to prevent the "real" notify event from being
+ // sent when it resizes the contents, even though it can send an
+ // artificial event with the correct position afterwards (and some
+ // window managers do not send this fake event anyway)
+ // So anyway, do a round trip to find the correct x,y:
+ case MapNotify:
+ event = FL_SHOW;
+
+ case ConfigureNotify: {
+ if (window->parent()) break; // ignore child windows
+
+ // figure out where OS really put window
+ XWindowAttributes actual;
+ XGetWindowAttributes(fl_display, fl_xid(window), &actual);
+ Window cr; int X, Y, W = actual.width, H = actual.height;
+ XTranslateCoordinates(fl_display, fl_xid(window), actual.root,
+ 0, 0, &X, &Y, &cr);
+
+ // tell Fl_Window about it and set flag to prevent echoing:
+ resize_bug_fix = window;
+ window->resize(X, Y, W, H);
+ break; // allow add_handler to do something too
+ }
+
+ case ReparentNotify: {
+ int xpos, ypos;
+ Window junk;
+
+ //ReparentNotify gives the new position of the window relative to
+ //the new parent. FLTK cares about the position on the root window.
+ XTranslateCoordinates(fl_display, xevent.xreparent.parent,
+ XRootWindow(fl_display, fl_screen),
+ xevent.xreparent.x, xevent.xreparent.y,
+ &xpos, &ypos, &junk);
+
+ // tell Fl_Window about it and set flag to prevent echoing:
+ resize_bug_fix = window;
+ window->position(xpos, ypos);
+ break;
+ }
+ }
+
+ return Fl::handle(event, window);
+}
+
+////////////////////////////////////////////////////////////////
+
+void Fl_Window::resize(int X,int Y,int W,int H) {
+ int is_a_move = (X != x() || Y != y());
+ int is_a_resize = (W != w() || H != h());
+ int resize_from_program = (this != resize_bug_fix);
+ if (!resize_from_program) resize_bug_fix = 0;
+ if (is_a_move && resize_from_program) set_flag(FL_FORCE_POSITION);
+ else if (!is_a_resize && !is_a_move) return;
+ if (is_a_resize) {
+ Fl_Group::resize(X,Y,W,H);
+ if (shown()) {redraw(); i->wait_for_expose = 1;}
+ } else {
+ x(X); y(Y);
+ }
+
+ if (resize_from_program && is_a_resize && !resizable()) {
+ size_range(w(), h(), w(), h());
+ }
+
+ if (resize_from_program && shown()) {
+ if (is_a_resize) {
+ if (!resizable()) size_range(w(),h(),w(),h());
+ if (is_a_move) {
+ XMoveResizeWindow(fl_display, i->xid, X, Y, W>0 ? W : 1, H>0 ? H : 1);
+ } else {
+ XResizeWindow(fl_display, i->xid, W>0 ? W : 1, H>0 ? H : 1);
+ }
+ } else
+ XMoveWindow(fl_display, i->xid, X, Y);
+ }
+}
+
+////////////////////////////////////////////////////////////////
+
+// A subclass of Fl_Window may call this to associate an X window it
+// creates with the Fl_Window:
+
+void fl_fix_focus(); // in Fl.cxx
+
+Fl_X* Fl_X::set_xid(Fl_Window* win, Window winxid) {
+ Fl_X* xp = new Fl_X;
+ xp->xid = winxid;
+ xp->other_xid = 0;
+ xp->setwindow(win);
+ xp->next = Fl_X::first;
+ xp->region = 0;
+ xp->wait_for_expose = 1;
+ xp->backbuffer_bad = 1;
+ Fl_X::first = xp;
+ if (win->modal()) {Fl::modal_ = win; fl_fix_focus();}
+ return xp;
+}
+
+// More commonly a subclass calls this, because it hides the really
+// ugly parts of X and sets all the stuff for a window that is set
+// normally. The global variables like fl_show_iconic are so that
+// subclasses of *that* class may change the behavior...
+
+char fl_show_iconic; // hack for iconize()
+int fl_background_pixel = -1; // hack to speed up bg box drawing
+int fl_disable_transient_for; // secret method of removing TRANSIENT_FOR
+
+static const int childEventMask = ExposureMask;
+
+static const int XEventMask =
+ExposureMask|StructureNotifyMask
+|KeyPressMask|KeyReleaseMask|KeymapStateMask|FocusChangeMask
+|ButtonPressMask|ButtonReleaseMask
+|EnterWindowMask|LeaveWindowMask
+|PointerMotionMask;
+
+void Fl_X::make_xid(Fl_Window* win, XVisualInfo *visual, Colormap colormap)
+{
+ Fl_Group::current(0); // get rid of very common user bug: forgot end()
+
+ int X = win->x();
+ int Y = win->y();
+ int W = win->w();
+ if (W <= 0) W = 1; // X don't like zero...
+ int H = win->h();
+ if (H <= 0) H = 1; // X don't like zero...
+ if (!win->parent() && !Fl::grab()) {
+ // center windows in case window manager does not do anything:
+#ifdef FL_CENTER_WINDOWS
+ if (!(win->flags() & Fl_Window::FL_FORCE_POSITION)) {
+ win->x(X = scr_x+(scr_w-W)/2);
+ win->y(Y = scr_y+(scr_h-H)/2);
+ }
+#endif // FL_CENTER_WINDOWS
+
+ // force the window to be on-screen. Usually the X window manager
+ // does this, but a few don't, so we do it here for consistency:
+ int scr_x, scr_y, scr_w, scr_h;
+ Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h, X, Y);
+
+ if (win->border()) {
+ // ensure border is on screen:
+ // (assumme extremely minimal dimensions for this border)
+ const int top = 20;
+ const int left = 1;
+ const int right = 1;
+ const int bottom = 1;
+ if (X+W+right > scr_x+scr_w) X = scr_x+scr_w-right-W;
+ if (X-left < scr_x) X = scr_x+left;
+ if (Y+H+bottom > scr_y+scr_h) Y = scr_y+scr_h-bottom-H;
+ if (Y-top < scr_y) Y = scr_y+top;
+ }
+ // now insure contents are on-screen (more important than border):
+ if (X+W > scr_x+scr_w) X = scr_x+scr_w-W;
+ if (X < scr_x) X = scr_x;
+ if (Y+H > scr_y+scr_h) Y = scr_y+scr_h-H;
+ if (Y < scr_y) Y = scr_y;
+ }
+
+ // if the window is a subwindow and our parent is not mapped yet, we
+ // mark this window visible, so that mapping the parent at a later
+ // point in time will call this function again to finally map the subwindow.
+ if (win->parent() && !Fl_X::i(win->window())) {
+ win->set_visible();
+ return;
+ }
+
+ ulong root = win->parent() ?
+ fl_xid(win->window()) : RootWindow(fl_display, fl_screen);
+
+ XSetWindowAttributes attr;
+ int mask = CWBorderPixel|CWColormap|CWEventMask|CWBitGravity;
+ attr.event_mask = win->parent() ? childEventMask : XEventMask;
+ attr.colormap = colormap;
+ attr.border_pixel = 0;
+ attr.bit_gravity = 0; // StaticGravity;
+ if (win->override()) {
+ attr.override_redirect = 1;
+ attr.save_under = 1;
+ mask |= CWOverrideRedirect | CWSaveUnder;
+ } else attr.override_redirect = 0;
+ if (Fl::grab()) {
+ attr.save_under = 1; mask |= CWSaveUnder;
+ if (!win->border()) {attr.override_redirect = 1; mask |= CWOverrideRedirect;}
+ }
+ if (fl_background_pixel >= 0) {
+ attr.background_pixel = fl_background_pixel;
+ fl_background_pixel = -1;
+ mask |= CWBackPixel;
+ }
+
+ Fl_X* xp =
+ set_xid(win, XCreateWindow(fl_display,
+ root,
+ X, Y, W, H,
+ 0, // borderwidth
+ visual->depth,
+ InputOutput,
+ visual->visual,
+ mask, &attr));
+ int showit = 1;
+
+ if (!win->parent() && !attr.override_redirect) {
+ // Communicate all kinds 'o junk to the X Window Manager:
+
+ win->label(win->label(), win->iconlabel());
+
+ XChangeProperty(fl_display, xp->xid, WM_PROTOCOLS,
+ XA_ATOM, 32, 0, (uchar*)&WM_DELETE_WINDOW, 1);
+
+ // send size limits and border:
+ xp->sendxjunk();
+
+ // set the class property, which controls the icon used:
+ if (win->xclass()) {
+ char buffer[1024];
+ char *p; const char *q;
+ // truncate on any punctuation, because they break XResource lookup:
+ for (p = buffer, q = win->xclass(); isalnum(*q)||(*q&128);) *p++ = *q++;
+ *p++ = 0;
+ // create the capitalized version:
+ q = buffer;
+ *p = toupper(*q++); if (*p++ == 'X') *p++ = toupper(*q++);
+ while ((*p++ = *q++));
+ XChangeProperty(fl_display, xp->xid, XA_WM_CLASS, XA_STRING, 8, 0,
+ (unsigned char *)buffer, p-buffer-1);
+ }
+
+ if (win->non_modal() && xp->next && !fl_disable_transient_for) {
+ // find some other window to be "transient for":
+ Fl_Window* wp = xp->next->w;
+ while (wp->parent()) wp = wp->window();
+ XSetTransientForHint(fl_display, xp->xid, fl_xid(wp));
+ if (!wp->visible()) showit = 0; // guess that wm will not show it
+ }
+
+ // Make sure that borderless windows do not show in the task bar
+ if (!win->border()) {
+ Atom net_wm_state = XInternAtom (fl_display, "_NET_WM_STATE", 0);
+ Atom net_wm_state_skip_taskbar = XInternAtom (fl_display, "_NET_WM_STATE_SKIP_TASKBAR", 0);
+ XChangeProperty (fl_display, xp->xid, net_wm_state, XA_ATOM, 32,
+ PropModeAppend, (unsigned char*) &net_wm_state_skip_taskbar, 1);
+ }
+
+ // Make it receptive to DnD:
+ long version = 4;
+ XChangeProperty(fl_display, xp->xid, fl_XdndAware,
+ XA_ATOM, sizeof(int)*8, 0, (unsigned char*)&version, 1);
+
+ XWMHints *hints = XAllocWMHints();
+ hints->input = True;
+ hints->flags = InputHint;
+ if (fl_show_iconic) {
+ hints->flags |= StateHint;
+ hints->initial_state = IconicState;
+ fl_show_iconic = 0;
+ showit = 0;
+ }
+ if (win->icon()) {
+ hints->icon_pixmap = (Pixmap)win->icon();
+ hints->flags |= IconPixmapHint;
+ }
+ XSetWMHints(fl_display, xp->xid, hints);
+ XFree(hints);
+ }
+
+ XMapWindow(fl_display, xp->xid);
+ if (showit) {
+ win->set_visible();
+ int old_event = Fl::e_number;
+ win->handle(Fl::e_number = FL_SHOW); // get child windows to appear
+ Fl::e_number = old_event;
+ win->redraw();
+ }
+}
+
+////////////////////////////////////////////////////////////////
+// Send X window stuff that can be changed over time:
+
+void Fl_X::sendxjunk() {
+ if (w->parent() || w->override()) return; // it's not a window manager window!
+
+ if (!w->size_range_set) { // default size_range based on resizable():
+ if (w->resizable()) {
+ Fl_Widget *o = w->resizable();
+ int minw = o->w(); if (minw > 100) minw = 100;
+ int minh = o->h(); if (minh > 100) minh = 100;
+ w->size_range(w->w() - o->w() + minw, w->h() - o->h() + minh, 0, 0);
+ } else {
+ w->size_range(w->w(), w->h(), w->w(), w->h());
+ }
+ return; // because this recursively called here
+ }
+
+ XSizeHints *hints = XAllocSizeHints();
+ // memset(&hints, 0, sizeof(hints)); jreiser suggestion to fix purify?
+ hints->min_width = w->minw;
+ hints->min_height = w->minh;
+ hints->max_width = w->maxw;
+ hints->max_height = w->maxh;
+ hints->width_inc = w->dw;
+ hints->height_inc = w->dh;
+ hints->win_gravity = StaticGravity;
+
+ // see the file /usr/include/X11/Xm/MwmUtil.h:
+ // fill all fields to avoid bugs in kwm and perhaps other window managers:
+ // 0, MWM_FUNC_ALL, MWM_DECOR_ALL
+ long prop[5] = {0, 1, 1, 0, 0};
+
+ if (hints->min_width != hints->max_width ||
+ hints->min_height != hints->max_height) { // resizable
+ hints->flags = PMinSize|PWinGravity;
+ if (hints->max_width >= hints->min_width ||
+ hints->max_height >= hints->min_height) {
+ hints->flags = PMinSize|PMaxSize|PWinGravity;
+ // unfortunately we can't set just one maximum size. Guess a
+ // value for the other one. Some window managers will make the
+ // window fit on screen when maximized, others will put it off screen:
+ if (hints->max_width < hints->min_width) hints->max_width = Fl::w();
+ if (hints->max_height < hints->min_height) hints->max_height = Fl::h();
+ }
+ if (hints->width_inc && hints->height_inc) hints->flags |= PResizeInc;
+ if (w->aspect) {
+ // stupid X! It could insist that the corner go on the
+ // straight line between min and max...
+ hints->min_aspect.x = hints->max_aspect.x = hints->min_width;
+ hints->min_aspect.y = hints->max_aspect.y = hints->min_height;
+ hints->flags |= PAspect;
+ }
+ } else { // not resizable:
+ hints->flags = PMinSize|PMaxSize|PWinGravity;
+ prop[0] = 1; // MWM_HINTS_FUNCTIONS
+ prop[1] = 1|2|16; // MWM_FUNC_ALL | MWM_FUNC_RESIZE | MWM_FUNC_MAXIMIZE
+ }
+
+ if (w->flags() & Fl_Window::FL_FORCE_POSITION) {
+ hints->flags |= USPosition;
+ hints->x = w->x();
+ hints->y = w->y();
+ }
+
+ if (!w->border()) {
+ prop[0] |= 2; // MWM_HINTS_DECORATIONS
+ prop[2] = 0; // no decorations
+ }
+
+ XSetWMNormalHints(fl_display, xid, hints);
+ XChangeProperty(fl_display, xid,
+ fl_MOTIF_WM_HINTS, fl_MOTIF_WM_HINTS,
+ 32, 0, (unsigned char *)prop, 5);
+ XFree(hints);
+}
+
+void Fl_Window::size_range_() {
+ size_range_set = 1;
+ if (shown()) i->sendxjunk();
+}
+
+////////////////////////////////////////////////////////////////
+
+// returns pointer to the filename, or null if name ends with '/'
+const char *fl_filename_name(const char *name) {
+ const char *p,*q;
+ if (!name) return (0);
+ for (p=q=name; *p;) if (*p++ == '/') q = p;
+ return q;
+}
+
+void Fl_Window::label(const char *name,const char *iname) {
+ Fl_Widget::label(name);
+ iconlabel_ = iname;
+ if (shown() && !parent()) {
+ if (!name) name = "";
+ XChangeProperty(fl_display, i->xid, XA_WM_NAME,
+ XA_STRING, 8, 0, (uchar*)name, strlen(name));
+ if (!iname) iname = fl_filename_name(name);
+ XChangeProperty(fl_display, i->xid, XA_WM_ICON_NAME,
+ XA_STRING, 8, 0, (uchar*)iname, strlen(iname));
+ }
+}
+
+////////////////////////////////////////////////////////////////
+// Implement the virtual functions for the base Fl_Window class:
+
+// If the box is a filled rectangle, we can make the redisplay *look*
+// faster by using X's background pixel erasing. We can make it
+// actually *be* faster by drawing the frame only, this is done by
+// setting fl_boxcheat, which is seen by code in fl_drawbox.cxx:
+//
+// On XFree86 (and prehaps all X's) this has a problem if the window
+// is resized while a save-behind window is atop it. The previous
+// contents are restored to the area, but this assummes the area
+// is cleared to background color. So this is disabled in this version.
+// Fl_Window *fl_boxcheat;
+static inline int can_boxcheat(uchar b) {return (b==1 || (b&2) && b<=15);}
+
+void Fl_Window::show() {
+ image(Fl::scheme_bg_);
+ if (Fl::scheme_bg_) {
+ labeltype(FL_NORMAL_LABEL);
+ align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE | FL_ALIGN_CLIP);
+ } else {
+ labeltype(FL_NO_LABEL);
+ }
+ Fl_Tooltip::exit(this);
+ if (!shown()) {
+ fl_open_display();
+ // Don't set background pixel for double-buffered windows...
+ if (type() == FL_WINDOW && can_boxcheat(box())) {
+ fl_background_pixel = int(fl_xpixel(color()));
+ }
+ Fl_X::make_xid(this);
+ } else {
+ XMapRaised(fl_display, i->xid);
+ }
+}
+
+Window fl_window;
+Fl_Window *Fl_Window::current_;
+GC fl_gc;
+
+// make X drawing go into this window (called by subclass flush() impl.)
+void Fl_Window::make_current() {
+ static GC gc; // the GC used by all X windows
+ if (!gc) gc = XCreateGC(fl_display, i->xid, 0, 0);
+ fl_window = i->xid;
+ fl_gc = gc;
+ current_ = this;
+ fl_clip_region(0);
+}
+
+#endif
+
+//
+// End of "$Id: Fl_x.cxx 5914 2007-06-18 13:08:57Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/Makefile b/third_party/windows/fltk-1.1.10/src/Makefile new file mode 100644 index 0000000..c9c7556 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Makefile @@ -0,0 +1,726 @@ +#
+# "$Id: Makefile 6817 2009-07-02 09:42:17Z AlbrechtS $"
+#
+# Library makefile for the Fast Light Tool Kit (FLTK).
+#
+# Copyright 1998-2009 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
+#
+
+CPPFILES = \
+ Fl.cxx \
+ Fl_Adjuster.cxx \
+ Fl_Bitmap.cxx \
+ Fl_Browser.cxx \
+ Fl_Browser_.cxx \
+ Fl_Browser_load.cxx \
+ Fl_Box.cxx \
+ Fl_Button.cxx \
+ Fl_Chart.cxx \
+ Fl_Check_Browser.cxx \
+ Fl_Check_Button.cxx \
+ Fl_Choice.cxx \
+ Fl_Clock.cxx \
+ Fl_Color_Chooser.cxx \
+ Fl_Counter.cxx \
+ Fl_Dial.cxx \
+ Fl_Double_Window.cxx \
+ Fl_File_Browser.cxx \
+ Fl_File_Chooser.cxx \
+ Fl_File_Chooser2.cxx \
+ Fl_File_Icon.cxx \
+ Fl_File_Input.cxx \
+ Fl_Group.cxx \
+ Fl_Help_View.cxx \
+ Fl_Image.cxx \
+ Fl_Input.cxx \
+ Fl_Input_.cxx \
+ Fl_Light_Button.cxx \
+ Fl_Menu.cxx \
+ Fl_Menu_.cxx \
+ Fl_Menu_Bar.cxx \
+ Fl_Sys_Menu_Bar.cxx \
+ Fl_Menu_Button.cxx \
+ Fl_Menu_Window.cxx \
+ Fl_Menu_add.cxx \
+ Fl_Menu_global.cxx \
+ Fl_Multi_Label.cxx \
+ Fl_Overlay_Window.cxx \
+ Fl_Pack.cxx \
+ Fl_Pixmap.cxx \
+ Fl_Positioner.cxx \
+ Fl_Preferences.cxx \
+ Fl_Progress.cxx \
+ Fl_Repeat_Button.cxx \
+ Fl_Return_Button.cxx \
+ Fl_Roller.cxx \
+ Fl_Round_Button.cxx \
+ Fl_Scroll.cxx \
+ Fl_Scrollbar.cxx \
+ Fl_Shared_Image.cxx \
+ Fl_Single_Window.cxx \
+ Fl_Slider.cxx \
+ Fl_Tabs.cxx \
+ Fl_Text_Buffer.cxx \
+ Fl_Text_Display.cxx \
+ Fl_Text_Editor.cxx \
+ Fl_Tile.cxx \
+ Fl_Tiled_Image.cxx \
+ Fl_Tooltip.cxx \
+ Fl_Valuator.cxx \
+ Fl_Value_Input.cxx \
+ Fl_Value_Output.cxx \
+ Fl_Value_Slider.cxx \
+ Fl_Widget.cxx \
+ Fl_Window.cxx \
+ Fl_Window_fullscreen.cxx \
+ Fl_Window_hotspot.cxx \
+ Fl_Window_iconize.cxx \
+ Fl_Wizard.cxx \
+ Fl_XBM_Image.cxx \
+ Fl_XPM_Image.cxx \
+ Fl_abort.cxx \
+ Fl_add_idle.cxx \
+ Fl_arg.cxx \
+ Fl_compose.cxx \
+ Fl_display.cxx \
+ Fl_get_key.cxx \
+ Fl_get_system_colors.cxx \
+ Fl_grab.cxx \
+ Fl_lock.cxx \
+ Fl_own_colormap.cxx \
+ Fl_visual.cxx \
+ Fl_x.cxx \
+ filename_absolute.cxx \
+ filename_expand.cxx \
+ filename_ext.cxx \
+ filename_isdir.cxx \
+ filename_list.cxx \
+ filename_match.cxx \
+ filename_setext.cxx \
+ fl_arc.cxx \
+ fl_arci.cxx \
+ fl_ask.cxx \
+ fl_boxtype.cxx \
+ fl_color.cxx \
+ fl_cursor.cxx \
+ fl_curve.cxx \
+ fl_diamond_box.cxx \
+ fl_dnd.cxx \
+ fl_draw.cxx \
+ fl_draw_image.cxx \
+ fl_draw_pixmap.cxx \
+ fl_encoding_latin1.cxx \
+ fl_encoding_mac_roman.cxx \
+ fl_engraved_label.cxx \
+ fl_file_dir.cxx \
+ fl_font.cxx \
+ fl_gtk.cxx \
+ fl_labeltype.cxx \
+ fl_line_style.cxx \
+ fl_open_uri.cxx \
+ fl_oval_box.cxx \
+ fl_overlay.cxx \
+ fl_overlay_visual.cxx \
+ fl_plastic.cxx \
+ fl_read_image.cxx \
+ fl_rect.cxx \
+ fl_round_box.cxx \
+ fl_rounded_box.cxx \
+ fl_set_font.cxx \
+ fl_set_fonts.cxx \
+ fl_scroll_area.cxx \
+ fl_shadow_box.cxx \
+ fl_shortcut.cxx \
+ fl_show_colormap.cxx \
+ fl_symbols.cxx \
+ fl_vertex.cxx \
+ screen_xywh.cxx
+
+FLCPPFILES = \
+ forms_compatability.cxx \
+ forms_bitmap.cxx \
+ forms_free.cxx \
+ forms_fselect.cxx \
+ forms_pixmap.cxx \
+ forms_timer.cxx
+
+GLCPPFILES = \
+ Fl_Gl_Choice.cxx \
+ Fl_Gl_Overlay.cxx \
+ Fl_Gl_Window.cxx \
+ freeglut_geometry.cxx \
+ freeglut_stroke_mono_roman.cxx \
+ freeglut_stroke_roman.cxx \
+ freeglut_teapot.cxx \
+ gl_draw.cxx \
+ gl_start.cxx \
+ glut_compatability.cxx \
+ glut_font.cxx
+
+IMGCPPFILES = \
+ fl_images_core.cxx \
+ Fl_BMP_Image.cxx \
+ Fl_File_Icon2.cxx \
+ Fl_GIF_Image.cxx \
+ Fl_Help_Dialog.cxx \
+ Fl_JPEG_Image.cxx \
+ Fl_PNG_Image.cxx \
+ Fl_PNM_Image.cxx
+
+CFILES = fl_call_main.c flstring.c scandir.c numericsort.c vsnprintf.c
+
+################################################################
+
+include ../makeinclude
+
+OBJECTS = $(CPPFILES:.cxx=.o) $(CFILES:.c=.o)
+GLOBJECTS = $(GLCPPFILES:.cxx=.o)
+FLOBJECTS = $(FLCPPFILES:.cxx=.o)
+IMGOBJECTS = $(IMGCPPFILES:.cxx=.o)
+
+all: $(LIBNAME) $(DSONAME) \
+ $(FLLIBNAME) $(FLDSONAME) \
+ $(GLLIBNAME) $(GLDSONAME) \
+ $(IMGLIBNAME) $(IMGDSONAME)
+
+$(LIBNAME): $(OBJECTS)
+ echo $(LIBCOMMAND) $@ ...
+ $(RM) $@
+ $(LIBCOMMAND) $@ $(OBJECTS)
+ $(RANLIB) $@
+
+libfltk.so.1.1: $(OBJECTS)
+ echo $(DSOCOMMAND) $@ ...
+ $(DSOCOMMAND) $@ $(OBJECTS)
+ $(RM) libfltk.so
+ $(LN) libfltk.so.1.1 libfltk.so
+
+libfltk.sl.1.1: $(OBJECTS)
+ echo $(DSOCOMMAND) $@ ...
+ $(DSOCOMMAND) $@ $(OBJECTS)
+ $(RM) libfltk.sl
+ $(LN) libfltk.sl.1.1 libfltk.sl
+
+libfltk.1.1.dylib: $(OBJECTS)
+ echo $(DSOCOMMAND) $@ ...
+ $(DSOCOMMAND) $@ \
+ -install_name $(libdir)/$@ \
+ -current_version 1.1.4 \
+ -compatibility_version 1.1.0 \
+ $(OBJECTS) $(LDLIBS)
+ $(RM) libfltk.dylib
+ $(LN) libfltk.1.1.dylib libfltk.dylib
+
+libfltk_s.a: $(OBJECTS)
+ echo $(DSOCOMMAND) libfltk_s.o ...
+ $(DSOCOMMAND) libfltk_s.o $(OBJECTS) $(IMAGELIBS)
+ echo $(LIBCOMMAND) libfltk_s.a libfltk_s.o
+ $(RM) $@
+ $(LIBCOMMAND) libfltk_s.a libfltk_s.o
+ $(CHMOD) +x libfltk_s.a
+
+$(FLLIBNAME): $(FLOBJECTS)
+ echo $(LIBCOMMAND) $@ ...
+ $(RM) $@
+ $(LIBCOMMAND) $@ $(FLOBJECTS)
+ $(RANLIB) $@
+
+libfltk_forms.so.1.1: $(FLOBJECTS) libfltk.so.1.1
+ echo $(DSOCOMMAND) $@ ...
+ $(DSOCOMMAND) $@ $(FLOBJECTS) -L. -lfltk
+ $(RM) libfltk_forms.so
+ $(LN) libfltk_forms.so.1.1 libfltk_forms.so
+
+libfltk_forms.sl.1.1: $(FLOBJECTS) libfltk.sl.1.1
+ echo $(DSOCOMMAND) $@ ...
+ $(DSOCOMMAND) $@ $(FLOBJECTS) -L. -lfltk
+ $(RM) libfltk_forms.sl
+ $(LN) libfltk_forms.sl.1.1 libfltk_forms.sl
+
+libfltk_forms.1.1.dylib: $(FLOBJECTS) libfltk.1.1.dylib
+ echo $(DSOCOMMAND) $@ ...
+ $(DSOCOMMAND) $@ \
+ -install_name $(libdir)/$@ \
+ -current_version 1.1.4 \
+ -compatibility_version 1.1.0 \
+ $(FLOBJECTS) -L. $(LDLIBS) -lfltk
+ $(RM) libfltk_forms.dylib
+ $(LN) libfltk_forms.1.1.dylib libfltk_forms.dylib
+
+libfltk_forms_s.a: $(FLOBJECTS)
+ echo $(DSOCOMMAND) libfltk_forms_s.o ...
+ $(DSOCOMMAND) libfltk_forms_s.o $(FLOBJECTS)
+ echo $(LIBCOMMAND) libfltk_forms_s.a libfltk_forms_s.o
+ $(RM) $@
+ $(LIBCOMMAND) libfltk_forms_s.a libfltk_forms_s.o
+ $(CHMOD) +x libfltk_forms_s.a
+
+$(GLLIBNAME): $(GLOBJECTS)
+ echo $(LIBCOMMAND) $@ ...
+ $(RM) $@
+ $(LIBCOMMAND) $@ $(GLOBJECTS)
+ $(RANLIB) $@
+
+libfltk_gl.so.1.1: $(GLOBJECTS) libfltk.so.1.1
+ echo $(DSOCOMMAND) $@ ...
+ $(DSOCOMMAND) $@ $(GLOBJECTS) -L. -lfltk
+ $(RM) libfltk_gl.so
+ $(LN) libfltk_gl.so.1.1 libfltk_gl.so
+
+libfltk_gl.sl.1.1: $(GLOBJECTS) libfltk.sl.1.1
+ echo $(DSOCOMMAND) $@ ...
+ $(DSOCOMMAND) $@ $(GLOBJECTS) -L. -lfltk
+ $(RM) libfltk_gl.sl
+ $(LN) libfltk_gl.sl.1.1 libfltk_gl.sl
+
+libfltk_gl.1.1.dylib: $(GLOBJECTS) libfltk.1.1.dylib
+ echo $(DSOCOMMAND) $@ ...
+ $(DSOCOMMAND) $@ \
+ -install_name $(libdir)/$@ \
+ -current_version 1.1.4 \
+ -compatibility_version 1.1.0 \
+ $(GLOBJECTS) -L. $(GLDLIBS) -lfltk
+ $(RM) libfltk_gl.dylib
+ $(LN) libfltk_gl.1.1.dylib libfltk_gl.dylib
+
+libfltk_gl_s.a: $(GLOBJECTS)
+ echo $(DSOCOMMAND) libfltk_gl_s.o ...
+ $(DSOCOMMAND) libfltk_gl_s.o $(GLOBJECTS)
+ echo $(LIBCOMMAND) libfltk_gl_s.a libfltk_gl_s.o
+ $(RM) $@
+ $(LIBCOMMAND) libfltk_gl_s.a libfltk_gl_s.o
+ $(CHMOD) +x libfltk_gl_s.a
+
+$(IMGLIBNAME): $(IMGOBJECTS)
+ echo $(LIBCOMMAND) $@ ...
+ $(RM) $@
+ $(LIBCOMMAND) $@ $(IMGOBJECTS)
+ $(RANLIB) $@
+
+libfltk_images.so.1.1: $(IMGOBJECTS) libfltk.so.1.1
+ echo $(DSOCOMMAND) $@ ...
+ $(DSOCOMMAND) $@ $(IMGOBJECTS) -L. $(IMAGELIBS) -lfltk
+ $(RM) libfltk_images.so
+ $(LN) libfltk_images.so.1.1 libfltk_images.so
+
+libfltk_images.sl.1.1: $(IMGOBJECTS) libfltk.sl.1.1
+ echo $(DSOCOMMAND) $@ ...
+ $(DSOCOMMAND) $@ $(IMGOBJECTS) -L. $(IMAGELIBS) -lfltk
+ $(RM) libfltk_images.sl
+ $(LN) libfltk_images.sl.1.1 libfltk_images.sl
+
+libfltk_images.1.1.dylib: $(IMGOBJECTS) libfltk.1.1.dylib
+ echo $(DSOCOMMAND) $@ ...
+ $(DSOCOMMAND) $@ \
+ -install_name $(libdir)/$@ \
+ -current_version 1.1.4 \
+ -compatibility_version 1.1.0 \
+ $(IMGOBJECTS) -L. $(LDLIBS) $(IMAGELIBS) -lfltk
+ $(RM) libfltk_images.dylib
+ $(LN) libfltk_images.1.1.dylib libfltk_images.dylib
+
+libfltk_images_s.a: $(IMGOBJECTS)
+ echo $(DSOCOMMAND) libfltk_images_s.o ...
+ $(DSOCOMMAND) libfltk_images_s.o $(IMGOBJECTS)
+ echo $(LIBCOMMAND) libfltk_images_s.a libfltk_images_s.o
+ $(RM) $@
+ $(LIBCOMMAND) libfltk_images_s.a libfltk_images_s.o
+ $(CHMOD) +x libfltk_images_s.a
+
+#-----------------------------------------------------------------
+# - the import libraries libfltk*.dll.a and the .dll files
+# are created from the libfltk*.a files. They are built
+# into the src dir.
+# - The _images, _gl, _forms and dlls must be linked
+# against the import libraries in the src dir.
+#-----------------------------------------------------------------
+
+cygfltknox-1.1.dll: $(LIBNAME)
+ echo $(DSOCOMMAND) $(LIBNAME) ...
+ $(DSOCOMMAND) $(LIBNAME) -Wl,--no-whole-archive \
+ -Wl,--out-implib=libfltk.dll.a $(LDLIBS)
+
+cygfltknox_forms-1.1.dll: $(FLLIBNAME) cygfltknox-1.1.dll
+ echo $(DSOCOMMAND) $(FLLIBNAME) ...
+ $(DSOCOMMAND) $(FLLIBNAME) -Wl,--no-whole-archive \
+ -Wl,--out-implib=libfltk_forms.dll.a \
+ -L. -lfltk $(LDLIBS)
+
+cygfltknox_gl-1.1.dll: $(GLLIBNAME) cygfltknox-1.1.dll
+ echo $(DSOCOMMAND) $(GLLIBNAME) ...
+ $(DSOCOMMAND) $(GLLIBNAME) -Wl,--no-whole-archive \
+ -Wl,--out-implib=libfltk_gl.dll.a \
+ -L. -lfltk $(GLDLIBS)
+
+cygfltknox_images-1.1.dll: $(IMGLIBNAME) cygfltknox-1.1.dll
+ echo $(DSOCOMMAND) $(IMGLIBNAME) ...
+ $(DSOCOMMAND) $(IMGLIBNAME) -Wl,--no-whole-archive \
+ -Wl,--out-implib=libfltk_images.dll.a \
+ -L. -lfltk -Wl,--exclude-libs -Wl,libfltk_png.a \
+ $(IMAGELIBS) $(LDLIBS)
+
+mgwfltknox-1.1.dll: $(LIBNAME)
+ echo $(DSOCOMMAND) $(LIBNAME) ...
+ $(DSOCOMMAND) $(LIBNAME) -Wl,--no-whole-archive \
+ -Wl,--out-implib=libfltk.dll.a $(LDLIBS)
+
+mgwfltknox_forms-1.1.dll: $(FLLIBNAME) mgwfltknox-1.1.dll
+ echo $(DSOCOMMAND) $(FLLIBNAME) ...
+ $(DSOCOMMAND) $(FLLIBNAME) -Wl,--no-whole-archive \
+ -Wl,--out-implib=libfltk_forms.dll.a \
+ -L. -lfltk $(LDLIBS)
+
+mgwfltknox_gl-1.1.dll: $(GLLIBNAME) mgwfltknox-1.1.dll
+ echo $(DSOCOMMAND) $(GLLIBNAME) ...
+ $(DSOCOMMAND) $(GLLIBNAME) -Wl,--no-whole-archive \
+ -Wl,--out-implib=libfltk_gl.dll.a \
+ -L. -lfltk $(GLDLIBS)
+
+#-----------------------------------------------------
+# See STR #1585 for --exclude-libs
+#-----------------------------------------------------
+
+mgwfltknox_images-1.1.dll: $(IMGLIBNAME) mgwfltknox-1.1.dll
+ echo $(DSOCOMMAND) $(IMGLIBNAME) ...
+ $(DSOCOMMAND) $(IMGLIBNAME) -Wl,--no-whole-archive \
+ -Wl,--out-implib=libfltk_images.dll.a \
+ -L. -lfltk -Wl,--exclude-libs -Wl,libfltk_png.a \
+ $(IMAGELIBS) $(LDLIBS)
+
+clean:
+ -$(RM) *.o *.dll.a core.* *~ *.bck *.bck
+ -$(RM) $(DSONAME) $(FLDSONAME) $(GLDSONAME) $(IMGDSONAME) \
+ $(LIBNAME) $(FLLIBNAME) $(GLLIBNAME) \
+ $(IMGLIBNAME) \
+ libfltk.so libfltk_forms.so libfltk_gl.so libfltk_images.so \
+ libfltk.sl libfltk_forms.sl libfltk_gl.sl libfltk_images.sl \
+ libfltk.dylib libfltk_forms.dylib \
+ libfltk_gl.dylib libfltk_images.dylib \
+ cmap core
+
+depend: $(CPPFILES) $(FLCPPFILES) $(GLCPPFILES) $(IMGCPPFILES) $(CFILES)
+ makedepend -Y -I.. -f makedepend $(CPPFILES) $(FLCPPFILES) \
+ $(GLCPPFILES) $(IMGCPPFILES) $(CFILES)
+
+# Automatically generated dependencies...
+include makedepend
+
+# These dependencies aren't part of the makedepend file since
+# they are part of the WIN32 and MacOS code base...
+Fl_get_key.o: Fl_get_key_mac.cxx Fl_get_key_win32.cxx
+Fl.o: Fl_mac.cxx Fl_win32.cxx
+fl_color.o: fl_color_mac.cxx fl_color_win32.cxx
+fl_dnd.o: fl_dnd_mac.cxx fl_dnd_win32.cxx fl_dnd_x.cxx
+fl_draw_image.o: fl_draw_image_mac.cxx fl_draw_image_win32.cxx
+fl_font.o: fl_font_mac.cxx fl_font_x.cxx fl_font_xft.cxx fl_font_win32.cxx
+fl_read_image.o: fl_read_image_mac.cxx fl_read_image_win32.cxx
+fl_set_fonts.o: fl_set_fonts_mac.cxx fl_set_fonts_x.cxx \
+ fl_set_fonts_xft.cxx fl_set_fonts_win32.cxx
+
+fl_arci.o: ../FL/mac.H ../FL/win32.H
+Fl_arg.o: ../FL/mac.H ../FL/win32.H
+fl_ask.o: ../FL/mac.H ../FL/win32.H
+Fl_Bitmap.o: ../FL/mac.H ../FL/win32.H
+fl_color.o: ../FL/mac.H ../FL/win32.H
+fl_cursor.o: ../FL/mac.H ../FL/win32.H
+fl_dnd.o: ../FL/mac.H ../FL/win32.H
+Fl.o: ../FL/mac.H ../FL/win32.H Fl_win32.cxx Fl_mac.cxx
+Fl_Double_Window.o: ../FL/mac.H ../FL/win32.H
+fl_draw_image.o: ../FL/mac.H ../FL/win32.H
+fl_draw_image_mac.o: ../FL/mac.H ../FL/win32.H
+fl_draw_image_win32.o: ../FL/mac.H ../FL/win32.H
+fl_draw_pixmap.o: ../FL/mac.H ../FL/win32.H
+fl_encoding_latin1.o: ../FL/mac.H ../FL/win32.H
+fl_encoding_mac_roman.o: ../FL/mac.H ../FL/win32.H
+Fl_File_Chooser2.o: ../FL/mac.H ../FL/win32.H
+fl_font.o: ../FL/mac.H ../FL/win32.H
+Fl_get_key.o: ../FL/mac.H ../FL/win32.H
+Fl_get_system_colors.o: ../FL/mac.H ../FL/win32.H
+Fl_Gl_Choice.o: ../FL/mac.H ../FL/win32.H
+Fl_Gl_Overlay.o: ../FL/mac.H ../FL/win32.H
+Fl_Gl_Window.o: ../FL/mac.H ../FL/win32.H
+Fl_grab.o: ../FL/mac.H ../FL/win32.H
+Fl_Image.o: ../FL/mac.H ../FL/win32.H
+fl_line_style.o: ../FL/mac.H ../FL/win32.H
+Fl_mac.o: ../FL/mac.H ../FL/win32.H
+Fl_Menu_Window.o: ../FL/mac.H ../FL/win32.H
+fl_overlay.o: ../FL/mac.H ../FL/win32.H
+fl_overlay_visual.o: ../FL/mac.H ../FL/win32.H
+Fl_Overlay_Window.o: ../FL/mac.H ../FL/win32.H
+Fl_own_colormap.o: ../FL/mac.H ../FL/win32.H
+Fl_Pixmap.o: ../FL/mac.H ../FL/win32.H
+fl_read_image.o: ../FL/mac.H ../FL/win32.H
+fl_read_image_mac.o: ../FL/mac.H ../FL/win32.H
+fl_read_image_win32.o: ../FL/mac.H ../FL/win32.H
+fl_rect.o: ../FL/mac.H ../FL/win32.H
+fl_scroll_area.o: ../FL/mac.H ../FL/win32.H
+fl_set_font.o: ../FL/mac.H ../FL/win32.H
+fl_set_fonts.o: ../FL/mac.H ../FL/win32.H
+fl_shortcut.o: ../FL/mac.H ../FL/win32.H
+fl_vertex.o: ../FL/mac.H ../FL/win32.H
+Fl_visual.o: ../FL/mac.H ../FL/win32.H
+Fl_Window_fullscreen.o: ../FL/mac.H ../FL/win32.H
+Fl_Window_iconize.o: ../FL/mac.H ../FL/win32.H
+Fl_x.o: ../FL/mac.H ../FL/win32.H
+gl_draw.o: ../FL/mac.H ../FL/win32.H
+gl_start.o: ../FL/mac.H ../FL/win32.H
+
+################################################################
+
+install: $(LIBNAME) $(DSONAME) \
+ $(FLLIBNAME) $(FLDSONAME) \
+ $(GLLIBNAME) $(GLDSONAME) \
+ $(IMGLIBNAME) $(IMGDSONAME)
+ echo "Installing libraries in $(DESTDIR)$(libdir)..."
+ -$(INSTALL_DIR) $(DESTDIR)$(libdir)
+ -$(INSTALL_DIR) $(DESTDIR)$(bindir)
+ $(RM) $(DESTDIR)$(libdir)/$(LIBBASENAME)
+ $(INSTALL_LIB) $(LIBNAME) $(DESTDIR)$(libdir)
+ $(INSTALL_LIB) $(FLLIBNAME) $(DESTDIR)$(libdir)
+ $(INSTALL_LIB) $(IMGLIBNAME) $(DESTDIR)$(libdir)
+ $(RANLIB) $(DESTDIR)$(libdir)/$(LIBBASENAME)
+ $(RANLIB) $(DESTDIR)$(libdir)/$(FLLIBBASENAME)
+ if test x$(GLLIBNAME) != x; then \
+ $(INSTALL_LIB) $(GLLIBNAME) $(DESTDIR)$(libdir); \
+ $(RANLIB) $(DESTDIR)$(libdir)/$(GLLIBBASENAME); \
+ fi
+ $(RANLIB) $(DESTDIR)$(libdir)/$(IMGLIBBASENAME)
+ if test x$(DSONAME) = xlibfltk.so.1.1; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk.so*;\
+ $(INSTALL_LIB) libfltk.so.1.1 $(DESTDIR)$(libdir); \
+ $(LN) libfltk.so.1.1 $(DESTDIR)$(libdir)/libfltk.so;\
+ fi
+ if test x$(DSONAME) = xlibfltk.sl.1.1; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk.sl*;\
+ $(INSTALL_LIB) libfltk.sl.1.1 $(DESTDIR)$(libdir); \
+ $(LN) libfltk.sl.1.1 $(DESTDIR)$(libdir)/libfltk.sl;\
+ fi
+ if test x$(DSONAME) = xlibfltk.1.1.dylib; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk.*dylib;\
+ $(INSTALL_LIB) libfltk.1.1.dylib $(DESTDIR)$(libdir); \
+ $(LN) libfltk.1.1.dylib $(DESTDIR)$(libdir)/libfltk.dylib;\
+ fi
+ if test x$(DSONAME) = xlibfltk_s.a; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk_s.a;\
+ $(INSTALL_LIB) libfltk_s.a $(DESTDIR)$(libdir); \
+ fi
+ if test x$(DSONAME) = xcygfltknox-1.1.dll; then\
+ $(RM) $(DESTDIR)$(bindir)/$(DSONAME);\
+ $(INSTALL_LIB) $(DSONAME) $(DESTDIR)$(bindir); \
+ $(RM) $(DESTDIR)$(libdir)/libfltk.dll.a;\
+ $(INSTALL_LIB) libfltk.dll.a $(DESTDIR)$(libdir); \
+ fi
+ if test x$(DSONAME) = xmgwfltknox-1.1.dll; then\
+ $(RM) $(DESTDIR)$(bindir)/$(DSONAME);\
+ $(INSTALL_LIB) $(DSONAME) $(DESTDIR)$(bindir); \
+ $(RM) $(DESTDIR)$(libdir)/libfltk.dll.a;\
+ $(INSTALL_LIB) libfltk.dll.a $(DESTDIR)$(libdir); \
+ fi
+ if test x$(FLDSONAME) = xlibfltk_forms.so.1.1; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk_forms.so*;\
+ $(INSTALL_LIB) libfltk_forms.so.1.1 $(DESTDIR)$(libdir); \
+ $(LN) libfltk_forms.so.1.1 $(DESTDIR)$(libdir)/libfltk_forms.so;\
+ fi
+ if test x$(FLDSONAME) = xlibfltk_forms.sl.1.1; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk_forms.sl*;\
+ $(INSTALL_LIB) libfltk_forms.sl.1.1 $(DESTDIR)$(libdir); \
+ $(LN) libfltk_forms.sl.1.1 $(DESTDIR)$(libdir)/libfltk_forms.sl;\
+ fi
+ if test x$(FLDSONAME) = xlibfltk_forms.1.1.dylib; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk_forms.*dylib;\
+ $(INSTALL_LIB) libfltk_forms.1.1.dylib $(DESTDIR)$(libdir); \
+ $(LN) libfltk_forms.1.1.dylib $(DESTDIR)$(libdir)/libfltk_forms.dylib;\
+ fi
+ if test x$(FLDSONAME) = xlibfltk_forms_s.a; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk_forms_s.a;\
+ $(INSTALL_LIB) libfltk_forms_s.a $(DESTDIR)$(libdir); \
+ fi
+ if test x$(FLDSONAME) = xcygfltknox_forms-1.1.dll; then\
+ $(RM) $(DESTDIR)$(bindir)/$(FLDSONAME);\
+ $(INSTALL_LIB) $(FLDSONAME) $(DESTDIR)$(bindir); \
+ $(RM) $(DESTDIR)$(libdir)/libfltk_forms.dll.a;\
+ $(INSTALL_LIB) libfltk_forms.dll.a $(DESTDIR)$(libdir); \
+ fi
+ if test x$(FLDSONAME) = xmgwfltknox_forms-1.1.dll; then\
+ $(RM) $(DESTDIR)$(bindir)/$(FLDSONAME);\
+ $(INSTALL_LIB) $(FLDSONAME) $(DESTDIR)$(bindir); \
+ $(RM) $(DESTDIR)$(libdir)/libfltk_forms.dll.a;\
+ $(INSTALL_LIB) libfltk_forms.dll.a $(DESTDIR)$(libdir); \
+ fi
+ if test x$(GLDSONAME) = xlibfltk_gl.so.1.1; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk_gl.so*;\
+ $(INSTALL_LIB) libfltk_gl.so.1.1 $(DESTDIR)$(libdir); \
+ $(LN) libfltk_gl.so.1.1 $(DESTDIR)$(libdir)/libfltk_gl.so;\
+ fi
+ if test x$(GLDSONAME) = xlibfltk_gl.sl.1.1; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk_gl.sl*;\
+ $(INSTALL_LIB) libfltk_gl.sl.1.1 $(DESTDIR)$(libdir); \
+ $(LN) libfltk_gl.sl.1.1 $(DESTDIR)$(libdir)/libfltk_gl.sl;\
+ fi
+ if test x$(GLDSONAME) = xlibfltk_gl.1.1.dylib; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk_gl.*dylib;\
+ $(INSTALL_LIB) libfltk_gl.1.1.dylib $(DESTDIR)$(libdir); \
+ $(LN) libfltk_gl.1.1.dylib $(DESTDIR)$(libdir)/libfltk_gl.dylib;\
+ fi
+ if test x$(GLDSONAME) = xlibfltk_gl_s.a; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk_gl_s.a;\
+ $(INSTALL_LIB) libfltk_gl_s.a $(DESTDIR)$(libdir); \
+ fi
+ if test x$(GLDSONAME) = xcygfltknox_gl-1.1.dll; then\
+ $(RM) $(DESTDIR)$(bindir)/$(GLDSONAME);\
+ $(INSTALL_LIB) $(GLDSONAME) $(DESTDIR)$(bindir); \
+ $(RM) $(DESTDIR)$(libdir)/libfltk_gl.dll.a;\
+ $(INSTALL_LIB) libfltk_gl.dll.a $(DESTDIR)$(libdir); \
+ fi
+ if test x$(GLDSONAME) = xmgwfltknox_gl-1.1.dll; then\
+ $(RM) $(DESTDIR)$(bindir)/$(GLDSONAME);\
+ $(INSTALL_LIB) $(GLDSONAME) $(DESTDIR)$(bindir); \
+ $(RM) $(DESTDIR)$(libdir)/libfltk_gl.dll.a;\
+ $(INSTALL_LIB) libfltk_gl.dll.a $(DESTDIR)$(libdir); \
+ fi
+ if test x$(IMGDSONAME) = xlibfltk_images.so.1.1; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk_images.so*;\
+ $(INSTALL_LIB) libfltk_images.so.1.1 $(DESTDIR)$(libdir); \
+ $(LN) libfltk_images.so.1.1 $(DESTDIR)$(libdir)/libfltk_images.so;\
+ fi
+ if test x$(IMGDSONAME) = xlibfltk_images.sl.1.1; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk_images.sl*;\
+ $(INSTALL_LIB) libfltk_images.sl.1.1 $(DESTDIR)$(libdir); \
+ $(LN) libfltk_images.sl.1.1 $(DESTDIR)$(libdir)/libfltk_images.sl;\
+ fi
+ if test x$(IMGDSONAME) = xlibfltk_images.1.1.dylib; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk_images.*dylib;\
+ $(INSTALL_LIB) libfltk_images.1.1.dylib $(DESTDIR)$(libdir); \
+ $(LN) libfltk_images.1.1.dylib $(DESTDIR)$(libdir)/libfltk_images.dylib;\
+ fi
+ if test x$(IMGDSONAME) = xlibfltk_images_s.a; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk_images_s.a;\
+ $(INSTALL_LIB) libfltk_images_s.a $(DESTDIR)$(libdir); \
+ fi
+ if test x$(IMGDSONAME) = xcygfltknox_images-1.1.dll; then\
+ $(RM) $(DESTDIR)$(bindir)/$(IMGDSONAME); \
+ $(INSTALL_LIB) $(IMGDSONAME) $(DESTDIR)$(bindir); \
+ $(RM) $(DESTDIR)$(libdir)/libfltk_images.dll.a;\
+ $(INSTALL_LIB) libfltk_images.dll.a $(DESTDIR)$(libdir); \
+ fi
+ if test x$(IMGDSONAME) = xmgwfltknox_images-1.1.dll; then\
+ $(RM) $(DESTDIR)$(bindir)/$(IMGDSONAME); \
+ $(INSTALL_LIB) $(IMGDSONAME) $(DESTDIR)$(bindir); \
+ $(RM) $(DESTDIR)$(libdir)/libfltk_images.dll.a;\
+ $(INSTALL_LIB) libfltk_images.dll.a $(DESTDIR)$(libdir); \
+ fi
+
+uninstall:
+ echo "Uninstalling libraries..."
+ $(RM) $(DESTDIR)$(libdir)/$(LIBBASENAME)
+ if test x$(DSONAME) = xlibfltk.so.1.1; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk.so*;\
+ fi
+ if test x$(DSONAME) = xlibfltk.sl.1.1; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk.sl*;\
+ fi
+ if test x$(DSONAME) = xlibfltk.1.1.dylib; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk.*dylib;\
+ fi
+ if test x$(DSONAME) = xlibfltk_s.a; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk_s.a;\
+ fi
+ if test x$(DSONAME) = xcygfltknox-1.1.dll; then\
+ $(RM) $(DESTDIR)$(bindir)/$(DSONAME); \
+ $(RM) $(DESTDIR)$(libdir)/libfltk.dll.a;\
+ fi
+ if test x$(DSONAME) = xmgwfltknox-1.1.dll; then\
+ $(RM) $(DESTDIR)$(bindir)/$(DSONAME); \
+ $(RM) $(DESTDIR)$(libdir)/libfltk.dll.a;\
+ fi
+ $(RM) $(DESTDIR)$(libdir)/$(FLLIBBASENAME);
+ if test x$(FLDSONAME) = xlibfltk_forms.so.1.1; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk_forms.so*;\
+ fi
+ if test x$(FLDSONAME) = xlibfltk_forms.sl.1.1; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk_forms.sl*;\
+ fi
+ if test x$(FLDSONAME) = xlibfltk_forms.1.1.dylib; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk_forms.*dylib;\
+ fi
+ if test x$(FLDSONAME) = xlibfltk_forms_s.a; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk_forms_s.a;\
+ fi
+ if test x$(FLDSONAME) = xcygfltknox_forms-1.1.dll; then\
+ $(RM) $(DESTDIR)$(bindir)/$(FLDSONAME); \
+ $(RM) $(DESTDIR)$(libdir)/libfltk_forms.dll.a;\
+ fi
+ if test x$(FLDSONAME) = xmgwfltknox_forms-1.1.dll; then\
+ $(RM) $(DESTDIR)$(bindir)/$(FLDSONAME); \
+ $(RM) $(DESTDIR)$(libdir)/libfltk_forms.dll.a;\
+ fi
+ if test x$(GLLIBNAME) != x; then\
+ $(RM) $(DESTDIR)$(libdir)/$(GLLIBBASENAME);\
+ fi
+ if test x$(GLDSONAME) = xlibfltk_gl.so.1.1; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk_gl.so*;\
+ fi
+ if test x$(GLDSONAME) = xlibfltk_gl.sl.1.1; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk_gl.sl*;\
+ fi
+ if test x$(GLDSONAME) = xlibfltk_gl.1.1.dylib; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk_gl.*dylib;\
+ fi
+ if test x$(GLDSONAME) = xlibfltk_gl_s.a; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk_gl_s.a;\
+ fi
+ if test x$(GLDSONAME) = xcygfltknox_gl-1.1.dll; then\
+ $(RM) $(DESTDIR)$(bindir)/$(GLDSONAME); \
+ $(RM) $(DESTDIR)$(libdir)/libfltk_gl.dll.a;\
+ fi
+ if test x$(GLDSONAME) = xmgwfltknox_gl-1.1.dll; then\
+ $(RM) $(DESTDIR)$(bindir)/$(GLDSONAME); \
+ $(RM) $(DESTDIR)$(libdir)/libfltk_gl.dll.a;\
+ fi
+ if test x$(IMGLIBNAME) != x; then\
+ $(RM) $(DESTDIR)$(libdir)/$(IMGLIBBASENAME);\
+ fi
+ if test x$(IMGDSONAME) = xlibfltk_images.so.1.1; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk_images.so*;\
+ fi
+ if test x$(IMGDSONAME) = xlibfltk_images.sl.1.1; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk_images.sl*;\
+ fi
+ if test x$(IMGDSONAME) = xlibfltk_images.1.1.dylib; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk_images.*dylib;\
+ fi
+ if test x$(IMGDSONAME) = xlibfltk_images_s.a; then\
+ $(RM) $(DESTDIR)$(libdir)/libfltk_images_s.a;\
+ fi
+ if test x$(IMGDSONAME) = xcygfltknox_images-1.1.dll; then\
+ $(RM) $(DESTDIR)$(bindir)/$(IMGDSONAME); \
+ $(RM) $(DESTDIR)$(libdir)/libfltk_images.dll.a;\
+ fi
+ if test x$(IMGDSONAME) = xmgwfltknox_images-1.1.dll; then\
+ $(RM) $(DESTDIR)$(bindir)/$(IMGDSONAME); \
+ $(RM) $(DESTDIR)$(libdir)/libfltk_images.dll.a;\
+ fi
+
+
+#
+# End of "$Id: Makefile 6817 2009-07-02 09:42:17Z AlbrechtS $".
+#
diff --git a/third_party/windows/fltk-1.1.10/src/allfiles.xbm b/third_party/windows/fltk-1.1.10/src/allfiles.xbm new file mode 100644 index 0000000..5aaec59 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/allfiles.xbm @@ -0,0 +1,6 @@ +#define allfiles_width 16
+#define allfiles_height 16
+static unsigned char allfiles_bits[] = {
+ 0xfc, 0x3f, 0x04, 0x20, 0x04, 0x20, 0x04, 0x20, 0x84, 0x21, 0xa4, 0x25,
+ 0xc4, 0x23, 0xf4, 0x2f, 0xf4, 0x2f, 0xc4, 0x23, 0xa4, 0x25, 0x84, 0x21,
+ 0x04, 0x20, 0x04, 0x20, 0x04, 0x20, 0xfc, 0x3f};
diff --git a/third_party/windows/fltk-1.1.10/src/cgdebug.h b/third_party/windows/fltk-1.1.10/src/cgdebug.h new file mode 100644 index 0000000..1217f15 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/cgdebug.h @@ -0,0 +1,215 @@ +//
+// "$Id:$"
+//
+// OS X Core Graphics debugging help for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// This file allows easier debugging of Mac OS X Core Graphics
+// code. This file is normally not included into any FLTK builds,
+// but since it has proven to be tremendously useful in debugging
+// the FLTK port to "Quartz", I decided to add this file in case
+// more bugs show up.
+//
+// This header is activated by adding the following
+// line to "config.h"
+// #include "src/cgdebug.h"
+//
+// Running "./configure" will remove this line from "config.h".
+//
+// When used erreanously, Core Graphics prints warnings to
+// stderr. This is helpful, however it is not possible to
+// associate a line number or source file with the warning message.
+// This headr file outputs a trace of CG calls, interweaveing
+// them with CG warnings.
+//
+// Matthias
+
+#ifndef CGDEBUG
+#define CGDEBUG
+
+#include <stdio.h>
+#include <Carbon/Carbon.h>
+
+//+BitmapContextCreate
+//+BitmapContextGetData
+// ClipCGContextToRegion
+// QDBeginCGContext
+// QDEndCGContext
+
+//+AddArc
+//+AddLineToPoint
+// ClipToRect
+// ClosePath
+//+ConcatCTM
+//+DrawImage
+// FillPath
+// FillRect
+// Flush
+//+GetCTM
+// MoveToPoint
+//+Release
+// RestoreGState
+// SaveGState
+//+ScaleCTM
+//+SetLineCap
+//+SetLineDash
+//+SetLineJoin
+//+SetLineWidth
+//+SetRGBFillColor
+//+SetRGBStrokeColor
+//+SetShouldAntialias
+//+SetTextMatrix
+//+StrokePath
+//+TranslateCTM
+
+inline OSStatus dbgLocation(const char *file, int line)
+{
+ fprintf(stderr, "%s:%d ", file, line);
+ return 0;
+}
+
+inline OSStatus dbgEndl()
+{
+ fprintf(stderr, "\n");
+ return 0;
+}
+
+
+inline void dbgCGContextClipToRect(CGContextRef a, CGRect b)
+{
+ CGContextClipToRect(a, b);
+}
+
+#define CGContextClipToRect(a, b) { \
+ fprintf(stderr, "%s:%d ", __FILE__, __LINE__); \
+ dbgCGContextClipToRect(a, b); \
+ fprintf(stderr, "\n"); }
+
+inline void dbgCGContextFillRect(CGContextRef a, CGRect b)
+{
+ CGContextFillRect(a, b);
+}
+
+#define CGContextFillRect(a, b) { \
+ fprintf(stderr, "%s:%d ", __FILE__, __LINE__); \
+ dbgCGContextFillRect(a, b); \
+ fprintf(stderr, "\n"); }
+
+inline OSStatus dbgQDEndCGContext(CGrafPtr a, CGContextRef *b)
+{
+ return QDEndCGContext(a, b);
+}
+
+#define QDEndCGContext(a, b) ( \
+ dbgLocation(__FILE__, __LINE__) + \
+ dbgQDEndCGContext(a, b) + \
+ dbgEndl() )
+
+inline OSStatus dbgQDBeginCGContext(CGrafPtr a, CGContextRef *b)
+{
+ return QDBeginCGContext(a, b);
+}
+
+#define QDBeginCGContext(a, b) ( \
+ dbgLocation(__FILE__, __LINE__) + \
+ dbgQDBeginCGContext(a, b) + \
+ dbgEndl() )
+
+inline void dbgClipCGContextToRegion(CGContextRef a, const Rect *b, RgnHandle c)
+{
+ ClipCGContextToRegion(a, b, c);
+}
+
+#define ClipCGContextToRegion(a, b, c) { \
+ fprintf(stderr, "%s:%d ", __FILE__, __LINE__); \
+ dbgClipCGContextToRegion(a, b, c); \
+ fprintf(stderr, "\n"); }
+
+inline void dbgCGContextMoveToPoint(CGContextRef context, float x, float y)
+{
+ CGContextMoveToPoint(context, x, y);
+}
+
+#define CGContextMoveToPoint(a, b, c) { \
+ fprintf(stderr, "%s:%d ", __FILE__, __LINE__); \
+ dbgCGContextMoveToPoint(a, b, c); \
+ fprintf(stderr, "\n"); }
+
+inline void dbgCGContextFillPath(CGContextRef context)
+{
+ CGContextFillPath(context);
+}
+
+#define CGContextFillPath(a) { \
+ fprintf(stderr, "%s:%d ", __FILE__, __LINE__); \
+ dbgCGContextFillPath(a); \
+ fprintf(stderr, "\n"); }
+
+inline void dbgCGContextClosePath(CGContextRef context)
+{
+ CGContextClosePath(context);
+}
+
+#define CGContextClosePath(a) { \
+ fprintf(stderr, "%s:%d ", __FILE__, __LINE__); \
+ dbgCGContextClosePath(a); \
+ fprintf(stderr, "\n"); }
+
+inline void dbgCGContextFlush(CGContextRef context)
+{
+ CGContextFlush(context);
+}
+
+#define CGContextFlush(a) { \
+ fprintf(stderr, "%s:%d ", __FILE__, __LINE__); \
+ dbgCGContextFlush(a); \
+ fprintf(stderr, "\n"); }
+
+inline void dbgCGContextSaveGState(CGContextRef context)
+{
+ CGContextSaveGState(context);
+}
+
+#define CGContextSaveGState(a) { \
+ fprintf(stderr, "%s:%d ", __FILE__, __LINE__); \
+ dbgCGContextSaveGState(a); \
+ fprintf(stderr, "\n"); }
+
+inline void dbgCGContextRestoreGState(CGContextRef context)
+{
+ CGContextRestoreGState(context);
+}
+
+#define CGContextRestoreGState(a) { \
+ fprintf(stderr, "%s:%d ", __FILE__, __LINE__); \
+ dbgCGContextRestoreGState(a); \
+ fprintf(stderr, "\n"); }
+
+
+#endif
+
+//
+// End of "$Id:$".
+//
+
diff --git a/third_party/windows/fltk-1.1.10/src/cmap.cxx b/third_party/windows/fltk-1.1.10/src/cmap.cxx new file mode 100644 index 0000000..75a1f98 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/cmap.cxx @@ -0,0 +1,179 @@ +//
+// "$Id: cmap.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Colormap generation program for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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 to "fltk-bugs@easysw.com".
+//
+
+// This program produces the contents of "fl_cmap.h" as stdout
+
+// #include <gl/gl.h>
+#include <stdio.h>
+
+// This table is initialized with color values I got by reading the
+// colormap on an IRIX 4.3 machine:
+
+// "full intensity colors" have been turned down some to make white
+// background less intense by default. The hope is that this will make
+// fltk programs more friendly on color-adjusted screens. If you want
+// pure colors you should get them out of the colormap.
+
+//#define III 244 // maximum intensity of the basic colors
+
+// that results in errors and unshared colormap entries, so full intensity:
+#define III 255 // maximum intensity of the basic colors
+
+static short cmap[256][3] = {
+// 3-bit colormap:
+ { 0, 0, 0}, // black
+ {III, 0, 0}, // red
+ { 0,III, 0}, // green
+ {III,III, 0}, // yellow
+ { 0, 0,III}, // blue
+ {III, 0,III}, // magenta
+ { 0,III,III}, // cyan
+ {III,III,III}, // white
+// pastel versions of those colors, from SGI's standard color map:
+ { 85, 85, 85}, // 1/3 gray
+ {198,113,113}, // salmon? pale red?
+ {113,198,113}, // pale green
+ {142,142, 56}, // khaki
+ {113,113,198}, // pale blue
+ {142, 56,142}, // purple, orchid, pale magenta
+ { 56,142,142}, // cadet blue, aquamarine, pale cyan
+// The next location is used for FL_SELECTION_COLOR. It formerly was 2/3 gray
+// but this is changed to be the Windows blue color. This allows the default
+// behavior on both X and Windows to match:
+ { 0, 0,128},
+//{170,170,170}, // old 2/3 gray color
+// These next 16 are the FL_FREE_COLOR area. In some versions of fltk
+// these were filled with random colors that a Irix 5.3 machine placed
+// in these locations. Other versions of fltk filled this with the 1/3
+// gray above to discourage their use. This newest version uses colors
+// that NewTek has assigned for their GUI:
+#if 0
+ // The Irix 5.3 colors:
+ { 16, 16, 16},
+ {128, 40,128},
+ {198, 30, 30},
+ { 66, 30, 30},
+ {176,140,140},
+ { 0, 20, 20},
+ { 20, 10, 10},
+ { 40, 20, 20},
+ { 60, 30, 30},
+ { 0, 80, 80},
+ { 0, 40, 40},
+ { 20, 20, 0},
+ { 40, 40, 0},
+ { 80, 80, 10},
+ {150,150, 20},
+ {160, 10, 10},
+#else
+ // The NewTek colors: (from George Yohng)
+ {168,168,152},
+ {232,232,216},
+ {104,104, 88},
+ {152,168,168},
+ {216,232,232},
+ { 88,104,104},
+ {156,156,168},
+ {220,220,232},
+ { 92, 92,104},
+ {156,168,156},
+ {220,232,220},
+ { 92,104, 92},
+ {144,144,144},
+ {192,192,192},
+ { 80, 80, 80},
+ {160,160,160},
+#endif
+// The rest of the colormap is a gray ramp and table, filled in below:
+};
+
+// This is Fl::background from Fl_get_system_colors.cxx, with modifications:
+
+#define FL_GRAY_RAMP 32
+#define FL_NUM_GRAY 24
+#define FL_GRAY 49 // old value is 47
+typedef unsigned char uchar;
+#include <math.h>
+
+void background(uchar r, uchar g, uchar b) {
+ // replace the gray ramp so that color 47 (by default 2/3) is this color
+ if (!r) r = 1; else if (r==255) r = 254;
+ double powr = log(r/255.0)/log((FL_GRAY-FL_GRAY_RAMP)/(FL_NUM_GRAY-1.0));
+ if (!g) g = 1; else if (g==255) g = 254;
+ double powg = log(g/255.0)/log((FL_GRAY-FL_GRAY_RAMP)/(FL_NUM_GRAY-1.0));
+ if (!b) b = 1; else if (b==255) b = 254;
+ double powb = log(b/255.0)/log((FL_GRAY-FL_GRAY_RAMP)/(FL_NUM_GRAY-1.0));
+ for (int i = 0; i < FL_NUM_GRAY; i++) {
+ double gray = i/(FL_NUM_GRAY-1.0);
+ cmap[i+FL_GRAY_RAMP][0] = uchar(pow(gray,powr)*255+.5);
+ cmap[i+FL_GRAY_RAMP][1] = uchar(pow(gray,powg)*255+.5);
+ cmap[i+FL_GRAY_RAMP][2] = uchar(pow(gray,powb)*255+.5);
+ }
+}
+
+int main() {
+ int i,r,g,b;
+#if 0
+ /* Read colormap colors into internal table */
+ long cmwin;
+ noport();
+ cmwin = winopen("CM");
+ for (i=0; i<256; i++)
+ getmcolor(i,&cmap[i][0],&cmap[i][1],&cmap[i][2]);
+ winclose(cmwin);
+#endif
+// overwrite the X allocation area with one color so people are
+// discouraged from using it:
+ //for (i=16; i<32; i++) {cmap[i][0]=cmap[i][1]=cmap[i][2] = 85;}
+
+ // fill in the gray ramp:
+ background(0xc0, 0xc0, 0xc0); // microsoft colors
+ // background(170, 170, 170); // old fltk colors
+ // copy the 1/3 and 2/3 gray to the closest locations in gray ramp:
+ cmap[39][0] = cmap[39][1] = cmap[39][2] = 85;
+ cmap[47][0] = cmap[47][1] = cmap[47][2] = 170;
+
+ // fill in the color cube
+ i = 56;
+ for (b=0; b<5; b++)
+ for (r=0; r<5; r++)
+ for (g=0; g<8; g++) {
+ cmap[i][0] = r*255/4;
+ cmap[i][1] = g*255/7;
+ cmap[i][2] = b*255/4;
+ i++;
+ }
+
+ for (i=0; i<256; i++) {
+ printf("\t0x%02x%02x%02x00",cmap[i][0],cmap[i][1],cmap[i][2]);
+ if (i < 255) printf(",\n");
+ }
+ printf("\n");
+ return 0;
+}
+
+//
+// End of "$Id: cmap.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/d1.xbm b/third_party/windows/fltk-1.1.10/src/d1.xbm new file mode 100644 index 0000000..7bb1232 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/d1.xbm @@ -0,0 +1,6 @@ +#define d1_width 16
+#define d1_height 16
+static unsigned char d1_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x38, 0x00, 0x78, 0x00,
+ 0xe8, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x17, 0x00, 0x1e, 0x00, 0x1c,
+ 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/third_party/windows/fltk-1.1.10/src/d1_mask.xbm b/third_party/windows/fltk-1.1.10/src/d1_mask.xbm new file mode 100644 index 0000000..6cbaca8 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/d1_mask.xbm @@ -0,0 +1,6 @@ +#define d1_mask_width 16
+#define d1_mask_height 16
+static unsigned char d1_mask_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x7c, 0x00, 0xfc, 0x00,
+ 0xfc, 0x01, 0xec, 0x03, 0xc0, 0x37, 0x80, 0x3f, 0x00, 0x3f, 0x00, 0x3e,
+ 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00};
diff --git a/third_party/windows/fltk-1.1.10/src/dump_compose.c b/third_party/windows/fltk-1.1.10/src/dump_compose.c new file mode 100644 index 0000000..94c4e44 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/dump_compose.c @@ -0,0 +1,26 @@ +/* write out the documentation for the compose key */
+
+/* copy the string from Fl_Input.C */
+static const char* const compose_pairs =
+" ! @ # $ y=| & : c a <<~ - r _ * +-2 3 ' u p . , 1 o >>141234? "
+"A`A'A^A~A:A*AEC,E`E'E^E:I`I'I^I:D-N~O`O'O^O~O:x O/U`U'U^U:Y'DDss"
+"a`a'a^a~a:a*aec,e`e'e^e:i`i'i^i:d-n~o`o'o^o~o:-:o/u`u'u^u:y'ddy:";
+
+#include <stdio.h>
+
+int main() {
+ int x,y;
+ for (x = 0; x<16; x++) {
+ for (y = 0; y<6; y++) {
+ const char *p = compose_pairs + (16*y+x)*2;
+ if (p[1] == ' ')
+ printf("<td><code>%c </code>   %c\n",
+ p[0],(p-compose_pairs)/2+0xA0);
+ else
+ printf("<td><code>%c%c</code>   %c\n",
+ p[0],p[1],(p-compose_pairs)/2+0xA0);
+ }
+ printf("<tr>");
+ }
+ return 0;
+}
diff --git a/third_party/windows/fltk-1.1.10/src/ew.xbm b/third_party/windows/fltk-1.1.10/src/ew.xbm new file mode 100644 index 0000000..0994e9c --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/ew.xbm @@ -0,0 +1,8 @@ +#define ew_width 16
+#define ew_height 16
+#define ew_x_hot 8
+#define ew_y_hot 8
+static unsigned char ew_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10,
+ 0x0c, 0x30, 0xfe, 0x7f, 0xfe, 0x7f, 0x0c, 0x30, 0x08, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/third_party/windows/fltk-1.1.10/src/ew_mask.xbm b/third_party/windows/fltk-1.1.10/src/ew_mask.xbm new file mode 100644 index 0000000..e0c6898 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/ew_mask.xbm @@ -0,0 +1,8 @@ +#define ew_mask_width 16
+#define ew_mask_height 16
+#define ew_mask_x_hot 8
+#define ew_mask_y_hot 8
+static unsigned char ew_mask_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x1c, 0x38,
+ 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0x1c, 0x38, 0x18, 0x18,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/third_party/windows/fltk-1.1.10/src/fastarrow.h b/third_party/windows/fltk-1.1.10/src/fastarrow.h new file mode 100644 index 0000000..f662930 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fastarrow.h @@ -0,0 +1,6 @@ +#define fastarrow_width 16
+#define fastarrow_height 16
+static unsigned char fastarrow_bits[] = {
+ 0x00, 0x00, 0x00, 0x07, 0xe0, 0x07, 0xfc, 0x03, 0xff, 0xff, 0xfc, 0x03,
+ 0xe0, 0x07, 0x00, 0x07, 0xe0, 0x00, 0xe0, 0x07, 0xc0, 0x3f, 0xff, 0xff,
+ 0xc0, 0x3f, 0xe0, 0x07, 0xe0, 0x00, 0x00, 0x00};
diff --git a/third_party/windows/fltk-1.1.10/src/filename_absolute.cxx b/third_party/windows/fltk-1.1.10/src/filename_absolute.cxx new file mode 100644 index 0000000..202519c --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/filename_absolute.cxx @@ -0,0 +1,212 @@ +//
+// "$Id: filename_absolute.cxx 6644 2009-01-23 10:47:53Z AlbrechtS $"
+//
+// Filename expansion routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+/* expand a file name by prepending current directory, deleting . and
+ .. (not really correct for symbolic links) between the prepended
+ current directory. Use $PWD if it exists.
+ Returns true if any changes were made.
+*/
+
+#include <FL/filename.H>
+#include <stdlib.h>
+#include "flstring.h"
+#include <ctype.h>
+#if defined(WIN32) && !defined(__CYGWIN__)
+# include <direct.h>
+// Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs
+// on Windows, which is supposed to be POSIX compliant...
+# define getcwd _getcwd
+#else
+# include <unistd.h>
+# ifdef __EMX__
+# define getcwd _getcwd2
+# endif
+#endif
+
+#if defined(WIN32) || defined(__EMX__) && !defined(__CYGWIN__)
+inline int isdirsep(char c) {return c=='/' || c=='\\';}
+#else
+#define isdirsep(c) ((c)=='/')
+#endif
+
+int fl_filename_absolute(char *to, int tolen, const char *from) {
+ if (isdirsep(*from) || *from == '|'
+#if defined(WIN32) || defined(__EMX__) && !defined(__CYGWIN__)
+ || from[1]==':'
+#endif
+ ) {
+ strlcpy(to, from, tolen);
+ return 0;
+ }
+
+ char *a;
+ char *temp = new char[tolen];
+ const char *start = from;
+
+ a = getcwd(temp, tolen);
+ if (!a) {
+ strlcpy(to, from, tolen);
+ delete[] temp;
+ return 0;
+ }
+#if defined(WIN32) || defined(__EMX__) && !defined(__CYGWIN__)
+ for (a = temp; *a; a++) if (*a=='\\') *a = '/'; // ha ha
+#else
+ a = temp+strlen(temp);
+#endif
+ if (isdirsep(*(a-1))) a--;
+ /* remove intermediate . and .. names: */
+ while (*start == '.') {
+ if (start[1]=='.' && isdirsep(start[2])) {
+ char *b;
+ for (b = a-1; b >= temp && !isdirsep(*b); b--);
+ if (b < temp) break;
+ a = b;
+ start += 3;
+ } else if (isdirsep(start[1])) {
+ start += 2;
+ } else if (!start[1]) {
+ start ++; // Skip lone "."
+ break;
+ } else
+ break;
+ }
+
+ *a++ = '/';
+ strlcpy(a,start,tolen - (a - temp));
+
+ strlcpy(to, temp, tolen);
+
+ delete[] temp;
+
+ return 1;
+}
+
+/*
+ * 'fl_filename_relative()' - Make a filename relative to the current working directory.
+ */
+
+int // O - 0 if no change, 1 if changed
+fl_filename_relative(char *to, // O - Relative filename
+ int tolen, // I - Size of "to" buffer
+ const char *from) {// I - Absolute filename
+ char *newslash; // Directory separator
+ const char *slash; // Directory separator
+ char cwd_buf[1024]; // Current directory
+ char *cwd = cwd_buf;
+
+
+ // return if "from" is not an absolute path
+#if defined(WIN32) || defined(__EMX__)
+ if (from[0] == '\0' ||
+ (!isdirsep(*from) && !isalpha(*from) && from[1] != ':' &&
+ !isdirsep(from[2]))) {
+#else
+ if (from[0] == '\0' || !isdirsep(*from)) {
+#endif // WIN32 || __EMX__
+ strlcpy(to, from, tolen);
+ return 0;
+ }
+
+ // get the current directory and return if we can't
+ if (!getcwd(cwd_buf, sizeof(cwd_buf))) {
+ strlcpy(to, from, tolen);
+ return 0;
+ }
+
+#if defined(WIN32) || defined(__EMX__)
+ // convert all backslashes into forward slashes
+ for (newslash = strchr(cwd, '\\'); newslash; newslash = strchr(newslash + 1, '\\'))
+ *newslash = '/';
+
+ // test for the exact same string and return "." if so
+ if (!strcasecmp(from, cwd)) {
+ strlcpy(to, ".", tolen);
+ return (1);
+ }
+
+ // test for the same drive. Return the absolute path if not
+ if (tolower(*from & 255) != tolower(*cwd & 255)) {
+ strlcpy(to, from, tolen);
+ return 0;
+ }
+
+ // compare the path name without the drive prefix
+ from += 2; cwd += 2;
+#else
+ // test for the exact same string and return "." if so
+ if (!strcmp(from, cwd)) {
+ strlcpy(to, ".", tolen);
+ return (1);
+ }
+#endif // WIN32 || __EMX__
+
+ // compare both path names until we find a difference
+ for (slash = from, newslash = cwd;
+ *slash != '\0' && *newslash != '\0';
+ slash ++, newslash ++)
+ if (isdirsep(*slash) && isdirsep(*newslash)) continue;
+#if defined(WIN32) || defined(__EMX__) || defined(__APPLE__)
+ else if (tolower(*slash & 255) != tolower(*newslash & 255)) break;
+#else
+ else if (*slash != *newslash) break;
+#endif // WIN32 || __EMX__ || __APPLE__
+
+ // skip over trailing slashes
+ if ( *newslash == '\0' && *slash != '\0' && !isdirsep(*slash)
+ &&(newslash==cwd || !isdirsep(newslash[-1])) )
+ newslash--;
+
+ // now go back to the first character of the first differing paths segment
+ while (!isdirsep(*slash) && slash > from) slash --;
+ if (isdirsep(*slash)) slash ++;
+
+ // do the same for the current dir
+ if (*newslash != '\0')
+ while (!isdirsep(*newslash) && newslash > cwd) newslash --;
+
+ // prepare the destination buffer
+ to[0] = '\0';
+ to[tolen - 1] = '\0';
+
+ // now add a "previous dir" sequence for every following slash in the cwd
+ while (*newslash != '\0') {
+ if (isdirsep(*newslash)) strlcat(to, "../", tolen);
+
+ newslash ++;
+ }
+
+ // finally add the differing path from "from"
+ strlcat(to, slash, tolen);
+
+ return 1;
+}
+
+
+//
+// End of "$Id: filename_absolute.cxx 6644 2009-01-23 10:47:53Z AlbrechtS $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/filename_expand.cxx b/third_party/windows/fltk-1.1.10/src/filename_expand.cxx new file mode 100644 index 0000000..e1c14c3 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/filename_expand.cxx @@ -0,0 +1,110 @@ +//
+// "$Id: filename_expand.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Filename expansion routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+/* expand a file name by substuting environment variables and
+ home directories. Returns true if any changes were made.
+ to & from may be the same buffer.
+*/
+
+#include <FL/filename.H>
+#include <stdlib.h>
+#include "flstring.h"
+#if defined(WIN32) && !defined(__CYGWIN__)
+#else
+# include <unistd.h>
+# include <pwd.h>
+#endif
+
+#if defined(WIN32) || defined(__EMX__) && !defined(__CYGWIN__)
+static inline int isdirsep(char c) {return c=='/' || c=='\\';}
+#else
+#define isdirsep(c) ((c)=='/')
+#endif
+
+int fl_filename_expand(char *to,int tolen, const char *from) {
+
+ char *temp = new char[tolen];
+ strlcpy(temp,from, tolen);
+ char *start = temp;
+ char *end = temp+strlen(temp);
+
+ int ret = 0;
+
+ for (char *a=temp; a<end; ) { // for each slash component
+ char *e; for (e=a; e<end && !isdirsep(*e); e++); // find next slash
+ const char *value = 0; // this will point at substitute value
+ switch (*a) {
+ case '~': // a home directory name
+ if (e <= a+1) { // current user's directory
+ value = getenv("HOME");
+#ifndef WIN32
+ } else { // another user's directory
+ struct passwd *pwd;
+ char t = *e; *(char *)e = 0;
+ pwd = getpwnam(a+1);
+ *(char *)e = t;
+ if (pwd) value = pwd->pw_dir;
+#endif
+ }
+ break;
+ case '$': /* an environment variable */
+ {char t = *e; *(char *)e = 0; value = getenv(a+1); *(char *)e = t;}
+ break;
+ }
+ if (value) {
+ // substitutions that start with slash delete everything before them:
+ if (isdirsep(value[0])) start = a;
+#if defined(WIN32) || defined(__EMX__) && !defined(__CYGWIN__)
+ // also if it starts with "A:"
+ if (value[0] && value[1]==':') start = a;
+#endif
+ int t = strlen(value); if (isdirsep(value[t-1])) t--;
+ if ((end+1-e+t) >= tolen) end += tolen - (end+1-e+t);
+ memmove(a+t, e, end+1-e);
+ end = a+t+(end-e);
+ *end = '\0';
+ memcpy(a, value, t);
+ ret++;
+ } else {
+ a = e+1;
+#if defined(WIN32) || defined(__EMX__) && !defined(__CYGWIN__)
+ if (*e == '\\') {*e = '/'; ret++;} // ha ha!
+#endif
+ }
+ }
+
+ strlcpy(to, start, tolen);
+
+ delete[] temp;
+
+ return ret;
+}
+
+
+//
+// End of "$Id: filename_expand.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/filename_ext.cxx b/third_party/windows/fltk-1.1.10/src/filename_ext.cxx new file mode 100644 index 0000000..45f57c4 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/filename_ext.cxx @@ -0,0 +1,47 @@ +//
+// "$Id: filename_ext.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Filename extension routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// returns pointer to the last '.' or to the null if none:
+
+#include <FL/filename.H>
+
+const char *fl_filename_ext(const char *buf) {
+ const char *q = 0;
+ const char *p = buf;
+ for (p=buf; *p; p++) {
+ if (*p == '/') q = 0;
+#if defined(WIN32) || defined(__EMX__) && !defined(__CYGWIN__)
+ else if (*p == '\\') q = 0;
+#endif
+ else if (*p == '.') q = p;
+ }
+ return q ? q : p;
+}
+
+//
+// End of "$Id: filename_ext.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/filename_isdir.cxx b/third_party/windows/fltk-1.1.10/src/filename_isdir.cxx new file mode 100644 index 0000000..45216a9 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/filename_isdir.cxx @@ -0,0 +1,91 @@ +//
+// "$Id: filename_isdir.cxx 5948 2007-10-07 10:12:32Z matt $"
+//
+// Directory detection routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Used by fl_file_chooser
+
+#include "flstring.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <FL/filename.H>
+
+
+#if defined(WIN32) || defined(__EMX__) && !defined(__CYGWIN__)
+static inline int isdirsep(char c) {return c=='/' || c=='\\';}
+#else
+#define isdirsep(c) ((c)=='/')
+#endif
+
+int _fl_filename_isdir_quick(const char* n) {
+ // Do a quick optimization for filenames with a trailing slash...
+ if (*n && isdirsep(n[strlen(n) - 1])) return 1;
+ return fl_filename_isdir(n);
+}
+
+int fl_filename_isdir(const char* n) {
+ struct stat s;
+ char fn[1024];
+ int length;
+
+ length = strlen(n);
+
+#ifdef WIN32
+ // This workaround brought to you by the fine folks at Microsoft!
+ // (read lots of sarcasm in that...)
+ if (length < (int)(sizeof(fn) - 1)) {
+ if (length < 4 && isalpha(n[0]) && n[1] == ':' &&
+ (isdirsep(n[2]) || !n[2])) {
+ // Always use D:/ for drive letters
+ fn[0] = n[0];
+ strcpy(fn + 1, ":/");
+ n = fn;
+ } else if (length > 0 && isdirsep(n[length - 1])) {
+ // Strip trailing slash from name...
+ length --;
+ memcpy(fn, n, length);
+ fn[length] = '\0';
+ n = fn;
+ }
+ }
+#else
+ // Matt: Just in case, we strip the slash for other operating
+ // systems as well, avoid bugs by sloppy implementations
+ // of "stat".
+ if (length > 1 && isdirsep(n[length - 1])) {
+ length --;
+ memcpy(fn, n, length);
+ fn[length] = '\0';
+ n = fn;
+ }
+#endif
+
+ return !stat(n, &s) && (s.st_mode&0170000)==0040000;
+}
+
+//
+// End of "$Id: filename_isdir.cxx 5948 2007-10-07 10:12:32Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/filename_list.cxx b/third_party/windows/fltk-1.1.10/src/filename_list.cxx new file mode 100644 index 0000000..7f4de5d --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/filename_list.cxx @@ -0,0 +1,107 @@ +//
+// "$Id: filename_list.cxx 6832 2009-07-23 22:36:04Z AlbrechtS $"
+//
+// Filename list routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Wrapper for scandir with const-correct function prototypes.
+
+#include <FL/filename.H>
+#include "flstring.h"
+#include <stdlib.h>
+
+
+extern "C" {
+#ifndef HAVE_SCANDIR
+ int fl_scandir (const char *dir, dirent ***namelist,
+ int (*select)(dirent *),
+ int (*compar)(dirent **, dirent **));
+# define scandir fl_scandir
+#endif
+}
+
+int fl_alphasort(struct dirent **a, struct dirent **b) {
+ return strcmp((*a)->d_name, (*b)->d_name);
+}
+
+int fl_casealphasort(struct dirent **a, struct dirent **b) {
+ return strcasecmp((*a)->d_name, (*b)->d_name);
+}
+
+
+int fl_filename_list(const char *d, dirent ***list,
+ Fl_File_Sort_F *sort) {
+#ifndef HAVE_SCANDIR
+ int n = scandir(d, list, 0, sort);
+#elif defined(HAVE_SCANDIR_POSIX)
+ // POSIX (2008) defines the comparison function like this:
+ int n = scandir(d, list, 0, (int(*)(const dirent **, const dirent **))sort);
+#elif defined(__osf__)
+ // OSF, DU 4.0x
+ int n = scandir(d, list, 0, (int(*)(dirent **, dirent **))sort);
+#elif defined(_AIX)
+ // AIX is almost standard...
+ int n = scandir(d, list, 0, (int(*)(void*, void*))sort);
+#elif !defined(__sgi)
+ // The vast majority of UNIX systems want the sort function to have this
+ // prototype, most likely so that it can be passed to qsort without any
+ // changes:
+ int n = scandir(d, list, 0, (int(*)(const void*,const void*))sort);
+#else
+ // This version is when we define our own scandir (WIN32 and perhaps
+ // some Unix systems) and apparently on IRIX:
+ int n = scandir(d, list, 0, sort);
+#endif
+
+#if defined(WIN32) && !defined(__CYGWIN__)
+ // we did this already during fl_scandir/win32
+#else
+ // append a '/' to all filenames that are directories
+ int i, dirlen = strlen(d);
+ char *fullname = (char*)malloc(dirlen+FL_PATH_MAX+3); // Add enough extra for two /'s and a nul
+ // Use memcpy for speed since we already know the length of the string...
+ memcpy(fullname, d, dirlen+1);
+ char *name = fullname + dirlen;
+ if (name!=fullname && name[-1]!='/') *name++ = '/';
+ for (i=0; i<n; i++) {
+ dirent *de = (*list)[i];
+ int len = strlen(de->d_name);
+ if (de->d_name[len-1]=='/' || len>FL_PATH_MAX) continue;
+ // Use memcpy for speed since we already know the length of the string...
+ memcpy(name, de->d_name, len+1);
+ if (fl_filename_isdir(fullname)) {
+ (*list)[i] = de = (dirent*)realloc(de, de->d_name - (char*)de + len + 2);
+ char *dst = de->d_name + len;
+ *dst++ = '/';
+ *dst = 0;
+ }
+ }
+ free(fullname);
+#endif
+ return n;
+}
+
+//
+// End of "$Id: filename_list.cxx 6832 2009-07-23 22:36:04Z AlbrechtS $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/filename_match.cxx b/third_party/windows/fltk-1.1.10/src/filename_match.cxx new file mode 100644 index 0000000..81da653 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/filename_match.cxx @@ -0,0 +1,106 @@ +//
+// "$Id: filename_match.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Pattern matching routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+/* Adapted from Rich Salz. */
+#include <FL/filename.H>
+#include <ctype.h>
+
+int fl_filename_match(const char *s, const char *p) {
+ int matched;
+
+ for (;;) {
+ switch(*p++) {
+
+ case '?' : // match any single character
+ if (!*s++) return 0;
+ break;
+
+ case '*' : // match 0-n of any characters
+ if (!*p) return 1; // do trailing * quickly
+ while (!fl_filename_match(s, p)) if (!*s++) return 0;
+ return 1;
+
+ case '[': { // match one character in set of form [abc-d] or [^a-b]
+ if (!*s) return 0;
+ int reverse = (*p=='^' || *p=='!'); if (reverse) p++;
+ matched = 0;
+ char last = 0;
+ while (*p) {
+ if (*p=='-' && last) {
+ if (*s <= *++p && *s >= last ) matched = 1;
+ last = 0;
+ } else {
+ if (*s == *p) matched = 1;
+ }
+ last = *p++;
+ if (*p==']') break;
+ }
+ if (matched == reverse) return 0;
+ s++; p++;}
+ break;
+
+ case '{' : // {pattern1|pattern2|pattern3}
+ NEXTCASE:
+ if (fl_filename_match(s,p)) return 1;
+ for (matched = 0;;) {
+ switch (*p++) {
+ case '\\': if (*p) p++; break;
+ case '{': matched++; break;
+ case '}': if (!matched--) return 0; break;
+ case '|': case ',': if (matched==0) goto NEXTCASE;
+ case 0: return 0;
+ }
+ }
+ case '|': // skip rest of |pattern|pattern} when called recursively
+ case ',':
+ for (matched = 0; *p && matched >= 0;) {
+ switch (*p++) {
+ case '\\': if (*p) p++; break;
+ case '{': matched++; break;
+ case '}': matched--; break;
+ }
+ }
+ break;
+ case '}':
+ break;
+
+ case 0: // end of pattern
+ return !*s;
+
+ case '\\': // quote next character
+ if (*p) p++;
+ default:
+ if (tolower(*s) != tolower(*(p-1))) return 0;
+ s++;
+ break;
+ }
+ }
+}
+
+//
+// End of "$Id: filename_match.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/filename_setext.cxx b/third_party/windows/fltk-1.1.10/src/filename_setext.cxx new file mode 100644 index 0000000..8887383 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/filename_setext.cxx @@ -0,0 +1,46 @@ +//
+// "$Id: filename_setext.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Filename extension routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Replace .ext with new extension
+// If no . in name, append new extension
+// If new extension is null, act like it is ""
+
+#include <FL/filename.H>
+#include "flstring.h"
+
+char *fl_filename_setext(char *buf, int buflen, const char *ext) {
+ char *q = (char *)fl_filename_ext(buf);
+ if (ext) {
+ strlcpy(q,ext,buflen - (q - buf));
+ } else *q = 0;
+ return(buf);
+}
+
+
+//
+// End of "$Id: filename_setext.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_arc.cxx b/third_party/windows/fltk-1.1.10/src/fl_arc.cxx new file mode 100644 index 0000000..2ff9ef0 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_arc.cxx @@ -0,0 +1,87 @@ +//
+// "$Id: fl_arc.cxx 5349 2006-08-23 14:43:07Z matt $"
+//
+// Arc functions for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Utility for drawing arcs and circles. They are added to
+// the current fl_begin/fl_vertex/fl_end path.
+// Incremental math implementation:
+
+#include <FL/fl_draw.H>
+#include <FL/math.h>
+
+// avoid problems with some platforms that don't
+// implement hypot.
+static double _fl_hypot(double x, double y) {
+ return sqrt(x*x + y*y);
+}
+
+
+void fl_arc(double x, double y, double r, double start, double end) {
+
+ // draw start point accurately:
+
+ double A = start*(M_PI/180); // Initial angle (radians)
+ double X = r*cos(A); // Initial displacement, (X,Y)
+ double Y = -r*sin(A); // from center to initial point
+ fl_vertex(x+X,y+Y); // Insert initial point
+
+ // Maximum arc length to approximate with chord with error <= 0.125
+
+ double epsilon; {
+ double r1 = _fl_hypot(fl_transform_dx(r,0), // Horizontal "radius"
+ fl_transform_dy(r,0));
+ double r2 = _fl_hypot(fl_transform_dx(0,r), // Vertical "radius"
+ fl_transform_dy(0,r));
+
+ if (r1 > r2) r1 = r2; // r1 = minimum "radius"
+ if (r1 < 2.) r1 = 2.; // radius for circa 9 chords/circle
+
+ epsilon = 2*acos(1.0 - 0.125/r1); // Maximum arc angle
+ }
+ A = end*(M_PI/180) - A; // Displacement angle (radians)
+ int i = int(ceil(fabs(A)/epsilon)); // Segments in approximation
+
+ if (i) {
+ epsilon = A/i; // Arc length for equal-size steps
+ double cos_e = cos(epsilon); // Rotation coefficients
+ double sin_e = sin(epsilon);
+ do {
+ double Xnew = cos_e*X + sin_e*Y;
+ Y = -sin_e*X + cos_e*Y;
+ fl_vertex(x + (X=Xnew), y + Y);
+ } while (--i);
+ }
+}
+
+#if 0 // portable version. X-specific one in fl_vertex.cxx
+void fl_circle(double x,double y,double r) {
+ _fl_arc(x, y, r, r, 0, 360);
+}
+#endif
+
+//
+// End of "$Id: fl_arc.cxx 5349 2006-08-23 14:43:07Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_arci.cxx b/third_party/windows/fltk-1.1.10/src/fl_arci.cxx new file mode 100644 index 0000000..1189bf2 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_arci.cxx @@ -0,0 +1,126 @@ +//
+// "$Id: fl_arci.cxx 5518 2006-10-11 01:23:52Z mike $"
+//
+// Arc (integer) drawing functions for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2006 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
+//
+
+// "integer" circle drawing functions. These draw the limited
+// circle types provided by X and NT graphics. The advantage of
+// these is that small ones draw quite nicely (probably due to stored
+// hand-drawn bitmaps of small circles!) and may be implemented by
+// hardware and thus are fast.
+
+// Probably should add fl_chord.
+
+// 3/10/98: created
+
+#include <FL/fl_draw.H>
+#include <FL/x.H>
+#ifdef WIN32
+# include <FL/math.h>
+#endif
+#ifdef __APPLE__
+# include <config.h>
+#endif
+
+void fl_arc(int x,int y,int w,int h,double a1,double a2) {
+ if (w <= 0 || h <= 0) return;
+#ifdef WIN32
+ int xa = x+w/2+int(w*cos(a1/180.0*M_PI));
+ int ya = y+h/2-int(h*sin(a1/180.0*M_PI));
+ int xb = x+w/2+int(w*cos(a2/180.0*M_PI));
+ int yb = y+h/2-int(h*sin(a2/180.0*M_PI));
+ if (fabs(a1 - a2) < 90) {
+ if (xa == xb && ya == yb) SetPixel(fl_gc, xa, ya, fl_RGB());
+ else Arc(fl_gc, x, y, x+w, y+h, xa, ya, xb, yb);
+ } else Arc(fl_gc, x, y, x+w, y+h, xa, ya, xb, yb);
+#elif defined(__APPLE_QD__)
+ Rect r; r.left=x; r.right=x+w; r.top=y; r.bottom=y+h;
+ a1 = a2-a1; a2 = 450-a2;
+ FrameArc(&r, (short int)a2, (short int)a1);
+#elif defined(__APPLE_QUARTZ__)
+ a1 = (-a1)/180.0f*M_PI; a2 = (-a2)/180.0f*M_PI;
+ float cx = x + 0.5f*w - 0.5f, cy = y + 0.5f*h - 0.5f;
+ if (w!=h) {
+ CGContextSaveGState(fl_gc);
+ CGContextTranslateCTM(fl_gc, cx, cy);
+ CGContextScaleCTM(fl_gc, w-1.0f, h-1.0f);
+ CGContextAddArc(fl_gc, 0, 0, 0.5, a1, a2, 1);
+ CGContextRestoreGState(fl_gc);
+ } else {
+ float r = (w+h)*0.25f-0.5f;
+ CGContextAddArc(fl_gc, cx, cy, r, a1, a2, 1);
+ }
+ CGContextStrokePath(fl_gc);
+#else
+ XDrawArc(fl_display, fl_window, fl_gc, x,y,w-1,h-1, int(a1*64),int((a2-a1)*64));
+#endif
+}
+
+void fl_pie(int x,int y,int w,int h,double a1,double a2) {
+ if (w <= 0 || h <= 0) return;
+#ifdef WIN32
+ if (a1 == a2) return;
+ int xa = x+w/2+int(w*cos(a1/180.0*M_PI));
+ int ya = y+h/2-int(h*sin(a1/180.0*M_PI));
+ int xb = x+w/2+int(w*cos(a2/180.0*M_PI));
+ int yb = y+h/2-int(h*sin(a2/180.0*M_PI));
+ SelectObject(fl_gc, fl_brush());
+ if (fabs(a1 - a2) < 90) {
+ if (xa == xb && ya == yb) {
+ MoveToEx(fl_gc, x+w/2, y+h/2, 0L);
+ LineTo(fl_gc, xa, ya);
+ SetPixel(fl_gc, xa, ya, fl_RGB());
+ } else Pie(fl_gc, x, y, x+w, y+h, xa, ya, xb, yb);
+ } else Pie(fl_gc, x, y, x+w, y+h, xa, ya, xb, yb);
+#elif defined(__APPLE_QD__)
+ Rect r; r.left=x; r.right=x+w; r.top=y; r.bottom=y+h;
+ a1 = a2-a1; a2 = 450-a2;
+ PaintArc(&r, (short int)a2, (short int)a1);
+#elif defined(__APPLE_QUARTZ__)
+ a1 = (-a1)/180.0f*M_PI; a2 = (-a2)/180.0f*M_PI;
+ float cx = x + 0.5f*w - 0.5f, cy = y + 0.5f*h - 0.5f;
+ if (w!=h) {
+ CGContextSaveGState(fl_gc);
+ CGContextTranslateCTM(fl_gc, cx, cy);
+ CGContextScaleCTM(fl_gc, w, h);
+ CGContextAddArc(fl_gc, 0, 0, 0.5, a1, a2, 1);
+ CGContextAddLineToPoint(fl_gc, 0, 0);
+ CGContextClosePath(fl_gc);
+ CGContextRestoreGState(fl_gc);
+ } else {
+ float r = (w+h)*0.25f;
+ CGContextAddArc(fl_gc, cx, cy, r, a1, a2, 1);
+ CGContextAddLineToPoint(fl_gc, cx, cy);
+ CGContextClosePath(fl_gc);
+ }
+ CGContextFillPath(fl_gc);
+#else
+ XFillArc(fl_display, fl_window, fl_gc, x,y,w-1,h-1, int(a1*64),int((a2-a1)*64));
+#endif
+}
+
+//
+// End of "$Id: fl_arci.cxx 5518 2006-10-11 01:23:52Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_ask.cxx b/third_party/windows/fltk-1.1.10/src/fl_ask.cxx new file mode 100644 index 0000000..8328566 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_ask.cxx @@ -0,0 +1,396 @@ +//
+// "$Id: fl_ask.cxx 6870 2009-09-13 22:02:30Z AlbrechtS $"
+//
+// Standard dialog functions for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Implementation of fl_message, fl_ask, fl_choice, fl_input
+// The three-message fl_show_x functions are for forms compatibility
+// mostly. In most cases it is easier to get a multi-line message
+// by putting newlines in the message.
+
+#include <stdio.h>
+#include <stdarg.h>
+#include "flstring.h"
+
+#include <FL/Fl.H>
+
+#include <FL/fl_ask.H>
+
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Return_Button.H>
+#include <FL/Fl_Window.H>
+#include <FL/Fl_Input.H>
+#include <FL/Fl_Secret_Input.H>
+#include <FL/x.H>
+#include <FL/fl_draw.H>
+
+static Fl_Window *message_form;
+static Fl_Box *message;
+static Fl_Box *icon;
+static Fl_Button *button[3];
+static Fl_Input *input;
+static const char *iconlabel = "?";
+Fl_Font fl_message_font_ = FL_HELVETICA;
+uchar fl_message_size_ = 14;
+
+static char avoidRecursion = 0;
+
+static Fl_Window *makeform() {
+ if (message_form) {
+ message_form->size(410,103);
+ return message_form;
+ }
+ // make sure that the dialog does not become the child of some
+ // current group
+ Fl_Group *previously_current_group = Fl_Group::current();
+ Fl_Group::current(0);
+ // create a new top level window
+ Fl_Window *w = message_form = new Fl_Window(410,103,"");
+ // w->clear_border();
+ // w->box(FL_UP_BOX);
+ (message = new Fl_Box(60, 25, 340, 20))
+ ->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_WRAP);
+ (input = new Fl_Input(60, 37, 340, 23))->hide();
+ {Fl_Box* o = icon = new Fl_Box(10, 10, 50, 50);
+ o->box(FL_THIN_UP_BOX);
+ o->labelfont(FL_TIMES_BOLD);
+ o->labelsize(34);
+ o->color(FL_WHITE);
+ o->labelcolor(FL_BLUE);
+ }
+ button[0] = new Fl_Button(310, 70, 90, 23);
+ button[0]->shortcut(FL_Escape);
+ button[0]->align(FL_ALIGN_INSIDE|FL_ALIGN_WRAP);
+ button[1] = new Fl_Return_Button(210, 70, 90, 23);
+ button[1]->align(FL_ALIGN_INSIDE|FL_ALIGN_WRAP);
+ button[2] = new Fl_Button(110, 70, 90, 23);
+ button[2]->align(FL_ALIGN_INSIDE|FL_ALIGN_WRAP);
+ w->resizable(new Fl_Box(60,10,110-60,27));
+ w->end();
+ w->set_modal();
+ Fl_Group::current(previously_current_group);
+ return w;
+}
+
+/*
+ * 'resizeform()' - Resize the form and widgets so that they hold everything
+ * that is asked of them...
+ */
+
+void resizeform() {
+ int i;
+ int message_w, message_h;
+ int text_height;
+ int button_w[3], button_h[3];
+ int x, w, h, max_w, max_h;
+ const int icon_size = 50;
+
+ fl_font(fl_message_font_, fl_message_size_);
+ message_w = message_h = 0;
+ fl_measure(message->label(), message_w, message_h);
+
+ message_w += 10;
+ message_h += 10;
+ if (message_w < 340)
+ message_w = 340;
+ if (message_h < 30)
+ message_h = 30;
+
+ fl_font(button[0]->labelfont(), button[0]->labelsize());
+
+ memset(button_w, 0, sizeof(button_w));
+ memset(button_h, 0, sizeof(button_h));
+
+ for (max_h = 25, i = 0; i < 3; i ++)
+ if (button[i]->visible())
+ {
+ fl_measure(button[i]->label(), button_w[i], button_h[i]);
+
+ if (i == 1)
+ button_w[1] += 20;
+
+ button_w[i] += 30;
+ button_h[i] += 10;
+
+ if (button_h[i] > max_h)
+ max_h = button_h[i];
+ }
+
+ if (input->visible()) text_height = message_h + 25;
+ else text_height = message_h;
+
+ max_w = message_w + 10 + icon_size;
+ w = button_w[0] + button_w[1] + button_w[2] - 10;
+
+ if (w > max_w)
+ max_w = w;
+
+ message_w = max_w - 10 - icon_size;
+
+ w = max_w + 20;
+ h = max_h + 30 + text_height;
+
+ message_form->size(w, h);
+ message_form->size_range(w, h, w, h);
+
+ message->resize(20 + icon_size, 10, message_w, message_h);
+ icon->resize(10, 10, icon_size, icon_size);
+ icon->labelsize((uchar)(icon_size - 10));
+ input->resize(20 + icon_size, 10 + message_h, message_w, 25);
+
+ for (x = w, i = 0; i < 3; i ++)
+ if (button_w[i])
+ {
+ x -= button_w[i];
+ button[i]->resize(x, h - 10 - max_h, button_w[i] - 10, max_h);
+
+// printf("button %d (%s) is %dx%d+%d,%d\n", i, button[i]->label(),
+// button[i]->w(), button[i]->h(),
+// button[i]->x(), button[i]->y());
+ }
+}
+
+static int innards(const char* fmt, va_list ap,
+ const char *b0,
+ const char *b1,
+ const char *b2)
+{
+ Fl::pushed(0); // stop dragging (STR #2159)
+
+ avoidRecursion = 1;
+
+ makeform();
+ char buffer[1024];
+ if (!strcmp(fmt,"%s")) {
+ message->label(va_arg(ap, const char*));
+ } else {
+ //: matt: MacOS provides two equally named vsnprintf's...
+ ::vsnprintf(buffer, 1024, fmt, ap);
+ message->label(buffer);
+ }
+
+ message->labelfont(fl_message_font_);
+ message->labelsize(fl_message_size_);
+ if (b0) {button[0]->show(); button[0]->label(b0); button[1]->position(210,70);}
+ else {button[0]->hide(); button[1]->position(310,70);}
+ if (b1) {button[1]->show(); button[1]->label(b1);}
+ else button[1]->hide();
+ if (b2) {button[2]->show(); button[2]->label(b2);}
+ else button[2]->hide();
+ const char* prev_icon_label = icon->label();
+ if (!prev_icon_label) icon->label(iconlabel);
+
+ resizeform();
+
+ if (button[1]->visible() && !input->visible())
+ button[1]->take_focus();
+ message_form->hotspot(button[0]);
+ if (b0 && Fl_Widget::label_shortcut(b0))
+ button[0]->shortcut(0);
+ else
+ button[0]->shortcut(FL_Escape);
+
+ message_form->show();
+ // deactivate Fl::grab(), because it is incompatible with Fl::readqueue()
+ Fl_Window* g = Fl::grab();
+ if (g) Fl::grab(0);
+ int r = 0;
+ for (;;) {
+ Fl_Widget *o = Fl::readqueue();
+ if (!o) Fl::wait();
+ else if (o == button[0]) {r = 0; break;}
+ else if (o == button[1]) {r = 1; break;}
+ else if (o == button[2]) {r = 2; break;}
+ else if (o == message_form) {r = 0; break;}
+ }
+ if (g) // regrab the previous popup menu, if there was one
+ Fl::grab(g);
+ message_form->hide();
+ icon->label(prev_icon_label);
+
+ avoidRecursion = 0;
+ return r;
+}
+
+// pointers you can use to change FLTK to a foreign language:
+const char* fl_no = "No";
+const char* fl_yes= "Yes";
+const char* fl_ok = "OK";
+const char* fl_cancel= "Cancel";
+const char* fl_close= "Close";
+
+// fltk functions:
+void fl_beep(int type) {
+#ifdef WIN32
+ switch (type) {
+ case FL_BEEP_QUESTION :
+ case FL_BEEP_PASSWORD :
+ MessageBeep(MB_ICONQUESTION);
+ break;
+ case FL_BEEP_MESSAGE :
+ MessageBeep(MB_ICONASTERISK);
+ break;
+ case FL_BEEP_NOTIFICATION :
+ MessageBeep(MB_ICONASTERISK);
+ break;
+ case FL_BEEP_ERROR :
+ MessageBeep(MB_ICONERROR);
+ break;
+ default :
+ MessageBeep(0xFFFFFFFF);
+ break;
+ }
+#elif defined(__APPLE__)
+ switch (type) {
+ case FL_BEEP_DEFAULT :
+ case FL_BEEP_ERROR :
+ SysBeep(30);
+ break;
+ default :
+ break;
+ }
+#else
+ switch (type) {
+ case FL_BEEP_DEFAULT :
+ case FL_BEEP_ERROR :
+ if (!fl_display) fl_open_display();
+
+ XBell(fl_display, 100);
+ break;
+ default :
+ if (!fl_display) fl_open_display();
+
+ XBell(fl_display, 50);
+ break;
+ }
+#endif // WIN32
+}
+
+void fl_message(const char *fmt, ...) {
+
+ if (avoidRecursion) return;
+
+ va_list ap;
+
+ fl_beep(FL_BEEP_MESSAGE);
+
+ va_start(ap, fmt);
+ iconlabel = "i";
+ innards(fmt, ap, 0, fl_close, 0);
+ va_end(ap);
+ iconlabel = "?";
+}
+
+void fl_alert(const char *fmt, ...) {
+
+ if (avoidRecursion) return;
+
+ va_list ap;
+
+ fl_beep(FL_BEEP_ERROR);
+
+ va_start(ap, fmt);
+ iconlabel = "!";
+ innards(fmt, ap, 0, fl_close, 0);
+ va_end(ap);
+ iconlabel = "?";
+}
+
+int fl_ask(const char *fmt, ...) {
+
+ if (avoidRecursion) return 0;
+
+ va_list ap;
+
+ fl_beep(FL_BEEP_QUESTION);
+
+ va_start(ap, fmt);
+ int r = innards(fmt, ap, fl_no, fl_yes, 0);
+ va_end(ap);
+
+ return r;
+}
+
+int fl_choice(const char*fmt,const char *b0,const char *b1,const char *b2,...){
+
+ if (avoidRecursion) return 0;
+
+ va_list ap;
+
+ fl_beep(FL_BEEP_QUESTION);
+
+ va_start(ap, b2);
+ int r = innards(fmt, ap, b0, b1, b2);
+ va_end(ap);
+ return r;
+}
+
+Fl_Widget *fl_message_icon() {makeform(); return icon;}
+
+static const char* input_innards(const char* fmt, va_list ap,
+ const char* defstr, uchar type) {
+ makeform();
+ message->position(60,10);
+ input->type(type);
+ input->show();
+ input->value(defstr);
+ input->take_focus();
+
+ int r = innards(fmt, ap, fl_cancel, fl_ok, 0);
+ input->hide();
+ message->position(60,25);
+ return r ? input->value() : 0;
+}
+
+const char* fl_input(const char *fmt, const char *defstr, ...) {
+
+ if (avoidRecursion) return 0;
+
+ fl_beep(FL_BEEP_QUESTION);
+
+ va_list ap;
+ va_start(ap, defstr);
+ const char* r = input_innards(fmt, ap, defstr, FL_NORMAL_INPUT);
+ va_end(ap);
+ return r;
+}
+
+const char *fl_password(const char *fmt, const char *defstr, ...) {
+
+ if (avoidRecursion) return 0;
+
+ fl_beep(FL_BEEP_PASSWORD);
+
+ va_list ap;
+ va_start(ap, defstr);
+ const char* r = input_innards(fmt, ap, defstr, FL_SECRET_INPUT);
+ va_end(ap);
+ return r;
+}
+
+//
+// End of "$Id: fl_ask.cxx 6870 2009-09-13 22:02:30Z AlbrechtS $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_boxtype.cxx b/third_party/windows/fltk-1.1.10/src/fl_boxtype.cxx new file mode 100644 index 0000000..f0d1e05 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_boxtype.cxx @@ -0,0 +1,322 @@ +//
+// "$Id: fl_boxtype.cxx 5505 2006-10-03 02:35:12Z mike $"
+//
+// Box drawing code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2006 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
+//
+
+// Box drawing code for the common box types and the table of
+// boxtypes. Other box types are in seperate files so they are not
+// linked in if not used.
+
+#include <FL/Fl.H>
+#include <FL/Fl_Widget.H>
+#include <FL/fl_draw.H>
+#include <config.h>
+
+////////////////////////////////////////////////////////////////
+
+static uchar active_ramp[24] = {
+ FL_GRAY_RAMP+0, FL_GRAY_RAMP+1, FL_GRAY_RAMP+2, FL_GRAY_RAMP+3,
+ FL_GRAY_RAMP+4, FL_GRAY_RAMP+5, FL_GRAY_RAMP+6, FL_GRAY_RAMP+7,
+ FL_GRAY_RAMP+8, FL_GRAY_RAMP+9, FL_GRAY_RAMP+10,FL_GRAY_RAMP+11,
+ FL_GRAY_RAMP+12,FL_GRAY_RAMP+13,FL_GRAY_RAMP+14,FL_GRAY_RAMP+15,
+ FL_GRAY_RAMP+16,FL_GRAY_RAMP+17,FL_GRAY_RAMP+18,FL_GRAY_RAMP+19,
+ FL_GRAY_RAMP+20,FL_GRAY_RAMP+21,FL_GRAY_RAMP+22,FL_GRAY_RAMP+23};
+static uchar inactive_ramp[24] = {
+ 43, 43, 44, 44,
+ 44, 45, 45, 46,
+ 46, 46, 47, 47,
+ 48, 48, 48, 49,
+ 49, 49, 50, 50,
+ 51, 51, 52, 52};
+static int draw_it_active = 1;
+
+int Fl::draw_box_active() { return draw_it_active; }
+
+uchar *fl_gray_ramp() {return (draw_it_active?active_ramp:inactive_ramp)-'A';}
+
+void fl_frame(const char* s, int x, int y, int w, int h) {
+ uchar *g = fl_gray_ramp();
+ if (h > 0 && w > 0) for (;*s;) {
+ // draw top line:
+ fl_color(g[*s++]);
+ fl_xyline(x, y, x+w-1);
+ y++; if (--h <= 0) break;
+ // draw left line:
+ fl_color(g[*s++]);
+ fl_yxline(x, y+h-1, y);
+ x++; if (--w <= 0) break;
+ // draw bottom line:
+ fl_color(g[*s++]);
+ fl_xyline(x, y+h-1, x+w-1);
+ if (--h <= 0) break;
+ // draw right line:
+ fl_color(g[*s++]);
+ fl_yxline(x+w-1, y+h-1, y);
+ if (--w <= 0) break;
+ }
+}
+
+void fl_frame2(const char* s, int x, int y, int w, int h) {
+ uchar *g = fl_gray_ramp();
+ if (h > 0 && w > 0) for (;*s;) {
+ // draw bottom line:
+ fl_color(g[*s++]);
+ fl_xyline(x, y+h-1, x+w-1);
+ if (--h <= 0) break;
+ // draw right line:
+ fl_color(g[*s++]);
+ fl_yxline(x+w-1, y+h-1, y);
+ if (--w <= 0) break;
+ // draw top line:
+ fl_color(g[*s++]);
+ fl_xyline(x, y, x+w-1);
+ y++; if (--h <= 0) break;
+ // draw left line:
+ fl_color(g[*s++]);
+ fl_yxline(x, y+h-1, y);
+ x++; if (--w <= 0) break;
+ }
+}
+
+void fl_no_box(int, int, int, int, Fl_Color) {}
+
+void fl_thin_down_frame(int x, int y, int w, int h, Fl_Color) {
+ fl_frame2("WWHH",x,y,w,h);
+}
+
+void fl_thin_down_box(int x, int y, int w, int h, Fl_Color c) {
+ fl_thin_down_frame(x,y,w,h,c);
+ fl_color(draw_it_active ? c : fl_inactive(c));
+ fl_rectf(x+1, y+1, w-2, h-2);
+}
+
+void fl_thin_up_frame(int x, int y, int w, int h, Fl_Color) {
+ fl_frame2("HHWW",x,y,w,h);
+}
+
+void fl_thin_up_box(int x, int y, int w, int h, Fl_Color c) {
+ fl_thin_up_frame(x,y,w,h,c);
+ fl_color(draw_it_active ? c : fl_inactive(c));
+ fl_rectf(x+1, y+1, w-2, h-2);
+}
+
+void fl_up_frame(int x, int y, int w, int h, Fl_Color) {
+#if BORDER_WIDTH == 1
+ fl_frame2("HHWW",x,y,w,h);
+#else
+#if BORDER_WIDTH == 2
+ fl_frame2("AAWWMMTT",x,y,w,h);
+#else
+ fl_frame("AAAAWWJJUTNN",x,y,w,h);
+#endif
+#endif
+}
+
+#define D1 BORDER_WIDTH
+#define D2 (BORDER_WIDTH+BORDER_WIDTH)
+
+void fl_up_box(int x, int y, int w, int h, Fl_Color c) {
+ fl_up_frame(x,y,w,h,c);
+ fl_color(draw_it_active ? c : fl_inactive(c));
+ fl_rectf(x+D1, y+D1, w-D2, h-D2);
+}
+
+void fl_down_frame(int x, int y, int w, int h, Fl_Color) {
+#if BORDER_WIDTH == 1
+ fl_frame2("WWHH",x,y,w,h);
+#else
+#if BORDER_WIDTH == 2
+ fl_frame2("WWMMPPAA",x,y,w,h);
+#else
+ fl_frame("NNTUJJWWAAAA",x,y,w,h);
+#endif
+#endif
+}
+
+void fl_down_box(int x, int y, int w, int h, Fl_Color c) {
+ fl_down_frame(x,y,w,h,c);
+ fl_color(c); fl_rectf(x+D1, y+D1, w-D2, h-D2);
+}
+
+void fl_engraved_frame(int x, int y, int w, int h, Fl_Color) {
+ fl_frame("HHWWWWHH",x,y,w,h);
+}
+
+void fl_engraved_box(int x, int y, int w, int h, Fl_Color c) {
+ fl_engraved_frame(x,y,w,h,c);
+ fl_color(draw_it_active ? c : fl_inactive(c));
+ fl_rectf(x+2, y+2, w-4, h-4);
+}
+
+void fl_embossed_frame(int x, int y, int w, int h, Fl_Color) {
+ fl_frame("WWHHHHWW",x,y,w,h);
+}
+
+void fl_embossed_box(int x, int y, int w, int h, Fl_Color c) {
+ fl_embossed_frame(x,y,w,h,c);
+ fl_color(draw_it_active ? c : fl_inactive(c));
+ fl_rectf(x+2, y+2, w-4, h-4);
+}
+
+void fl_rectbound(int x, int y, int w, int h, Fl_Color bgcolor) {
+ fl_color(draw_it_active ? FL_BLACK : fl_inactive(FL_BLACK));
+ fl_rect(x, y, w, h);
+ fl_color(draw_it_active ? bgcolor : fl_inactive(bgcolor));
+ fl_rectf(x+1, y+1, w-2, h-2);
+}
+#define fl_border_box fl_rectbound
+
+void fl_border_frame(int x, int y, int w, int h, Fl_Color c) {
+ fl_color(draw_it_active ? c : fl_inactive(c));
+ fl_rect(x, y, w, h);
+}
+
+////////////////////////////////////////////////////////////////
+
+static struct {
+ Fl_Box_Draw_F *f;
+ uchar dx, dy, dw, dh;
+ int set;
+} fl_box_table[256] = {
+// must match list in Enumerations.H!!!
+ {fl_no_box, 0,0,0,0,1},
+ {fl_rectf, 0,0,0,0,1}, // FL_FLAT_BOX
+ {fl_up_box, D1,D1,D2,D2,1},
+ {fl_down_box, D1,D1,D2,D2,1},
+ {fl_up_frame, D1,D1,D2,D2,1},
+ {fl_down_frame, D1,D1,D2,D2,1},
+ {fl_thin_up_box, 1,1,2,2,1},
+ {fl_thin_down_box, 1,1,2,2,1},
+ {fl_thin_up_frame, 1,1,2,2,1},
+ {fl_thin_down_frame, 1,1,2,2,1},
+ {fl_engraved_box, 2,2,4,4,1},
+ {fl_embossed_box, 2,2,4,4,1},
+ {fl_engraved_frame, 2,2,4,4,1},
+ {fl_embossed_frame, 2,2,4,4,1},
+ {fl_border_box, 1,1,2,2,1},
+ {fl_border_box, 1,1,5,5,0}, // _FL_SHADOW_BOX,
+ {fl_border_frame, 1,1,2,2,1},
+ {fl_border_frame, 1,1,5,5,0}, // _FL_SHADOW_FRAME,
+ {fl_border_box, 1,1,2,2,0}, // _FL_ROUNDED_BOX,
+ {fl_border_box, 1,1,2,2,0}, // _FL_RSHADOW_BOX,
+ {fl_border_frame, 1,1,2,2,0}, // _FL_ROUNDED_FRAME
+ {fl_rectf, 0,0,0,0,0}, // _FL_RFLAT_BOX,
+ {fl_up_box, 3,3,6,6,0}, // _FL_ROUND_UP_BOX
+ {fl_down_box, 3,3,6,6,0}, // _FL_ROUND_DOWN_BOX,
+ {fl_up_box, 0,0,0,0,0}, // _FL_DIAMOND_UP_BOX
+ {fl_down_box, 0,0,0,0,0}, // _FL_DIAMOND_DOWN_BOX
+ {fl_border_box, 1,1,2,2,0}, // _FL_OVAL_BOX,
+ {fl_border_box, 1,1,2,2,0}, // _FL_OVAL_SHADOW_BOX,
+ {fl_border_frame, 1,1,2,2,0}, // _FL_OVAL_FRAME
+ {fl_rectf, 0,0,0,0,0}, // _FL_OVAL_FLAT_BOX,
+ {fl_up_box, 4,4,8,8,0}, // _FL_PLASTIC_UP_BOX,
+ {fl_down_box, 2,2,4,4,0}, // _FL_PLASTIC_DOWN_BOX,
+ {fl_up_frame, 2,2,4,4,0}, // _FL_PLASTIC_UP_FRAME,
+ {fl_down_frame, 2,2,4,4,0}, // _FL_PLASTIC_DOWN_FRAME,
+ {fl_up_box, 2,2,4,4,0}, // _FL_PLASTIC_THIN_UP_BOX,
+ {fl_down_box, 2,2,4,4,0}, // _FL_PLASTIC_THIN_DOWN_BOX,
+ {fl_up_box, 2,2,4,4,0}, // _FL_PLASTIC_ROUND_UP_BOX,
+ {fl_down_box, 2,2,4,4,0}, // _FL_PLASTIC_ROUND_DOWN_BOX,
+ {fl_up_box, 2,2,4,4,0}, // _FL_GTK_UP_BOX,
+ {fl_down_box, 2,2,4,4,0}, // _FL_GTK_DOWN_BOX,
+ {fl_up_frame, 2,2,4,4,0}, // _FL_GTK_UP_FRAME,
+ {fl_down_frame, 2,2,4,4,0}, // _FL_GTK_DOWN_FRAME,
+ {fl_up_frame, 1,1,2,2,0}, // _FL_GTK_THIN_UP_FRAME,
+ {fl_down_frame, 1,1,2,2,0}, // _FL_GTK_THIN_DOWN_FRAME,
+ {fl_up_box, 1,1,2,2,0}, // _FL_GTK_THIN_ROUND_UP_BOX,
+ {fl_down_box, 1,1,2,2,0}, // _FL_GTK_THIN_ROUND_DOWN_BOX,
+ {fl_up_box, 2,2,4,4,0}, // _FL_GTK_ROUND_UP_BOX,
+ {fl_down_box, 2,2,4,4,0}, // _FL_GTK_ROUND_DOWN_BOX,
+ {fl_up_box, 3,3,6,6,0}, // FL_FREE_BOX+0
+ {fl_down_box, 3,3,6,6,0}, // FL_FREE_BOX+1
+ {fl_up_box, 3,3,6,6,0}, // FL_FREE_BOX+2
+ {fl_down_box, 3,3,6,6,0}, // FL_FREE_BOX+3
+ {fl_up_box, 3,3,6,6,0}, // FL_FREE_BOX+4
+ {fl_down_box, 3,3,6,6,0}, // FL_FREE_BOX+5
+ {fl_up_box, 3,3,6,6,0}, // FL_FREE_BOX+6
+ {fl_down_box, 3,3,6,6,0}, // FL_FREE_BOX+7
+};
+
+int Fl::box_dx(Fl_Boxtype t) {return fl_box_table[t].dx;}
+int Fl::box_dy(Fl_Boxtype t) {return fl_box_table[t].dy;}
+int Fl::box_dw(Fl_Boxtype t) {return fl_box_table[t].dw;}
+int Fl::box_dh(Fl_Boxtype t) {return fl_box_table[t].dh;}
+
+void fl_internal_boxtype(Fl_Boxtype t, Fl_Box_Draw_F* f) {
+ if (!fl_box_table[t].set) {
+ fl_box_table[t].f = f;
+ fl_box_table[t].set = 1;
+ }
+}
+
+Fl_Box_Draw_F *Fl::get_boxtype(Fl_Boxtype t) {
+ return fl_box_table[t].f;
+}
+
+void Fl::set_boxtype(Fl_Boxtype t, Fl_Box_Draw_F* f,
+ uchar a, uchar b, uchar c, uchar d) {
+ fl_box_table[t].f = f;
+ fl_box_table[t].set = 1;
+ fl_box_table[t].dx = a;
+ fl_box_table[t].dy = b;
+ fl_box_table[t].dw = c;
+ fl_box_table[t].dh = d;
+}
+
+void Fl::set_boxtype(Fl_Boxtype t, Fl_Boxtype f) {
+ fl_box_table[t] = fl_box_table[f];
+}
+
+void fl_draw_box(Fl_Boxtype t, int x, int y, int w, int h, Fl_Color c) {
+ if (t && fl_box_table[t].f) fl_box_table[t].f(x,y,w,h,c);
+}
+
+//extern Fl_Widget *fl_boxcheat; // hack set by Fl_Window.cxx
+
+void Fl_Widget::draw_box() const {
+ int t = box_;
+ if (!t) return;
+// if (this == fl_boxcheat) {
+// fl_boxcheat = 0;
+// if (t == FL_FLAT_BOX) return;
+// t += 2; // convert box to frame
+// }
+ draw_box((Fl_Boxtype)t, x_, y_, w_, h_, (Fl_Color)color_);
+}
+
+void Fl_Widget::draw_box(Fl_Boxtype b, Fl_Color c) const {
+ draw_box(b, x_, y_, w_, h_, c);
+}
+
+void Fl_Widget::draw_box(Fl_Boxtype b, int X, int Y, int W, int H, Fl_Color c)
+const {
+ draw_it_active = active_r();
+ fl_box_table[b].f(X, Y, W, H, c);
+ draw_it_active = 1;
+}
+
+//
+// End of "$Id: fl_boxtype.cxx 5505 2006-10-03 02:35:12Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_call_main.c b/third_party/windows/fltk-1.1.10/src/fl_call_main.c new file mode 100644 index 0000000..5865497 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_call_main.c @@ -0,0 +1,107 @@ +/*
+ * "$Id: fl_call_main.c 5848 2007-05-20 16:18:31Z mike $"
+ *
+ * Copyright 1998-2005 by Bill Spitzak and others.
+ *
+ * fl_call_main() calls main() for you Windows people. Needs to be done in C
+ * because Borland C++ won't let you call main() from C++.
+ *
+ * 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
+ */
+
+/*
+ * This WinMain() function can be overridden by an application and
+ * is provided for compatibility with programs written for other
+ * operating systems that conform to the ANSI standard entry point
+ * "main()". This will allow you to build a WIN32 Application
+ * without any special settings.
+ *
+ * Because of problems with the Microsoft Visual C++ header files
+ * and/or compiler, you cannot have a WinMain function in a DLL.
+ * I don't know why. Thus, this nifty feature is only available
+ * if you link to the static library.
+ *
+ * Currently the debug version of this library will create a
+ * console window for your application so you can put printf()
+ * statements for debugging or informational purposes. Ultimately
+ * we want to update this to always use the parent's console,
+ * but at present we have not identified a function or API in
+ * Microsoft(r) Windows(r) that allows for it.
+ */
+
+#if defined(WIN32) && !defined(FL_DLL) && !defined (__GNUC__)
+
+# include <windows.h>
+# include <stdio.h>
+# include <stdlib.h>
+
+# ifdef __MWERKS__
+# include <crtl.h>
+# endif
+
+extern int main(int, char *[]);
+
+# ifdef BORLAND5
+# define __argc _argc
+# define __argv _argv
+# endif /* BORLAND5 */
+
+int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
+ LPSTR lpCmdLine, int nCmdShow) {
+ int rc;
+
+# ifdef _DEBUG
+ /*
+ * If we are using compiling in debug mode, open a console window so
+ * we can see any printf's, etc...
+ *
+ * While we can detect if the program was run from the command-line -
+ * look at the CMDLINE environment variable, it will be "WIN" for
+ * programs started from the GUI - the shell seems to run all WIN32
+ * applications in the background anyways...
+ */
+
+ AllocConsole();
+ freopen("conin$", "r", stdin);
+ freopen("conout$", "w", stdout);
+ freopen("conout$", "w", stderr);
+# endif /* _DEBUG */
+
+ /* Run the standard main entry point function... */
+ rc = main(__argc, __argv);
+
+# ifdef _DEBUG
+ fclose(stdin);
+ fclose(stdout);
+ fclose(stderr);
+# endif /* _DEBUG */
+
+ return rc;
+}
+
+#elif defined(__hpux)
+/* This code to prevent "empty translation unit" or similar warnings... */
+static void dummy(void) {}
+#endif // WIN32 && !FL_DLL && !__GNUC__
+
+/*
+ * End of "$Id: fl_call_main.c 5848 2007-05-20 16:18:31Z mike $".
+ */
+
diff --git a/third_party/windows/fltk-1.1.10/src/fl_cmap.h b/third_party/windows/fltk-1.1.10/src/fl_cmap.h new file mode 100644 index 0000000..19b4202 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_cmap.h @@ -0,0 +1,256 @@ + 0x00000000,
+ 0xff000000,
+ 0x00ff0000,
+ 0xffff0000,
+ 0x0000ff00,
+ 0xff00ff00,
+ 0x00ffff00,
+ 0xffffff00,
+ 0x55555500,
+ 0xc6717100,
+ 0x71c67100,
+ 0x8e8e3800,
+ 0x7171c600,
+ 0x8e388e00,
+ 0x388e8e00,
+ 0x00008000,
+ 0xa8a89800,
+ 0xe8e8d800,
+ 0x68685800,
+ 0x98a8a800,
+ 0xd8e8e800,
+ 0x58686800,
+ 0x9c9ca800,
+ 0xdcdce800,
+ 0x5c5c6800,
+ 0x9ca89c00,
+ 0xdce8dc00,
+ 0x5c685c00,
+ 0x90909000,
+ 0xc0c0c000,
+ 0x50505000,
+ 0xa0a0a000,
+ 0x00000000,
+ 0x0d0d0d00,
+ 0x1a1a1a00,
+ 0x26262600,
+ 0x31313100,
+ 0x3d3d3d00,
+ 0x48484800,
+ 0x55555500,
+ 0x5f5f5f00,
+ 0x6a6a6a00,
+ 0x75757500,
+ 0x80808000,
+ 0x8a8a8a00,
+ 0x95959500,
+ 0xa0a0a000,
+ 0xaaaaaa00,
+ 0xb5b5b500,
+ 0xc0c0c000,
+ 0xcbcbcb00,
+ 0xd5d5d500,
+ 0xe0e0e000,
+ 0xeaeaea00,
+ 0xf5f5f500,
+ 0xffffff00,
+ 0x00000000,
+ 0x00240000,
+ 0x00480000,
+ 0x006d0000,
+ 0x00910000,
+ 0x00b60000,
+ 0x00da0000,
+ 0x00ff0000,
+ 0x3f000000,
+ 0x3f240000,
+ 0x3f480000,
+ 0x3f6d0000,
+ 0x3f910000,
+ 0x3fb60000,
+ 0x3fda0000,
+ 0x3fff0000,
+ 0x7f000000,
+ 0x7f240000,
+ 0x7f480000,
+ 0x7f6d0000,
+ 0x7f910000,
+ 0x7fb60000,
+ 0x7fda0000,
+ 0x7fff0000,
+ 0xbf000000,
+ 0xbf240000,
+ 0xbf480000,
+ 0xbf6d0000,
+ 0xbf910000,
+ 0xbfb60000,
+ 0xbfda0000,
+ 0xbfff0000,
+ 0xff000000,
+ 0xff240000,
+ 0xff480000,
+ 0xff6d0000,
+ 0xff910000,
+ 0xffb60000,
+ 0xffda0000,
+ 0xffff0000,
+ 0x00003f00,
+ 0x00243f00,
+ 0x00483f00,
+ 0x006d3f00,
+ 0x00913f00,
+ 0x00b63f00,
+ 0x00da3f00,
+ 0x00ff3f00,
+ 0x3f003f00,
+ 0x3f243f00,
+ 0x3f483f00,
+ 0x3f6d3f00,
+ 0x3f913f00,
+ 0x3fb63f00,
+ 0x3fda3f00,
+ 0x3fff3f00,
+ 0x7f003f00,
+ 0x7f243f00,
+ 0x7f483f00,
+ 0x7f6d3f00,
+ 0x7f913f00,
+ 0x7fb63f00,
+ 0x7fda3f00,
+ 0x7fff3f00,
+ 0xbf003f00,
+ 0xbf243f00,
+ 0xbf483f00,
+ 0xbf6d3f00,
+ 0xbf913f00,
+ 0xbfb63f00,
+ 0xbfda3f00,
+ 0xbfff3f00,
+ 0xff003f00,
+ 0xff243f00,
+ 0xff483f00,
+ 0xff6d3f00,
+ 0xff913f00,
+ 0xffb63f00,
+ 0xffda3f00,
+ 0xffff3f00,
+ 0x00007f00,
+ 0x00247f00,
+ 0x00487f00,
+ 0x006d7f00,
+ 0x00917f00,
+ 0x00b67f00,
+ 0x00da7f00,
+ 0x00ff7f00,
+ 0x3f007f00,
+ 0x3f247f00,
+ 0x3f487f00,
+ 0x3f6d7f00,
+ 0x3f917f00,
+ 0x3fb67f00,
+ 0x3fda7f00,
+ 0x3fff7f00,
+ 0x7f007f00,
+ 0x7f247f00,
+ 0x7f487f00,
+ 0x7f6d7f00,
+ 0x7f917f00,
+ 0x7fb67f00,
+ 0x7fda7f00,
+ 0x7fff7f00,
+ 0xbf007f00,
+ 0xbf247f00,
+ 0xbf487f00,
+ 0xbf6d7f00,
+ 0xbf917f00,
+ 0xbfb67f00,
+ 0xbfda7f00,
+ 0xbfff7f00,
+ 0xff007f00,
+ 0xff247f00,
+ 0xff487f00,
+ 0xff6d7f00,
+ 0xff917f00,
+ 0xffb67f00,
+ 0xffda7f00,
+ 0xffff7f00,
+ 0x0000bf00,
+ 0x0024bf00,
+ 0x0048bf00,
+ 0x006dbf00,
+ 0x0091bf00,
+ 0x00b6bf00,
+ 0x00dabf00,
+ 0x00ffbf00,
+ 0x3f00bf00,
+ 0x3f24bf00,
+ 0x3f48bf00,
+ 0x3f6dbf00,
+ 0x3f91bf00,
+ 0x3fb6bf00,
+ 0x3fdabf00,
+ 0x3fffbf00,
+ 0x7f00bf00,
+ 0x7f24bf00,
+ 0x7f48bf00,
+ 0x7f6dbf00,
+ 0x7f91bf00,
+ 0x7fb6bf00,
+ 0x7fdabf00,
+ 0x7fffbf00,
+ 0xbf00bf00,
+ 0xbf24bf00,
+ 0xbf48bf00,
+ 0xbf6dbf00,
+ 0xbf91bf00,
+ 0xbfb6bf00,
+ 0xbfdabf00,
+ 0xbfffbf00,
+ 0xff00bf00,
+ 0xff24bf00,
+ 0xff48bf00,
+ 0xff6dbf00,
+ 0xff91bf00,
+ 0xffb6bf00,
+ 0xffdabf00,
+ 0xffffbf00,
+ 0x0000ff00,
+ 0x0024ff00,
+ 0x0048ff00,
+ 0x006dff00,
+ 0x0091ff00,
+ 0x00b6ff00,
+ 0x00daff00,
+ 0x00ffff00,
+ 0x3f00ff00,
+ 0x3f24ff00,
+ 0x3f48ff00,
+ 0x3f6dff00,
+ 0x3f91ff00,
+ 0x3fb6ff00,
+ 0x3fdaff00,
+ 0x3fffff00,
+ 0x7f00ff00,
+ 0x7f24ff00,
+ 0x7f48ff00,
+ 0x7f6dff00,
+ 0x7f91ff00,
+ 0x7fb6ff00,
+ 0x7fdaff00,
+ 0x7fffff00,
+ 0xbf00ff00,
+ 0xbf24ff00,
+ 0xbf48ff00,
+ 0xbf6dff00,
+ 0xbf91ff00,
+ 0xbfb6ff00,
+ 0xbfdaff00,
+ 0xbfffff00,
+ 0xff00ff00,
+ 0xff24ff00,
+ 0xff48ff00,
+ 0xff6dff00,
+ 0xff91ff00,
+ 0xffb6ff00,
+ 0xffdaff00,
+ 0xffffff00
diff --git a/third_party/windows/fltk-1.1.10/src/fl_color.cxx b/third_party/windows/fltk-1.1.10/src/fl_color.cxx new file mode 100644 index 0000000..a08fe8a --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_color.cxx @@ -0,0 +1,389 @@ +//
+// "$Id: fl_color.cxx 5835 2007-05-16 11:46:07Z matt $"
+//
+// Color functions for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Implementation of fl_color(i), fl_color(r,g,b).
+
+#ifdef WIN32
+# include "fl_color_win32.cxx"
+#elif defined(__APPLE__)
+# include "fl_color_mac.cxx"
+#else
+
+// Also code to look at the X visual and figure out the best way to turn
+// a color into a pixel value.
+
+// SGI compiler seems to have problems with unsigned char arguments
+// being used to index arrays. So I always copy them to an integer
+// before use.
+
+# include "Fl_XColor.H"
+# include <FL/Fl.H>
+# include <FL/x.H>
+# include <FL/fl_draw.H>
+
+////////////////////////////////////////////////////////////////
+// figure_out_visual() calculates masks & shifts for generating
+// pixels in true-color visuals:
+
+uchar fl_redmask, fl_greenmask, fl_bluemask;
+int fl_redshift, fl_greenshift, fl_blueshift, fl_extrashift;
+static uchar beenhere;
+
+static void figure_out_visual() {
+ beenhere = 1;
+ if (!fl_visual->red_mask || !fl_visual->green_mask || !fl_visual->blue_mask){
+# if USE_COLORMAP
+ fl_redmask = 0;
+ return;
+# else
+ Fl::fatal("Requires true color visual");
+# endif
+ }
+
+ // get the bit masks into a more useful form:
+ int i,j,m;
+
+ for (i = 0, m = 1; m; i++, m<<=1) if (fl_visual->red_mask & m) break;
+ for (j = i; m; j++, m<<=1) if (!(fl_visual->red_mask & m)) break;
+ fl_redshift = j-8;
+ fl_redmask = (j-i >= 8) ? 0xFF : 0xFF-(255>>(j-i));
+
+ for (i = 0, m = 1; m; i++, m<<=1) if (fl_visual->green_mask & m) break;
+ for (j = i; m; j++, m<<=1) if (!(fl_visual->green_mask & m)) break;
+ fl_greenshift = j-8;
+ fl_greenmask = (j-i >= 8) ? 0xFF : 0xFF-(255>>(j-i));
+
+ for (i = 0, m = 1; m; i++, m<<=1) if (fl_visual->blue_mask & m) break;
+ for (j = i; m; j++, m<<=1) if (!(fl_visual->blue_mask & m)) break;
+ fl_blueshift = j-8;
+ fl_bluemask = (j-i >= 8) ? 0xFF : 0xFF-(255>>(j-i));
+
+ i = fl_redshift;
+ if (fl_greenshift < i) i = fl_greenshift;
+ if (fl_blueshift < i) i = fl_blueshift;
+ if (i < 0) {
+ fl_extrashift = -i;
+ fl_redshift -= i; fl_greenshift -= i; fl_blueshift -= i;
+ } else
+ fl_extrashift = 0;
+
+}
+
+static unsigned fl_cmap[256] = {
+#include "fl_cmap.h" // this is a file produced by "cmap.cxx":
+};
+
+# if HAVE_OVERLAY
+Fl_XColor fl_xmap[2][256];
+uchar fl_overlay;
+Colormap fl_overlay_colormap;
+XVisualInfo* fl_overlay_visual;
+ulong fl_transparent_pixel;
+# else
+Fl_XColor fl_xmap[1][256];
+# define fl_overlay 0
+# endif
+
+////////////////////////////////////////////////////////////////
+// Get an rgb color. This is easy for a truecolor visual. For
+// colormapped it picks the closest color out of the cube in the
+// fltk colormap. However if this color cube entry has been
+// requested before, you will get the earlier requested color, and
+// even this may be approximated if the X colormap was full.
+
+ulong fl_xpixel(uchar r,uchar g,uchar b) {
+ if (!beenhere) figure_out_visual();
+# if USE_COLORMAP
+ if (!fl_redmask) {
+ // find closest entry in the colormap:
+ Fl_Color i =
+ fl_color_cube(r*FL_NUM_RED/256,g*FL_NUM_GREEN/256,b*FL_NUM_BLUE/256);
+ Fl_XColor &xmap = fl_xmap[fl_overlay][i];
+ if (xmap.mapped) return xmap.pixel;
+ // if not black or white, change the entry to be an exact match:
+ if (i != FL_COLOR_CUBE && i != 0xFF)
+ fl_cmap[i] = (r<<24)|(g<<16)|(b<<8);
+ return fl_xpixel(i); // allocate an X color
+ }
+# endif
+ return
+ (((r&fl_redmask) << fl_redshift)+
+ ((g&fl_greenmask)<<fl_greenshift)+
+ ((b&fl_bluemask)<< fl_blueshift)
+ ) >> fl_extrashift;
+}
+
+void fl_color(uchar r,uchar g,uchar b) {
+ fl_color_ = fl_rgb_color(r, g, b);
+ XSetForeground(fl_display, fl_gc, fl_xpixel(r,g,b));
+}
+
+////////////////////////////////////////////////////////////////
+// Get a color out of the the fltk colormap. Again for truecolor
+// visuals this is easy. For colormap this actually tries to allocate
+// an X color, and does a least-squares match to find the closest
+// color if X cannot allocate that color.
+
+// calculate what color is actually on the screen for a mask:
+static inline uchar realcolor(uchar color, uchar mask) {
+# if 0
+ // accurate version if the display has linear gamma, but fl_draw_image
+ // works better with the simpler version on most screens...
+ uchar m = mask;
+ uchar result = color&m;
+ for (;;) {
+ while (m&mask) {m>>=1; color>>=1;}
+ if (!m) break;
+ mask = m;
+ result |= color&m;
+ }
+ return result;
+# else
+ return (color&mask) | (~mask)&(mask>>1);
+# endif
+}
+
+ulong fl_xpixel(Fl_Color i) {
+ if (i & 0xffffff00) {
+ return fl_xpixel((i >> 24) & 255, (i >> 16) & 255, (i >> 8) & 255);
+ }
+
+ Fl_XColor &xmap = fl_xmap[fl_overlay][i];
+ if (xmap.mapped) return xmap.pixel;
+
+ if (!beenhere) figure_out_visual();
+
+ uchar r,g,b;
+ {unsigned c = fl_cmap[i]; r=uchar(c>>24); g=uchar(c>>16); b=uchar(c>>8);}
+
+# if USE_COLORMAP
+ Colormap colormap = fl_colormap;
+# if HAVE_OVERLAY
+ if (fl_overlay) colormap = fl_overlay_colormap; else
+# endif
+ if (fl_redmask) {
+# endif
+ // return color for a truecolor visual:
+ xmap.mapped = 2; // 2 prevents XFreeColor from being called
+ xmap.r = realcolor(r, fl_redmask);
+ xmap.g = realcolor(g, fl_greenmask);
+ xmap.b = realcolor(b, fl_bluemask);
+ return xmap.pixel =
+ (((r&fl_redmask) << fl_redshift)+
+ ((g&fl_greenmask)<<fl_greenshift)+
+ ((b&fl_bluemask)<< fl_blueshift)
+ ) >> fl_extrashift;
+# if USE_COLORMAP
+ }
+# if HAVE_OVERLAY
+ static XColor* ac[2];
+ XColor*& allcolors = ac[fl_overlay];
+ static int nc[2];
+ int& numcolors = nc[fl_overlay];
+# else
+ static XColor *allcolors;
+ static int numcolors;
+# endif
+
+ // I don't try to allocate colors with XAllocColor once it fails
+ // with any color. It is possible that it will work, since a color
+ // may have been freed, but some servers are extremely slow and this
+ // avoids one round trip:
+ if (!numcolors) { // don't try after a failure
+ XColor xcol;
+ xcol.red = r<<8; xcol.green = g<<8; xcol.blue = b<<8;
+ if (XAllocColor(fl_display, colormap, &xcol)) {
+ xmap.mapped = 1;
+ xmap.r = xcol.red>>8;
+ xmap.g = xcol.green>>8;
+ xmap.b = xcol.blue>>8;
+ return xmap.pixel = xcol.pixel;
+ }
+
+ // I only read the colormap once. Again this is due to the slowness
+ // of round-trips to the X server, even though other programs may alter
+ // the colormap after this and make decisions here wrong.
+# if HAVE_OVERLAY
+ if (fl_overlay) numcolors = fl_overlay_visual->colormap_size; else
+# endif
+ numcolors = fl_visual->colormap_size;
+ if (!allcolors) allcolors = new XColor[numcolors];
+ for (int p = numcolors; p--;) allcolors[p].pixel = p;
+ XQueryColors(fl_display, colormap, allcolors, numcolors);
+ }
+
+ // find least-squares match:
+ int mindist = 0x7FFFFFFF;
+ unsigned int bestmatch = 0;
+ for (unsigned int n = numcolors; n--;) {
+# if HAVE_OVERLAY
+ if (fl_overlay && n == fl_transparent_pixel) continue;
+# endif
+ XColor &a = allcolors[n];
+ int d, t;
+ t = int(r)-int(a.red>>8); d = t*t;
+ t = int(g)-int(a.green>>8); d += t*t;
+ t = int(b)-int(a.blue>>8); d += t*t;
+ if (d <= mindist) {bestmatch = n; mindist = d;}
+ }
+ XColor &p = allcolors[bestmatch];
+
+ // It appears to "work" to not call this XAllocColor, which will
+ // avoid another round-trip to the server. But then X does not
+ // know that this program "owns" this value, and can (and will)
+ // change it when the program that did allocate it exits:
+ if (XAllocColor(fl_display, colormap, &p)) {
+ xmap.mapped = 1;
+ xmap.pixel = p.pixel;
+ } else {
+ // However, if that XAllocColor fails, I have to give up and
+ // assumme the pixel is ok for the duration of the program. This
+ // is due to bugs (?) in the Solaris X and some X terminals
+ // where XAllocColor *always* fails when the colormap is full,
+ // even if we ask for a color already in it...
+ xmap.mapped = 2; // 2 prevents XFreeColor from being called
+ xmap.pixel = bestmatch;
+ }
+ xmap.r = p.red>>8;
+ xmap.g = p.green>>8;
+ xmap.b = p.blue>>8;
+ return xmap.pixel;
+# endif
+}
+
+Fl_Color fl_color_;
+
+void fl_color(Fl_Color i) {
+ if (i & 0xffffff00) {
+ unsigned rgb = (unsigned)i;
+ fl_color((uchar)(rgb >> 24), (uchar)(rgb >> 16), (uchar)(rgb >> 8));
+ } else {
+ fl_color_ = i;
+ XSetForeground(fl_display, fl_gc, fl_xpixel(i));
+ }
+}
+
+void Fl::free_color(Fl_Color i, int overlay) {
+# if HAVE_OVERLAY
+# else
+ if (overlay) return;
+# endif
+ if (fl_xmap[overlay][i].mapped) {
+# if USE_COLORMAP
+# if HAVE_OVERLAY
+ Colormap colormap = overlay ? fl_overlay_colormap : fl_colormap;
+# else
+ Colormap colormap = fl_colormap;
+# endif
+ if (fl_xmap[overlay][i].mapped == 1)
+ XFreeColors(fl_display, colormap, &(fl_xmap[overlay][i].pixel), 1, 0);
+# endif
+ fl_xmap[overlay][i].mapped = 0;
+ }
+}
+
+void Fl::set_color(Fl_Color i, unsigned c) {
+ if (fl_cmap[i] != c) {
+ free_color(i,0);
+# if HAVE_OVERLAY
+ free_color(i,1);
+# endif
+ fl_cmap[i] = c;
+ }
+}
+
+#endif // end of X-specific code
+
+unsigned Fl::get_color(Fl_Color i) {
+ if (i & 0xffffff00) return (i);
+ else return fl_cmap[i];
+}
+
+void Fl::set_color(Fl_Color i, uchar red, uchar green, uchar blue) {
+ Fl::set_color((Fl_Color)(i & 255),
+ ((unsigned)red<<24)+((unsigned)green<<16)+((unsigned)blue<<8));
+}
+
+void Fl::get_color(Fl_Color i, uchar &red, uchar &green, uchar &blue) {
+ unsigned c;
+
+ if (i & 0xffffff00) c = (unsigned)i;
+ else c = fl_cmap[i];
+
+ red = uchar(c>>24);
+ green = uchar(c>>16);
+ blue = uchar(c>>8);
+}
+
+Fl_Color fl_color_average(Fl_Color color1, Fl_Color color2, float weight) {
+ unsigned rgb1;
+ unsigned rgb2;
+ uchar r, g, b;
+
+ if (color1 & 0xffffff00) rgb1 = color1;
+ else rgb1 = fl_cmap[color1 & 255];
+
+ if (color2 & 0xffffff00) rgb2 = color2;
+ else rgb2 = fl_cmap[color2 & 255];
+
+ r = (uchar)(((uchar)(rgb1>>24))*weight + ((uchar)(rgb2>>24))*(1-weight));
+ g = (uchar)(((uchar)(rgb1>>16))*weight + ((uchar)(rgb2>>16))*(1-weight));
+ b = (uchar)(((uchar)(rgb1>>8))*weight + ((uchar)(rgb2>>8))*(1-weight));
+
+ return fl_rgb_color(r, g, b);
+}
+
+Fl_Color fl_inactive(Fl_Color c) {
+ return fl_color_average(c, FL_GRAY, .33f);
+}
+
+Fl_Color fl_contrast(Fl_Color fg, Fl_Color bg) {
+ unsigned c1, c2; // RGB colors
+ int l1, l2; // Luminosities
+
+
+ // Get the RGB values for each color...
+ if (fg & 0xffffff00) c1 = (unsigned)fg;
+ else c1 = fl_cmap[fg];
+
+ if (bg & 0xffffff00) c2 = (unsigned)bg;
+ else c2 = fl_cmap[bg];
+
+ // Compute the luminosity...
+ l1 = ((c1 >> 24) * 30 + ((c1 >> 16) & 255) * 59 + ((c1 >> 8) & 255) * 11) / 100;
+ l2 = ((c2 >> 24) * 30 + ((c2 >> 16) & 255) * 59 + ((c2 >> 8) & 255) * 11) / 100;
+
+ // Compare and return the contrasting color...
+ if ((l1 - l2) > 99) return fg;
+ else if ((l2 - l1) > 99) return fg;
+ else if (l2 > 127) return FL_BLACK;
+ else return FL_WHITE;
+}
+
+//
+// End of "$Id: fl_color.cxx 5835 2007-05-16 11:46:07Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_color_mac.cxx b/third_party/windows/fltk-1.1.10/src/fl_color_mac.cxx new file mode 100644 index 0000000..55f3e29 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_color_mac.cxx @@ -0,0 +1,114 @@ +//
+// "$Id: fl_color_mac.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// MacOS color functions for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// The fltk "colormap". This allows ui colors to be stored in 8-bit
+// locations, and provides a level of indirection so that global color
+// changes can be made. Not to be confused with the X colormap, which
+// I try to hide completely.
+
+// matt: Neither Quartz nor Quickdraw support colormaps in this implementation
+// matt: Quartz support done
+
+#include <config.h>
+#include <FL/Fl.H>
+#include <FL/x.H>
+#include <FL/fl_draw.H>
+
+static unsigned fl_cmap[256] = {
+#include "fl_cmap.h" // this is a file produced by "cmap.cxx":
+};
+
+// Translations to mac data structures:
+Fl_XMap fl_xmap[256];
+
+Fl_XMap* fl_current_xmap;
+
+Fl_Color fl_color_;
+
+void fl_color(Fl_Color i) {
+ fl_color_ = i;
+ int index;
+ uchar r, g, b;
+ if (i & 0xFFFFFF00) {
+ // translate rgb colors into color index
+ r = i>>24;
+ g = i>>16;
+ b = i>> 8;
+ } else {
+ // translate index into rgb:
+ index = i;
+ unsigned c = fl_cmap[i];
+ r = c>>24;
+ g = c>>16;
+ b = c>> 8;
+ }
+#ifdef __APPLE_QD__
+ RGBColor rgb;
+ rgb.red = (r<<8)|r;
+ rgb.green = (g<<8)|g;
+ rgb.blue = (b<<8)|b;
+ RGBForeColor(&rgb);
+#elif defined(__APPLE_QUARTZ__)
+ if (!fl_gc) return; // no context yet? We will assign the color later.
+ float fr = r/255.0f;
+ float fg = g/255.0f;
+ float fb = b/255.0f;
+ CGContextSetRGBFillColor(fl_gc, fr, fg, fb, 1.0f);
+ CGContextSetRGBStrokeColor(fl_gc, fr, fg, fb, 1.0f);
+#else
+# error : neither Quickdraw nor Quartz defined
+#endif
+}
+
+void fl_color(uchar r, uchar g, uchar b) {
+ fl_color_ = fl_rgb_color(r, g, b);
+#ifdef __APPLE_QD__
+ RGBColor rgb;
+ rgb.red = (r<<8)|r;
+ rgb.green = (g<<8)|g;
+ rgb.blue = (b<<8)|b;
+ RGBForeColor(&rgb);
+#elif defined(__APPLE_QUARTZ__)
+ float fr = r/255.0f;
+ float fg = g/255.0f;
+ float fb = b/255.0f;
+ CGContextSetRGBFillColor(fl_gc, fr, fg, fb, 1.0f);
+ CGContextSetRGBStrokeColor(fl_gc, fr, fg, fb, 1.0f);
+#else
+# error : neither Quickdraw nor Quartz defined
+#endif
+}
+
+void Fl::set_color(Fl_Color i, unsigned c) {
+ if (fl_cmap[i] != c) {
+ fl_cmap[i] = c;
+ }
+}
+
+//
+// End of "$Id: fl_color_mac.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_color_win32.cxx b/third_party/windows/fltk-1.1.10/src/fl_color_win32.cxx new file mode 100644 index 0000000..1e2a7da --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_color_win32.cxx @@ -0,0 +1,254 @@ +//
+// "$Id: fl_color_win32.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// WIN32 color functions for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// The fltk "colormap". This allows ui colors to be stored in 8-bit
+// locations, and provides a level of indirection so that global color
+// changes can be made. Not to be confused with the X colormap, which
+// I try to hide completely.
+
+// SGI compiler seems to have problems with unsigned char arguments
+// being used to index arrays. So I always copy them to an integer
+// before use.
+
+#include <config.h>
+#include <FL/Fl.H>
+#include <FL/x.H>
+#include <FL/fl_draw.H>
+
+static unsigned fl_cmap[256] = {
+#include "fl_cmap.h" // this is a file produced by "cmap.cxx":
+};
+
+// Translations to win32 data structures:
+Fl_XMap fl_xmap[256];
+
+Fl_XMap* fl_current_xmap;
+
+HPALETTE fl_palette;
+static HGDIOBJ tmppen=0;
+static HPEN savepen=0;
+
+void fl_cleanup_pens(void) {
+ for (int i=0; i<256; i++) {
+ if (fl_xmap[i].pen) DeleteObject(fl_xmap[i].pen);
+ }
+}
+
+void fl_save_pen(void) {
+ if(!tmppen) tmppen = CreatePen(PS_SOLID, 1, 0);
+ savepen = (HPEN)SelectObject(fl_gc, tmppen);
+}
+
+void fl_restore_pen(void) {
+ if (savepen) SelectObject(fl_gc, savepen);
+ DeleteObject(tmppen);
+ tmppen = 0;
+ savepen = 0;
+}
+
+static void clear_xmap(Fl_XMap& xmap) {
+ if (xmap.pen) {
+ HGDIOBJ tmppen = GetStockObject(BLACK_PEN);
+ HGDIOBJ oldpen = SelectObject(fl_gc, tmppen); // Push out the current pen of the gc
+ if(oldpen != xmap.pen) SelectObject(fl_gc, oldpen); // Put it back if it is not the one we are about to delete
+ DeleteObject((HGDIOBJ)(xmap.pen));
+ xmap.pen = 0;
+ xmap.brush = -1;
+ }
+}
+
+static void set_xmap(Fl_XMap& xmap, COLORREF c) {
+ xmap.rgb = c;
+ if (xmap.pen) {
+ HGDIOBJ oldpen = SelectObject(fl_gc,GetStockObject(BLACK_PEN)); // replace current pen with safe one
+ if (oldpen != xmap.pen)SelectObject(fl_gc,oldpen); // if old one not xmap.pen, need to put it back
+ DeleteObject(xmap.pen); // delete pen
+ }
+ xmap.pen = CreatePen(PS_SOLID, 1, xmap.rgb); // get a pen into xmap.pen
+ xmap.brush = -1;
+}
+
+Fl_Color fl_color_;
+
+void fl_color(Fl_Color i) {
+ if (i & 0xffffff00) {
+ unsigned rgb = (unsigned)i;
+ fl_color((uchar)(rgb >> 24), (uchar)(rgb >> 16), (uchar)(rgb >> 8));
+ } else {
+ fl_color_ = i;
+ Fl_XMap &xmap = fl_xmap[i];
+ if (!xmap.pen) {
+#if USE_COLORMAP
+ if (fl_palette) {
+ set_xmap(xmap, PALETTEINDEX(i));
+ } else {
+#endif
+ unsigned c = fl_cmap[i];
+ set_xmap(xmap, RGB(uchar(c>>24), uchar(c>>16), uchar(c>>8)));
+#if USE_COLORMAP
+ }
+#endif
+ }
+ fl_current_xmap = ⟼
+ SelectObject(fl_gc, (HGDIOBJ)(xmap.pen));
+ }
+}
+
+void fl_color(uchar r, uchar g, uchar b) {
+ static Fl_XMap xmap;
+ COLORREF c = RGB(r,g,b);
+ fl_color_ = fl_rgb_color(r, g, b);
+ if (!xmap.pen || c != xmap.rgb) {
+ clear_xmap(xmap);
+ set_xmap(xmap, c);
+ }
+ fl_current_xmap = ⟼
+ SelectObject(fl_gc, (HGDIOBJ)(xmap.pen));
+}
+
+HBRUSH fl_brush() {
+ return fl_brush_action(0);
+}
+
+HBRUSH fl_brush_action(int action) {
+ Fl_XMap *xmap = fl_current_xmap;
+ // Wonko: we use some statistics to cache only a limited number
+ // of brushes:
+#define FL_N_BRUSH 16
+ static struct Fl_Brush {
+ HBRUSH brush;
+ unsigned short usage;
+ Fl_XMap* backref;
+ } brushes[FL_N_BRUSH];
+
+ if (action) {
+ SelectObject(fl_gc, GetStockObject(BLACK_BRUSH)); // Load stock object
+ for (int i=0; i<FL_N_BRUSH; i++) {
+ if (brushes[i].brush)
+ DeleteObject(brushes[i].brush); // delete all brushes in array
+ }
+ return NULL;
+ }
+
+ int i = xmap->brush; // find the associated brush
+ if (i != -1) { // if the brush was allready allocated
+ if (brushes[i].brush == NULL) goto CREATE_BRUSH;
+ if ( (++brushes[i].usage) > 32000 ) { // keep a usage statistic
+ for (int j=0; j<FL_N_BRUSH; j++) {
+ if (brushes[j].usage>16000)
+ brushes[j].usage -= 16000;
+ else
+ brushes[j].usage = 0;
+ }
+ }
+ return brushes[i].brush;
+ } else {
+ int umin = 32000, imin = 0;
+ for (i=0; i<FL_N_BRUSH; i++) {
+ if (brushes[i].brush == NULL) goto CREATE_BRUSH;
+ if (brushes[i].usage<umin) {
+ umin = brushes[i].usage;
+ imin = i;
+ }
+ }
+ i = imin;
+ HGDIOBJ tmpbrush = GetStockObject(BLACK_BRUSH); // get a stock brush
+ HGDIOBJ oldbrush = SelectObject(fl_gc,tmpbrush); // load in into current context
+ if (oldbrush != brushes[i].brush) SelectObject(fl_gc,oldbrush); // reload old one
+ DeleteObject(brushes[i].brush); // delete the one in list
+ brushes[i].brush = NULL;
+ brushes[i].backref->brush = -1;
+ }
+CREATE_BRUSH:
+ brushes[i].brush = CreateSolidBrush(xmap->rgb);
+ brushes[i].usage = 0;
+ brushes[i].backref = xmap;
+ xmap->brush = i;
+ return brushes[i].brush;
+}
+
+void Fl::free_color(Fl_Color i, int overlay) {
+ if (overlay) return; // do something about GL overlay?
+ clear_xmap(fl_xmap[i]);
+}
+
+void Fl::set_color(Fl_Color i, unsigned c) {
+ if (fl_cmap[i] != c) {
+ clear_xmap(fl_xmap[i]);
+ fl_cmap[i] = c;
+ }
+}
+
+#if USE_COLORMAP
+
+// 'fl_select_palette()' - Make a color palette for 8-bit displays if necessary
+// Thanks to Michael Sweet @ Easy Software Products for this
+
+HPALETTE
+fl_select_palette(void)
+{
+ static char beenhere;
+ if (!beenhere) {
+ beenhere = 1;
+
+ //if (GetDeviceCaps(fl_gc, BITSPIXEL) > 8) return NULL;
+ int nColors = GetDeviceCaps(fl_gc, SIZEPALETTE);
+ if (nColors <= 0 || nColors > 256) return NULL;
+ // this will try to work on < 256 color screens, but will probably
+ // come out quite badly.
+
+ // I lamely try to get this variable-sized object allocated on stack:
+ ulong foo[(sizeof(LOGPALETTE)+256*sizeof(PALETTEENTRY))/sizeof(ulong)+1];
+ LOGPALETTE *pPal = (LOGPALETTE*)foo;
+
+ pPal->palVersion = 0x300;
+ pPal->palNumEntries = nColors;
+
+ // Build 256 colors from the standard FLTK colormap...
+
+ for (int i = 0; i < nColors; i ++) {
+ pPal->palPalEntry[i].peRed = (fl_cmap[i] >> 24) & 255;
+ pPal->palPalEntry[i].peGreen = (fl_cmap[i] >> 16) & 255;
+ pPal->palPalEntry[i].peBlue = (fl_cmap[i] >> 8) & 255;
+ pPal->palPalEntry[i].peFlags = 0;
+ };
+
+ // Create the palette:
+ fl_palette = CreatePalette(pPal);
+ }
+ if (fl_palette) {
+ SelectPalette(fl_gc, fl_palette, FALSE);
+ RealizePalette(fl_gc);
+ }
+ return fl_palette;
+}
+
+#endif
+
+//
+// End of "$Id: fl_color_win32.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_cursor.cxx b/third_party/windows/fltk-1.1.10/src/fl_cursor.cxx new file mode 100644 index 0000000..0e91169 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_cursor.cxx @@ -0,0 +1,335 @@ +//
+// "$Id: fl_cursor.cxx 5654 2007-02-02 13:52:37Z matt $"
+//
+// Mouse cursor support for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Change the current cursor.
+// Under X the cursor is attached to the X window. I tried to hide
+// this and pretend that changing the cursor is a drawing function.
+// This avoids a field in the Fl_Window, and I suspect is more
+// portable to other systems.
+
+#include <FL/Fl.H>
+#include <FL/Fl_Window.H>
+#include <FL/x.H>
+#if !defined(WIN32) && !defined(__APPLE__)
+# include <X11/cursorfont.h>
+#endif
+#include <FL/fl_draw.H>
+
+void fl_cursor(Fl_Cursor c, Fl_Color fg, Fl_Color bg) {
+ if (Fl::first_window()) Fl::first_window()->cursor(c,fg,bg);
+}
+
+void Fl_Window::default_cursor(Fl_Cursor c, Fl_Color fg, Fl_Color bg) {
+// if (c == FL_CURSOR_DEFAULT) c = FL_CURSOR_ARROW;
+
+ cursor_default = c;
+ cursor_fg = fg;
+ cursor_bg = bg;
+
+ cursor(c, fg, bg);
+}
+
+#ifdef WIN32
+
+# ifndef IDC_HAND
+# define IDC_HAND MAKEINTRESOURCE(32649)
+# endif // !IDC_HAND
+
+void Fl_Window::cursor(Fl_Cursor c, Fl_Color c1, Fl_Color c2) {
+ if (!shown()) return;
+ // the cursor must be set for the top level window, not for subwindows
+ Fl_Window *w = window(), *toplevel = this;
+ while (w) { toplevel = w; w = w->window(); }
+ if (toplevel != this) { toplevel->cursor(c, c1, c2); return; }
+ // now set the actual cursor
+ if (c == FL_CURSOR_DEFAULT) {
+ c = cursor_default;
+ }
+ if (c > FL_CURSOR_NESW) {
+ i->cursor = 0;
+ } else if (c == FL_CURSOR_DEFAULT) {
+ i->cursor = fl_default_cursor;
+ } else {
+ LPSTR n;
+ switch (c) {
+ case FL_CURSOR_ARROW: n = IDC_ARROW; break;
+ case FL_CURSOR_CROSS: n = IDC_CROSS; break;
+ case FL_CURSOR_WAIT: n = IDC_WAIT; break;
+ case FL_CURSOR_INSERT: n = IDC_IBEAM; break;
+ case FL_CURSOR_HELP: n = IDC_HELP; break;
+ case FL_CURSOR_HAND: {
+ OSVERSIONINFO osvi;
+
+ // Get the OS version: Windows 98 and 2000 have a standard
+ // hand cursor.
+ memset(&osvi, 0, sizeof(OSVERSIONINFO));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ GetVersionEx(&osvi);
+
+ if (osvi.dwMajorVersion > 4 ||
+ (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion > 0 &&
+ osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)) n = IDC_HAND;
+ else n = IDC_UPARROW;
+ } break;
+ case FL_CURSOR_MOVE: n = IDC_SIZEALL; break;
+ case FL_CURSOR_N:
+ case FL_CURSOR_S:
+ case FL_CURSOR_NS: n = IDC_SIZENS; break;
+ case FL_CURSOR_NE:
+ case FL_CURSOR_SW:
+ case FL_CURSOR_NESW: n = IDC_SIZENESW; break;
+ case FL_CURSOR_E:
+ case FL_CURSOR_W:
+ case FL_CURSOR_WE: n = IDC_SIZEWE; break;
+ case FL_CURSOR_SE:
+ case FL_CURSOR_NW:
+ case FL_CURSOR_NWSE: n = IDC_SIZENWSE; break;
+ default: n = IDC_NO; break;
+ }
+ i->cursor = LoadCursor(NULL, n);
+ }
+ SetCursor(i->cursor);
+}
+
+#elif defined(__APPLE__)
+
+#ifdef __BIG_ENDIAN__
+# define E(x) x
+#elif defined __LITTLE_ENDIAN__
+// Don't worry. This will be resolved at compile time
+# define E(x) (x>>8)|((x<<8)&0xff00)
+#else
+# error "Either __LITTLE_ENDIAN__ or __BIG_ENDIAN__ must be defined"
+#endif
+
+static Cursor crsrHAND =
+{
+ { E(0x0600), E(0x0900), E(0x0900), E(0x0900), E(0x09C0), E(0x0938), E(0x6926), E(0x9805),
+ E(0x8801), E(0x4801), E(0x2002), E(0x2002), E(0x1004), E(0x0804), E(0x0408), E(0x0408) },
+ { E(0x0600), E(0x0F00), E(0x0F00), E(0x0F00), E(0x0FC0), E(0x0FF8), E(0x6FFE), E(0xFFFF),
+ E(0xFFFF), E(0x7FFF), E(0x3FFE), E(0x3FFE), E(0x1FFC), E(0x0FFC), E(0x07F8), E(0x07F8) },
+ { 1, 5 } // Hotspot: ( y, x )
+}, *crsrHANDptr = &crsrHAND;
+static Cursor crsrHELP =
+{
+ { E(0x0000), E(0x4000), E(0x6000), E(0x7000), E(0x783C), E(0x7C7E), E(0x7E66), E(0x7F06),
+ E(0x7F8C), E(0x7C18), E(0x6C18), E(0x4600), E(0x0618), E(0x0318), E(0x0300), E(0x0000) },
+ { E(0xC000), E(0xE000), E(0xF000), E(0xF83C), E(0xFC7E), E(0xFEFF), E(0xFFFF), E(0xFFFF),
+ E(0xFFFE), E(0xFFFC), E(0xFE3C), E(0xEF3C), E(0xCF3C), E(0x07BC), E(0x0798), E(0x0380) },
+ { 1, 1 }
+}, *crsrHELPptr = &crsrHELP;
+static Cursor crsrMOVE =
+{
+ { E(0x0000), E(0x0180), E(0x03C0), E(0x07E0), E(0x07E0), E(0x1998), E(0x399C), E(0x7FFE),
+ E(0x7FFE), E(0x399C), E(0x1998), E(0x07E0), E(0x07E0), E(0x03C0), E(0x0180), E(0x0000) },
+ { E(0x0180), E(0x03C0), E(0x07E0), E(0x0FF0), E(0x1FF8), E(0x3FFC), E(0x7FFE), E(0xFFFF),
+ E(0xFFFF), E(0x7FFE), E(0x3FFC), E(0x1FF8), E(0x0FF0), E(0x07E0), E(0x03C0), E(0x0180) },
+ { 8, 8 }
+}, *crsrMOVEptr = &crsrMOVE;
+static Cursor crsrNS =
+{
+ { E(0x0000), E(0x0180), E(0x03C0), E(0x07E0), E(0x0FF0), E(0x0180), E(0x0180), E(0x0180),
+ E(0x0180), E(0x0180), E(0x0180), E(0x0FF0), E(0x07E0), E(0x03C0), E(0x0180), E(0x0000) },
+ { E(0x0180), E(0x03C0), E(0x07E0), E(0x0FF0), E(0x1FF8), E(0x1FF8), E(0x03C0), E(0x03C0),
+ E(0x03C0), E(0x03C0), E(0x1FF8), E(0x1FF8), E(0x0FF0), E(0x07E0), E(0x03C0), E(0x0180) },
+ { 8, 8 }
+}, *crsrNSptr = &crsrNS;
+static Cursor crsrWE =
+{
+ { E(0x0000), E(0x0000), E(0x0000), E(0x0000), E(0x0810), E(0x1818), E(0x381C), E(0x7FFE),
+ E(0x7FFE), E(0x381C), E(0x1818), E(0x0810), E(0x0000), E(0x0000), E(0x0000), E(0x0000) },
+ { E(0x0000), E(0x0000), E(0x0000), E(0x0C30), E(0x1C38), E(0x3C3C), E(0x7FFE), E(0xFFFF),
+ E(0xFFFF), E(0x7FFE), E(0x3C3C), E(0x1C38), E(0x0C30), E(0x0000), E(0x0000), E(0x0000) },
+ { 8, 8 }
+}, *crsrWEptr = &crsrWE;
+static Cursor crsrNWSE =
+{
+ { E(0x0000), E(0x7E00), E(0x7C00), E(0x7800), E(0x7C00), E(0x6E00), E(0x4710), E(0x03B0),
+ E(0x01F0), E(0x00F0), E(0x01F0), E(0x03F0), E(0x0000), E(0x0000), E(0x0000), E(0x0000) },
+ { E(0xFF00), E(0xFF00), E(0xFE00), E(0xFC00), E(0xFE00), E(0xFF18), E(0xEFB8), E(0xC7F8),
+ E(0x03F8), E(0x01F8), E(0x03F8), E(0x07F8), E(0x07F8), E(0x0000), E(0x0000), E(0x0000) },
+ { 8, 8 }
+}, *crsrNWSEptr = &crsrNWSE;
+static Cursor crsrNESW =
+{
+ { E(0x0000), E(0x03F0), E(0x01F0), E(0x00F0), E(0x01F0), E(0x03B0), E(0x4710), E(0x6E00),
+ E(0x7C00), E(0x7800), E(0x7C00), E(0x7E00), E(0x0000), E(0x0000), E(0x0000), E(0x0000) },
+ { E(0x07F8), E(0x07F8), E(0x03F8), E(0x01F8), E(0x03F8), E(0xC7F8), E(0xEFB8), E(0xFF18),
+ E(0xFE00), E(0xFC00), E(0xFE00), E(0xFF00), E(0xFF00), E(0x0000), E(0x0000), E(0x0000) },
+ { 8, 8 }
+}, *crsrNESWptr = &crsrNESW;
+static Cursor crsrNONE =
+{
+ { E(0x0000), E(0x0000), E(0x0000), E(0x0000), E(0x0000), E(0x0000), E(0x0000), E(0x0000),
+ E(0x0000), E(0x0000), E(0x0000), E(0x0000), E(0x0000), E(0x0000), E(0x0000), E(0x0000) },
+ { E(0x0000), E(0x0000), E(0x0000), E(0x0000), E(0x0000), E(0x0000), E(0x0000), E(0x0000),
+ E(0x0000), E(0x0000), E(0x0000), E(0x0000), E(0x0000), E(0x0000), E(0x0000), E(0x0000) },
+ { 0, 0 }
+}, *crsrNONEptr = &crsrNONE;
+static Cursor crsrARROW =
+{
+ { E(0x0000), E(0x4000), E(0x6000), E(0x7000), E(0x7800), E(0x7C00), E(0x7E00), E(0x7F00),
+ E(0x7F80), E(0x7C00), E(0x6C00), E(0x4600), E(0x0600), E(0x0300), E(0x0300), E(0x0000) },
+ { E(0xC000), E(0xE000), E(0xF000), E(0xF800), E(0xFC00), E(0xFE00), E(0xFF00), E(0xFF80),
+ E(0xFFC0), E(0xFFC0), E(0xFE00), E(0xEF00), E(0xCF00), E(0x0780), E(0x0780), E(0x0380) },
+ { 1, 1 }
+}, *crsrARROWptr = &crsrARROW;
+
+#undef E
+
+void Fl_Window::cursor(Fl_Cursor c, Fl_Color, Fl_Color) {
+ if (c == FL_CURSOR_DEFAULT) {
+ c = cursor_default;
+ }
+ CursHandle icrsr = fl_default_cursor;
+ switch (c) {
+ case FL_CURSOR_CROSS: icrsr = GetCursor( crossCursor ); break;
+ case FL_CURSOR_WAIT: icrsr = GetCursor( watchCursor ); break;
+ case FL_CURSOR_INSERT: icrsr = GetCursor( iBeamCursor ); break;
+ case FL_CURSOR_N:
+ case FL_CURSOR_S:
+ case FL_CURSOR_NS: icrsr = &crsrNSptr; break;
+ case FL_CURSOR_HELP: icrsr = &crsrHELPptr; break;
+ case FL_CURSOR_HAND: icrsr = &crsrHANDptr; break;
+ case FL_CURSOR_MOVE: icrsr = &crsrMOVEptr; break;
+ case FL_CURSOR_NE:
+ case FL_CURSOR_SW:
+ case FL_CURSOR_NESW: icrsr = &crsrNESWptr; break;
+ case FL_CURSOR_E:
+ case FL_CURSOR_W:
+ case FL_CURSOR_WE: icrsr = &crsrWEptr; break;
+ case FL_CURSOR_SE:
+ case FL_CURSOR_NW:
+ case FL_CURSOR_NWSE: icrsr = &crsrNWSEptr; break;
+ case FL_CURSOR_NONE: icrsr = &crsrNONEptr; break;
+ case FL_CURSOR_ARROW: icrsr = &crsrARROWptr; break;
+ case FL_CURSOR_DEFAULT:
+ default: break;
+ }
+ SetCursor( *icrsr );
+ if (i) {
+ i->cursor = icrsr;
+ }
+}
+
+#else
+
+// I like the MSWindows resize cursors, so I duplicate them here:
+
+#define CURSORSIZE 16
+#define HOTXY 7
+static struct TableEntry {
+ uchar bits[CURSORSIZE*CURSORSIZE/8];
+ uchar mask[CURSORSIZE*CURSORSIZE/8];
+ Cursor cursor;
+} table[] = {
+ {{ // FL_CURSOR_NS
+ 0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0x80, 0x01, 0x80, 0x01,
+ 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
+ 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00},
+ {
+ 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f, 0xf0, 0x0f, 0xc0, 0x03,
+ 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xf0, 0x0f,
+ 0xf0, 0x0f, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01}},
+ {{ // FL_CURSOR_EW
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10,
+ 0x0c, 0x30, 0xfe, 0x7f, 0xfe, 0x7f, 0x0c, 0x30, 0x08, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x1c, 0x38,
+ 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0x1c, 0x38, 0x18, 0x18,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
+ {{ // FL_CURSOR_NWSE
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x38, 0x00, 0x78, 0x00,
+ 0xe8, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x17, 0x00, 0x1e, 0x00, 0x1c,
+ 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {
+ 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x7c, 0x00, 0xfc, 0x00,
+ 0xfc, 0x01, 0xec, 0x03, 0xc0, 0x37, 0x80, 0x3f, 0x00, 0x3f, 0x00, 0x3e,
+ 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00}},
+ {{ // FL_CURSOR_NESW
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x1c, 0x00, 0x1e,
+ 0x00, 0x17, 0x80, 0x03, 0xc0, 0x01, 0xe8, 0x00, 0x78, 0x00, 0x38, 0x00,
+ 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x3f,
+ 0x80, 0x3f, 0xc0, 0x37, 0xec, 0x03, 0xfc, 0x01, 0xfc, 0x00, 0x7c, 0x00,
+ 0xfc, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00}},
+ {{0}, {0}} // FL_CURSOR_NONE & unknown
+};
+
+void Fl_Window::cursor(Fl_Cursor c, Fl_Color fg, Fl_Color bg) {
+ if (!shown()) return;
+ Cursor xc;
+ int deleteit = 0;
+ if (c == FL_CURSOR_DEFAULT) {
+ c = cursor_default;
+ fg = cursor_fg;
+ bg = cursor_bg;
+ }
+
+ if (!c) {
+ xc = None;
+ } else {
+ if (c >= FL_CURSOR_NS) {
+ TableEntry *q = (c > FL_CURSOR_NESW) ? table+4 : table+(c-FL_CURSOR_NS);
+ if (!(q->cursor)) {
+ XColor dummy = { 0 };
+ Pixmap p = XCreateBitmapFromData(fl_display,
+ RootWindow(fl_display, fl_screen), (const char*)(q->bits),
+ CURSORSIZE, CURSORSIZE);
+ Pixmap m = XCreateBitmapFromData(fl_display,
+ RootWindow(fl_display, fl_screen), (const char*)(q->mask),
+ CURSORSIZE, CURSORSIZE);
+ q->cursor = XCreatePixmapCursor(fl_display, p,m,&dummy, &dummy,
+ HOTXY, HOTXY);
+ XFreePixmap(fl_display, m);
+ XFreePixmap(fl_display, p);
+ }
+ xc = q->cursor;
+ } else {
+ xc = XCreateFontCursor(fl_display, (c-1)*2);
+ deleteit = 1;
+ }
+ XColor fgc;
+ uchar r,g,b;
+ Fl::get_color(fg,r,g,b);
+ fgc.red = r<<8; fgc.green = g<<8; fgc.blue = b<<8;
+ XColor bgc;
+ Fl::get_color(bg,r,g,b);
+ bgc.red = r<<8; bgc.green = g<<8; bgc.blue = b<<8;
+ XRecolorCursor(fl_display, xc, &fgc, &bgc);
+ }
+ XDefineCursor(fl_display, fl_xid(this), xc);
+ if (deleteit) XFreeCursor(fl_display, xc);
+}
+
+#endif
+
+//
+// End of "$Id: fl_cursor.cxx 5654 2007-02-02 13:52:37Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_curve.cxx b/third_party/windows/fltk-1.1.10/src/fl_curve.cxx new file mode 100644 index 0000000..5007e9a --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_curve.cxx @@ -0,0 +1,106 @@ +//
+// "$Id: fl_curve.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Bezier curve functions for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Utility for drawing Bezier curves, adding the points to
+// the current fl_begin/fl_vertex/fl_end path.
+// Incremental math implementation:
+// I very much doubt this is optimal! From Foley/vanDam page 511.
+// If anybody has a better algorithim, please send it!
+
+#include <FL/fl_draw.H>
+#include <math.h>
+
+void fl_curve(double X0, double Y0,
+ double X1, double Y1,
+ double X2, double Y2,
+ double X3, double Y3) {
+
+ double x = fl_transform_x(X0,Y0);
+ double y = fl_transform_y(X0,Y0);
+
+ // draw point 0:
+ fl_transformed_vertex(x,y);
+
+ double x1 = fl_transform_x(X1,Y1);
+ double yy1 = fl_transform_y(X1,Y1);
+ double x2 = fl_transform_x(X2,Y2);
+ double y2 = fl_transform_y(X2,Y2);
+ double x3 = fl_transform_x(X3,Y3);
+ double y3 = fl_transform_y(X3,Y3);
+
+ // find the area:
+ double a = fabs((x-x2)*(y3-yy1)-(y-y2)*(x3-x1));
+ double b = fabs((x-x3)*(y2-yy1)-(y-y3)*(x2-x1));
+ if (b > a) a = b;
+
+ // use that to guess at the number of segments:
+ int n = int(sqrt(a)/4);
+ if (n > 1) {
+ if (n > 100) n = 100; // make huge curves not hang forever
+
+ double e = 1.0/n;
+
+ // calculate the coefficients of 3rd order equation:
+ double xa = (x3-3*x2+3*x1-x);
+ double xb = 3*(x2-2*x1+x);
+ double xc = 3*(x1-x);
+ // calculate the forward differences:
+ double dx1 = ((xa*e+xb)*e+xc)*e;
+ double dx3 = 6*xa*e*e*e;
+ double dx2 = dx3 + 2*xb*e*e;
+
+ // calculate the coefficients of 3rd order equation:
+ double ya = (y3-3*y2+3*yy1-y);
+ double yb = 3*(y2-2*yy1+y);
+ double yc = 3*(yy1-y);
+ // calculate the forward differences:
+ double dy1 = ((ya*e+yb)*e+yc)*e;
+ double dy3 = 6*ya*e*e*e;
+ double dy2 = dy3 + 2*yb*e*e;
+
+ // draw points 1 .. n-2:
+ for (int m=2; m<n; m++) {
+ x += dx1;
+ dx1 += dx2;
+ dx2 += dx3;
+ y += dy1;
+ dy1 += dy2;
+ dy2 += dy3;
+ fl_transformed_vertex(x,y);
+ }
+
+ // draw point n-1:
+ fl_transformed_vertex(x+dx1, y+dy1);
+ }
+
+ // draw point n:
+ fl_transformed_vertex(x3,y3);
+}
+
+//
+// End of "$Id: fl_curve.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_diamond_box.cxx b/third_party/windows/fltk-1.1.10/src/fl_diamond_box.cxx new file mode 100644 index 0000000..9df082c --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_diamond_box.cxx @@ -0,0 +1,80 @@ +//
+// "$Id: fl_diamond_box.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Diamond box code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Box drawing code for an obscure box type.
+// These box types are in seperate files so they are not linked
+// in if not used.
+
+// The diamond box draws best if the area is square!
+
+#include <FL/Fl.H>
+#include <FL/fl_draw.H>
+
+extern uchar* fl_gray_ramp();
+
+static void fl_diamond_up_box(int x,int y,int w,int h,Fl_Color bgcolor) {
+ w &= -2;
+ h &= -2;
+ int x1 = x+w/2;
+ int y1 = y+h/2;
+ fl_color(bgcolor); fl_polygon(x+3, y1, x1,y+3, x+w-3,y1, x1,y+h-3);
+ uchar *g = fl_gray_ramp();
+ fl_color(g['W']); fl_line(x+1, y1, x1, y+1, x+w-1, y1);
+ fl_color(g['U']); fl_line(x+2, y1, x1, y+2, x+w-2, y1);
+ fl_color(g['S']); fl_line(x+3, y1, x1, y+3, x+w-3, y1);
+ fl_color(g['P']); fl_line(x+3, y1, x1, y+h-3, x+w-3, y1);
+ fl_color(g['N']); fl_line(x+2, y1, x1, y+h-2, x+w-2, y1);
+ fl_color(g['H']); fl_line(x+1, y1, x1, y+h-1, x+w-1, y1);
+ fl_color(g['A']); fl_loop(x, y1, x1, y, x+w, y1, x1, y+h);
+}
+
+static void fl_diamond_down_box(int x,int y,int w,int h,Fl_Color bgcolor) {
+ w &= -2;
+ h &= -2;
+ int x1 = x+w/2;
+ int y1 = y+h/2;
+ uchar *g = fl_gray_ramp();
+ fl_color(g['P']); fl_line(x+0, y1, x1, y+0, x+w-0, y1);
+ fl_color(g['N']); fl_line(x+1, y1, x1, y+1, x+w-1, y1);
+ fl_color(g['H']); fl_line(x+2, y1, x1, y+2, x+w-2, y1);
+ fl_color(g['W']); fl_line(x+2, y1, x1, y+h-2, x+w-2, y1);
+ fl_color(g['U']); fl_line(x+1, y1, x1, y+h-1, x+w-1, y1);
+ fl_color(g['S']); fl_line(x+0, y1, x1, y+h-0, x+w-0, y1);
+ fl_color(bgcolor); fl_polygon(x+3, y1, x1,y+3, x+w-3,y1, x1,y+h-3);
+ fl_color(g['A']); fl_loop(x+3, y1, x1, y+3, x+w-3, y1, x1, y+h-3);
+}
+
+extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*);
+Fl_Boxtype fl_define_FL_DIAMOND_BOX() {
+ fl_internal_boxtype(_FL_DIAMOND_DOWN_BOX, fl_diamond_down_box);
+ fl_internal_boxtype(_FL_DIAMOND_UP_BOX,fl_diamond_up_box);
+ return _FL_DIAMOND_UP_BOX;
+}
+
+//
+// End of "$Id: fl_diamond_box.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_dnd.cxx b/third_party/windows/fltk-1.1.10/src/fl_dnd.cxx new file mode 100644 index 0000000..9193505 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_dnd.cxx @@ -0,0 +1,38 @@ +//
+// "$Id: fl_dnd.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Drag & Drop code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+#ifdef WIN32
+# include "fl_dnd_win32.cxx"
+#elif defined(__APPLE__)
+# include "fl_dnd_mac.cxx"
+#else
+# include "fl_dnd_x.cxx"
+#endif
+
+//
+// End of "$Id: fl_dnd.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_dnd_mac.cxx b/third_party/windows/fltk-1.1.10/src/fl_dnd_mac.cxx new file mode 100644 index 0000000..7415b7b --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_dnd_mac.cxx @@ -0,0 +1,90 @@ +//
+// "$Id: fl_dnd_mac.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Drag & Drop code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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 to "fltk-bugs@fltk.org
+
+// This file contains win32-specific code for fltk which is always linked
+// in. Search other files for "WIN32" or filenames ending in _win32.cxx
+// for other system-specific code.
+
+#include <config.h>
+#include <FL/Fl.H>
+#include <FL/x.H>
+#include <FL/Fl_Window.H>
+
+// warning: this function is only implemented in Quickdraw. The function
+// below may not work If FLTK is compiled with Quartz enabled
+
+extern EventRef fl_os_event;
+extern char *fl_selection_buffer;
+extern int fl_selection_length;
+
+
+/**
+ * drag and drop whatever is in the cut-copy-paste buffer
+ * - create a selection first using:
+ * Fl::copy(const char *stuff, int len, 0)
+ */
+int Fl::dnd()
+{
+ OSErr result;
+ DragReference dragRef;
+ result = NewDrag( &dragRef );
+ if ( result != noErr ) return false;
+
+ result = AddDragItemFlavor( dragRef, 1, 'TEXT', fl_selection_buffer, fl_selection_length, 0 );
+ if ( result != noErr ) { DisposeDrag( dragRef ); return false; }
+
+ Point mp;
+ GetMouse(&mp);
+ LocalToGlobal( &mp );
+ RgnHandle region = NewRgn();
+ SetRectRgn( region, mp.h-10, mp.v-10, mp.h+10, mp.v+10 );
+ RgnHandle r2 = NewRgn();
+ SetRectRgn( r2, mp.h-8, mp.v-8, mp.h+8, mp.v+8 );
+ DiffRgn( region, r2, region );
+ DisposeRgn( r2 );
+
+ EventRecord event;
+ ConvertEventRefToEventRecord( fl_os_event, &event );
+ result = TrackDrag( dragRef, &event, region );
+
+ Fl_Widget *w = Fl::pushed();
+ if ( w )
+ {
+ int old_event = Fl::e_number;
+ w->handle(Fl::e_number = FL_RELEASE);
+ Fl::e_number = old_event;
+ Fl::pushed( 0 );
+ }
+
+ if ( result != noErr ) { DisposeRgn( region ); DisposeDrag( dragRef ); return false; }
+
+ DisposeRgn( region );
+ DisposeDrag( dragRef );
+ return true;
+}
+
+
+//
+// End of "$Id: fl_dnd_mac.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_dnd_win32.cxx b/third_party/windows/fltk-1.1.10/src/fl_dnd_win32.cxx new file mode 100644 index 0000000..cd7511b --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_dnd_win32.cxx @@ -0,0 +1,404 @@ +//
+// "$Id: fl_dnd_win32.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Drag & Drop code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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 to "fltk-bugs@fltk.org
+
+// This file contains win32-specific code for fltk which is always linked
+// in. Search other files for "WIN32" or filenames ending in _win32.cxx
+// for other system-specific code.
+
+#include <FL/Fl.H>
+#include <FL/x.H>
+#include <FL/Fl_Window.H>
+#include "flstring.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <time.h>
+#if defined(__CYGWIN__)
+#include <sys/time.h>
+#include <unistd.h>
+#else
+#include <winsock.h>
+#endif
+
+extern char *fl_selection_buffer[2];
+extern int fl_selection_length[2];
+extern int fl_selection_buffer_length[2];
+extern char fl_i_own_selection[2];
+
+Fl_Window *fl_dnd_target_window = 0;
+
+// All of the following code requires GCC 3.x or a non-GNU compiler...
+#if !defined(__GNUC__) || __GNUC__ >= 3
+
+#include <ole2.h>
+#include <shellapi.h>
+
+/**
+ * subclass the IDropTarget to receive data from DnD operations
+ */
+class FLDropTarget : public IDropTarget
+{
+ DWORD m_cRefCount;
+ DWORD lastEffect;
+ int px, py;
+public:
+ FLDropTarget() : m_cRefCount(0) { } // initialize
+ HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, LPVOID *ppvObject ) {
+ if (IID_IUnknown==riid || IID_IDropTarget==riid)
+ {
+ *ppvObject=this;
+ ((LPUNKNOWN)*ppvObject)->AddRef();
+ return S_OK;
+ }
+ *ppvObject = NULL;
+ return E_NOINTERFACE;
+ }
+ ULONG STDMETHODCALLTYPE AddRef() { return ++m_cRefCount; }
+ ULONG STDMETHODCALLTYPE Release() {
+ long nTemp;
+ nTemp = --m_cRefCount;
+ if(nTemp==0)
+ delete this;
+ return nTemp;
+ }
+ HRESULT STDMETHODCALLTYPE DragEnter( IDataObject *pDataObj, DWORD /*grfKeyState*/, POINTL pt, DWORD *pdwEffect) {
+ if( !pDataObj ) return E_INVALIDARG;
+ // set e_modifiers here from grfKeyState, set e_x and e_root_x
+ // check if FLTK handles this drag and return if it can't (i.e. BMP drag without filename)
+ POINT ppt;
+ Fl::e_x_root = ppt.x = pt.x;
+ Fl::e_y_root = ppt.y = pt.y;
+ HWND hWnd = WindowFromPoint( ppt );
+ Fl_Window *target = fl_find( hWnd );
+ if (target) {
+ Fl::e_x = Fl::e_x_root-target->x();
+ Fl::e_y = Fl::e_y_root-target->y();
+ }
+ fl_dnd_target_window = target;
+ px = pt.x; py = pt.y;
+ if (fillCurrentDragData(pDataObj)) {
+ // FLTK has no mechanism yet for the different drop effects, so we allow move and copy
+ if ( target && Fl::handle( FL_DND_ENTER, target ) )
+ *pdwEffect = DROPEFFECT_MOVE|DROPEFFECT_COPY; //|DROPEFFECT_LINK;
+ else
+ *pdwEffect = DROPEFFECT_NONE;
+ } else {
+ *pdwEffect = DROPEFFECT_NONE;
+ }
+ lastEffect = *pdwEffect;
+ return S_OK;
+ }
+ HRESULT STDMETHODCALLTYPE DragOver( DWORD /*grfKeyState*/, POINTL pt, DWORD *pdwEffect) {
+ if ( px==pt.x && py==pt.y )
+ {
+ *pdwEffect = lastEffect;
+ return S_OK;
+ }
+ if ( !fl_dnd_target_window )
+ {
+ *pdwEffect = lastEffect = DROPEFFECT_NONE;
+ return S_OK;
+ }
+ // set e_modifiers here from grfKeyState, set e_x and e_root_x
+ Fl::e_x_root = pt.x;
+ Fl::e_y_root = pt.y;
+ if (fl_dnd_target_window) {
+ Fl::e_x = Fl::e_x_root-fl_dnd_target_window->x();
+ Fl::e_y = Fl::e_y_root-fl_dnd_target_window->y();
+ }
+ if (fillCurrentDragData(0)) {
+ // Fl_Group will change DND_DRAG into DND_ENTER and DND_LEAVE if needed
+ if ( Fl::handle( FL_DND_DRAG, fl_dnd_target_window ) )
+ *pdwEffect = DROPEFFECT_MOVE|DROPEFFECT_COPY; //|DROPEFFECT_LINK;
+ else
+ *pdwEffect = DROPEFFECT_NONE;
+ } else {
+ *pdwEffect = DROPEFFECT_NONE;
+ }
+ px = pt.x; py = pt.y;
+ lastEffect = *pdwEffect;
+ return S_OK;
+ }
+ HRESULT STDMETHODCALLTYPE DragLeave() {
+ if ( fl_dnd_target_window && fillCurrentDragData(0))
+ {
+ Fl::handle( FL_DND_LEAVE, fl_dnd_target_window );
+ fl_dnd_target_window = 0;
+ clearCurrentDragData();
+ }
+ return S_OK;
+ }
+ HRESULT STDMETHODCALLTYPE Drop( IDataObject *data, DWORD /*grfKeyState*/, POINTL pt, DWORD* /*pdwEffect*/) {
+ if ( !fl_dnd_target_window )
+ return S_OK;
+ Fl_Window *target = fl_dnd_target_window;
+ fl_dnd_target_window = 0;
+ Fl::e_x_root = pt.x;
+ Fl::e_y_root = pt.y;
+ if (target) {
+ Fl::e_x = Fl::e_x_root-target->x();
+ Fl::e_y = Fl::e_y_root-target->y();
+ }
+ // tell FLTK that the user released an object on this widget
+ if ( !Fl::handle( FL_DND_RELEASE, target ) )
+ return S_OK;
+
+ Fl_Widget *w = target;
+ while (w->parent()) w = w->window();
+ HWND hwnd = fl_xid( (Fl_Window*)w );
+ if (fillCurrentDragData(data)) {
+ int old_event = Fl::e_number;
+ Fl::belowmouse()->handle(Fl::e_number = FL_PASTE); // e_text will be invalid after this call
+ Fl::e_number = old_event;
+ SetForegroundWindow( hwnd );
+ clearCurrentDragData();
+ return S_OK;
+ }
+ return S_OK;
+ }
+private:
+
+ static IDataObject *currDragRef;
+ static char *currDragData;
+ static int currDragSize;
+ static char currDragResult;
+
+ static void clearCurrentDragData() {
+ currDragRef = 0;
+ if (currDragData) free(currDragData);
+ currDragData = 0;
+ currDragSize = 0;
+ currDragResult = 0;
+ }
+ static char fillCurrentDragData(IDataObject *data) {
+ // shortcut through this whole procedure if there is no fresh data
+ if (!data)
+ return currDragResult;
+ // shortcut through this whole procedure if this is still the same drag event
+ // (* this is safe, because 'currDragRef' is cleared on Leave and Drop events)
+ if (data==currDragRef)
+ return currDragResult;
+
+ // clear currDrag* for a new drag event
+ clearCurrentDragData();
+
+ // fill currDrag* with ASCII data, if available
+ FORMATETC fmt = { 0 };
+ STGMEDIUM medium = { 0 };
+ fmt.tymed = TYMED_HGLOBAL;
+ fmt.dwAspect = DVASPECT_CONTENT;
+ fmt.lindex = -1;
+ fmt.cfFormat = CF_TEXT;
+ // if it is ASCII text, return a copy of it
+ if ( data->GetData( &fmt, &medium )==S_OK )
+ {
+ void *stuff = GlobalLock( medium.hGlobal );
+ Fl::e_length = strlen((char*)stuff);
+ Fl::e_text = strdup((char*)stuff);
+ GlobalUnlock( medium.hGlobal );
+ ReleaseStgMedium( &medium );
+ currDragResult = 1;
+ return currDragResult;
+ }
+ // else fill currDrag* with filenames, if possible
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.tymed = TYMED_HGLOBAL;
+ fmt.dwAspect = DVASPECT_CONTENT;
+ fmt.lindex = -1;
+ fmt.cfFormat = CF_HDROP;
+ // if it is a pathname list, send an FL_PASTE with a \n seperated list of filepaths
+ if ( data->GetData( &fmt, &medium )==S_OK )
+ {
+ HDROP hdrop = (HDROP)medium.hGlobal;
+ int i, n, nn = 0, nf = DragQueryFile( hdrop, (UINT)-1, 0, 0 );
+ for ( i=0; i<nf; i++ ) nn += DragQueryFile( hdrop, i, 0, 0 );
+ nn += nf;
+ Fl::e_length = nn-1;
+ char *dst = Fl::e_text = (char*)malloc(nn+1);
+ for ( i=0; i<nf; i++ ) {
+ n = DragQueryFile( hdrop, i, dst, nn );
+ dst += n;
+ if ( i<nf-1 ) *dst++ = '\n';
+ }
+ *dst = 0;
+ ReleaseStgMedium( &medium );
+ currDragResult = 1;
+ return currDragResult;
+ }
+ currDragResult = 0;
+ return currDragResult;
+ }
+} flDropTarget;
+
+IDropTarget *flIDropTarget = &flDropTarget;
+
+IDataObject *FLDropTarget::currDragRef = 0;
+char *FLDropTarget::currDragData = 0;
+int FLDropTarget::currDragSize = 0;
+char FLDropTarget::currDragResult = 0;
+
+/**
+ * this class is needed to allow FLTK apps to be a DnD source
+ */
+class FLDropSource : public IDropSource
+{
+ DWORD m_cRefCount;
+public:
+ FLDropSource() { m_cRefCount = 0; }
+ HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, LPVOID *ppvObject ) {
+ if (IID_IUnknown==riid || IID_IDropSource==riid)
+ {
+ *ppvObject=this;
+ ((LPUNKNOWN)*ppvObject)->AddRef();
+ return S_OK;
+ }
+ *ppvObject = NULL;
+ return E_NOINTERFACE;
+ }
+ ULONG STDMETHODCALLTYPE AddRef() { return ++m_cRefCount; }
+ ULONG STDMETHODCALLTYPE Release() {
+ long nTemp;
+ nTemp = --m_cRefCount;
+ if(nTemp==0)
+ delete this;
+ return nTemp;
+ }
+ STDMETHODIMP GiveFeedback( ulong ) { return DRAGDROP_S_USEDEFAULTCURSORS; }
+ STDMETHODIMP QueryContinueDrag( BOOL esc, DWORD keyState ) {
+ if ( esc )
+ return DRAGDROP_S_CANCEL;
+ if ( !(keyState & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON)) )
+ return DRAGDROP_S_DROP;
+ return S_OK;
+ }
+};
+
+/**
+ * this is the actual object that FLTK can drop somewhere
+ * - the implementation is minimal, but it should work with all decent Win32 drop targets
+ */
+class FLDataObject : public IDataObject
+{
+ DWORD m_cRefCount;
+public:
+ FLDataObject() { m_cRefCount = 1; }
+ HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, LPVOID *ppvObject ) {
+ if (IID_IUnknown==riid || IID_IDataObject==riid)
+ {
+ *ppvObject=this;
+ ((LPUNKNOWN)*ppvObject)->AddRef();
+ return S_OK;
+ }
+ *ppvObject = NULL;
+ return E_NOINTERFACE;
+ }
+ ULONG STDMETHODCALLTYPE AddRef() { return ++m_cRefCount; }
+ ULONG STDMETHODCALLTYPE Release() {
+ long nTemp;
+ nTemp = --m_cRefCount;
+ if(nTemp==0)
+ delete this;
+ return nTemp;
+ }
+ // GetData currently allows ASCII text through Global Memory only
+ HRESULT STDMETHODCALLTYPE GetData( FORMATETC *pformatetcIn, STGMEDIUM *pmedium ) {
+ if ((pformatetcIn->dwAspect & DVASPECT_CONTENT) &&
+ (pformatetcIn->tymed & TYMED_HGLOBAL) &&
+ (pformatetcIn->cfFormat == CF_TEXT))
+ {
+ HGLOBAL gh = GlobalAlloc( GHND, fl_selection_length[0]+1 );
+ char *pMem = (char*)GlobalLock( gh );
+ memmove( pMem, fl_selection_buffer[0], fl_selection_length[0] );
+ pMem[ fl_selection_length[0] ] = 0;
+ pmedium->tymed = TYMED_HGLOBAL;
+ pmedium->hGlobal = gh;
+ pmedium->pUnkForRelease = NULL;
+ GlobalUnlock( gh );
+ return S_OK;
+ }
+ return DV_E_FORMATETC;
+ }
+ HRESULT STDMETHODCALLTYPE QueryGetData( FORMATETC *pformatetc )
+ {
+ if ((pformatetc->dwAspect & DVASPECT_CONTENT) &&
+ (pformatetc->tymed & TYMED_HGLOBAL) &&
+ (pformatetc->cfFormat == CF_TEXT))
+ return S_OK;
+ return DV_E_FORMATETC;
+ }
+ // all the following methods are not really needed for a DnD object
+ HRESULT STDMETHODCALLTYPE GetDataHere( FORMATETC* /*pformatetcIn*/, STGMEDIUM* /*pmedium*/) { return E_NOTIMPL; }
+ HRESULT STDMETHODCALLTYPE GetCanonicalFormatEtc( FORMATETC* /*in*/, FORMATETC* /*out*/) { return E_NOTIMPL; }
+ HRESULT STDMETHODCALLTYPE SetData( FORMATETC* /*pformatetc*/, STGMEDIUM* /*pmedium*/, BOOL /*fRelease*/) { return E_NOTIMPL; }
+ HRESULT STDMETHODCALLTYPE EnumFormatEtc( DWORD /*dir*/, IEnumFORMATETC** /*ppenumFormatEtc*/) { return E_NOTIMPL; }
+ HRESULT STDMETHODCALLTYPE DAdvise( FORMATETC* /*pformatetc*/, DWORD /*advf*/,
+ IAdviseSink* /*pAdvSink*/, DWORD* /*pdwConnection*/) { return E_NOTIMPL; }
+ HRESULT STDMETHODCALLTYPE DUnadvise( DWORD /*dwConnection*/) { return E_NOTIMPL; }
+ HRESULT STDMETHODCALLTYPE EnumDAdvise( IEnumSTATDATA** /*ppenumAdvise*/) { return E_NOTIMPL; }
+};
+
+
+/**
+ * drag and drop whatever is in the cut-copy-paste buffer
+ * - create a selection first using:
+ * Fl::copy(const char *stuff, int len, 0)
+ */
+int Fl::dnd()
+{
+ DWORD dropEffect;
+ ReleaseCapture();
+
+ FLDataObject *fdo = new FLDataObject;
+ fdo->AddRef();
+ FLDropSource *fds = new FLDropSource;
+ fds->AddRef();
+
+ HRESULT ret = DoDragDrop( fdo, fds, DROPEFFECT_MOVE|DROPEFFECT_LINK|DROPEFFECT_COPY, &dropEffect );
+
+ fdo->Release();
+ fds->Release();
+
+ Fl_Widget *w = Fl::pushed();
+ if ( w )
+ {
+ int old_event = Fl::e_number;
+ w->handle(Fl::e_number = FL_RELEASE);
+ Fl::e_number = old_event;
+ Fl::pushed( 0 );
+ }
+ if ( ret==DRAGDROP_S_DROP ) return 1; // or DD_S_CANCEL
+ return 0;
+}
+#else
+int Fl::dnd()
+{
+ // Always indicate DnD failed when using GCC < 3...
+ return 1;
+}
+#endif // !__GNUC__ || __GNUC__ >= 3
+
+
+//
+// End of "$Id: fl_dnd_win32.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_dnd_x.cxx b/third_party/windows/fltk-1.1.10/src/fl_dnd_x.cxx new file mode 100644 index 0000000..56368a2 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_dnd_x.cxx @@ -0,0 +1,201 @@ +//
+// "$Id: fl_dnd_x.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Drag & Drop code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2006 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_Window.H>
+#include <FL/x.H>
+#include "flstring.h"
+
+
+extern Atom fl_XdndAware;
+extern Atom fl_XdndSelection;
+extern Atom fl_XdndEnter;
+extern Atom fl_XdndTypeList;
+extern Atom fl_XdndPosition;
+extern Atom fl_XdndLeave;
+extern Atom fl_XdndDrop;
+extern Atom fl_XdndStatus;
+extern Atom fl_XdndActionCopy;
+extern Atom fl_XdndFinished;
+//extern Atom fl_XdndProxy;
+extern Atom fl_XdndURIList;
+
+extern char fl_i_own_selection[2];
+extern char *fl_selection_buffer[2];
+
+extern void fl_sendClientMessage(Window window, Atom message,
+ unsigned long d0,
+ unsigned long d1=0,
+ unsigned long d2=0,
+ unsigned long d3=0,
+ unsigned long d4=0);
+
+// return version # of Xdnd this window supports. Also change the
+// window to the proxy if it uses a proxy:
+static int dnd_aware(Window& window) {
+ Atom actual; int format; unsigned long count, remaining;
+ unsigned char *data = 0;
+ XGetWindowProperty(fl_display, window, fl_XdndAware,
+ 0, 4, False, XA_ATOM,
+ &actual, &format,
+ &count, &remaining, &data);
+ if (actual == XA_ATOM && format==32 && count && data)
+ return int(*(Atom*)data);
+ return 0;
+}
+
+static int grabfunc(int event) {
+ if (event == FL_RELEASE) Fl::pushed(0);
+ return 0;
+}
+
+extern int (*fl_local_grab)(int); // in Fl.cxx
+
+// send an event to an fltk window belonging to this program:
+static int local_handle(int event, Fl_Window* window) {
+ fl_local_grab = 0;
+ Fl::e_x = Fl::e_x_root-window->x();
+ Fl::e_y = Fl::e_y_root-window->y();
+ int ret = Fl::handle(event,window);
+ fl_local_grab = grabfunc;
+ return ret;
+}
+
+int Fl::dnd() {
+ Fl_Window *source_fl_win = Fl::first_window();
+ Fl::first_window()->cursor((Fl_Cursor)21);
+ Window source_window = fl_xid(Fl::first_window());
+ fl_local_grab = grabfunc;
+ Window target_window = 0;
+ Fl_Window* local_window = 0;
+ int dndversion = 4; int dest_x, dest_y;
+ XSetSelectionOwner(fl_display, fl_XdndSelection, fl_message_window, fl_event_time);
+
+ while (Fl::pushed()) {
+
+ // figure out what window we are pointing at:
+ Window new_window = 0; int new_version = 0;
+ Fl_Window* new_local_window = 0;
+ for (Window child = RootWindow(fl_display, fl_screen);;) {
+ Window root; unsigned int junk3;
+ XQueryPointer(fl_display, child, &root, &child,
+ &e_x_root, &e_y_root, &dest_x, &dest_y, &junk3);
+ if (!child) {
+ if (!new_window && (new_version = dnd_aware(root))) new_window = root;
+ break;
+ }
+ new_window = child;
+ if ((new_local_window = fl_find(child))) break;
+ if ((new_version = dnd_aware(new_window))) break;
+ }
+
+ if (new_window != target_window) {
+ if (local_window) {
+ local_handle(FL_DND_LEAVE, local_window);
+ } else if (dndversion) {
+ fl_sendClientMessage(target_window, fl_XdndLeave, source_window);
+ }
+ dndversion = new_version;
+ target_window = new_window;
+ local_window = new_local_window;
+ if (local_window) {
+ local_handle(FL_DND_ENTER, local_window);
+ } else if (dndversion) {
+ // Send an X-DND message to the target window. In order to
+ // support dragging of files/URLs as well as arbitrary text,
+ // we look at the selection buffer - if the buffer starts
+ // with a common URI scheme, does not contain spaces, and
+ // contains at least one CR LF, then we flag the data as
+ // both a URI list (MIME media type "text/uri-list") and
+ // plain text. Otherwise, we just say it is plain text.
+ if ((!strncmp(fl_selection_buffer[0], "file:///", 8) ||
+ !strncmp(fl_selection_buffer[0], "ftp://", 6) ||
+ !strncmp(fl_selection_buffer[0], "http://", 7) ||
+ !strncmp(fl_selection_buffer[0], "https://", 8) ||
+ !strncmp(fl_selection_buffer[0], "ipp://", 6) ||
+ !strncmp(fl_selection_buffer[0], "ldap:", 5) ||
+ !strncmp(fl_selection_buffer[0], "mailto:", 7) ||
+ !strncmp(fl_selection_buffer[0], "news:", 5) ||
+ !strncmp(fl_selection_buffer[0], "smb://", 6)) &&
+ !strchr(fl_selection_buffer[0], ' ') &&
+ strstr(fl_selection_buffer[0], "\r\n")) {
+ // Send file/URI list...
+ fl_sendClientMessage(target_window, fl_XdndEnter, source_window,
+ dndversion<<24, fl_XdndURIList, XA_STRING, 0);
+ } else {
+ // Send plain text...
+ fl_sendClientMessage(target_window, fl_XdndEnter, source_window,
+ dndversion<<24, XA_STRING, 0, 0);
+ }
+ }
+ }
+ if (local_window) {
+ local_handle(FL_DND_DRAG, local_window);
+ } else if (dndversion) {
+ fl_sendClientMessage(target_window, fl_XdndPosition, source_window,
+ 0, (e_x_root<<16)|e_y_root, fl_event_time,
+ fl_XdndActionCopy);
+ }
+ Fl::wait();
+ }
+
+ if (local_window) {
+ fl_i_own_selection[0] = 1;
+ if (local_handle(FL_DND_RELEASE, local_window)) paste(*belowmouse(), 0);
+ } else if (dndversion) {
+ fl_sendClientMessage(target_window, fl_XdndDrop, source_window,
+ 0, fl_event_time);
+ } else if (target_window) {
+ // fake a drop by clicking the middle mouse button:
+ XButtonEvent msg;
+ msg.type = ButtonPress;
+ msg.window = target_window;
+ msg.root = RootWindow(fl_display, fl_screen);
+ msg.subwindow = 0;
+ msg.time = fl_event_time+1;
+ msg.x = dest_x;
+ msg.y = dest_y;
+ msg.x_root = Fl::e_x_root;
+ msg.y_root = Fl::e_y_root;
+ msg.state = 0x0;
+ msg.button = Button2;
+ XSendEvent(fl_display, target_window, False, 0L, (XEvent*)&msg);
+ msg.time++;
+ msg.state = 0x200;
+ msg.type = ButtonRelease;
+ XSendEvent(fl_display, target_window, False, 0L, (XEvent*)&msg);
+ }
+
+ fl_local_grab = 0;
+ source_fl_win->cursor(FL_CURSOR_DEFAULT);
+ return 1;
+}
+
+
+//
+// End of "$Id: fl_dnd_x.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_draw.cxx b/third_party/windows/fltk-1.1.10/src/fl_draw.cxx new file mode 100644 index 0000000..006cc45 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_draw.cxx @@ -0,0 +1,336 @@ +//
+// "$Id: fl_draw.cxx 5565 2006-12-21 19:39:26Z mike $"
+//
+// Label drawing code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Implementation of fl_draw(const char*,int,int,int,int,Fl_Align)
+// Used to draw all the labels and text, this routine:
+// Word wraps the labels to fit into their bounding box.
+// Breaks them into lines at the newlines.
+// Expands all unprintable characters to ^X or \nnn notation
+// Aligns them against the inside of the box.
+
+#define min(a,b) ((a)<(b)?(a):(b))
+#include <FL/fl_draw.H>
+#include <FL/Fl_Image.H>
+
+#include "flstring.h"
+#include <ctype.h>
+#include <math.h>
+
+#define MAXBUF 1024
+
+char fl_draw_shortcut; // set by fl_labeltypes.cxx
+
+static char* underline_at;
+
+// Copy p to buf, replacing unprintable characters with ^X and \nnn
+// Stop at a newline or if MAXBUF characters written to buffer.
+// Also word-wrap if width exceeds maxw.
+// Returns a pointer to the start of the next line of caharcters.
+// Sets n to the number of characters put into the buffer.
+// Sets width to the width of the string in the current font.
+
+static const char*
+expand(const char* from, char* buf, double maxw, int& n, double &width,
+ int wrap, int draw_symbols) {
+ char* o = buf;
+ char* e = buf+(MAXBUF-4);
+ underline_at = 0;
+ char* word_end = o;
+ const char* word_start = from;
+ double w = 0;
+
+ const char* p = from;
+ for (;; p++) {
+
+ int c = *p & 255;
+
+ if (!c || c == ' ' || c == '\n') {
+ // test for word-wrap:
+ if (word_start < p && wrap) {
+ double newwidth = w + fl_width(word_end, o-word_end);
+ if (word_end > buf && newwidth > maxw) { // break before this word
+ o = word_end;
+ p = word_start;
+ break;
+ }
+ word_end = o;
+ w = newwidth;
+ }
+ if (!c) break;
+ else if (c == '\n') {p++; break;}
+ word_start = p+1;
+ }
+
+ if (o > e) break; // don't overflow buffer
+
+ if (c == '\t') {
+ for (c = (o-buf)%8; c<8 && o<e; c++) *o++ = ' ';
+ } else if (c == '&' && fl_draw_shortcut && *(p+1)) {
+ if (*(p+1) == '&') {p++; *o++ = '&';}
+ else if (fl_draw_shortcut != 2) underline_at = o;
+ } else if (c < ' ' || c == 127) { // ^X
+ *o++ = '^';
+ *o++ = c ^ 0x40;
+#ifdef __APPLE__
+ } else if (c == 0xCA) { // non-breaking space in MacRoman
+#else
+ } else if (c == 0xA0) { // non-breaking space in ISO 8859
+#endif
+ *o++ = ' ';
+ } else if (c == '@' && draw_symbols) { // Symbol???
+ if (p[1] && p[1] != '@') break;
+ *o++ = c;
+ if (p[1]) p++;
+ } else {
+ *o++ = c;
+ }
+ }
+
+ width = w + fl_width(word_end, o-word_end);
+ *o = 0;
+ n = o-buf;
+ return p;
+}
+
+void fl_draw(
+ const char* str, // the (multi-line) string
+ int x, int y, int w, int h, // bounding box
+ Fl_Align align,
+ void (*callthis)(const char*,int,int,int),
+ Fl_Image* img, int draw_symbols) {
+ const char* p;
+ const char* e;
+ char buf[MAXBUF];
+ int buflen;
+ char symbol[2][255], *symptr;
+ int symwidth[2], symoffset, symtotal;
+
+ // count how many lines and put the last one into the buffer:
+ int lines;
+ double width;
+
+ symbol[0][0] = '\0';
+ symwidth[0] = 0;
+
+ symbol[1][0] = '\0';
+ symwidth[1] = 0;
+
+ if (draw_symbols) {
+ if (str && str[0] == '@' && str[1] && str[1] != '@') {
+ // Start with a symbol...
+ for (symptr = symbol[0];
+ *str && !isspace(*str) && symptr < (symbol[0] + sizeof(symbol[0]) - 1);
+ *symptr++ = *str++);
+ *symptr = '\0';
+ if (isspace(*str)) str++;
+ symwidth[0] = min(w,h);
+ }
+
+ if (str && (p = strrchr(str, '@')) != NULL && p > (str + 1) && p[-1] != '@') {
+ strlcpy(symbol[1], p, sizeof(symbol[1]));
+ symwidth[1] = min(w,h);
+ }
+ }
+
+ symtotal = symwidth[0] + symwidth[1];
+
+ for (p = str, lines=0; p;) {
+ e = expand(p, buf, w - symtotal, buflen, width, align&FL_ALIGN_WRAP,
+ draw_symbols);
+ lines++;
+ if (!*e || (*e == '@' && e[1] != '@' && draw_symbols)) break;
+ p = e;
+ }
+
+ if ((symwidth[0] || symwidth[1]) && lines) {
+ if (symwidth[0]) symwidth[0] = lines * fl_height();
+ if (symwidth[1]) symwidth[1] = lines * fl_height();
+ }
+
+ symtotal = symwidth[0] + symwidth[1];
+
+ // figure out vertical position of the first line:
+ int xpos;
+ int ypos;
+ int height = fl_height();
+ int imgh = img ? img->h() : 0;
+
+ symoffset = 0;
+
+ if (align & FL_ALIGN_BOTTOM) ypos = y+h-(lines-1)*height-imgh;
+ else if (align & FL_ALIGN_TOP) ypos = y+height;
+ else ypos = y+(h-lines*height-imgh)/2+height;
+
+ // draw the image unless the "text over image" alignment flag is set...
+ if (img && !(align & FL_ALIGN_TEXT_OVER_IMAGE)) {
+ if (img->w() > symoffset) symoffset = img->w();
+
+ if (align & FL_ALIGN_LEFT) xpos = x + symwidth[0];
+ else if (align & FL_ALIGN_RIGHT) xpos = x + w - img->w() - symwidth[1];
+ else xpos = x + (w - img->w() - symtotal) / 2 + symwidth[0];
+
+ img->draw(xpos, ypos - height);
+ ypos += img->h();
+ }
+
+ // now draw all the lines:
+ if (str) {
+ int desc = fl_descent();
+ for (p=str; ; ypos += height) {
+ if (lines>1) e = expand(p, buf, w - symtotal, buflen, width,
+ align&FL_ALIGN_WRAP, draw_symbols);
+ else e = "";
+
+ if (width > symoffset) symoffset = (int)(width + 0.5);
+
+ if (align & FL_ALIGN_LEFT) xpos = x + symwidth[0];
+ else if (align & FL_ALIGN_RIGHT) xpos = x + w - (int)(width + .5) - symwidth[1];
+ else xpos = x + (w - (int)(width + .5) - symtotal) / 2 + symwidth[0];
+
+ callthis(buf,buflen,xpos,ypos-desc);
+
+ if (underline_at && underline_at >= buf && underline_at < (buf + buflen))
+ callthis("_",1,xpos+int(fl_width(buf,underline_at-buf)),ypos-desc);
+
+ if (!*e || (*e == '@' && e[1] != '@')) break;
+ p = e;
+ }
+ }
+
+ // draw the image if the "text over image" alignment flag is set...
+ if (img && (align & FL_ALIGN_TEXT_OVER_IMAGE)) {
+ if (img->w() > symoffset) symoffset = img->w();
+
+ if (align & FL_ALIGN_LEFT) xpos = x + symwidth[0];
+ else if (align & FL_ALIGN_RIGHT) xpos = x + w - img->w() - symwidth[1];
+ else xpos = x + (w - img->w() - symtotal) / 2 + symwidth[0];
+
+ img->draw(xpos, ypos);
+ }
+
+ // draw the symbols, if any...
+ if (symwidth[0]) {
+ // draw to the left
+ if (align & FL_ALIGN_LEFT) xpos = x;
+ else if (align & FL_ALIGN_RIGHT) xpos = x + w - symtotal - symoffset;
+ else xpos = x + (w - symoffset - symtotal) / 2;
+
+ if (align & FL_ALIGN_BOTTOM) ypos = y + h - symwidth[0];
+ else if (align & FL_ALIGN_TOP) ypos = y;
+ else ypos = y + (h - symwidth[0]) / 2;
+
+ fl_draw_symbol(symbol[0], xpos, ypos, symwidth[0], symwidth[0], fl_color());
+ }
+
+ if (symwidth[1]) {
+ // draw to the right
+ if (align & FL_ALIGN_LEFT) xpos = x + symoffset + symwidth[0];
+ else if (align & FL_ALIGN_RIGHT) xpos = x + w - symwidth[1];
+ else xpos = x + (w - symoffset - symtotal) / 2 + symoffset + symwidth[0];
+
+ if (align & FL_ALIGN_BOTTOM) ypos = y + h - symwidth[1];
+ else if (align & FL_ALIGN_TOP) ypos = y;
+ else ypos = y + (h - symwidth[1]) / 2;
+
+ fl_draw_symbol(symbol[1], xpos, ypos, symwidth[1], symwidth[1], fl_color());
+ }
+}
+
+void fl_draw(
+ const char* str, // the (multi-line) string
+ int x, int y, int w, int h, // bounding box
+ Fl_Align align,
+ Fl_Image* img,
+ int draw_symbols) {
+ if ((!str || !*str) && !img) return;
+ if (w && h && !fl_not_clipped(x, y, w, h) && (align & FL_ALIGN_INSIDE)) return;
+ if (align & FL_ALIGN_CLIP) fl_clip(x, y, w, h);
+ fl_draw(str, x, y, w, h, align, fl_draw, img, draw_symbols);
+ if (align & FL_ALIGN_CLIP) fl_pop_clip();
+}
+
+void fl_measure(const char* str, int& w, int& h, int draw_symbols) {
+ if (!str || !*str) {w = 0; h = 0; return;}
+ h = fl_height();
+ const char* p;
+ const char* e;
+ char buf[MAXBUF];
+ int buflen;
+ int lines;
+ double width;
+ int W = 0;
+ char symbol[2][255], *symptr;
+ int symwidth[2], symtotal;
+
+ // count how many lines and put the last one into the buffer:
+ symbol[0][0] = '\0';
+ symwidth[0] = 0;
+
+ symbol[1][0] = '\0';
+ symwidth[1] = 0;
+
+ if (draw_symbols) {
+ if (str && str[0] == '@' && str[1] && str[1] != '@') {
+ // Start with a symbol...
+ for (symptr = symbol[0];
+ *str && !isspace(*str) && symptr < (symbol[0] + sizeof(symbol[0]) - 1);
+ *symptr++ = *str++);
+ *symptr = '\0';
+ if (isspace(*str)) str++;
+ symwidth[0] = h;
+ }
+
+ if (str && (p = strrchr(str, '@')) != NULL && p > (str + 1) && p[-1]!='@') {
+ strlcpy(symbol[1], p, sizeof(symbol[1]));
+ symwidth[1] = h;
+ }
+ }
+
+ symtotal = symwidth[0] + symwidth[1];
+
+ for (p = str, lines=0; p;) {
+ e = expand(p, buf, w - symtotal, buflen, width, w != 0, draw_symbols);
+ if ((int)ceil(width) > W) W = (int)ceil(width);
+ lines++;
+ if (!*e || (*e == '@' && draw_symbols)) break;
+ p = e;
+ }
+
+ if ((symwidth[0] || symwidth[1]) && lines) {
+ if (symwidth[0]) symwidth[0] = lines * fl_height();
+ if (symwidth[1]) symwidth[1] = lines * fl_height();
+ }
+
+ symtotal = symwidth[0] + symwidth[1];
+
+ w = W + symtotal;
+ h = lines*h;
+}
+
+//
+// End of "$Id: fl_draw.cxx 5565 2006-12-21 19:39:26Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_draw_image.cxx b/third_party/windows/fltk-1.1.10/src/fl_draw_image.cxx new file mode 100644 index 0000000..74ff178 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_draw_image.cxx @@ -0,0 +1,576 @@ +//
+// "$Id: fl_draw_image.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Image drawing routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// I hope a simple and portable method of drawing color and monochrome
+// images. To keep this simple, only a single storage type is
+// supported: 8 bit unsigned data, byte order RGB, and pixels are
+// stored packed into rows with the origin at the top-left. It is
+// possible to alter the size of pixels with the "delta" argument, to
+// add alpha or other information per pixel. It is also possible to
+// change the origin and direction of the image data by messing with
+// the "delta" and "linedelta", making them negative, though this may
+// defeat some of the shortcuts in translating the image for X.
+
+#ifdef WIN32
+# include "fl_draw_image_win32.cxx"
+#elif defined(__APPLE__)
+# include "fl_draw_image_mac.cxx"
+#else
+
+// A list of assumptions made about the X display:
+
+// bits_per_pixel must be one of 8, 16, 24, 32.
+
+// scanline_pad must be a power of 2 and greater or equal to 8.
+
+// PsuedoColor visuals must have 8 bits_per_pixel (although the depth
+// may be less than 8). This is the only limitation that affects any
+// modern X displays, you can't use 12 or 16 bit colormaps.
+
+// The mask bits in TrueColor visuals for each color are
+// contiguous and have at least one bit of each color. This
+// is not checked for.
+
+// For 24 and 32 bit visuals there must be at least 8 bits of each color.
+
+////////////////////////////////////////////////////////////////
+
+# include <FL/Fl.H>
+# include <FL/fl_draw.H>
+# include <FL/x.H>
+# include "Fl_XColor.H"
+# include "flstring.h"
+
+static XImage xi; // template used to pass info to X
+static int bytes_per_pixel;
+static int scanline_add;
+static int scanline_mask;
+
+static void (*converter)(const uchar *from, uchar *to, int w, int delta);
+static void (*mono_converter)(const uchar *from, uchar *to, int w, int delta);
+
+static int dir; // direction-alternator
+static int ri,gi,bi; // saved error-diffusion value
+
+# if USE_COLORMAP
+////////////////////////////////////////////////////////////////
+// 8-bit converter with error diffusion
+
+static void color8_converter(const uchar *from, uchar *to, int w, int delta) {
+ int r=ri, g=gi, b=bi;
+ int d, td;
+ if (dir) {
+ dir = 0;
+ from = from+(w-1)*delta;
+ to = to+(w-1);
+ d = -delta;
+ td = -1;
+ } else {
+ dir = 1;
+ d = delta;
+ td = 1;
+ }
+ for (; w--; from += d, to += td) {
+ r += from[0]; if (r < 0) r = 0; else if (r>255) r = 255;
+ g += from[1]; if (g < 0) g = 0; else if (g>255) g = 255;
+ b += from[2]; if (b < 0) b = 0; else if (b>255) b = 255;
+ Fl_Color i = fl_color_cube(r*FL_NUM_RED/256,g*FL_NUM_GREEN/256,b*FL_NUM_BLUE/256);
+ Fl_XColor& xmap = fl_xmap[0][i];
+ if (!xmap.mapped) {if (!fl_redmask) fl_xpixel(r,g,b); else fl_xpixel(i);}
+ r -= xmap.r;
+ g -= xmap.g;
+ b -= xmap.b;
+ *to = uchar(xmap.pixel);
+ }
+ ri = r; gi = g; bi = b;
+}
+
+static void mono8_converter(const uchar *from, uchar *to, int w, int delta) {
+ int r=ri, g=gi, b=bi;
+ int d, td;
+ if (dir) {
+ dir = 0;
+ from = from+(w-1)*delta;
+ to = to+(w-1);
+ d = -delta;
+ td = -1;
+ } else {
+ dir = 1;
+ d = delta;
+ td = 1;
+ }
+ for (; w--; from += d, to += td) {
+ r += from[0]; if (r < 0) r = 0; else if (r>255) r = 255;
+ g += from[0]; if (g < 0) g = 0; else if (g>255) g = 255;
+ b += from[0]; if (b < 0) b = 0; else if (b>255) b = 255;
+ Fl_Color i = fl_color_cube(r*FL_NUM_RED/256,g*FL_NUM_GREEN/256,b*FL_NUM_BLUE/256);
+ Fl_XColor& xmap = fl_xmap[0][i];
+ if (!xmap.mapped) {if (!fl_redmask) fl_xpixel(r,g,b); else fl_xpixel(i);}
+ r -= xmap.r;
+ g -= xmap.g;
+ b -= xmap.b;
+ *to = uchar(xmap.pixel);
+ }
+ ri = r; gi = g; bi = b;
+}
+
+# endif
+
+////////////////////////////////////////////////////////////////
+// 16 bit TrueColor converters with error diffusion
+// Cray computers have no 16-bit type, so we use character pointers
+// (which may be slow)
+
+# ifdef U16
+# define OUTTYPE U16
+# define OUTSIZE 1
+# define OUTASSIGN(v) *t = v
+# else
+# define OUTTYPE uchar
+# define OUTSIZE 2
+# define OUTASSIGN(v) int tt=v; t[0] = uchar(tt>>8); t[1] = uchar(tt)
+# endif
+
+static void color16_converter(const uchar *from, uchar *to, int w, int delta) {
+ OUTTYPE *t = (OUTTYPE *)to;
+ int d, td;
+ if (dir) {
+ dir = 0;
+ from = from+(w-1)*delta;
+ t = t+(w-1)*OUTSIZE;
+ d = -delta;
+ td = -OUTSIZE;
+ } else {
+ dir = 1;
+ d = delta;
+ td = OUTSIZE;
+ }
+ int r=ri, g=gi, b=bi;
+ for (; w--; from += d, t += td) {
+ r = (r&~fl_redmask) +from[0]; if (r>255) r = 255;
+ g = (g&~fl_greenmask)+from[1]; if (g>255) g = 255;
+ b = (b&~fl_bluemask) +from[2]; if (b>255) b = 255;
+ OUTASSIGN((
+ ((r&fl_redmask)<<fl_redshift)+
+ ((g&fl_greenmask)<<fl_greenshift)+
+ ((b&fl_bluemask)<<fl_blueshift)
+ ) >> fl_extrashift);
+ }
+ ri = r; gi = g; bi = b;
+}
+
+static void mono16_converter(const uchar *from,uchar *to,int w, int delta) {
+ OUTTYPE *t = (OUTTYPE *)to;
+ int d, td;
+ if (dir) {
+ dir = 0;
+ from = from+(w-1)*delta;
+ t = t+(w-1)*OUTSIZE;
+ d = -delta;
+ td = -OUTSIZE;
+ } else {
+ dir = 1;
+ d = delta;
+ td = OUTSIZE;
+ }
+ uchar mask = fl_redmask & fl_greenmask & fl_bluemask;
+ int r=ri;
+ for (; w--; from += d, t += td) {
+ r = (r&~mask) + *from; if (r > 255) r = 255;
+ uchar m = r&mask;
+ OUTASSIGN((
+ (m<<fl_redshift)+
+ (m<<fl_greenshift)+
+ (m<<fl_blueshift)
+ ) >> fl_extrashift);
+ }
+ ri = r;
+}
+
+// special-case the 5r6g5b layout used by XFree86:
+
+static void c565_converter(const uchar *from, uchar *to, int w, int delta) {
+ OUTTYPE *t = (OUTTYPE *)to;
+ int d, td;
+ if (dir) {
+ dir = 0;
+ from = from+(w-1)*delta;
+ t = t+(w-1)*OUTSIZE;
+ d = -delta;
+ td = -OUTSIZE;
+ } else {
+ dir = 1;
+ d = delta;
+ td = OUTSIZE;
+ }
+ int r=ri, g=gi, b=bi;
+ for (; w--; from += d, t += td) {
+ r = (r&7)+from[0]; if (r>255) r = 255;
+ g = (g&3)+from[1]; if (g>255) g = 255;
+ b = (b&7)+from[2]; if (b>255) b = 255;
+ OUTASSIGN(((r&0xf8)<<8) + ((g&0xfc)<<3) + (b>>3));
+ }
+ ri = r; gi = g; bi = b;
+}
+
+static void m565_converter(const uchar *from,uchar *to,int w, int delta) {
+ OUTTYPE *t = (OUTTYPE *)to;
+ int d, td;
+ if (dir) {
+ dir = 0;
+ from = from+(w-1)*delta;
+ t = t+(w-1)*OUTSIZE;
+ d = -delta;
+ td = -OUTSIZE;
+ } else {
+ dir = 1;
+ d = delta;
+ td = OUTSIZE;
+ }
+ int r=ri;
+ for (; w--; from += d, t += td) {
+ r = (r&7) + *from; if (r > 255) r = 255;
+ OUTASSIGN((r>>3) * 0x841);
+ }
+ ri = r;
+}
+
+////////////////////////////////////////////////////////////////
+// 24bit TrueColor converters:
+
+static void rgb_converter(const uchar *from, uchar *to, int w, int delta) {
+ int d = delta-3;
+ for (; w--; from += d) {
+ *to++ = *from++;
+ *to++ = *from++;
+ *to++ = *from++;
+ }
+}
+
+static void bgr_converter(const uchar *from, uchar *to, int w, int delta) {
+ for (; w--; from += delta) {
+ uchar r = from[0];
+ uchar g = from[1];
+ *to++ = from[2];
+ *to++ = g;
+ *to++ = r;
+ }
+}
+
+static void rrr_converter(const uchar *from, uchar *to, int w, int delta) {
+ for (; w--; from += delta) {
+ *to++ = *from;
+ *to++ = *from;
+ *to++ = *from;
+ }
+}
+
+////////////////////////////////////////////////////////////////
+// 32bit TrueColor converters on a 32 or 64-bit machine:
+
+# ifdef U64
+# define STORETYPE U64
+# if WORDS_BIGENDIAN
+# define INNARDS32(f) \
+ U64 *t = (U64*)to; \
+ int w1 = (w+1)/2; \
+ for (; w1--; from += delta) {U64 i = f; from += delta; *t++ = (i<<32)|(f);}
+# else
+# define INNARDS32(f) \
+ U64 *t = (U64*)to; \
+ int w1 = (w+1)/2; \
+ for (; w1--; from += delta) {U64 i=f; from+= delta; *t++ = ((U64)(f)<<32)|i;}
+# endif
+# else
+# define STORETYPE U32
+# define INNARDS32(f) \
+ U32 *t = (U32*)to; for (; w--; from += delta) *t++ = f
+# endif
+
+static void rgbx_converter(const uchar *from, uchar *to, int w, int delta) {
+ INNARDS32((unsigned(from[0])<<24)+(from[1]<<16)+(from[2]<<8));
+}
+
+static void xbgr_converter(const uchar *from, uchar *to, int w, int delta) {
+ INNARDS32((from[0])+(from[1]<<8)+(from[2]<<16));
+}
+
+static void xrgb_converter(const uchar *from, uchar *to, int w, int delta) {
+ INNARDS32((from[0]<<16)+(from[1]<<8)+(from[2]));
+}
+
+static void bgrx_converter(const uchar *from, uchar *to, int w, int delta) {
+ INNARDS32((from[0]<<8)+(from[1]<<16)+(unsigned(from[2])<<24));
+}
+
+static void rrrx_converter(const uchar *from, uchar *to, int w, int delta) {
+ INNARDS32(unsigned(*from) * 0x1010100U);
+}
+
+static void xrrr_converter(const uchar *from, uchar *to, int w, int delta) {
+ INNARDS32(*from * 0x10101U);
+}
+
+static void
+color32_converter(const uchar *from, uchar *to, int w, int delta) {
+ INNARDS32(
+ (from[0]<<fl_redshift)+(from[1]<<fl_greenshift)+(from[2]<<fl_blueshift));
+}
+
+static void
+mono32_converter(const uchar *from,uchar *to,int w, int delta) {
+ INNARDS32(
+ (*from << fl_redshift)+(*from << fl_greenshift)+(*from << fl_blueshift));
+}
+
+////////////////////////////////////////////////////////////////
+
+static void figure_out_visual() {
+
+ fl_xpixel(FL_BLACK); // setup fl_redmask, etc, in fl_color.cxx
+ fl_xpixel(FL_WHITE); // also make sure white is allocated
+
+ static XPixmapFormatValues *pfvlist;
+ static int FL_NUM_pfv;
+ if (!pfvlist) pfvlist = XListPixmapFormats(fl_display,&FL_NUM_pfv);
+ XPixmapFormatValues *pfv;
+ for (pfv = pfvlist; pfv < pfvlist+FL_NUM_pfv; pfv++)
+ if (pfv->depth == fl_visual->depth) break;
+ xi.format = ZPixmap;
+ xi.byte_order = ImageByteOrder(fl_display);
+//i.bitmap_unit = 8;
+//i.bitmap_bit_order = MSBFirst;
+//i.bitmap_pad = 8;
+ xi.depth = fl_visual->depth;
+ xi.bits_per_pixel = pfv->bits_per_pixel;
+
+ if (xi.bits_per_pixel & 7) bytes_per_pixel = 0; // produce fatal error
+ else bytes_per_pixel = xi.bits_per_pixel/8;
+
+ unsigned int n = pfv->scanline_pad/8;
+ if (pfv->scanline_pad & 7 || (n&(n-1)))
+ Fl::fatal("Can't do scanline_pad of %d",pfv->scanline_pad);
+ if (n < sizeof(STORETYPE)) n = sizeof(STORETYPE);
+ scanline_add = n-1;
+ scanline_mask = -n;
+
+# if USE_COLORMAP
+ if (bytes_per_pixel == 1) {
+ converter = color8_converter;
+ mono_converter = mono8_converter;
+ return;
+ }
+ if (!fl_visual->red_mask)
+ Fl::fatal("Can't do %d bits_per_pixel colormap",xi.bits_per_pixel);
+# endif
+
+ // otherwise it is a TrueColor visual:
+
+ int rs = fl_redshift;
+ int gs = fl_greenshift;
+ int bs = fl_blueshift;
+
+ switch (bytes_per_pixel) {
+
+ case 2:
+ // All 16-bit TrueColor visuals are supported on any machine with
+ // 24 or more bits per integer.
+# ifdef U16
+ xi.byte_order = WORDS_BIGENDIAN;
+# else
+ xi.byte_order = 1;
+# endif
+ if (rs == 11 && gs == 6 && bs == 0 && fl_extrashift == 3) {
+ converter = c565_converter;
+ mono_converter = m565_converter;
+ } else {
+ converter = color16_converter;
+ mono_converter = mono16_converter;
+ }
+ break;
+
+ case 3:
+ if (xi.byte_order) {rs = 16-rs; gs = 16-gs; bs = 16-bs;}
+ if (rs == 0 && gs == 8 && bs == 16) {
+ converter = rgb_converter;
+ mono_converter = rrr_converter;
+ } else if (rs == 16 && gs == 8 && bs == 0) {
+ converter = bgr_converter;
+ mono_converter = rrr_converter;
+ } else {
+ Fl::fatal("Can't do arbitrary 24bit color");
+ }
+ break;
+
+ case 4:
+ if ((xi.byte_order!=0) != WORDS_BIGENDIAN)
+ {rs = 24-rs; gs = 24-gs; bs = 24-bs;}
+ if (rs == 0 && gs == 8 && bs == 16) {
+ converter = xbgr_converter;
+ mono_converter = xrrr_converter;
+ } else if (rs == 24 && gs == 16 && bs == 8) {
+ converter = rgbx_converter;
+ mono_converter = rrrx_converter;
+ } else if (rs == 8 && gs == 16 && bs == 24) {
+ converter = bgrx_converter;
+ mono_converter = rrrx_converter;
+ } else if (rs == 16 && gs == 8 && bs == 0) {
+ converter = xrgb_converter;
+ mono_converter = xrrr_converter;
+ } else {
+ xi.byte_order = WORDS_BIGENDIAN;
+ converter = color32_converter;
+ mono_converter = mono32_converter;
+ }
+ break;
+
+ default:
+ Fl::fatal("Can't do %d bits_per_pixel",xi.bits_per_pixel);
+ }
+
+}
+
+# define MAXBUFFER 0x40000 // 256k
+
+static void innards(const uchar *buf, int X, int Y, int W, int H,
+ int delta, int linedelta, int mono,
+ Fl_Draw_Image_Cb cb, void* userdata)
+{
+ if (!linedelta) linedelta = W*delta;
+
+ int dx, dy, w, h;
+ fl_clip_box(X,Y,W,H,dx,dy,w,h);
+ if (w<=0 || h<=0) return;
+ dx -= X;
+ dy -= Y;
+
+ if (!bytes_per_pixel) figure_out_visual();
+ xi.width = w;
+ xi.height = h;
+
+ void (*conv)(const uchar *from, uchar *to, int w, int delta) = converter;
+ if (mono) conv = mono_converter;
+
+ // See if the data is already in the right format. Unfortunately
+ // some 32-bit x servers (XFree86) care about the unknown 8 bits
+ // and they must be zero. I can't confirm this for user-supplied
+ // data, so the 32-bit shortcut is disabled...
+ // This can set bytes_per_line negative if image is bottom-to-top
+ // I tested it on Linux, but it may fail on other Xlib implementations:
+ if (buf && (
+# if 0 // set this to 1 to allow 32-bit shortcut
+ delta == 4 &&
+# if WORDS_BIGENDIAN
+ conv == rgbx_converter
+# else
+ conv == xbgr_converter
+# endif
+ ||
+# endif
+ conv == rgb_converter && delta==3
+ ) && !(linedelta&scanline_add)) {
+ xi.data = (char *)(buf+delta*dx+linedelta*dy);
+ xi.bytes_per_line = linedelta;
+
+ } else {
+ int linesize = ((w*bytes_per_pixel+scanline_add)&scanline_mask)/sizeof(STORETYPE);
+ int blocking = h;
+ static STORETYPE *buffer; // our storage, always word aligned
+ static long buffer_size;
+ {int size = linesize*h;
+ if (size > MAXBUFFER) {
+ size = MAXBUFFER;
+ blocking = MAXBUFFER/linesize;
+ }
+ if (size > buffer_size) {
+ delete[] buffer;
+ buffer_size = size;
+ buffer = new STORETYPE[size];
+ }}
+ xi.data = (char *)buffer;
+ xi.bytes_per_line = linesize*sizeof(STORETYPE);
+ if (buf) {
+ buf += delta*dx+linedelta*dy;
+ for (int j=0; j<h; ) {
+ STORETYPE *to = buffer;
+ int k;
+ for (k = 0; j<h && k<blocking; k++, j++) {
+ conv(buf, (uchar*)to, w, delta);
+ buf += linedelta;
+ to += linesize;
+ }
+ XPutImage(fl_display,fl_window,fl_gc, &xi, 0, 0, X+dx, Y+dy+j-k, w, k);
+ }
+ } else {
+ STORETYPE* linebuf = new STORETYPE[(W*delta+(sizeof(STORETYPE)-1))/sizeof(STORETYPE)];
+ for (int j=0; j<h; ) {
+ STORETYPE *to = buffer;
+ int k;
+ for (k = 0; j<h && k<blocking; k++, j++) {
+ cb(userdata, dx, dy+j, w, (uchar*)linebuf);
+ conv((uchar*)linebuf, (uchar*)to, w, delta);
+ to += linesize;
+ }
+ XPutImage(fl_display,fl_window,fl_gc, &xi, 0, 0, X+dx, Y+dy+j-k, w, k);
+ }
+
+ delete[] linebuf;
+ }
+ }
+}
+
+void fl_draw_image(const uchar* buf, int x, int y, int w, int h, int d, int l){
+ innards(buf,x,y,w,h,d,l,(d<3&&d>-3),0,0);
+}
+void fl_draw_image(Fl_Draw_Image_Cb cb, void* data,
+ int x, int y, int w, int h,int d) {
+ innards(0,x,y,w,h,d,0,(d<3&&d>-3),cb,data);
+}
+void fl_draw_image_mono(const uchar* buf, int x, int y, int w, int h, int d, int l){
+ innards(buf,x,y,w,h,d,l,1,0,0);
+}
+void fl_draw_image_mono(Fl_Draw_Image_Cb cb, void* data,
+ int x, int y, int w, int h,int d) {
+ innards(0,x,y,w,h,d,0,1,cb,data);
+}
+
+void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) {
+ if (fl_visual->depth > 16) {
+ fl_color(r,g,b);
+ fl_rectf(x,y,w,h);
+ } else {
+ uchar c[3];
+ c[0] = r; c[1] = g; c[2] = b;
+ innards(c,x,y,w,h,0,0,0,0,0);
+ }
+}
+
+#endif
+
+//
+// End of "$Id: fl_draw_image.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_draw_image_mac.cxx b/third_party/windows/fltk-1.1.10/src/fl_draw_image_mac.cxx new file mode 100644 index 0000000..63abe27 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_draw_image_mac.cxx @@ -0,0 +1,274 @@ +//
+// "$Id: fl_draw_image_mac.cxx 5614 2007-01-18 15:25:09Z matt $"
+//
+// MacOS image drawing code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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 <config.h>
+#include <FL/Fl.H>
+#include <FL/fl_draw.H>
+#include <FL/x.H>
+
+#define MAXBUFFER 0x40000 // 256k
+
+/**
+ * draw an image based on the input parameters
+ *
+ * buf: image source data
+ * X, Y: position (in buffer?!)
+ * W, H: size of picture (in pixel?)
+ * delta: distance from pixel to pixel in buf in bytes
+ * linedelta: distance from line to line in buf in bytes
+ * mono: if set, pixel is one byte - if zero, pixel is 3 byte
+ * cb: callback to copy image data into (RGB?) buffer
+ * buf: pointer to first byte in image source
+ * x, y: position in buffer
+ * w: width (in bytes?)
+ * dst: destination buffer
+ * userdata: ?
+ */
+static void innards(const uchar *buf, int X, int Y, int W, int H,
+ int delta, int linedelta, int mono,
+ Fl_Draw_Image_Cb cb, void* userdata)
+{
+ if (!linedelta) linedelta = W*delta;
+
+#ifdef __APPLE_QD__
+ // theoretically, if the current GPort permits, we could write
+ // directly into it, avoiding the temporary GWorld. For now I
+ // will go the safe way... .
+ char direct = 0;
+ GWorldPtr gw;
+ Rect bounds;
+ bounds.left=0; bounds.right=W; bounds.top=0; bounds.bottom=H;
+ QDErr err = NewGWorld( &gw, 32, &bounds, 0L, 0L, useTempMem );
+ if (err==noErr && gw) {
+ PixMapHandle pm = GetGWorldPixMap( gw );
+ if ( pm ) {
+ LockPixels( pm );
+ if ( *pm ) {
+ uchar *base = (uchar*)GetPixBaseAddr( pm );
+ if ( base ) {
+ PixMapPtr pmp = *pm;
+ // make absolutely sure that we can use a direct memory write to
+ // create the pixmap!
+ if ( pmp->pixelType == 16 || pmp->pixelSize == 32 || pmp->cmpCount == 3 || pmp->cmpSize == 8 ) {
+ int rowBytes = pmp->rowBytes & 0x3fff;
+ if ( cb )
+ {
+ uchar *tmpBuf = new uchar[ W*delta ];
+ if ( mono ) delta -= 1; else delta -= 3;
+ for ( int i=0; i<H; i++ )
+ {
+ uchar *src = tmpBuf;
+ uchar *dst = base + i*rowBytes;
+ cb( userdata, 0, i, W, tmpBuf );
+ if ( mono ) {
+ for ( int j=0; j<W; j++ )
+ { uchar c = *src++; *dst++ = 0; *dst++ = c; *dst++ = c; *dst++ = c; src += delta; }
+ } else {
+ for ( int j=0; j<W; j++ )
+ { *dst++ = 0; *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; src += delta; }
+ }
+ }
+ delete[] tmpBuf;
+ }
+ else
+ {
+ if ( mono ) delta -= 1; else delta -= 3;
+ for ( int i=0; i<H; i++ )
+ {
+ const uchar *src = buf+i*linedelta;
+ uchar *dst = base + i*rowBytes;
+ if ( mono ) {
+ for ( int j=0; j<W; j++ )
+ { uchar c = *src++; *dst++ = 0; *dst++ = c; *dst++ = c; *dst++ = c; src += delta; }
+ } else {
+ for ( int j=0; j<W; j++ )
+ { *dst++ = 0; *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; src += delta; }
+ }
+ }
+ }
+
+ fl_copy_offscreen( X, Y, W, H, gw, 0, 0 );
+ direct = 1;
+ }
+ }
+ }
+
+ UnlockPixels( pm );
+ }
+
+ DisposeGWorld( gw );
+ }
+
+ // great. We were able to write the pixels directly into memory, so we can return now.
+ if ( direct )
+ return;
+
+ // following the very save (and very slow) way to write the image into the give port
+ if ( cb )
+ {
+ uchar *tmpBuf = new uchar[ W*3 ];
+ for ( int i=0; i<H; i++ )
+ {
+ uchar *src = tmpBuf;
+ cb( userdata, 0, i, W, tmpBuf );
+ for ( int j=0; j<W; j++ )
+ {
+ if ( mono )
+ { fl_color( src[0], src[0], src[0] ); src++; }
+ else
+ { fl_color( src[0], src[1], src[2] ); src+=3; }
+ MoveTo( X+j, Y+i );
+ Line( 0, 0 );
+ }
+ }
+ delete[] tmpBuf;
+ }
+ else
+ {
+ for ( int i=0; i<H; i++ )
+ {
+ const uchar *src = buf+i*linedelta;
+ for ( int j=0; j<W; j++ )
+ {
+ if ( mono )
+ fl_color( src[0], src[0], src[0] );
+ else
+ fl_color( src[0], src[1], src[2] );
+ MoveTo( X+j, Y+i );
+ Line( 0, 0 );
+ src += delta;
+ }
+ }
+ }
+#elif defined(__APPLE_QUARTZ__)
+ const void *array = buf;
+ uchar *tmpBuf = 0;
+ if (cb) {
+ tmpBuf = new uchar[ H*W*delta ];
+ for (int i=0; i<H; i++) {
+ cb(userdata, 0, i, W, tmpBuf+i*W*delta);
+ }
+ array = (void*)tmpBuf;
+ linedelta = W*delta;
+ }
+ // create an image context
+ CGColorSpaceRef lut = 0;
+ if (delta<=2)
+ lut = CGColorSpaceCreateDeviceGray();
+ else
+ lut = CGColorSpaceCreateDeviceRGB();
+ CGDataProviderRef src = CGDataProviderCreateWithData( 0L, array, linedelta*H, 0L);
+ CGImageRef img = CGImageCreate( W, H, 8, 8*delta, linedelta,
+ lut, delta&1?kCGImageAlphaNone:kCGImageAlphaNoneSkipLast,
+ src, 0L, false, kCGRenderingIntentDefault);
+ // draw the image into the destination context
+ if (img) {
+ CGRect rect = { { X, Y }, { W, H } };
+ Fl_X::q_begin_image(rect, 0, 0, W, H);
+ CGContextDrawImage(fl_gc, rect, img);
+ Fl_X::q_end_image();
+ // release all allocated resources
+ CGImageRelease(img);
+ }
+ CGColorSpaceRelease(lut);
+ CGDataProviderRelease(src);
+ if (cb) {
+ delete[] tmpBuf;
+ }
+ if (img) return; // else fall through to slow mode
+ // following the very save (and very slow) way to write the image into the give port
+ CGContextSetShouldAntialias(fl_gc, false);
+ if ( cb )
+ {
+ uchar *tmpBuf = new uchar[ W*4 ];
+ for ( int i=0; i<H; i++ )
+ {
+ uchar *src = tmpBuf;
+ cb( userdata, 0, i, W, tmpBuf );
+ for ( int j=0; j<W; j++ )
+ {
+ if ( mono )
+ { fl_color( src[0], src[0], src[0] ); }
+ else
+ { fl_color( src[0], src[1], src[2] ); }
+ CGContextMoveToPoint(fl_gc, X+j, Y+i);
+ CGContextAddLineToPoint(fl_gc, X+j, Y+i);
+ CGContextStrokePath(fl_gc);
+ src+=delta;
+ }
+ }
+ delete[] tmpBuf;
+ }
+ else
+ {
+ for ( int i=0; i<H; i++ )
+ {
+ const uchar *src = buf+i*linedelta;
+ for ( int j=0; j<W; j++ )
+ {
+ if ( mono )
+ fl_color( src[0], src[0], src[0] );
+ else
+ fl_color( src[0], src[1], src[2] );
+ CGContextMoveToPoint(fl_gc, X+j, Y+i);
+ CGContextAddLineToPoint(fl_gc, X+j, Y+i);
+ CGContextStrokePath(fl_gc);
+ src += delta;
+ }
+ }
+ }
+ CGContextSetShouldAntialias(fl_gc, true);
+#else
+# error : you must defined __APPLE_QD__ or __APPLE_QUARTZ__
+#endif
+}
+
+void fl_draw_image(const uchar* buf, int x, int y, int w, int h, int d, int l){
+ innards(buf,x,y,w,h,d,l,(d<3&&d>-3),0,0);
+}
+void fl_draw_image(Fl_Draw_Image_Cb cb, void* data,
+ int x, int y, int w, int h,int d) {
+ innards(0,x,y,w,h,d,0,(d<3&&d>-3),cb,data);
+}
+void fl_draw_image_mono(const uchar* buf, int x, int y, int w, int h, int d, int l){
+ innards(buf,x,y,w,h,d,l,1,0,0);
+}
+void fl_draw_image_mono(Fl_Draw_Image_Cb cb, void* data,
+ int x, int y, int w, int h,int d) {
+ innards(0,x,y,w,h,d,0,1,cb,data);
+}
+
+void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) {
+ fl_color(r,g,b);
+ fl_rectf(x,y,w,h);
+}
+
+//
+// End of "$Id: fl_draw_image_mac.cxx 5614 2007-01-18 15:25:09Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_draw_image_win32.cxx b/third_party/windows/fltk-1.1.10/src/fl_draw_image_win32.cxx new file mode 100644 index 0000000..2f505a1 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_draw_image_win32.cxx @@ -0,0 +1,325 @@ +//
+// "$Id: fl_draw_image_win32.cxx 6843 2009-08-24 19:53:06Z AlbrechtS $"
+//
+// WIN32 image drawing code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// I hope a simple and portable method of drawing color and monochrome
+// images. To keep this simple, only a single storage type is
+// supported: 8 bit unsigned data, byte order RGB, and pixels are
+// stored packed into rows with the origin at the top-left. It is
+// possible to alter the size of pixels with the "delta" argument, to
+// add alpha or other information per pixel. It is also possible to
+// change the origin and direction of the image data by messing with
+// the "delta" and "linedelta", making them negative, though this may
+// defeat some of the shortcuts in translating the image for X.
+
+// Unbelievably (since it conflicts with how most PC software works)
+// Micro$oft picked a bottom-up and BGR storage format for their
+// DIB images. I'm pretty certain there is a way around this, but
+// I can't find any other than the brute-force method of drawing
+// each line as a seperate image. This may also need to be done
+// if the delta is any amount other than 1, 3, or 4.
+
+////////////////////////////////////////////////////////////////
+
+#include <config.h>
+#include <FL/Fl.H>
+#include <FL/fl_draw.H>
+#include <FL/x.H>
+
+#define MAXBUFFER 0x40000 // 256k
+
+#if USE_COLORMAP
+
+// error-diffusion dither into the FLTK colormap
+static void dither(uchar* to, const uchar* from, int w, int delta) {
+ static int ri, gi, bi, dir;
+ int r=ri, g=gi, b=bi;
+ int d, td;
+ if (dir) {
+ dir = 0;
+ from = from+(w-1)*delta;
+ to = to+(w-1);
+ d = -delta;
+ td = -1;
+ } else {
+ dir = 1;
+ d = delta;
+ td = 1;
+ }
+ for (; w--; from += d, to += td) {
+ r += from[0]; if (r < 0) r = 0; else if (r>255) r = 255;
+ int rr = r*FL_NUM_RED/256;
+ r -= rr*255/(FL_NUM_RED-1);
+ g += from[1]; if (g < 0) g = 0; else if (g>255) g = 255;
+ int gg = g*FL_NUM_GREEN/256;
+ g -= gg*255/(FL_NUM_GREEN-1);
+ b += from[2]; if (b < 0) b = 0; else if (b>255) b = 255;
+ int bb = b*FL_NUM_BLUE/256;
+ b -= bb*255/(FL_NUM_BLUE-1);
+ *to = uchar(FL_COLOR_CUBE+(bb*FL_NUM_RED+rr)*FL_NUM_GREEN+gg);
+ }
+ ri = r; gi = g; bi = b;
+}
+
+// error-diffusion dither into the FLTK colormap
+static void monodither(uchar* to, const uchar* from, int w, int delta) {
+ static int ri,dir;
+ int r=ri;
+ int d, td;
+ if (dir) {
+ dir = 0;
+ from = from+(w-1)*delta;
+ to = to+(w-1);
+ d = -delta;
+ td = -1;
+ } else {
+ dir = 1;
+ d = delta;
+ td = 1;
+ }
+ for (; w--; from += d, to += td) {
+ r += *from; if (r < 0) r = 0; else if (r>255) r = 255;
+ int rr = r*FL_NUM_GRAY/256;
+ r -= rr*255/(FL_NUM_GRAY-1);
+ *to = uchar(FL_GRAY_RAMP+rr);
+ }
+ ri = r;
+}
+
+#endif // USE_COLORMAP
+
+static void innards(const uchar *buf, int X, int Y, int W, int H,
+ int delta, int linedelta, int depth,
+ Fl_Draw_Image_Cb cb, void* userdata)
+{
+ char indexed = 0;
+
+#if USE_COLORMAP
+ indexed = (fl_palette != 0);
+#endif
+
+ if (depth==0) depth = 3;
+ if (indexed || !fl_can_do_alpha_blending())
+ depth = (depth-1)|1;
+
+ if (!linedelta) linedelta = W*delta;
+
+ int x, y, w, h;
+ fl_clip_box(X,Y,W,H,x,y,w,h);
+ if (w<=0 || h<=0) return;
+ if (buf) buf += (x-X)*delta + (y-Y)*linedelta;
+
+ static U32 bmibuffer[256+12];
+ BITMAPINFO &bmi = *((BITMAPINFO*)bmibuffer);
+ if (!bmi.bmiHeader.biSize) {
+ bmi.bmiHeader.biSize = sizeof(bmi)-4; // does it use this to determine type?
+ bmi.bmiHeader.biPlanes = 1;
+ bmi.bmiHeader.biCompression = BI_RGB;
+ bmi.bmiHeader.biXPelsPerMeter = 0;
+ bmi.bmiHeader.biYPelsPerMeter = 0;
+ bmi.bmiHeader.biClrUsed = 0;
+ bmi.bmiHeader.biClrImportant = 0;
+ }
+#if USE_COLORMAP
+ if (indexed) {
+ for (short i=0; i<256; i++) {
+ *((short*)(bmi.bmiColors)+i) = i;
+ }
+ } else
+#endif
+ if (depth<3) {
+ for (int i=0; i<256; i++) {
+ bmi.bmiColors[i].rgbBlue = (uchar)i;
+ bmi.bmiColors[i].rgbGreen = (uchar)i;
+ bmi.bmiColors[i].rgbRed = (uchar)i;
+ bmi.bmiColors[i].rgbReserved = (uchar)0; // must be zero
+ }
+ }
+ bmi.bmiHeader.biWidth = w;
+#if USE_COLORMAP
+ bmi.bmiHeader.biBitCount = indexed ? 8 : depth*8;
+ int pixelsize = indexed ? 1 : depth;
+#else
+ bmi.bmiHeader.biBitCount = depth*8;
+ int pixelsize = depth;
+#endif
+ if (depth==2) { // special case: gray with alpha
+ bmi.bmiHeader.biBitCount = 32;
+ pixelsize = 4;
+ }
+ int linesize = (pixelsize*w+3)&~3;
+
+ static U32* buffer;
+ int blocking = h;
+ {int size = linesize*h;
+ if (size > MAXBUFFER) {
+ size = MAXBUFFER;
+ blocking = MAXBUFFER/linesize;
+ }
+ static long buffer_size;
+ if (size > buffer_size) {
+ delete[] buffer;
+ buffer_size = size;
+ buffer = new U32[(size+3)/4];
+ }}
+ bmi.bmiHeader.biHeight = blocking;
+ static U32* line_buffer;
+ if (!buf) {
+ int size = W*delta;
+ static int line_buf_size;
+ if (size > line_buf_size) {
+ delete[] line_buffer;
+ line_buf_size = size;
+ line_buffer = new U32[(size+3)/4];
+ }
+ }
+ for (int j=0; j<h; ) {
+ int k;
+ for (k = 0; j<h && k<blocking; k++, j++) {
+ const uchar* from;
+ if (!buf) { // run the converter:
+ cb(userdata, x-X, y-Y+j, w, (uchar*)line_buffer);
+ from = (uchar*)line_buffer;
+ } else {
+ from = buf;
+ buf += linedelta;
+ }
+ uchar *to = (uchar*)buffer+(blocking-k-1)*linesize;
+#if USE_COLORMAP
+ if (indexed) {
+ if (depth<3)
+ monodither(to, from, w, delta);
+ else
+ dither(to, from, w, delta);
+ to += w;
+ } else
+#endif
+ {
+ int i;
+ switch (depth) {
+ case 1:
+ for (i=w; i--; from += delta) *to++ = *from;
+ break;
+ case 2:
+ for (i=w; i--; from += delta, to += 4) {
+ uchar a = from[1];
+ uchar gray = (from[0]*a)>>8;
+ to[0] = gray;
+ to[1] = gray;
+ to[2] = gray;
+ to[3] = a;
+ }
+ break;
+ case 3:
+ for (i=w; i--; from += delta, to += 3) {
+ uchar r = from[0];
+ to[0] = from[2];
+ to[1] = from[1];
+ to[2] = r;
+ }
+ break;
+ case 4:
+ for (i=w; i--; from += delta, to += 4) {
+ uchar a = from[3];
+ uchar r = from[0];
+ to[0] = (from[2]*a)>>8;
+ to[1] = (from[1]*a)>>8;
+ to[2] = (r*a)>>8;
+ to[3] = from[3];
+ }
+ break;
+ }
+ }
+ }
+ SetDIBitsToDevice(fl_gc, x, y+j-k, w, k, 0, 0, 0, k,
+ (LPSTR)((uchar*)buffer+(blocking-k)*linesize),
+ &bmi,
+#if USE_COLORMAP
+ indexed ? DIB_PAL_COLORS : DIB_RGB_COLORS
+#else
+ DIB_RGB_COLORS
+#endif
+ );
+ }
+}
+
+static int fl_abs(int v) { return v<0 ? -v : v; }
+
+void fl_draw_image(const uchar* buf, int x, int y, int w, int h, int d, int l){
+ if (fl_abs(d)&FL_IMAGE_WITH_ALPHA) {
+ d ^= FL_IMAGE_WITH_ALPHA;
+ innards(buf,x,y,w,h,d,l,fl_abs(d),0,0);
+ } else {
+ innards(buf,x,y,w,h,d,l,(d<3&&d>-3),0,0);
+ }
+}
+
+void fl_draw_image(Fl_Draw_Image_Cb cb, void* data,
+ int x, int y, int w, int h,int d) {
+ if (fl_abs(d)&FL_IMAGE_WITH_ALPHA) {
+ d ^= FL_IMAGE_WITH_ALPHA;
+ innards(0,x,y,w,h,d,0,(d<3&&d>-3),cb,data);
+ } else {
+ innards(0,x,y,w,h,d,0,(d<3&&d>-3),cb,data);
+ }
+}
+
+void fl_draw_image_mono(const uchar* buf, int x, int y, int w, int h, int d, int l){
+ if (fl_abs(d)&FL_IMAGE_WITH_ALPHA) {
+ d ^= FL_IMAGE_WITH_ALPHA;
+ innards(buf,x,y,w,h,d,l,1,0,0);
+ } else {
+ innards(buf,x,y,w,h,d,l,1,0,0);
+ }
+}
+
+void fl_draw_image_mono(Fl_Draw_Image_Cb cb, void* data,
+ int x, int y, int w, int h,int d) {
+ if (fl_abs(d)&FL_IMAGE_WITH_ALPHA) {
+ d ^= FL_IMAGE_WITH_ALPHA;
+ innards(0,x,y,w,h,d,0,1,cb,data);
+ } else {
+ innards(0,x,y,w,h,d,0,1,cb,data);
+ }
+}
+
+void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) {
+#if USE_COLORMAP
+ // use the error diffusion dithering code to produce a much nicer block:
+ if (fl_palette) {
+ uchar c[3];
+ c[0] = r; c[1] = g; c[2] = b;
+ innards(c,x,y,w,h,0,0,0,0,0);
+ return;
+ }
+#endif
+ fl_color(r,g,b);
+ fl_rectf(x,y,w,h);
+}
+
+//
+// End of "$Id: fl_draw_image_win32.cxx 6843 2009-08-24 19:53:06Z AlbrechtS $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_draw_pixmap.cxx b/third_party/windows/fltk-1.1.10/src/fl_draw_pixmap.cxx new file mode 100644 index 0000000..c76be55 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_draw_pixmap.cxx @@ -0,0 +1,340 @@ +//
+// "$Id: fl_draw_pixmap.cxx 6026 2008-02-14 18:17:06Z matt $"
+//
+// Pixmap drawing code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Implemented without using the xpm library (which I can't use because
+// it interferes with the color cube used by fl_draw_image).
+// Current implementation is cheap and slow, and works best on a full-color
+// display. Transparency is not handled, and colors are dithered to
+// the color cube. Color index is achieved by adding the id
+// characters together! Also mallocs a lot of temporary memory!
+// Notice that there is no pixmap file interface. This is on purpose,
+// as I want to discourage programs that require support files to work.
+// All data needed by a program ui should be compiled in!!!
+
+#include <FL/Fl.H>
+#include <FL/fl_draw.H>
+#include <FL/x.H>
+#include <stdio.h>
+#include "flstring.h"
+
+static int ncolors, chars_per_pixel;
+
+int fl_measure_pixmap(/*const*/ char* const* data, int &w, int &h) {
+ return fl_measure_pixmap((const char*const*)data,w,h);
+}
+
+int fl_measure_pixmap(const char * const *data, int &w, int &h) {
+ int i = sscanf(data[0],"%d%d%d%d",&w,&h,&ncolors,&chars_per_pixel);
+ if (i<4 || w<=0 || h<=0 ||
+ chars_per_pixel!=1 && chars_per_pixel!=2) return w=0;
+ return 1;
+}
+
+#ifdef U64
+
+// The callback from fl_draw_image to get a row of data passes this:
+struct pixmap_data {
+ int w, h;
+ const uchar*const* data;
+ union {
+ U64 colors[256];
+ U64* byte1[256];
+ };
+};
+
+// callback for 1 byte per pixel:
+static void cb1(void*v, int x, int y, int w, uchar* buf) {
+ pixmap_data& d = *(pixmap_data*)v;
+ const uchar* p = d.data[y]+x;
+ U64* q = (U64*)buf;
+ for (int X=w; X>0; X-=2, p += 2) {
+ if (X>1) {
+# if WORDS_BIGENDIAN
+ *q++ = (d.colors[p[0]]<<32) | d.colors[p[1]];
+# else
+ *q++ = (d.colors[p[1]]<<32) | d.colors[p[0]];
+# endif
+ } else {
+# if WORDS_BIGENDIAN
+ *q++ = d.colors[p[0]]<<32;
+# else
+ *q++ = d.colors[p[0]];
+# endif
+ }
+ }
+}
+
+// callback for 2 bytes per pixel:
+static void cb2(void*v, int x, int y, int w, uchar* buf) {
+ pixmap_data& d = *(pixmap_data*)v;
+ const uchar* p = d.data[y]+2*x;
+ U64* q = (U64*)buf;
+ for (int X=w; X>0; X-=2) {
+ U64* colors = d.byte1[*p++];
+ int index = *p++;
+ if (X>1) {
+ U64* colors1 = d.byte1[*p++];
+ int index1 = *p++;
+# if WORDS_BIGENDIAN
+ *q++ = (colors[index]<<32) | colors1[index1];
+# else
+ *q++ = (colors1[index1]<<32) | colors[index];
+# endif
+ } else {
+# if WORDS_BIGENDIAN
+ *q++ = colors[index]<<32;
+# else
+ *q++ = colors[index];
+# endif
+ }
+ }
+}
+
+#else // U32
+
+// The callback from fl_draw_image to get a row of data passes this:
+struct pixmap_data {
+ int w, h;
+ const uchar*const* data;
+ union {
+ U32 colors[256];
+ U32* byte1[256];
+ };
+};
+
+# ifndef __APPLE_QUARTZ__
+
+// callback for 1 byte per pixel:
+static void cb1(void*v, int x, int y, int w, uchar* buf) {
+ pixmap_data& d = *(pixmap_data*)v;
+ const uchar* p = d.data[y]+x;
+ U32* q = (U32*)buf;
+ for (int X=w; X--;) *q++ = d.colors[*p++];
+}
+
+// callback for 2 bytes per pixel:
+static void cb2(void*v, int x, int y, int w, uchar* buf) {
+ pixmap_data& d = *(pixmap_data*)v;
+ const uchar* p = d.data[y]+2*x;
+ U32* q = (U32*)buf;
+ for (int X=w; X--;) {
+ U32* colors = d.byte1[*p++];
+ *q++ = colors[*p++];
+ }
+}
+
+# endif // !__APPLE_QUARTZ__
+
+#endif // U64 else U32
+
+uchar **fl_mask_bitmap; // if non-zero, create bitmap and store pointer here
+
+int fl_draw_pixmap(/*const*/ char* const* data, int x,int y,Fl_Color bg) {
+ return fl_draw_pixmap((const char*const*)data,x,y,bg);
+}
+
+int fl_draw_pixmap(const char*const* di, int x, int y, Fl_Color bg) {
+ pixmap_data d;
+ if (!fl_measure_pixmap(di, d.w, d.h)) return 0;
+ const uchar*const* data = (const uchar*const*)(di+1);
+ int transparent_index = -1;
+
+ if (ncolors < 0) { // FLTK (non standard) compressed colormap
+ ncolors = -ncolors;
+ const uchar *p = *data++;
+ // if first color is ' ' it is transparent (put it later to make
+ // it not be transparent):
+ if (*p == ' ') {
+ uchar* c = (uchar*)&d.colors[(int)' '];
+#ifdef U64
+ *(U64*)c = 0;
+# if WORDS_BIGENDIAN
+ c += 4;
+# endif
+#endif
+ transparent_index = ' ';
+ Fl::get_color(bg, c[0], c[1], c[2]); c[3] = 0;
+ p += 4;
+ ncolors--;
+ }
+ // read all the rest of the colors:
+ for (int i=0; i < ncolors; i++) {
+ uchar* c = (uchar*)&d.colors[*p++];
+#ifdef U64
+ *(U64*)c = 0;
+# if WORDS_BIGENDIAN
+ c += 4;
+# endif
+#endif
+ *c++ = *p++;
+ *c++ = *p++;
+ *c++ = *p++;
+#ifdef __APPLE_QUARTZ__
+ *c = 255;
+#else
+ *c = 0;
+#endif
+ }
+ } else { // normal XPM colormap with names
+ if (chars_per_pixel>1) memset(d.byte1, 0, sizeof(d.byte1));
+ for (int i=0; i<ncolors; i++) {
+ const uchar *p = *data++;
+ // the first 1 or 2 characters are the color index:
+ int ind = *p++;
+ uchar* c;
+ if (chars_per_pixel>1) {
+#ifdef U64
+ U64* colors = d.byte1[ind];
+ if (!colors) colors = d.byte1[ind] = new U64[256];
+#else
+ U32* colors = d.byte1[ind];
+ if (!colors) colors = d.byte1[ind] = new U32[256];
+#endif
+ c = (uchar*)&colors[*p];
+ ind = (ind<<8)|*p++;
+ } else {
+ c = (uchar *)&d.colors[ind];
+ }
+ // look for "c word", or last word if none:
+ const uchar *previous_word = p;
+ for (;;) {
+ while (*p && isspace(*p)) p++;
+ uchar what = *p++;
+ while (*p && !isspace(*p)) p++;
+ while (*p && isspace(*p)) p++;
+ if (!*p) {p = previous_word; break;}
+ if (what == 'c') break;
+ previous_word = p;
+ while (*p && !isspace(*p)) p++;
+ }
+#ifdef U64
+ *(U64*)c = 0;
+# if WORDS_BIGENDIAN
+ c += 4;
+# endif
+#endif
+#ifdef __APPLE_QUARTZ__
+ c[3] = 255;
+#endif
+ if (!fl_parse_color((const char*)p, c[0], c[1], c[2])) {
+ // assume "None" or "#transparent" for any errors
+ // "bg" should be transparent...
+ Fl::get_color(bg, c[0], c[1], c[2]);
+#ifdef __APPLE_QUARTZ__
+ c[3] = 0;
+#endif
+ transparent_index = ind;
+ }
+ }
+ }
+ d.data = data;
+
+#ifndef __APPLE_QUARTZ__
+
+ // build the mask bitmap used by Fl_Pixmap:
+ if (fl_mask_bitmap && transparent_index >= 0) {
+ int W = (d.w+7)/8;
+ uchar* bitmap = new uchar[W * d.h];
+ *fl_mask_bitmap = bitmap;
+ for (int Y = 0; Y < d.h; Y++) {
+ const uchar* p = data[Y];
+ if (chars_per_pixel <= 1) {
+ int dw = d.w;
+ for (int X = 0; X < W; X++) {
+ uchar b = (dw-->0 && *p++ != transparent_index);
+ if (dw-->0 && *p++ != transparent_index) b |= 2;
+ if (dw-->0 && *p++ != transparent_index) b |= 4;
+ if (dw-->0 && *p++ != transparent_index) b |= 8;
+ if (dw-->0 && *p++ != transparent_index) b |= 16;
+ if (dw-->0 && *p++ != transparent_index) b |= 32;
+ if (dw-->0 && *p++ != transparent_index) b |= 64;
+ if (dw-->0 && *p++ != transparent_index) b |= 128;
+ *bitmap++ = b;
+ }
+ } else {
+ uchar b = 0, bit = 1;
+ for (int X = 0; X < d.w; X++) {
+ int ind = *p++;
+ ind = (ind<<8) | (*p++);
+ if (ind != transparent_index) b |= bit;
+
+ if (bit < 128) bit <<= 1;
+ else {
+ *bitmap++ = b;
+ b = 0;
+ bit = 1;
+ }
+ }
+
+ if (bit > 1) *bitmap++ = b;
+ }
+ }
+ }
+
+ fl_draw_image(chars_per_pixel==1 ? cb1 : cb2, &d, x, y, d.w, d.h, 4);
+
+#else // __APPLE_QUARTZ__
+
+ bool transparent = (transparent_index>=0);
+ transparent = true;
+ U32 *array = new U32[d.w * d.h], *q = array;
+ for (int Y = 0; Y < d.h; Y++) {
+ const uchar* p = data[Y];
+ if (chars_per_pixel <= 1) {
+ for (int X = 0; X < d.w; X++) {
+ *q++ = d.colors[*p++];
+ }
+ } else {
+ for (int X = 0; X < d.w; X++) {
+ U32* colors = d.byte1[*p++];
+ *q++ = colors[*p++];
+ }
+ }
+ }
+ CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB();
+ CGDataProviderRef src = CGDataProviderCreateWithData( 0L, array, d.w * d.h * 4, 0L);
+ CGImageRef img = CGImageCreate(d.w, d.h, 8, 4*8, 4*d.w,
+ lut, transparent?kCGImageAlphaLast:kCGImageAlphaNoneSkipLast,
+ src, 0L, false, kCGRenderingIntentDefault);
+ CGColorSpaceRelease(lut);
+ CGDataProviderRelease(src);
+ CGRect rect = { { x, y} , { d.w, d.h } };
+ Fl_X::q_begin_image(rect, 0, 0, d.w, d.h);
+ CGContextDrawImage(fl_gc, rect, img);
+ Fl_X::q_end_image();
+ CGImageRelease(img);
+ delete array;
+
+#endif // !__APPLE_QUARTZ__
+
+ if (chars_per_pixel > 1) for (int i = 0; i < 256; i++) delete[] d.byte1[i];
+ return 1;
+}
+
+//
+// End of "$Id: fl_draw_pixmap.cxx 6026 2008-02-14 18:17:06Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_encoding_latin1.cxx b/third_party/windows/fltk-1.1.10/src/fl_encoding_latin1.cxx new file mode 100644 index 0000000..a3ef041 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_encoding_latin1.cxx @@ -0,0 +1,137 @@ +//
+// "$Id: fl_encoding_latin1.cxx 6922 2009-10-29 20:00:12Z matt $"
+//
+// Convert MSWindows-1252 (Latin-1) encoded text to the local encoding.
+//
+// Copyright 1998-2006 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_draw.H>
+#include <FL/Enumerations.H>
+#include <stdlib.h>
+#include "flstring.h"
+
+#ifdef __APPLE__
+
+// These function assume a western code page. If you need to support
+// scripts that are not part of this code page, you might want to
+// take a look at FLTK2, which uses utf8 for text encoding.
+//
+// By keeping these conversion tables in their own module, they will not
+// be statically linked (by a smart linker) unless actually used.
+//
+// On MS-Windows, nothing need to be converted. We simply return the
+// original pointer.
+//
+// Most X11 implementations seem to default to Latin-1 as a code since it
+// is a superset of ISO 8859-1, the original wetsern codepage on X11.
+//
+// Apple's OS X however renders text in MacRoman for western settings. The
+// lookup tables below will convert all common character codes and replace
+// unknown characters with an upsidedown question mark.
+
+// This table converts MSWindows-1252/Latin 1 into MacRoman encoding
+static uchar latin2roman[128] = {
+0xdb, 0xc0, 0xe2, 0xc4, 0xe3, 0xc9, 0xa0, 0xe0, 0xf6, 0xe4, 0xc0, 0xdc, 0xce, 0xc0, 0xc0, 0xc0,
+0xc0, 0xd4, 0xd5, 0xd2, 0xd3, 0xa5, 0xd0, 0xd1, 0xf7, 0xaa, 0xc0, 0xdd, 0xcf, 0xc0, 0xc0, 0xd9,
+0xca, 0xc1, 0xa2, 0xa3, 0xc0, 0xb4, 0xc0, 0xa4, 0xac, 0xa9, 0xbb, 0xc7, 0xc2, 0xc0, 0xa8, 0xf8,
+0xa1, 0xb1, 0xc0, 0xc0, 0xab, 0xb5, 0xa6, 0xe1, 0xfc, 0xc0, 0xbc, 0xc8, 0xc0, 0xc0, 0xc0, 0xc0,
+0xcb, 0xe7, 0xe5, 0xcc, 0x80, 0x81, 0xae, 0x82, 0xe9, 0x83, 0xe6, 0xe8, 0xed, 0xea, 0xeb, 0xec,
+0xc0, 0x84, 0xf1, 0xee, 0xef, 0xcd, 0x85, 0xc0, 0xaf, 0xf4, 0xf2, 0xf3, 0x86, 0xc0, 0xc0, 0xa7,
+0x88, 0x87, 0x89, 0x8b, 0x8a, 0x8c, 0xbe, 0x8d, 0x8f, 0x8e, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95,
+0xc0, 0x96, 0x98, 0x97, 0x99, 0x9b, 0x9a, 0xd6, 0xbf, 0x9d, 0x9c, 0x9e, 0x9f, 0xc0, 0xc0, 0xd8
+};
+
+// This table converts MacRoman into MSWindows-1252/Latin 1
+static uchar roman2latin[128] = {
+0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1, 0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8,
+0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3, 0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc,
+0x86, 0xb0, 0xa2, 0xa3, 0xa7, 0x95, 0xb6, 0xdf, 0xae, 0xa9, 0x99, 0xb4, 0xa8, 0xbf, 0xc6, 0xd8,
+0xbf, 0xb1, 0xbf, 0xbf, 0xa5, 0xb5, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xaa, 0xba, 0xbf, 0xe6, 0xf8,
+0xbf, 0xa1, 0xac, 0xbf, 0x83, 0xbf, 0xbf, 0xab, 0xbb, 0x85, 0xa0, 0xc0, 0xc3, 0xd5, 0x8c, 0x9c,
+0x96, 0x97, 0x93, 0x94, 0x91, 0x92, 0xf7, 0xbf, 0xff, 0x9f, 0xbf, 0x80, 0x8b, 0x9b, 0xbf, 0xbf,
+0x87, 0xb7, 0x82, 0x84, 0x89, 0xc2, 0xca, 0xc1, 0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4,
+0xbf, 0xd2, 0xda, 0xdb, 0xd9, 0xbf, 0x88, 0x98, 0xaf, 0xbf, 0xbf, 0xbf, 0xb8, 0xbf, 0xbf, 0xbf
+};
+
+static char *buf = 0;
+static int n_buf = 0;
+
+const char *fl_latin1_to_local(const char *t, int n)
+{
+ if (n==-1) n = strlen(t)+1;
+ if (n>=n_buf) {
+ n_buf = (n + 257) & 0x7fffff00;
+ if (buf) free(buf);
+ buf = (char*)malloc(n_buf);
+ }
+ const uchar *src = (const uchar*)t;
+ uchar *dst = (uchar*)buf;
+ for ( ; n>0; n--) {
+ uchar c = *src++;
+ if (c>127)
+ *dst++ = latin2roman[c-128];
+ else
+ *dst++ = c;
+ }
+ //*dst = 0; // this would be wrong!
+ return buf;
+}
+
+const char *fl_local_to_latin1(const char *t, int n)
+{
+ if (n==-1) n = strlen(t)+1;
+ if (n>=n_buf) {
+ n_buf = (n + 257) & 0x7fffff00;
+ if (buf) free(buf);
+ buf = (char*)malloc(n_buf);
+ }
+ const uchar *src = (const uchar*)t;
+ uchar *dst = (uchar*)buf;
+ for ( ; n>0; n--) {
+ uchar c = *src++;
+ if (c>127)
+ *dst++ = roman2latin[c-128];
+ else
+ *dst++ = c;
+ }
+ //*dst = 0; // this would be wrong
+ return buf;
+}
+
+#else
+
+const char *fl_latin1_to_local(const char *t, int)
+{
+ return t;
+}
+
+const char *fl_local_to_latin1(const char *t, int)
+{
+ return t;
+}
+
+#endif
+
+//
+// End of "$Id: fl_encoding_latin1.cxx 6922 2009-10-29 20:00:12Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_encoding_mac_roman.cxx b/third_party/windows/fltk-1.1.10/src/fl_encoding_mac_roman.cxx new file mode 100644 index 0000000..838a8b0 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_encoding_mac_roman.cxx @@ -0,0 +1,134 @@ +//
+// "$Id: fl_encoding_mac_roman.cxx 6922 2009-10-29 20:00:12Z matt $"
+//
+// Convert Mac Roman encoded text to the local encoding.
+//
+// Copyright 1998-2006 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_draw.H>
+#include <FL/Enumerations.H>
+#include <stdlib.h>
+#include "flstring.h"
+
+// These function assume a western code page. If you need to support
+// scripts that are not part of this code page, you might want to
+// take a look at FLTK2, which uses utf8 for text encoding.
+//
+// By keeping these conversion tables in their own module, they will not
+// be statically linked (by a smart linker) unless actually used.
+//
+// On Mac OS X, nothing need to be converted. We simply return the
+// original pointer.
+//
+// MSWindows and X11 render text in ISO or Latin-1 for western settings. The
+// lookup tables below will convert all common character codes and replace
+// unknown characters with an upsidedown question mark.
+
+#ifdef __APPLE__
+
+const char *fl_mac_roman_to_local(const char *t, int)
+{
+ return t;
+}
+
+const char *fl_local_to_mac_roman(const char *t, int)
+{
+ return t;
+}
+
+#else
+
+// This table converts MSWindows-1252/Latin 1 into MacRoman encoding
+static uchar latin2roman[128] = {
+0xdb, 0xc0, 0xe2, 0xc4, 0xe3, 0xc9, 0xa0, 0xe0, 0xf6, 0xe4, 0xc0, 0xdc, 0xce, 0xc0, 0xc0, 0xc0,
+0xc0, 0xd4, 0xd5, 0xd2, 0xd3, 0xa5, 0xd0, 0xd1, 0xf7, 0xaa, 0xc0, 0xdd, 0xcf, 0xc0, 0xc0, 0xd9,
+0xca, 0xc1, 0xa2, 0xa3, 0xc0, 0xb4, 0xc0, 0xa4, 0xac, 0xa9, 0xbb, 0xc7, 0xc2, 0xc0, 0xa8, 0xf8,
+0xa1, 0xb1, 0xc0, 0xc0, 0xab, 0xb5, 0xa6, 0xe1, 0xfc, 0xc0, 0xbc, 0xc8, 0xc0, 0xc0, 0xc0, 0xc0,
+0xcb, 0xe7, 0xe5, 0xcc, 0x80, 0x81, 0xae, 0x82, 0xe9, 0x83, 0xe6, 0xe8, 0xed, 0xea, 0xeb, 0xec,
+0xc0, 0x84, 0xf1, 0xee, 0xef, 0xcd, 0x85, 0xc0, 0xaf, 0xf4, 0xf2, 0xf3, 0x86, 0xc0, 0xc0, 0xa7,
+0x88, 0x87, 0x89, 0x8b, 0x8a, 0x8c, 0xbe, 0x8d, 0x8f, 0x8e, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95,
+0xc0, 0x96, 0x98, 0x97, 0x99, 0x9b, 0x9a, 0xd6, 0xbf, 0x9d, 0x9c, 0x9e, 0x9f, 0xc0, 0xc0, 0xd8
+};
+
+// This table converts MacRoman into MSWindows-1252/Latin 1
+static uchar roman2latin[128] = {
+0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1, 0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8,
+0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3, 0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc,
+0x86, 0xb0, 0xa2, 0xa3, 0xa7, 0x95, 0xb6, 0xdf, 0xae, 0xa9, 0x99, 0xb4, 0xa8, 0xbf, 0xc6, 0xd8,
+0xbf, 0xb1, 0xbf, 0xbf, 0xa5, 0xb5, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xaa, 0xba, 0xbf, 0xe6, 0xf8,
+0xbf, 0xa1, 0xac, 0xbf, 0x83, 0xbf, 0xbf, 0xab, 0xbb, 0x85, 0xa0, 0xc0, 0xc3, 0xd5, 0x8c, 0x9c,
+0x96, 0x97, 0x93, 0x94, 0x91, 0x92, 0xf7, 0xbf, 0xff, 0x9f, 0xbf, 0x80, 0x8b, 0x9b, 0xbf, 0xbf,
+0x87, 0xb7, 0x82, 0x84, 0x89, 0xc2, 0xca, 0xc1, 0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4,
+0xbf, 0xd2, 0xda, 0xdb, 0xd9, 0xbf, 0x88, 0x98, 0xaf, 0xbf, 0xbf, 0xbf, 0xb8, 0xbf, 0xbf, 0xbf
+};
+
+static char *buf = 0;
+static int n_buf = 0;
+
+const char *fl_local_to_mac_roman(const char *t, int n)
+{
+ if (n==-1) n = strlen(t)+1;
+ if (n>=n_buf) {
+ n_buf = (n + 257) & 0x7fffff00;
+ if (buf) free(buf);
+ buf = (char*)malloc(n_buf);
+ }
+ const uchar *src = (const uchar*)t;
+ uchar *dst = (uchar*)buf;
+ for ( ; n>0; n--) {
+ uchar c = *src;
+ if (c>127)
+ *dst++ = latin2roman[c-128];
+ else
+ *dst++ = c;
+ }
+ //*dst = 0; // this would be wrong!
+ return buf;
+}
+
+const char *fl_mac_roman_to_local(const char *t, int n)
+{
+ if (n==-1) n = strlen(t)+1;
+ if (n>=n_buf) {
+ n_buf = (n + 257) & 0x7fffff00;
+ if (buf) free(buf);
+ buf = (char*)malloc(n_buf);
+ }
+ const uchar *src = (const uchar*)t;
+ uchar *dst = (uchar*)buf;
+ for ( ; n>0; n--) {
+ uchar c = *src++;
+ if (c>127)
+ *dst++ = roman2latin[c-128];
+ else
+ *dst++ = c;
+ }
+ //*dst = 0; // this would be wrong
+ return buf;
+}
+
+#endif
+
+//
+// End of "$Id: fl_encoding_mac_roman.cxx 6922 2009-10-29 20:00:12Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_engraved_label.cxx b/third_party/windows/fltk-1.1.10/src/fl_engraved_label.cxx new file mode 100644 index 0000000..f882265 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_engraved_label.cxx @@ -0,0 +1,93 @@ +//
+// "$Id: fl_engraved_label.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Engraved label drawing routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Drawing code for XForms style engraved & embossed labels
+
+#include <FL/Fl.H>
+#include <FL/Fl_Widget.H>
+#include <FL/fl_draw.H>
+
+// data[] is dx, dy, color triples
+
+static void innards(
+ const Fl_Label* o, int X, int Y, int W, int H, Fl_Align align,
+ int data[][3], int n)
+{
+ Fl_Align a1 = align;
+ if (a1 & FL_ALIGN_CLIP) {
+ fl_clip(X, Y, W, H); a1 = (Fl_Align)(a1&~FL_ALIGN_CLIP);}
+ fl_font((Fl_Font)o->font, o->size);
+ for (int i = 0; i < n; i++) {
+ fl_color((Fl_Color)(i < n-1 ? data[i][2] : o->color));
+ fl_draw(o->value, X+data[i][0], Y+data[i][1], W, H, a1);
+ }
+ if (align & FL_ALIGN_CLIP) fl_pop_clip();
+}
+
+static void fl_shadow_label(
+ const Fl_Label* o, int X, int Y, int W, int H, Fl_Align align)
+{
+ static int data[2][3] = {{2,2,FL_DARK3},{0,0,0}};
+ innards(o, X, Y, W, H, align, data, 2);
+}
+
+static void fl_engraved_label(
+ const Fl_Label* o, int X, int Y, int W, int H, Fl_Align align)
+{
+ static int data[7][3] = {
+ {1,0,FL_LIGHT3},{1,1,FL_LIGHT3},{0,1,FL_LIGHT3},
+ {-1,0,FL_DARK3},{-1,-1,FL_DARK3},{0,-1,FL_DARK3},
+ {0,0,0}};
+ innards(o, X, Y, W, H, align, data, 7);
+}
+
+static void fl_embossed_label(
+ const Fl_Label* o, int X, int Y, int W, int H, Fl_Align align)
+{
+ static int data[7][3] = {
+ {-1,0,FL_LIGHT3},{-1,-1,FL_LIGHT3},{0,-1,FL_LIGHT3},
+ {1,0,FL_DARK3},{1,1,FL_DARK3},{0,1,FL_DARK3},
+ {0,0,0}};
+ innards(o, X, Y, W, H, align, data, 7);
+}
+
+Fl_Labeltype fl_define_FL_SHADOW_LABEL() {
+ Fl::set_labeltype(_FL_SHADOW_LABEL, fl_shadow_label, 0);
+ return _FL_SHADOW_LABEL;
+}
+Fl_Labeltype fl_define_FL_ENGRAVED_LABEL() {
+ Fl::set_labeltype(_FL_ENGRAVED_LABEL, fl_engraved_label, 0);
+ return _FL_ENGRAVED_LABEL;
+}
+Fl_Labeltype fl_define_FL_EMBOSSED_LABEL() {
+ Fl::set_labeltype(_FL_EMBOSSED_LABEL, fl_embossed_label, 0);
+ return _FL_EMBOSSED_LABEL;
+}
+
+//
+// End of "$Id: fl_engraved_label.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_file_dir.cxx b/third_party/windows/fltk-1.1.10/src/fl_file_dir.cxx new file mode 100644 index 0000000..f38c2dc --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_file_dir.cxx @@ -0,0 +1,178 @@ +//
+// "$Id: fl_file_dir.cxx 5417 2006-09-05 09:57:41Z matt $"
+//
+// File chooser widget for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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 "flstring.h"
+#include <FL/filename.H>
+#include <FL/Fl_File_Chooser.H>
+#include <FL/fl_ask.H>
+
+
+static Fl_File_Chooser *fc = (Fl_File_Chooser *)0;
+static void (*current_callback)(const char*) = 0;
+static const char *current_label = fl_ok;
+
+
+// Do a file chooser callback...
+static void callback(Fl_File_Chooser *, void*) {
+ if (current_callback && fc->value())
+ (*current_callback)(fc->value());
+}
+
+
+// Set the file chooser callback
+void fl_file_chooser_callback(void (*cb)(const char*)) {
+ current_callback = cb;
+}
+
+
+// Set the "OK" button label
+void fl_file_chooser_ok_label(const char *l) {
+ if (l) current_label = l;
+ else current_label = fl_ok;
+}
+
+
+//
+// 'fl_file_chooser()' - Show a file chooser dialog and get a filename.
+//
+
+char * // O - Filename or NULL
+fl_file_chooser(const char *message, // I - Message in titlebar
+ const char *pat, // I - Filename pattern
+ const char *fname, // I - Initial filename selection
+ int relative) { // I - 0 for absolute path
+ static char retname[1024]; // Returned filename
+
+ if (!fc) {
+ if (!fname || !*fname) fname = ".";
+
+ fc = new Fl_File_Chooser(fname, pat, Fl_File_Chooser::CREATE, message);
+ fc->callback(callback, 0);
+ } else {
+ fc->type(Fl_File_Chooser::CREATE);
+ // see, if we use the same pattern between calls
+ char same_pattern = 0;
+ const char *fcf = fc->filter();
+ if ( fcf && pat && strcmp(fcf, pat)==0)
+ same_pattern = 1;
+ else if ( (fcf==0L || *fcf==0) && (pat==0L || *pat==0) )
+ same_pattern = 1;
+ // now set the pattern to the new pattern (even if they are the same)
+ fc->filter(pat);
+ fc->label(message);
+
+ if (!fname) { // null pointer reuses same filename if pattern didn't change
+ if (!same_pattern && fc->value()) {
+ // if pattern is different, remove name but leave old directory:
+ strlcpy(retname, fc->value(), sizeof(retname));
+
+ char *p = strrchr(retname, '/');
+
+ if (p) {
+ // If the filename is "/foo", then the directory will be "/", not
+ // ""...
+ if (p == retname)
+ retname[1] = '\0';
+ else
+ *p = '\0';
+ }
+ // Set the directory...
+ fc->value(retname);
+ } else {
+ // re-use the previously selected name
+ }
+ } else if (!*fname) { // empty filename reuses directory with empty name
+ const char *fcv = fc->value();
+ if (fcv)
+ strlcpy(retname, fc->value(), sizeof(retname));
+ else
+ *retname = 0;
+ const char *n = fl_filename_name(retname);
+ if (n) *((char*)n) = 0;
+ fc->value("");
+ fc->directory(retname);
+ } else {
+ fc->value(fname);
+ }
+ }
+
+ fc->ok_label(current_label);
+ fc->show();
+
+ while (fc->shown())
+ Fl::wait();
+
+ if (fc->value() && relative) {
+ fl_filename_relative(retname, sizeof(retname), fc->value());
+
+ return retname;
+ } else if (fc->value()) return (char *)fc->value();
+ else return 0;
+}
+
+
+//
+// 'fl_dir_chooser()' - Show a file chooser dialog and get a directory.
+//
+
+char * // O - Directory or NULL
+fl_dir_chooser(const char *message, // I - Message for titlebar
+ const char *fname, // I - Initial directory name
+ int relative) // I - 0 for absolute
+{
+ static char retname[1024]; // Returned directory name
+
+ if (!fc) {
+ if (!fname || !*fname) fname = ".";
+
+ fc = new Fl_File_Chooser(fname, "*", Fl_File_Chooser::CREATE |
+ Fl_File_Chooser::DIRECTORY, message);
+ fc->callback(callback, 0);
+ } else {
+ fc->type(Fl_File_Chooser::CREATE | Fl_File_Chooser::DIRECTORY);
+ fc->filter("*");
+ if (fname && *fname) fc->value(fname);
+ fc->label(message);
+ }
+
+ fc->show();
+
+ while (fc->shown())
+ Fl::wait();
+
+ if (fc->value() && relative) {
+ fl_filename_relative(retname, sizeof(retname), fc->value());
+
+ return retname;
+ } else if (fc->value()) return (char *)fc->value();
+ else return 0;
+}
+
+
+//
+// End of "$Id: fl_file_dir.cxx 5417 2006-09-05 09:57:41Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_font.cxx b/third_party/windows/fltk-1.1.10/src/fl_font.cxx new file mode 100644 index 0000000..fa35c02 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_font.cxx @@ -0,0 +1,60 @@ +//
+// "$Id: fl_font.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Font selection code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Select fonts from the FLTK font table.
+#include "flstring.h"
+#include <FL/Fl.H>
+#include <FL/fl_draw.H>
+#include <FL/x.H>
+#include "Fl_Font.H"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef WIN32
+# include "fl_font_win32.cxx"
+#elif defined(__APPLE__)
+# include "fl_font_mac.cxx"
+#elif USE_XFT
+# include "fl_font_xft.cxx"
+#else
+# include "fl_font_x.cxx"
+#endif // WIN32
+
+
+double fl_width(const char* c) {
+ if (c) return fl_width(c, strlen(c));
+ else return 0.0f;
+}
+
+void fl_draw(const char* str, int x, int y) {
+ fl_draw(str, strlen(str), x, y);
+}
+
+//
+// End of "$Id: fl_font.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_font_mac.cxx b/third_party/windows/fltk-1.1.10/src/fl_font_mac.cxx new file mode 100644 index 0000000..4b7d081 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_font_mac.cxx @@ -0,0 +1,379 @@ +//
+// "$Id: fl_font_mac.cxx 5651 2007-02-01 20:13:57Z matt $"
+//
+// MacOS font selection routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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 <config.h>
+
+Fl_FontSize::Fl_FontSize(const char* name, int Size) {
+ next = 0;
+# if HAVE_GL
+ listbase = 0;
+# endif
+#ifdef __APPLE_QD__
+ knowMetrics = 0;
+ switch (*name++) {
+ case 'I': face = italic; break;
+ case 'P': face = italic | bold; break;
+ case 'B': face = bold; break;
+ default: face = 0; break;
+ }
+ unsigned char fn[80];
+ fn[0] = strlen(name); strcpy((char*)(fn+1), name);
+ GetFNum(fn, &font);
+ size = Size;
+ FMInput fIn = { font, size, face, 0, 0, { 1, 1}, { 1, 1} };
+ FMOutput *fOut = FMSwapFont(&fIn);
+ ascent = fOut->ascent; //: the following three lines give only temporary aproimations
+ descent = fOut->descent;
+ for (int i=0; i<256; i++) width[i] = fOut->widMax;
+ minsize = maxsize = size;
+#elif defined(__APPLE_QUARTZ__)
+ knowWidths = 0;
+ // OpenGL needs those for its font handling
+ q_name = strdup(name);
+ size = Size;
+ OSStatus err;
+ // fill our structure with a few default values
+ ascent = Size*3/4;
+ descent = Size-ascent;
+ q_width = Size*2/3;
+ minsize = maxsize = Size;
+ // now use ATS to get the actual Glyph size information
+ CFStringRef cfname = CFStringCreateWithCString(0L, name, kCFStringEncodingASCII);
+ ATSFontRef font = ATSFontFindFromName(cfname, kATSOptionFlagsDefault);
+ if (font) {
+ ATSFontMetrics m = { 0 };
+ ATSFontGetHorizontalMetrics(font, kATSOptionFlagsDefault, &m);
+ if (m.avgAdvanceWidth) q_width = int(m.avgAdvanceWidth*Size);
+ // playing with the offsets a little to make standard sizes fit
+ if (m.ascent) ascent = int(m.ascent*Size-0.5f);
+ if (m.descent) descent = -int(m.descent*Size-1.5f);
+ }
+ CFRelease(cfname);
+ // now we allocate everything needed to render text in this font later
+ // get us the default layout and style
+ err = ATSUCreateTextLayout(&layout);
+ UniChar mTxt[2] = { 65, 0 };
+ err = ATSUSetTextPointerLocation(layout, mTxt, kATSUFromTextBeginning, 1, 1);
+ err = ATSUCreateStyle(&style);
+ err = ATSUSetRunStyle(layout, style, kATSUFromTextBeginning, kATSUToTextEnd);
+ // now set the actual font, size and attributes. We also set the font matrix to
+ // render our font up-side-down, so when rendered through our inverted CGContext,
+ // text will appear normal again.
+ Fixed fsize = IntToFixed(Size);
+ ATSUFontID fontID = FMGetFontFromATSFontRef(font);
+ static CGAffineTransform font_mx = { 1, 0, 0, -1, 0, 0 };
+ ATSUAttributeTag sTag[] = { kATSUFontTag, kATSUSizeTag, kATSUFontMatrixTag };
+ ByteCount sBytes[] = { sizeof(ATSUFontID), sizeof(Fixed), sizeof(CGAffineTransform) };
+ ATSUAttributeValuePtr sAttr[] = { &fontID, &fsize, &font_mx };
+ err = ATSUSetAttributes(style, 3, sTag, sBytes, sAttr);
+ // next, make sure that Quartz will only render at integer coordinates
+ ATSLineLayoutOptions llo = kATSLineUseDeviceMetrics|kATSLineDisableAllLayoutOperations;
+ ATSUAttributeTag aTag[] = { kATSULineLayoutOptionsTag };
+ ByteCount aBytes[] = { sizeof(ATSLineLayoutOptions) };
+ ATSUAttributeValuePtr aAttr[] = { &llo };
+ err = ATSUSetLineControls (layout, kATSUFromTextBeginning, 1, aTag, aBytes, aAttr);
+ // now we are finally ready to measure some letter to get the bounding box
+ Fixed bBefore, bAfter, bAscent, bDescent;
+ err = ATSUGetUnjustifiedBounds(layout, kATSUFromTextBeginning, 1, &bBefore, &bAfter, &bAscent, &bDescent);
+ // Requesting a certain height font on Mac does not guarantee that ascent+descent
+ // equal the requested height. fl_height will reflect the actual height that we got.
+ // The font "Apple Chancery" is a pretty extreme example of overlapping letters.
+ float fa = -FixedToFloat(bAscent), fd = -FixedToFloat(bDescent);
+ if (fa>0.0f && fd>0.0f) {
+ //float f = Size/(fa+fd);
+ ascent = fa; //int(fa*f+0.5f);
+ descent = fd; //Size - ascent;
+ }
+ int w = FixedToInt(bAfter);
+ if (w)
+ q_width = FixedToInt(bAfter);
+#endif
+}
+
+Fl_FontSize* fl_fontsize = 0L;
+
+Fl_FontSize::~Fl_FontSize() {
+/*
+#if HAVE_GL
+ // ++ todo: remove OpenGL font alocations
+// Delete list created by gl_draw(). This is not done by this code
+// as it will link in GL unnecessarily. There should be some kind
+// of "free" routine pointer, or a subclass?
+// if (listbase) {
+// int base = font->min_char_or_byte2;
+// int size = font->max_char_or_byte2-base+1;
+// int base = 0; int size = 256;
+// glDeleteLists(listbase+base,size);
+// }
+#endif
+ */
+ if (this == fl_fontsize) fl_fontsize = 0;
+#ifdef __APPLE_QUARTZ__
+ ATSUDisposeTextLayout(layout);
+ ATSUDisposeStyle(style);
+#endif
+}
+
+////////////////////////////////////////////////////////////////
+
+static Fl_Fontdesc built_in_table[] = {
+#ifdef __APPLE_QD__
+{" Arial"},
+{"BArial"},
+{"IArial"},
+{"PArial"},
+{" Courier New"},
+{"BCourier New"},
+{"ICourier New"},
+{"PCourier New"},
+{" Times New Roman"},
+{"BTimes New Roman"},
+{"ITimes New Roman"},
+{"PTimes New Roman"},
+{" Symbol"},
+{" Chicago"},
+{"BChicago"},
+{" Webdings"},
+#elif defined(__APPLE_QUARTZ__)
+{"Arial"},
+{"Arial Bold"},
+{"Arial Italic"},
+{"Arial Bold Italic"},
+{"Courier New"},
+{"Courier New Bold"},
+{"Courier New Italic"},
+{"Courier New Bold Italic"},
+{"Times New Roman"},
+{"Times New Roman Bold"},
+{"Times New Roman Italic"},
+{"Times New Roman Bold Italic"},
+{"Symbol"},
+{"Monaco"},
+{"Andale Mono"}, // there is no bold Monaco font on standard Mac
+{"Webdings"},
+#endif
+};
+
+#ifdef __APPLE_QUARTZ__
+static UniChar utf16lut[128] = {
+ 0x00c4, 0x00c5, 0x00c7, 0x00c9, 0x00d1, 0x00d6, 0x00dc, 0x00e1,
+ 0x00e0, 0x00e2, 0x00e4, 0x00e3, 0x00e5, 0x00e7, 0x00e9, 0x00e8,
+ 0x00ea, 0x00eb, 0x00ed, 0x00ec, 0x00ee, 0x00ef, 0x00f1, 0x00f3,
+ 0x00f2, 0x00f4, 0x00f6, 0x00f5, 0x00fa, 0x00f9, 0x00fb, 0x00fc,
+ 0x2020, 0x00b0, 0x00a2, 0x00a3, 0x00a7, 0x2022, 0x00b6, 0x00df,
+ 0x00ae, 0x00a9, 0x2122, 0x00b4, 0x00a8, 0x2260, 0x00c6, 0x00d8,
+ 0x221e, 0x00b1, 0x2264, 0x2265, 0x00a5, 0x00b5, 0x2202, 0x2211,
+ 0x220f, 0x03c0, 0x222b, 0x00aa, 0x00ba, 0x03a9, 0x00e6, 0x00f8,
+ 0x00bf, 0x00a1, 0x00ac, 0x221a, 0x0192, 0x2248, 0x2206, 0x00ab,
+ 0x00bb, 0x2026, 0x00a0, 0x00c0, 0x00c3, 0x00d5, 0x0152, 0x0153,
+ 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0x00f7, 0x25ca,
+ 0x00ff, 0x0178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02,
+ 0x2021, 0x00b7, 0x201a, 0x201e, 0x2030, 0x00c2, 0x00ca, 0x00c1,
+ 0x00cb, 0x00c8, 0x00cd, 0x00ce, 0x00cf, 0x00cc, 0x00d3, 0x00d4,
+ 0xf8ff, 0x00d2, 0x00da, 0x00db, 0x00d9, 0x0131, 0x02c6, 0x02dc,
+ 0x00af, 0x02d8, 0x02d9, 0x02da, 0x00b8, 0x02dd, 0x02db, 0x02c7,
+};
+static UniChar *utf16buf = 0;
+static int utf16len = 0;
+UniChar *fl_macToUtf16(const char *txt, int len)
+{
+ if ((len+1)>utf16len) {
+ utf16len = len+100;
+ free(utf16buf);
+ utf16buf = (UniChar*)malloc((utf16len+1)*sizeof(UniChar));
+ }
+ int i;
+ unsigned char c;
+ const unsigned char *src = (unsigned char const*)txt;
+ UniChar *dst = utf16buf;
+ for (i=0; i<len; i++) {
+ c = *src++;
+ *dst++ =(c<128) ? c : utf16lut[c-128];
+ }
+ *dst = 0;
+ return utf16buf;
+}
+#endif
+
+Fl_Fontdesc* fl_fonts = built_in_table;
+
+void fl_font(Fl_FontSize* s) {
+ fl_fontsize = s;
+#ifdef __APPLE_QD__
+ if (fl_window) SetPort( GetWindowPort(fl_window) );
+ TextFont(fl_fontsize->font); //: select font into current QuickDraw GC
+ TextFace(fl_fontsize->face);
+ TextSize(fl_fontsize->size);
+ if (!fl_fontsize->knowMetrics) { //: get the true metrics for the currnet GC
+ //: (fails on multiple monitors with different dpi's!)
+ FontInfo fi; GetFontInfo(&fi);
+ fl_fontsize->ascent = fi.ascent;
+ fl_fontsize->descent = fi.descent;
+ FMetricRec mr; FontMetrics(&mr);
+ short *f = (short*)*mr.wTabHandle; //: get the char size table
+ for (int i=0; i<256; i++) fl_fontsize->width[i] = f[2*i];
+ fl_fontsize->knowMetrics = 1;
+ }
+#elif defined(__APPLE_QUARTZ__)
+ // we will use fl_fontsize later to access the required style and layout
+#else
+# error : need to defined either Quartz or Quickdraw
+#endif
+}
+
+static Fl_FontSize* find(int fnum, int size) {
+ Fl_Fontdesc* s = fl_fonts+fnum;
+ if (!s->name) s = fl_fonts; // use 0 if fnum undefined
+ Fl_FontSize* f;
+ for (f = s->first; f; f = f->next)
+ if (f->minsize <= size && f->maxsize >= size) return f;
+ f = new Fl_FontSize(s->name, size);
+ f->next = s->first;
+ s->first = f;
+ return f;
+}
+
+////////////////////////////////////////////////////////////////
+// Public interface:
+
+int fl_font_ = 0;
+int fl_size_ = 0;
+
+void fl_font(int fnum, int size) {
+ if (fnum==-1) {
+ fl_font_ = 0;
+ fl_size_ = 0;
+ return;
+ }
+ fl_font_ = fnum;
+ fl_size_ = size;
+ fl_font(find(fnum, size));
+}
+
+int fl_height() {
+ if (fl_fontsize) return fl_fontsize->ascent+fl_fontsize->descent;
+ else return -1;
+}
+
+int fl_descent() {
+ if (fl_fontsize) return fl_fontsize->descent;
+ else return -1;
+}
+
+double fl_width(const char* txt, int n) {
+#ifdef __APPLE_QD__
+ return (double)TextWidth( txt, 0, n );
+#else
+ if (!fl_fontsize) {
+ fl_font(0, 12); // avoid a crash!
+ if (!fl_fontsize)
+ return 8*n; // user must select a font first!
+ }
+ if (!fl_fontsize->knowWidths) {
+ if (!fl_gc) {
+ Fl_Window *w = Fl::first_window();
+ if (w) w->make_current();
+ if (!fl_gc) {
+ if (fl_fontsize) return fl_fontsize->q_width*n;
+ return 8*n;
+ // We fall back to some internal QuickDraw port.
+ // The result should be the same.
+ }
+ }
+ char buf[2];
+ for (int i=0; i<256; i++) {
+ OSStatus err;
+ buf[0] = (char)i;
+ // convert to UTF-16 first
+ UniChar *uniStr = fl_macToUtf16(buf, 1);
+ // now collect our ATSU resources
+ ATSUTextLayout layout = fl_fontsize->layout;
+ // activate the current GC
+ ByteCount iSize = sizeof(CGContextRef);
+ ATSUAttributeTag iTag = kATSUCGContextTag;
+ ATSUAttributeValuePtr iValuePtr=&fl_gc;
+ ATSUSetLayoutControls(layout, 1, &iTag, &iSize, &iValuePtr);
+ // now measure the bounding box
+ err = ATSUSetTextPointerLocation(layout, uniStr, kATSUFromTextBeginning, 1, 1);
+ Fixed bBefore, bAfter, bAscent, bDescent;
+ err = ATSUGetUnjustifiedBounds(layout, kATSUFromTextBeginning, 1, &bBefore, &bAfter, &bAscent, &bDescent);
+ fl_fontsize->width[i] = FixedToInt(bAfter);
+ }
+ fl_fontsize->knowWidths = 1;
+ }
+ int len = 0;
+ const char *src = txt;
+ for (int j=0; j<n; j++) {
+ unsigned char c = *src++;
+ len += fl_fontsize->width[c];
+ }
+ return len;
+#endif
+}
+
+double fl_width(uchar c) {
+ return fl_width((const char*)(&c), 1);
+}
+
+void fl_draw(const char *str, int n, float x, float y);
+
+void fl_draw(const char* str, int n, int x, int y) {
+#ifdef __APPLE_QD__
+ MoveTo(x, y);
+ DrawText((const char *)str, 0, n);
+#elif defined(__APPLE_QUARTZ__)
+ fl_draw(str, n, (float)x-0.0f, (float)y-0.5f);
+#else
+# error : neither Quartz no Quickdraw chosen
+#endif
+}
+
+void fl_draw(const char *str, int n, float x, float y) {
+#ifdef __APPLE_QD__
+ fl_draw(str, n, (int)x, (int)y);
+#elif defined(__APPLE_QUARTZ__)
+ OSStatus err;
+ // convert to UTF-16 first
+ UniChar *uniStr = fl_macToUtf16(str, n);
+ // now collect our ATSU resources
+ ATSUTextLayout layout = fl_fontsize->layout;
+
+ ByteCount iSize = sizeof(CGContextRef);
+ ATSUAttributeTag iTag = kATSUCGContextTag;
+ ATSUAttributeValuePtr iValuePtr=&fl_gc;
+ ATSUSetLayoutControls(layout, 1, &iTag, &iSize, &iValuePtr);
+
+ err = ATSUSetTextPointerLocation(layout, uniStr, kATSUFromTextBeginning, n, n);
+ err = ATSUDrawText(layout, kATSUFromTextBeginning, n, FloatToFixed(x), FloatToFixed(y));
+#else
+# error : neither Quartz no Quickdraw chosen
+#endif
+}
+
+//
+// End of "$Id: fl_font_mac.cxx 5651 2007-02-01 20:13:57Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_font_win32.cxx b/third_party/windows/fltk-1.1.10/src/fl_font_win32.cxx new file mode 100644 index 0000000..cfa0bda --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_font_win32.cxx @@ -0,0 +1,173 @@ +//
+// "$Id: fl_font_win32.cxx 5420 2006-09-05 11:16:15Z matt $"
+//
+// WIN32 font selection routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+Fl_FontSize::Fl_FontSize(const char* name, int size) {
+ int weight = FW_NORMAL;
+ int italic = 0;
+ switch (*name++) {
+ case 'I': italic = 1; break;
+ case 'P': italic = 1;
+ case 'B': weight = FW_BOLD; break;
+ case ' ': break;
+ default: name--;
+ }
+ fid = CreateFont(
+ -size, // negative makes it use "char size"
+ 0, // logical average character width
+ 0, // angle of escapement
+ 0, // base-line orientation angle
+ weight,
+ italic,
+ FALSE, // underline attribute flag
+ FALSE, // strikeout attribute flag
+ DEFAULT_CHARSET, // character set identifier
+ OUT_DEFAULT_PRECIS, // output precision
+ CLIP_DEFAULT_PRECIS,// clipping precision
+ DEFAULT_QUALITY, // output quality
+ DEFAULT_PITCH, // pitch and family
+ name // pointer to typeface name string
+ );
+ if (!fl_gc) fl_GetDC(0);
+ SelectObject(fl_gc, fid);
+ GetTextMetrics(fl_gc, &metr);
+// BOOL ret = GetCharWidthFloat(fl_gc, metr.tmFirstChar, metr.tmLastChar, font->width+metr.tmFirstChar);
+// ...would be the right call, but is not implemented into Window95! (WinNT?)
+ GetCharWidth(fl_gc, 0, 255, width);
+#if HAVE_GL
+ listbase = 0;
+#endif
+ minsize = maxsize = size;
+}
+
+Fl_FontSize* fl_fontsize;
+
+Fl_FontSize::~Fl_FontSize() {
+#if HAVE_GL
+// Delete list created by gl_draw(). This is not done by this code
+// as it will link in GL unnecessarily. There should be some kind
+// of "free" routine pointer, or a subclass?
+// if (listbase) {
+// int base = font->min_char_or_byte2;
+// int size = font->max_char_or_byte2-base+1;
+// int base = 0; int size = 256;
+// glDeleteLists(listbase+base,size);
+// }
+#endif
+ if (this == fl_fontsize) fl_fontsize = 0;
+ DeleteObject(fid);
+}
+
+////////////////////////////////////////////////////////////////
+
+// WARNING: if you add to this table, you must redefine FL_FREE_FONT
+// in Enumerations.H & recompile!!
+static Fl_Fontdesc built_in_table[] = {
+{" Arial"},
+{"BArial"},
+{"IArial"},
+{"PArial"},
+{" Courier New"},
+{"BCourier New"},
+{"ICourier New"},
+{"PCourier New"},
+{" Times New Roman"},
+{"BTimes New Roman"},
+{"ITimes New Roman"},
+{"PTimes New Roman"},
+{" Symbol"},
+{" Terminal"},
+{"BTerminal"},
+{" Wingdings"},
+};
+
+Fl_Fontdesc* fl_fonts = built_in_table;
+
+static Fl_FontSize* find(int fnum, int size) {
+ Fl_Fontdesc* s = fl_fonts+fnum;
+ if (!s->name) s = fl_fonts; // use 0 if fnum undefined
+ Fl_FontSize* f;
+ for (f = s->first; f; f = f->next)
+ if (f->minsize <= size && f->maxsize >= size) return f;
+ f = new Fl_FontSize(s->name, size);
+ f->next = s->first;
+ s->first = f;
+ return f;
+}
+
+////////////////////////////////////////////////////////////////
+// Public interface:
+
+int fl_font_ = 0;
+int fl_size_ = 0;
+//static HDC font_gc;
+
+void fl_font(int fnum, int size) {
+ if (fnum==-1) { // just make sure that we will load a new font next time
+ fl_font_ = 0; fl_size_ = 0;
+ return;
+ }
+ if (fnum == fl_font_ && size == fl_size_) return;
+ fl_font_ = fnum; fl_size_ = size;
+ fl_fontsize = find(fnum, size);
+}
+
+int fl_height() {
+ if (fl_fontsize) return (fl_fontsize->metr.tmAscent + fl_fontsize->metr.tmDescent);
+ else return -1;
+}
+
+int fl_descent() {
+ if (fl_fontsize) return fl_fontsize->metr.tmDescent;
+ else return -1;
+}
+
+double fl_width(const char* c, int n) {
+ if (!fl_fontsize) return -1.0;
+ double w = 0.0;
+ while (n--) w += fl_fontsize->width[uchar(*c++)];
+ return w;
+}
+
+double fl_width(uchar c) {
+ if (fl_fontsize) return fl_fontsize->width[c];
+ else return -1.0;
+}
+
+void fl_draw(const char* str, int n, int x, int y) {
+ COLORREF oldColor = SetTextColor(fl_gc, fl_RGB());
+ if (fl_fontsize) SelectObject(fl_gc, fl_fontsize->fid);
+ TextOut(fl_gc, x, y, str, n);
+ SetTextColor(fl_gc, oldColor);
+}
+
+void fl_draw(const char* str, int n, float x, float y) {
+ fl_draw(str, n, (int)x, (int)y);
+}
+
+//
+// End of "$Id: fl_font_win32.cxx 5420 2006-09-05 11:16:15Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_font_x.cxx b/third_party/windows/fltk-1.1.10/src/fl_font_x.cxx new file mode 100644 index 0000000..4db151c --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_font_x.cxx @@ -0,0 +1,269 @@ +//
+// "$Id: fl_font_x.cxx 5421 2006-09-05 11:26:41Z matt $"
+//
+// Standard X11 font selection code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+Fl_FontSize::Fl_FontSize(const char* name) {
+ font = XLoadQueryFont(fl_display, name);
+ if (!font) {
+ Fl::warning("bad font: %s", name);
+ font = XLoadQueryFont(fl_display, "fixed"); // if fixed fails we crash
+ }
+# if HAVE_GL
+ listbase = 0;
+# endif
+}
+
+Fl_FontSize* fl_fontsize;
+
+Fl_FontSize::~Fl_FontSize() {
+# if HAVE_GL
+// Delete list created by gl_draw(). This is not done by this code
+// as it will link in GL unnecessarily. There should be some kind
+// of "free" routine pointer, or a subclass?
+// if (listbase) {
+// int base = font->min_char_or_byte2;
+// int size = font->max_char_or_byte2-base+1;
+// int base = 0; int size = 256;
+// glDeleteLists(listbase+base,size);
+// }
+# endif
+ if (this == fl_fontsize) fl_fontsize = 0;
+ XFreeFont(fl_display, font);
+}
+
+////////////////////////////////////////////////////////////////
+
+// WARNING: if you add to this table, you must redefine FL_FREE_FONT
+// in Enumerations.H & recompile!!
+static Fl_Fontdesc built_in_table[] = {
+{"-*-helvetica-medium-r-normal--*"},
+{"-*-helvetica-bold-r-normal--*"},
+{"-*-helvetica-medium-o-normal--*"},
+{"-*-helvetica-bold-o-normal--*"},
+{"-*-courier-medium-r-normal--*"},
+{"-*-courier-bold-r-normal--*"},
+{"-*-courier-medium-o-normal--*"},
+{"-*-courier-bold-o-normal--*"},
+{"-*-times-medium-r-normal--*"},
+{"-*-times-bold-r-normal--*"},
+{"-*-times-medium-i-normal--*"},
+{"-*-times-bold-i-normal--*"},
+{"-*-symbol-*"},
+{"-*-lucidatypewriter-medium-r-normal-sans-*"},
+{"-*-lucidatypewriter-bold-r-normal-sans-*"},
+{"-*-*zapf dingbats-*"}
+};
+
+Fl_Fontdesc* fl_fonts = built_in_table;
+
+#define MAXSIZE 32767
+
+// return dash number N, or pointer to ending null if none:
+const char* fl_font_word(const char* p, int n) {
+ while (*p) {if (*p=='-') {if (!--n) break;} p++;}
+ return p;
+}
+
+// return a pointer to a number we think is "point size":
+char* fl_find_fontsize(char* name) {
+ char* c = name;
+ // for standard x font names, try after 7th dash:
+ if (*c == '-') {
+ c = (char*)fl_font_word(c,7);
+ if (*c++ && isdigit(*c)) return c;
+ return 0; // malformed x font name?
+ }
+ char* r = 0;
+ // find last set of digits:
+ for (c++;* c; c++)
+ if (isdigit(*c) && !isdigit(*(c-1))) r = c;
+ return r;
+}
+
+const char* fl_encoding = "iso8859-1";
+
+// return true if this matches fl_encoding:
+int fl_correct_encoding(const char* name) {
+ if (*name != '-') return 0;
+ const char* c = fl_font_word(name,13);
+ return (*c++ && !strcmp(c,fl_encoding));
+}
+
+// locate or create an Fl_FontSize for a given Fl_Fontdesc and size:
+static Fl_FontSize* find(int fnum, int size) {
+ Fl_Fontdesc* s = fl_fonts+fnum;
+ if (!s->name) s = fl_fonts; // use font 0 if still undefined
+ Fl_FontSize* f;
+ for (f = s->first; f; f = f->next)
+ if (f->minsize <= size && f->maxsize >= size) return f;
+ fl_open_display();
+ if (!s->xlist) {
+ s->xlist = XListFonts(fl_display, s->name, 100, &(s->n));
+ if (!s->xlist) { // use fixed if no matching font...
+ s->first = new Fl_FontSize("fixed");
+ s->first->minsize = 0;
+ s->first->maxsize = 32767;
+ return s->first;
+ }
+ }
+ // search for largest <= font size:
+ char* name = s->xlist[0]; int ptsize = 0; // best one found so far
+ int matchedlength = 32767;
+ char namebuffer[1024]; // holds scalable font name
+ int found_encoding = 0;
+ int m = s->n; if (m<0) m = -m;
+ for (int n=0; n < m; n++) {
+
+ char* thisname = s->xlist[n];
+ if (fl_correct_encoding(thisname)) {
+ if (!found_encoding) ptsize = 0; // force it to choose this
+ found_encoding = 1;
+ } else {
+ if (found_encoding) continue;
+ }
+ char* c = fl_find_fontsize(thisname);
+ int thissize = c ? atoi(c) : MAXSIZE;
+ int thislength = strlen(thisname);
+ if (thissize == size && thislength < matchedlength) {
+ // exact match, use it:
+ name = thisname;
+ ptsize = size;
+ matchedlength = thislength;
+ } else if (!thissize && ptsize!=size) {
+ // whoa! A scalable font! Use unless exact match found:
+ int l = c-thisname;
+ memcpy(namebuffer,thisname,l);
+ l += sprintf(namebuffer+l,"%d",size);
+ while (*c == '0') c++;
+ strcpy(namebuffer+l,c);
+ name = namebuffer;
+ ptsize = size;
+ } else if (!ptsize || // no fonts yet
+ thissize < ptsize && ptsize > size || // current font too big
+ thissize > ptsize && thissize <= size // current too small
+ ) {
+ name = thisname; ptsize = thissize;
+ matchedlength = thislength;
+ }
+ }
+
+ if (ptsize != size) { // see if we already found this unscalable font:
+ for (f = s->first; f; f = f->next) {
+ if (f->minsize <= ptsize && f->maxsize >= ptsize) {
+ if (f->minsize > size) f->minsize = size;
+ if (f->maxsize < size) f->maxsize = size;
+ return f;
+ }
+ }
+ }
+
+ // okay, we definately have some name, make the font:
+ f = new Fl_FontSize(name);
+ if (ptsize < size) {f->minsize = ptsize; f->maxsize = size;}
+ else {f->minsize = size; f->maxsize = ptsize;}
+ f->next = s->first;
+ s->first = f;
+ return f;
+
+}
+
+////////////////////////////////////////////////////////////////
+// Public interface:
+
+int fl_font_ = 0;
+int fl_size_ = 0;
+XFontStruct* fl_xfont = 0;
+void *fl_xftfont = 0;
+static GC font_gc;
+
+void fl_font(int fnum, int size) {
+ if (fnum==-1) {
+ fl_font_ = 0; fl_size_ = 0;
+ return;
+ }
+ if (fnum == fl_font_ && size == fl_size_) return;
+ fl_font_ = fnum; fl_size_ = size;
+ Fl_FontSize* f = find(fnum, size);
+ if (f != fl_fontsize) {
+ fl_fontsize = f;
+ fl_xfont = f->font;
+ font_gc = 0;
+ }
+}
+
+int fl_height() {
+ if (fl_xfont) return (fl_xfont->ascent + fl_xfont->descent);
+ else return -1;
+}
+
+int fl_descent() {
+ if (fl_xfont) return fl_xfont->descent;
+ else return -1;
+}
+
+double fl_width(const char* c, int n) {
+ if (!fl_xfont) return -1.0;
+ XCharStruct* p = fl_xfont->per_char;
+ if (!p) return n*fl_xfont->min_bounds.width;
+ int a = fl_xfont->min_char_or_byte2;
+ int b = fl_xfont->max_char_or_byte2 - a;
+ int w = 0;
+ while (n--) {
+ int x = *(uchar*)c++ - a;
+ if (x >= 0 && x <= b) w += p[x].width;
+ else w += fl_xfont->min_bounds.width;
+ }
+ return w;
+}
+
+double fl_width(uchar c) {
+ if (!fl_xfont) return -1;
+ XCharStruct* p = fl_xfont->per_char;
+ if (p) {
+ int a = fl_xfont->min_char_or_byte2;
+ int b = fl_xfont->max_char_or_byte2 - a;
+ int x = c-a;
+ if (x >= 0 && x <= b) return p[x].width;
+ }
+ return fl_xfont->min_bounds.width;
+}
+
+void fl_draw(const char* str, int n, int x, int y) {
+ if (font_gc != fl_gc) {
+ if (!fl_xfont) fl_font(FL_HELVETICA, 14);
+ font_gc = fl_gc;
+ XSetFont(fl_display, fl_gc, fl_xfont->fid);
+ }
+ XDrawString(fl_display, fl_window, fl_gc, x, y, str, n);
+}
+
+void fl_draw(const char* str, int n, float x, float y) {
+ fl_draw(str, n, (int)x, (int)y);
+}
+
+//
+// End of "$Id: fl_font_x.cxx 5421 2006-09-05 11:26:41Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_font_xft.cxx b/third_party/windows/fltk-1.1.10/src/fl_font_xft.cxx new file mode 100644 index 0000000..a9ea6b7 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_font_xft.cxx @@ -0,0 +1,445 @@ +//
+// "$Id: fl_font_xft.cxx 6871 2009-09-15 20:33:55Z matt $"
+//
+// Xft font code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 2001-2007 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
+//
+
+//
+// Draw fonts using Keith Packard's Xft library to provide anti-
+// aliased text. Yow!
+//
+// Many thanks to Carl for making the original version of this.
+//
+// This font code only requires libXft to work. Contrary to popular
+// belief there is no need to have FreeType, or the Xrender extension
+// available to use this code. You will just get normal Xlib fonts
+// (Xft calls them "core" fonts) The Xft algorithms for choosing
+// these is about as good as the FLTK ones (I hope to fix it so it is
+// exactly as good...), plus it can cache it's results and share them
+// between programs, so using this should be a win in all cases. Also
+// it should be obvious by comparing this file and fl_font_x.cxx that
+// it is a lot easier to program with Xft than with Xlib.
+//
+// Also, Xft supports UTF-8 text rendering directly, which will allow
+// us to support UTF-8 on all platforms more easily.
+//
+// To actually get antialiasing you need the following:
+//
+// 1. You have XFree86 4
+// 2. You have the XRender extension
+// 3. Your X device driver supports the render extension
+// 4. You have libXft
+// 5. Your libXft has FreeType2 support compiled in
+// 6. You have the FreeType2 library
+//
+// Distributions that have XFree86 4.0.3 or later should have all of this...
+//
+// Unlike some other Xft packages, I tried to keep this simple and not
+// to work around the current problems in Xft by making the "patterns"
+// complicated. I belive doing this defeats our ability to improve Xft
+// itself. You should edit the ~/.xftconfig file to "fix" things, there
+// are several web pages of information on how to do this.
+//
+
+#include <X11/Xft/Xft.h>
+
+// The predefined fonts that FLTK has:
+static Fl_Fontdesc built_in_table[] = {
+{" sans"},
+{"Bsans"},
+{"Isans"},
+{"Psans"},
+{" mono"},
+{"Bmono"},
+{"Imono"},
+{"Pmono"},
+{" serif"},
+{"Bserif"},
+{"Iserif"},
+{"Pserif"},
+{" symbol"},
+{" screen"},
+{"Bscreen"},
+{" dingbats"},
+};
+
+Fl_Fontdesc* fl_fonts = built_in_table;
+
+#define current_font (fl_fontsize->font)
+
+int fl_font_ = 0;
+int fl_size_ = 0;
+XFontStruct* fl_xfont = 0;
+void *fl_xftfont = 0;
+const char* fl_encoding_ = "iso8859-1";
+Fl_FontSize* fl_fontsize = 0;
+
+void fl_font(int fnum, int size) {
+ if (fnum==-1) { // special case to stop font caching
+ fl_font_ = 0; fl_size_ = 0;
+ return;
+ }
+ if (fnum == fl_font_ && size == fl_size_
+ && fl_fontsize
+ && !strcasecmp(fl_fontsize->encoding, fl_encoding_))
+ return;
+ fl_font_ = fnum; fl_size_ = size;
+ Fl_Fontdesc *font = fl_fonts + fnum;
+ Fl_FontSize* f;
+ // search the fontsizes we have generated already
+ for (f = font->first; f; f = f->next) {
+ if (f->size == size && !strcasecmp(f->encoding, fl_encoding_))
+ break;
+ }
+ if (!f) {
+ f = new Fl_FontSize(font->name);
+ f->next = font->first;
+ font->first = f;
+ }
+ fl_fontsize = f;
+#if XFT_MAJOR < 2
+ fl_xfont = f->font->u.core.font;
+#endif // XFT_MAJOR < 2
+ fl_xftfont = (void*)f->font;
+}
+
+static XftFont* fontopen(const char* name, bool core) {
+ // Check: does it look like we have been passed an old-school XLFD fontname?
+ bool is_xlfd = false;
+ int hyphen_count = 0;
+ int comma_count = 0;
+ unsigned len = strlen(name);
+ if (len > 512) len = 512; // ensure we are not passed an unbounded font name
+ for(unsigned idx = 0; idx < len; idx++) {
+ if(name[idx] == '-') hyphen_count++; // check for XLFD hyphens
+ if(name[idx] == ',') comma_count++; // are there multiple names?
+ }
+ if(hyphen_count >= 14) is_xlfd = true; // Not a robust check, but good enough?
+
+ fl_open_display();
+
+ if(!is_xlfd) { // Not an XLFD - open as a XFT style name
+ XftFont *the_font; // the font we will return;
+ XftPattern *fnt_pat = XftPatternCreate(); // the pattern we will use for matching
+ int slant = XFT_SLANT_ROMAN;
+ int weight = XFT_WEIGHT_MEDIUM;
+
+ /* This "converts" FLTK-style font names back into "regular" names, extracting
+ * the BOLD and ITALIC codes as it does so - all FLTK font names are prefixed
+ * by 'I' (italic) 'B' (bold) 'P' (bold italic) or ' ' (regular) modifiers.
+ * This gives a fairly limited font selection ability, but is retained for
+ * compatability reasons. If you really need a more complex choice, you are best
+ * calling Fl::set_fonts(*) then selecting the font by font-index rather than by
+ * name anyway. Probably.
+ * If you want to load a font who's name does actually begin with I, B or P, you
+ * MUST use a leading space OR simply use lowercase for the name...
+ */
+ /* This may be efficient, but it is non-obvious. */
+ switch (*name++) {
+ case 'I': slant = XFT_SLANT_ITALIC; break; // italic
+ case 'P': slant = XFT_SLANT_ITALIC; // bold-italic (falls-through)
+ case 'B': weight = XFT_WEIGHT_BOLD; break; // bold
+ case ' ': break; // regular
+ default: name--; // no prefix, restore name
+ }
+
+ if(comma_count) { // multiple comma-spearated names were passed
+ char *local_name = strdup(name); // duplicate the full name so we can edit the copy
+ char *curr = local_name; // points to first name in string
+ char *nxt; // next name in string
+ do {
+ nxt = strchr(curr, ','); // find comma seperator
+ if (nxt) {
+ *nxt = 0; // terminate first name
+ nxt++; // first char of next name
+ }
+
+ // Add the current name to the match pattern
+ XftPatternAddString(fnt_pat, XFT_FAMILY, curr);
+
+ if(nxt) curr = nxt; // move onto next name (if it exists)
+ // Now do a cut-down version of the FLTK name conversion.
+ // NOTE: we only use the slant and weight of the first name,
+ // subsequent names we ignore this for... But we still need to do the check.
+ switch (*curr++) {
+ case 'I': break; // italic
+ case 'P': // bold-italic (falls-through)
+ case 'B': break; // bold
+ case ' ': break; // regular
+ default: curr--; // no prefix, restore name
+ }
+
+ comma_count--; // decrement name sections count
+ } while (comma_count >= 0);
+ free(local_name); // release our local copy of font names
+ }
+ else { // single name was passed - add it directly
+ XftPatternAddString(fnt_pat, XFT_FAMILY, name);
+ }
+
+ // Construct a match pattern for the font we want...
+ XftPatternAddInteger(fnt_pat, XFT_WEIGHT, weight);
+ XftPatternAddInteger(fnt_pat, XFT_SLANT, slant);
+ XftPatternAddDouble (fnt_pat, XFT_PIXEL_SIZE, (double)fl_size_);
+ XftPatternAddString (fnt_pat, XFT_ENCODING, fl_encoding_);
+ if (core) {
+ XftPatternAddBool(fnt_pat, XFT_CORE, FcTrue);
+ XftPatternAddBool(fnt_pat, XFT_RENDER, FcFalse);
+ }
+
+ XftPattern *match_pat; // the best available match on the system
+ XftResult match_result; // the result of our matching attempt
+ // query the system to find a match for this font
+ match_pat = XftFontMatch(fl_display, fl_screen, fnt_pat, &match_result);
+ // open the matched font
+ the_font = XftFontOpenPattern(fl_display, match_pat);
+ // Tidy up the resources we allocated
+ XftPatternDestroy(fnt_pat);
+// XftPatternDestroy(match_pat); // FontConfig will destroy this resource for us. We must not!
+ return the_font;
+ }
+ else { // We were passed a font name in XLFD format
+ char *local_name = strdup(name);
+ if(comma_count) { // This means we were passed multiple XLFD's
+ char *pc = strchr(local_name, ',');
+ *pc = 0; // terminate the XLFD at the first comma
+ }
+ XftFont *the_font = XftFontOpenXlfd(fl_display, fl_screen, local_name);
+ free(local_name);
+ return the_font;
+ }
+} // end of fontopen
+
+Fl_FontSize::Fl_FontSize(const char* name) {
+ encoding = fl_encoding_;
+ size = fl_size_;
+#if HAVE_GL
+ listbase = 0;
+#endif // HAVE_GL
+ font = fontopen(name, false);
+}
+
+Fl_FontSize::~Fl_FontSize() {
+ if (this == fl_fontsize) fl_fontsize = 0;
+// XftFontClose(fl_display, font);
+}
+
+int fl_height() {
+ if (current_font) return current_font->ascent + current_font->descent;
+ else return -1;
+}
+
+int fl_descent() {
+ if (current_font) return current_font->descent;
+ else return -1;
+}
+
+double fl_width(const char *str, int n) {
+ if (!current_font) return -1.0;
+ XGlyphInfo i;
+ XftTextExtents8(fl_display, current_font, (XftChar8 *)str, n, &i);
+ return i.xOff;
+}
+
+double fl_width(uchar c) {
+ return fl_width((const char *)(&c), 1);
+}
+
+#if HAVE_GL
+/* This code is used by opengl to get a bitmapped font. The original XFT-1 code
+ * used XFT's "core" fonts methods to load an XFT font that was actually a
+ * X-bitmap font, that could then be readily used with GL.
+ * But XFT-2 does not provide that ability, and there is no easy method to use
+ * an XFT font directly with GL. So...
+*/
+
+# if XFT_MAJOR > 1
+// This function attempts, on XFT2 systems, to find a suitable "core" Xfont
+// for GL to use, since we dont have an XglUseXftFont(...) function.
+// There's probably a better way to do this. I can't believe it is this hard...
+// Anyway... This code attempts to make an XLFD out of the fltk-style font
+// name it is passed, then tries to load that font. Surprisingly, this quite
+// often works - boxes that have XFT generally also have a fontserver that
+// can serve TTF and other fonts to X, and so the font name that fltk makes
+// from the XFT name often also "exists" as an "core" X font...
+// If this code fails to load the requested font, it falls back through a
+// series of tried 'n tested alternatives, ultimately resorting to what the
+// original fltk code did.
+// NOTE:
+// On my test boxes (FC6, FC7) this works well for the fltk "built-in" font names.
+static XFontStruct* load_xfont_for_xft2(void) {
+ XFontStruct* xgl_font = 0;
+ int size = fl_size_;
+ const char *weight = "medium"; // no specifc weight requested - accept any
+ char slant = 'r'; // regular non-italic by default
+ char xlfd[128]; // we will put our synthetic XLFD in here
+ char *pc = strdup(fl_fonts[fl_font_].name); // what font were we asked for?
+ const char *name = pc; // keep a handle to the original name for freeing later
+ // Parse the "fltk-name" of the font
+ switch (*name++) {
+ case 'I': slant = 'i'; break; // italic
+ case 'P': slant = 'i'; // bold-italic (falls-through)
+ case 'B': weight = "bold"; break; // bold
+ case ' ': break; // regular
+ default: name--; // no prefix, restore name
+ }
+
+ // map generic Xft names to customary XLFD faces
+ if (!strcmp(name, "sans")) {
+ name = "helvetica";
+ } else if (!strcmp(name, "mono")) {
+ name = "courier";
+ } else if (!strcmp(name, "serif")) {
+ name = "times";
+ } else if (!strcmp(name, "screen")) {
+ name = "lucidatypewriter";
+ } else if (!strcmp(name, "dingbats")) {
+ name = "zapf dingbats";
+ }
+
+ // first, we do a query with no prefered size, to see if the font exists at all
+ snprintf(xlfd, 128, "-*-*%s*-%s-%c-*--*-*-*-*-*-*-*-*", name, weight, slant); // make up xlfd style name
+ xgl_font = XLoadQueryFont(fl_display, xlfd);
+ if(xgl_font) { // the face exists, but can we get it in a suitable size?
+ XFreeFont(fl_display, xgl_font); // release the non-sized version
+ snprintf(xlfd, 128, "-*-*%s*-%s-%c-*--*-%d-*-*-*-*-*-*", name, weight, slant, (size*10));
+ xgl_font = XLoadQueryFont(fl_display, xlfd); // attempt to load the font at the right size
+ }
+ free(pc); // release our copy of the font name
+
+ // if we have nothing loaded, try a generic proportional font
+ if(!xgl_font) {
+ snprintf(xlfd, 128, "-*-helvetica-*-%c-*--*-%d-*-*-*-*-*-*", slant, (size*10));
+ xgl_font = XLoadQueryFont(fl_display, xlfd);
+ }
+ // If that still didn't work, try this instead
+ if(!xgl_font) {
+ snprintf(xlfd, 128, "-*-courier-medium-%c-*--*-%d-*-*-*-*-*-*", slant, (size*10));
+ xgl_font = XLoadQueryFont(fl_display, xlfd);
+ }
+ // Last chance fallback - this usually loads something...
+ if (!xgl_font) xgl_font = XLoadQueryFont(fl_display, "fixed");
+
+ return xgl_font;
+} // end of load_xfont_for_xft2
+# endif
+
+XFontStruct* fl_xxfont() {
+# if XFT_MAJOR > 1
+ // kludge! XFT 2 and later does not provide core fonts for us to use with GL
+ // try to load a bitmap X font instead
+ static XFontStruct* xgl_font = 0;
+ static int glsize = 0;
+ static int glfont = -1;
+ // Do we need to load a new font?
+ if ((!xgl_font) || (glsize != fl_size_) || (glfont != fl_font_)) {
+ if (xgl_font) XFreeFont(fl_display, xgl_font); // font already loaded, free it
+ glsize = fl_size_; // record current font size
+ glfont = fl_font_; // and face
+ // create a dummy XLFD for some font of the appropriate size...
+ xgl_font = load_xfont_for_xft2();
+ }
+ return xgl_font;
+# else // XFT-1 provides a means to load a "core" font directly
+ if (current_font->core) return current_font->u.core.font; // is the current font a "core" font? If so, use it.
+ static XftFont* xftfont;
+ if (xftfont) XftFontClose (fl_display, xftfont);
+ xftfont = fontopen(fl_fonts[fl_font_].name, true); // else request XFT to load a suitable "core" font instead.
+ return xftfont->u.core.font;
+# endif // XFT_MAJOR > 1
+}
+#endif // HAVE_GL
+
+#if USE_OVERLAY
+// Currently Xft does not work with colormapped visuals, so this probably
+// does not work unless you have a true-color overlay.
+extern bool fl_overlay;
+extern Colormap fl_overlay_colormap;
+extern XVisualInfo* fl_overlay_visual;
+#endif
+
+// For some reason Xft produces errors if you destroy a window whose id
+// still exists in an XftDraw structure. It would be nice if this is not
+// true, a lot of junk is needed to try to stop this:
+
+static XftDraw* draw;
+static Window draw_window;
+#if USE_OVERLAY
+static XftDraw* draw_overlay;
+static Window draw_overlay_window;
+#endif
+
+void fl_destroy_xft_draw(Window id) {
+ if (id == draw_window)
+ XftDrawChange(draw, draw_window = fl_message_window);
+#if USE_OVERLAY
+ if (id == draw_overlay_window)
+ XftDrawChange(draw_overlay, draw_overlay_window = fl_message_window);
+#endif
+}
+
+void fl_draw(const char *str, int n, int x, int y) {
+ if ( !current_font ) {
+ fl_font(FL_HELVETICA, 14);
+ }
+#if USE_OVERLAY
+ XftDraw*& draw = fl_overlay ? draw_overlay : ::draw;
+ if (fl_overlay) {
+ if (!draw)
+ draw = XftDrawCreate(fl_display, draw_overlay_window = fl_window,
+ fl_overlay_visual->visual, fl_overlay_colormap);
+ else //if (draw_overlay_window != fl_window)
+ XftDrawChange(draw, draw_overlay_window = fl_window);
+ } else
+#endif
+ if (!draw)
+ draw = XftDrawCreate(fl_display, draw_window = fl_window,
+ fl_visual->visual, fl_colormap);
+ else //if (draw_window != fl_window)
+ XftDrawChange(draw, draw_window = fl_window);
+
+ Region region = fl_clip_region();
+ if (region && XEmptyRegion(region)) return;
+ XftDrawSetClip(draw, region);
+
+ // Use fltk's color allocator, copy the results to match what
+ // XftCollorAllocValue returns:
+ XftColor color;
+ color.pixel = fl_xpixel(fl_color_);
+ uchar r,g,b; Fl::get_color(fl_color_, r,g,b);
+ color.color.red = ((int)r)*0x101;
+ color.color.green = ((int)g)*0x101;
+ color.color.blue = ((int)b)*0x101;
+ color.color.alpha = 0xffff;
+
+ XftDrawString8(draw, &color, current_font, x, y, (XftChar8 *)str, n);
+}
+
+void fl_draw(const char* str, int n, float x, float y) {
+ fl_draw(str, n, (int)x, (int)y);
+}
+
+//
+// End of "$Id: fl_font_xft.cxx 6871 2009-09-15 20:33:55Z matt $"
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_gtk.cxx b/third_party/windows/fltk-1.1.10/src/fl_gtk.cxx new file mode 100644 index 0000000..5a674f0 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_gtk.cxx @@ -0,0 +1,304 @@ +//
+// "$Id: fl_gtk.cxx 5721 2007-02-27 19:23:24Z matt $"
+//
+// "GTK" drawing routines for the Fast Light Tool Kit (FLTK).
+//
+// These box types provide a GTK+ look, based on Red Hat's Bluecurve
+// theme...
+//
+// Copyright 2006 by Michael Sweet.
+//
+// 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
+//
+
+// Box drawing code for an obscure box type.
+// These box types are in seperate files so they are not linked
+// in if not used.
+
+#include <FL/Fl.H>
+#include <FL/fl_draw.H>
+
+extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*);
+
+
+static void gtk_color(Fl_Color c) {
+ if (Fl::draw_box_active()) fl_color(c);
+ else fl_color(fl_inactive(c));
+}
+
+
+static void gtk_up_frame(int x, int y, int w, int h, Fl_Color c) {
+ gtk_color(fl_color_average(FL_WHITE, c, 0.5));
+ fl_xyline(x + 2, y + 1, x + w - 3);
+ fl_yxline(x + 1, y + 2, y + h - 3);
+
+ gtk_color(fl_color_average(FL_BLACK, c, 0.5));
+ fl_begin_loop();
+ fl_vertex(x, y + 2);
+ fl_vertex(x + 2, y);
+ fl_vertex(x + w - 3, y);
+ fl_vertex(x + w - 1, y + 2);
+ fl_vertex(x + w - 1, y + h - 3);
+ fl_vertex(x + w - 3, y + h - 1);
+ fl_vertex(x + 2, y + h - 1);
+ fl_vertex(x, y + h - 3);
+ fl_end_loop();
+}
+
+
+static void gtk_up_box(int x, int y, int w, int h, Fl_Color c) {
+ gtk_up_frame(x, y, w, h, c);
+
+ gtk_color(fl_color_average(FL_WHITE, c, 0.4f));
+ fl_xyline(x + 2, y + 2, x + w - 3);
+ gtk_color(fl_color_average(FL_WHITE, c, 0.2f));
+ fl_xyline(x + 2, y + 3, x + w - 3);
+ gtk_color(fl_color_average(FL_WHITE, c, 0.1f));
+ fl_xyline(x + 2, y + 4, x + w - 3);
+ gtk_color(c);
+ fl_rectf(x + 2, y + 5, w - 4, h - 7);
+ gtk_color(fl_color_average(FL_BLACK, c, 0.025f));
+ fl_xyline(x + 2, y + h - 4, x + w - 3);
+ gtk_color(fl_color_average(FL_BLACK, c, 0.05f));
+ fl_xyline(x + 2, y + h - 3, x + w - 3);
+ gtk_color(fl_color_average(FL_BLACK, c, 0.1f));
+ fl_xyline(x + 2, y + h - 2, x + w - 3);
+ fl_yxline(x + w - 2, y + 2, y + h - 3);
+}
+
+
+static void gtk_down_frame(int x, int y, int w, int h, Fl_Color c) {
+ gtk_color(fl_color_average(FL_BLACK, c, 0.5));
+ fl_begin_loop();
+ fl_vertex(x, y + 2);
+ fl_vertex(x + 2, y);
+ fl_vertex(x + w - 3, y);
+ fl_vertex(x + w - 1, y + 2);
+ fl_vertex(x + w - 1, y + h - 3);
+ fl_vertex(x + w - 3, y + h - 1);
+ fl_vertex(x + 2, y + h - 1);
+ fl_vertex(x, y + h - 3);
+ fl_end_loop();
+
+ gtk_color(fl_color_average(FL_BLACK, c, 0.1f));
+ fl_xyline(x + 2, y + 1, x + w - 3);
+ fl_yxline(x + 1, y + 2, y + h - 3);
+
+ gtk_color(fl_color_average(FL_BLACK, c, 0.05f));
+ fl_yxline(x + 2, y + h - 2, y + 2, x + w - 2);
+}
+
+
+static void gtk_down_box(int x, int y, int w, int h, Fl_Color c) {
+ gtk_down_frame(x, y, w, h, c);
+
+ gtk_color(c);
+ fl_rectf(x + 3, y + 3, w - 5, h - 4);
+ fl_yxline(x + w - 2, y + 3, y + h - 3);
+}
+
+
+static void gtk_thin_up_frame(int x, int y, int w, int h, Fl_Color c) {
+ gtk_color(fl_color_average(FL_WHITE, c, 0.6f));
+ fl_xyline(x + 1, y, x + w - 2);
+ fl_yxline(x, y + 1, y + h - 2);
+
+ gtk_color(fl_color_average(FL_BLACK, c, 0.4f));
+ fl_xyline(x + 1, y + h - 1, x + w - 2);
+ fl_yxline(x + w - 1, y + 1, y + h - 2);
+}
+
+
+static void gtk_thin_up_box(int x, int y, int w, int h, Fl_Color c) {
+ gtk_thin_up_frame(x, y, w, h, c);
+
+ gtk_color(fl_color_average(FL_WHITE, c, 0.4f));
+ fl_xyline(x + 1, y + 1, x + w - 2);
+ gtk_color(fl_color_average(FL_WHITE, c, 0.2f));
+ fl_xyline(x + 1, y + 2, x + w - 2);
+ gtk_color(fl_color_average(FL_WHITE, c, 0.1f));
+ fl_xyline(x + 1, y + 3, x + w - 2);
+ gtk_color(c);
+ fl_rectf(x + 1, y + 4, w - 2, h - 8);
+ gtk_color(fl_color_average(FL_BLACK, c, 0.025f));
+ fl_xyline(x + 1, y + h - 4, x + w - 2);
+ gtk_color(fl_color_average(FL_BLACK, c, 0.05f));
+ fl_xyline(x + 1, y + h - 3, x + w - 2);
+ gtk_color(fl_color_average(FL_BLACK, c, 0.1f));
+ fl_xyline(x + 1, y + h - 2, x + w - 2);
+}
+
+
+static void gtk_thin_down_frame(int x, int y, int w, int h, Fl_Color c) {
+ gtk_color(fl_color_average(FL_BLACK, c, 0.4f));
+ fl_xyline(x + 1, y, x + w - 2);
+ fl_yxline(x, y + 1, y + h - 2);
+
+ gtk_color(fl_color_average(FL_WHITE, c, 0.6f));
+ fl_xyline(x + 1, y + h - 1, x + w - 2);
+ fl_yxline(x + w - 1, y + 1, y + h - 2);
+}
+
+
+static void gtk_thin_down_box(int x, int y, int w, int h, Fl_Color c) {
+ gtk_thin_down_frame(x, y, w, h, c);
+
+ gtk_color(c);
+ fl_rectf(x + 1, y + 1, w - 2, h - 2);
+}
+
+//------------------------
+// new GTK+ style for round buttons
+#if 1
+
+static void fl_arc_i(int x,int y,int w,int h,double a1,double a2) {
+ fl_arc(x,y,w,h,a1,a2);
+}
+
+enum {UPPER_LEFT, LOWER_RIGHT, CLOSED, FILL};
+
+static void draw(int which, int x,int y,int w,int h, int inset)
+{
+ if (inset*2 >= w) inset = (w-1)/2;
+ if (inset*2 >= h) inset = (h-1)/2;
+ x += inset;
+ y += inset;
+ w -= 2*inset;
+ h -= 2*inset;
+ int d = w <= h ? w : h;
+ if (d <= 1) return;
+ void (*f)(int,int,int,int,double,double);
+ f = (which==FILL) ? fl_pie : fl_arc_i;
+ if (which >= CLOSED) {
+ f(x+w-d, y, d, d, w<=h ? 0 : -90, w<=h ? 180 : 90);
+ f(x, y+h-d, d, d, w<=h ? 180 : 90, w<=h ? 360 : 270);
+ } else if (which == UPPER_LEFT) {
+ f(x+w-d, y, d, d, 45, w<=h ? 180 : 90);
+ f(x, y+h-d, d, d, w<=h ? 180 : 90, 225);
+ } else { // LOWER_RIGHT
+ f(x, y+h-d, d, d, 225, w<=h ? 360 : 270);
+ f(x+w-d, y, d, d, w<=h ? 360 : 270, 360+45);
+ }
+ if (which == FILL) {
+ if (w < h)
+ fl_rectf(x, y+d/2, w, h-(d&-2));
+ else if (w > h)
+ fl_rectf(x+d/2, y, w-(d&-2), h);
+ } else {
+ if (w < h) {
+ if (which != UPPER_LEFT) fl_yxline(x+w-1, y+d/2-1, y+h-d/2+1);
+ if (which != LOWER_RIGHT) fl_yxline(x, y+d/2-1, y+h-d/2+1);
+ } else if (w > h) {
+ if (which != UPPER_LEFT) fl_xyline(x+d/2-1, y+h-1, x+w-d/2+1);
+ if (which != LOWER_RIGHT) fl_xyline(x+d/2-1, y, x+w-d/2+1);
+ }
+ }
+}
+
+void gtk_round_up_box(int x, int y, int w, int h, Fl_Color c) {
+ fl_color(c);
+ draw(FILL, x, y, w, h, 2);
+
+ gtk_color(fl_color_average(FL_BLACK, c, 0.025f));
+ draw(LOWER_RIGHT, x+1, y, w-2, h, 2);
+ draw(LOWER_RIGHT, x, y, w, h, 3);
+ gtk_color(fl_color_average(FL_BLACK, c, 0.05f));
+ draw(LOWER_RIGHT, x+1, y, w-2, h, 1);
+ draw(LOWER_RIGHT, x, y, w, h, 2);
+ gtk_color(fl_color_average(FL_BLACK, c, 0.1f));
+ draw(LOWER_RIGHT, x+1, y, w-2, h, 0);
+ draw(LOWER_RIGHT, x, y, w, h, 1);
+
+ gtk_color(fl_color_average(FL_WHITE, c, 0.1f));
+ draw(UPPER_LEFT, x, y, w, h, 4);
+ draw(UPPER_LEFT, x+1, y, w-2, h, 3);
+ gtk_color(fl_color_average(FL_WHITE, c, 0.2f));
+ draw(UPPER_LEFT, x, y, w, h, 3);
+ draw(UPPER_LEFT, x+1, y, w-2, h, 2);
+ gtk_color(fl_color_average(FL_WHITE, c, 0.4f));
+ draw(UPPER_LEFT, x, y, w, h, 2);
+ draw(UPPER_LEFT, x+1, y, w-2, h, 1);
+ gtk_color(fl_color_average(FL_WHITE, c, 0.5f));
+ draw(UPPER_LEFT, x, y, w, h, 1);
+ draw(UPPER_LEFT, x+1, y, w-2, h, 0);
+
+ gtk_color(fl_color_average(FL_BLACK, c, 0.5f));
+ draw(CLOSED, x, y, w, h, 0);
+}
+
+void gtk_round_down_box(int x, int y, int w, int h, Fl_Color c) {
+ fl_color(c);
+ draw(FILL, x, y, w, h, 2);
+
+ gtk_color(fl_color_average(FL_BLACK, c, 0.05f));
+ draw(UPPER_LEFT, x, y, w, h, 2);
+ draw(UPPER_LEFT, x+1, y, w-2, h, 1);
+ gtk_color(fl_color_average(FL_BLACK, c, 0.1f));
+ draw(UPPER_LEFT, x, y, w, h, 1);
+ draw(UPPER_LEFT, x+1, y, w-2, h, 0);
+
+ gtk_color(fl_color_average(FL_BLACK, c, 0.5f));
+ draw(CLOSED, x, y, w, h, 0);
+}
+
+#else
+
+static void gtk_round_up_box(int x, int y, int w, int h, Fl_Color c) {
+ gtk_color(c);
+ fl_pie(x, y, w, h, 0.0, 360.0);
+ gtk_color(fl_color_average(FL_WHITE, c, 0.5f));
+ fl_arc(x, y, w, h, 45.0, 180.0);
+ gtk_color(fl_color_average(FL_WHITE, c, 0.25f));
+ fl_arc(x, y, w, h, 180.0, 405.0);
+ gtk_color(fl_color_average(FL_BLACK, c, 0.5f));
+ fl_arc(x, y, w, h, 225.0, 360.0);
+}
+
+
+static void gtk_round_down_box(int x, int y, int w, int h, Fl_Color c) {
+ gtk_color(c);
+ fl_pie(x, y, w, h, 0.0, 360.0);
+ gtk_color(fl_color_average(FL_BLACK, c, 0.2));
+ fl_arc(x + 1, y, w, h, 90.0, 210.0);
+ gtk_color(fl_color_average(FL_BLACK, c, 0.6));
+ fl_arc(x, y, w, h, 0.0, 360.0);
+}
+
+#endif
+
+Fl_Boxtype fl_define_FL_GTK_UP_BOX() {
+ fl_internal_boxtype(_FL_GTK_UP_BOX, gtk_up_box);
+ fl_internal_boxtype(_FL_GTK_DOWN_BOX, gtk_down_box);
+ fl_internal_boxtype(_FL_GTK_UP_FRAME, gtk_up_frame);
+ fl_internal_boxtype(_FL_GTK_DOWN_FRAME, gtk_down_frame);
+ fl_internal_boxtype(_FL_GTK_THIN_UP_BOX, gtk_thin_up_box);
+ fl_internal_boxtype(_FL_GTK_THIN_DOWN_BOX, gtk_thin_down_box);
+ fl_internal_boxtype(_FL_GTK_THIN_UP_FRAME, gtk_thin_up_frame);
+ fl_internal_boxtype(_FL_GTK_THIN_DOWN_FRAME, gtk_thin_down_frame);
+ fl_internal_boxtype(_FL_GTK_ROUND_UP_BOX, gtk_round_up_box);
+ fl_internal_boxtype(_FL_GTK_ROUND_DOWN_BOX, gtk_round_down_box);
+
+ return _FL_GTK_UP_BOX;
+}
+
+
+//
+// End of "$Id: fl_gtk.cxx 5721 2007-02-27 19:23:24Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_images_core.cxx b/third_party/windows/fltk-1.1.10/src/fl_images_core.cxx new file mode 100644 index 0000000..eff0055 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_images_core.cxx @@ -0,0 +1,103 @@ +//
+// "$Id: fl_images_core.cxx 5845 2007-05-20 00:01:06Z mike $"
+//
+// FLTK images library core.
+//
+// Copyright 1997-2005 by Easy Software Products.
+//
+// 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
+//
+// Contents:
+//
+// fl_register_images() - Register the image formats.
+// fl_check_images() - Check for a supported image format.
+//
+
+//
+// Include necessary header files...
+//
+
+#include <FL/Fl_Shared_Image.H>
+#include <FL/Fl_BMP_Image.H>
+#include <FL/Fl_GIF_Image.H>
+#include <FL/Fl_JPEG_Image.H>
+#include <FL/Fl_PNG_Image.H>
+#include <FL/Fl_PNM_Image.H>
+#include <stdio.h>
+#include <stdlib.h>
+#include "flstring.h"
+
+
+//
+// Define a simple global image registration function that registers
+// the extra image formats that aren't part of the core FLTK library.
+//
+
+static Fl_Image *fl_check_images(const char *name, uchar *header, int headerlen);
+
+
+//
+// 'fl_register_images()' - Register the image formats.
+//
+
+void fl_register_images() {
+ Fl_Shared_Image::add_handler(fl_check_images);
+}
+
+
+//
+// 'fl_check_images()' - Check for a supported image format.
+//
+
+Fl_Image * // O - Image, if found
+fl_check_images(const char *name, // I - Filename
+ uchar *header, // I - Header data from file
+ int) { // I - Amount of data (not used)
+ if (memcmp(header, "GIF87a", 6) == 0 ||
+ memcmp(header, "GIF89a", 6) == 0) // GIF file
+ return new Fl_GIF_Image(name);
+
+ if (memcmp(header, "BM", 2) == 0) // BMP file
+ return new Fl_BMP_Image(name);
+
+ if (header[0] == 'P' && header[1] >= '1' && header[1] <= '7')
+ // Portable anymap
+ return new Fl_PNM_Image(name);
+
+#ifdef HAVE_LIBPNG
+ if (memcmp(header, "\211PNG", 4) == 0)// PNG file
+ return new Fl_PNG_Image(name);
+#endif // HAVE_LIBPNG
+
+#ifdef HAVE_LIBJPEG
+ if (memcmp(header, "\377\330\377", 3) == 0 &&
+ // Start-of-Image
+ header[3] >= 0xc0 && header[3] <= 0xef)
+ // APPn for JPEG file
+ return new Fl_JPEG_Image(name);
+#endif // HAVE_LIBJPEG
+
+ return 0;
+}
+
+
+//
+// End of "$Id: fl_images_core.cxx 5845 2007-05-20 00:01:06Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_labeltype.cxx b/third_party/windows/fltk-1.1.10/src/fl_labeltype.cxx new file mode 100644 index 0000000..dc2289e --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_labeltype.cxx @@ -0,0 +1,133 @@ +//
+// "$Id: fl_labeltype.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Label drawing routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Drawing code for the (one) common label types.
+// Other label types (symbols) are in their own source files
+// to avoid linking if not used.
+
+#include <FL/Fl.H>
+#include <FL/Fl_Widget.H>
+#include <FL/Fl_Group.H>
+#include <FL/fl_draw.H>
+#include <FL/Fl_Image.H>
+
+void
+fl_no_label(const Fl_Label*,int,int,int,int,Fl_Align) {}
+
+void
+fl_normal_label(const Fl_Label* o, int X, int Y, int W, int H, Fl_Align align)
+{
+ fl_font(o->font, o->size);
+ fl_color((Fl_Color)o->color);
+ fl_draw(o->value, X, Y, W, H, align, o->image);
+}
+
+void
+fl_normal_measure(const Fl_Label* o, int& W, int& H) {
+ fl_font(o->font, o->size);
+ fl_measure(o->value, W, H);
+ if (o->image) {
+ if (o->image->w() > W) W = o->image->w();
+ H += o->image->h();
+ }
+}
+
+#define MAX_LABELTYPE 16
+
+static Fl_Label_Draw_F* table[MAX_LABELTYPE] = {
+ fl_normal_label,
+ fl_no_label,
+ fl_normal_label, // _FL_SHADOW_LABEL,
+ fl_normal_label, // _FL_ENGRAVED_LABEL,
+ fl_normal_label, // _FL_EMBOSSED_LABEL,
+ fl_no_label, // _FL_MULTI_LABEL,
+ fl_no_label, // _FL_ICON_LABEL,
+ // FL_FREE_LABELTYPE+n:
+ fl_no_label, fl_no_label, fl_no_label,
+ fl_no_label, fl_no_label, fl_no_label,
+ fl_no_label, fl_no_label, fl_no_label
+};
+
+static Fl_Label_Measure_F* measure[MAX_LABELTYPE];
+
+void Fl::set_labeltype(Fl_Labeltype t,Fl_Label_Draw_F* f,Fl_Label_Measure_F*m)
+{
+ table[t] = f; measure[t] = m;
+}
+
+////////////////////////////////////////////////////////////////
+
+// draw label with arbitrary alignment in arbitrary box:
+void Fl_Label::draw(int X, int Y, int W, int H, Fl_Align align) const {
+ if (!value && !image) return;
+ table[type](this, X, Y, W, H, align);
+}
+
+void Fl_Label::measure(int& W, int& H) const {
+ if (!value && !image) {
+ W = H = 0;
+ return;
+ }
+
+ Fl_Label_Measure_F* f = ::measure[type]; if (!f) f = fl_normal_measure;
+ f(this, W, H);
+}
+
+// The normal call for a draw() method:
+void Fl_Widget::draw_label() const {
+ int X = x_+Fl::box_dx(box());
+ int W = w_-Fl::box_dw(box());
+ if (W > 11 && align()&(FL_ALIGN_LEFT|FL_ALIGN_RIGHT)) {X += 3; W -= 6;}
+ draw_label(X, y_+Fl::box_dy(box()), W, h_-Fl::box_dh(box()));
+}
+
+// draw() can use this instead to change the bounding box:
+void Fl_Widget::draw_label(int X, int Y, int W, int H) const {
+ // quit if we are not drawing a label inside the widget:
+ if ((align()&15) && !(align() & FL_ALIGN_INSIDE)) return;
+ draw_label(X,Y,W,H,align());
+}
+
+// Anybody can call this to force the label to draw anywhere:
+void Fl_Widget::draw_label(int X, int Y, int W, int H, Fl_Align a) const {
+ if (flags()&SHORTCUT_LABEL) fl_draw_shortcut = 1;
+ Fl_Label l1 = label_;
+ if (!active_r()) {
+ l1.color = fl_inactive((Fl_Color)l1.color);
+ if (l1.deimage) l1.image = l1.deimage;
+ }
+ l1.draw(X,Y,W,H,a);
+ fl_draw_shortcut = 0;
+}
+
+// include these vars here so they can be referenced without including
+// Fl_Input_ code:
+#include <FL/Fl_Input_.H>
+
+//
+// End of "$Id: fl_labeltype.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_line_style.cxx b/third_party/windows/fltk-1.1.10/src/fl_line_style.cxx new file mode 100644 index 0000000..3798da5 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_line_style.cxx @@ -0,0 +1,165 @@ +//
+// "$Id: fl_line_style.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Line style code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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_draw.H>
+#include <FL/x.H>
+#include "flstring.h"
+#include <stdio.h>
+
+#ifdef __APPLE_QUARTZ__
+float fl_quartz_line_width_ = 1.0f;
+static enum CGLineCap fl_quartz_line_cap_ = kCGLineCapButt;
+static enum CGLineJoin fl_quartz_line_join_ = kCGLineJoinMiter;
+static float *fl_quartz_line_pattern = 0;
+static int fl_quartz_line_pattern_size = 0;
+void fl_quartz_restore_line_style_() {
+ CGContextSetLineWidth(fl_gc, fl_quartz_line_width_);
+ CGContextSetLineCap(fl_gc, fl_quartz_line_cap_);
+ CGContextSetLineJoin(fl_gc, fl_quartz_line_join_);
+ CGContextSetLineDash(fl_gc, 0, fl_quartz_line_pattern, fl_quartz_line_pattern_size);
+}
+#endif
+
+void fl_line_style(int style, int width, char* dashes) {
+#ifdef WIN32
+ // According to Bill, the "default" cap and join should be the
+ // "fastest" mode supported for the platform. I don't know why
+ // they should be different (same graphics cards, etc., right?) MRS
+ static DWORD Cap[4]= {PS_ENDCAP_FLAT, PS_ENDCAP_FLAT, PS_ENDCAP_ROUND, PS_ENDCAP_SQUARE};
+ static DWORD Join[4]={PS_JOIN_ROUND, PS_JOIN_MITER, PS_JOIN_ROUND, PS_JOIN_BEVEL};
+ int s1 = PS_GEOMETRIC | Cap[(style>>8)&3] | Join[(style>>12)&3];
+ DWORD a[16]; int n = 0;
+ if (dashes && dashes[0]) {
+ s1 |= PS_USERSTYLE;
+ for (n = 0; n < 16 && *dashes; n++) a[n] = *dashes++;
+ } else {
+ s1 |= style & 0xff; // allow them to pass any low 8 bits for style
+ }
+ if ((style || n) && !width) width = 1; // fix cards that do nothing for 0?
+ LOGBRUSH penbrush = {BS_SOLID,fl_RGB(),0}; // can this be fl_brush()?
+ HPEN newpen = ExtCreatePen(s1, width, &penbrush, n, n ? a : 0);
+ if (!newpen) {
+ Fl::error("fl_line_style(): Could not create GDI pen object.");
+ return;
+ }
+ HPEN oldpen = (HPEN)SelectObject(fl_gc, newpen);
+ DeleteObject(oldpen);
+ DeleteObject(fl_current_xmap->pen);
+ fl_current_xmap->pen = newpen;
+#elif defined(__APPLE_QD__)
+ // QuickDraw supports pen size and pattern, but no arbitrary line styles.
+ static Pattern styles[] = {
+ { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } }, // FL_SOLID
+ { { 0xf0, 0xf0, 0xf0, 0xf0, 0x0f, 0x0f, 0x0f, 0x0f } }, // FL_DASH
+ { { 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 } } // FL_DOT
+ };
+
+ if (!width) width = 1;
+ PenSize(width, width);
+
+ style &= 0xff;
+ if (style > 2) style = 2;
+ PenPat(styles + style);
+#elif defined(__APPLE_QUARTZ__)
+ static enum CGLineCap Cap[4] = { kCGLineCapButt, kCGLineCapButt,
+ kCGLineCapRound, kCGLineCapSquare };
+ static enum CGLineJoin Join[4] = { kCGLineJoinMiter, kCGLineJoinMiter,
+ kCGLineJoinRound, kCGLineJoinBevel };
+ if (width<1) width = 1;
+ fl_quartz_line_width_ = (float)width;
+ fl_quartz_line_cap_ = Cap[(style>>8)&3];
+ fl_quartz_line_join_ = Join[(style>>12)&3];
+ char *d = dashes;
+ static float pattern[16];
+ if (d && *d) {
+ float *p = pattern;
+ while (*d) { *p++ = (float)*d++; }
+ fl_quartz_line_pattern = pattern;
+ fl_quartz_line_pattern_size = d-dashes;
+ } else if (style & 0xff) {
+ char dash, dot, gap;
+ // adjust lengths to account for cap:
+ if (style & 0x200) {
+ dash = char(2*width);
+ dot = 1;
+ gap = char(2*width-1);
+ } else {
+ dash = char(3*width);
+ dot = gap = char(width);
+ }
+ float *p = pattern;
+ switch (style & 0xff) {
+ case FL_DASH: *p++ = dash; *p++ = gap; break;
+ case FL_DOT: *p++ = dot; *p++ = gap; break;
+ case FL_DASHDOT: *p++ = dash; *p++ = gap; *p++ = dot; *p++ = gap; break;
+ case FL_DASHDOTDOT: *p++ = dash; *p++ = gap; *p++ = dot; *p++ = gap; *p++ = dot; *p++ = gap; break;
+ }
+ fl_quartz_line_pattern_size = p-pattern;
+ fl_quartz_line_pattern = pattern;
+ } else {
+ fl_quartz_line_pattern = 0; fl_quartz_line_pattern_size = 0;
+ }
+ fl_quartz_restore_line_style_();
+#else
+ int ndashes = dashes ? strlen(dashes) : 0;
+ // emulate the WIN32 dash patterns on X
+ char buf[7];
+ if (!ndashes && (style&0xff)) {
+ int w = width ? width : 1;
+ char dash, dot, gap;
+ // adjust lengths to account for cap:
+ if (style & 0x200) {
+ dash = char(2*w);
+ dot = 1; // unfortunately 0 does not work
+ gap = char(2*w-1);
+ } else {
+ dash = char(3*w);
+ dot = gap = char(w);
+ }
+ char* p = dashes = buf;
+ switch (style & 0xff) {
+ case FL_DASH: *p++ = dash; *p++ = gap; break;
+ case FL_DOT: *p++ = dot; *p++ = gap; break;
+ case FL_DASHDOT: *p++ = dash; *p++ = gap; *p++ = dot; *p++ = gap; break;
+ case FL_DASHDOTDOT: *p++ = dash; *p++ = gap; *p++ = dot; *p++ = gap; *p++ = dot; *p++ = gap; break;
+ }
+ ndashes = p-buf;
+ }
+ static int Cap[4] = {CapButt, CapButt, CapRound, CapProjecting};
+ static int Join[4] = {JoinMiter, JoinMiter, JoinRound, JoinBevel};
+ XSetLineAttributes(fl_display, fl_gc, width,
+ ndashes ? LineOnOffDash : LineSolid,
+ Cap[(style>>8)&3], Join[(style>>12)&3]);
+ if (ndashes) XSetDashes(fl_display, fl_gc, 0, dashes, ndashes);
+#endif
+}
+
+
+//
+// End of "$Id: fl_line_style.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_open_uri.cxx b/third_party/windows/fltk-1.1.10/src/fl_open_uri.cxx new file mode 100644 index 0000000..f0b5e4f --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_open_uri.cxx @@ -0,0 +1,370 @@ +//
+// "$Id: fl_open_uri.cxx 5636 2007-01-23 20:45:28Z mike $"
+//
+// fl_open_uri() code for FLTK.
+//
+// Test with:
+//
+// gcc -I/fltk/dir -I/fltk/dir/src -DTEST -o fl_open_uri fl_open_uri.cxx -lfltk
+//
+// Copyright 2003-2007 by Michael R Sweet
+//
+// 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.
+//
+
+//
+// Include necessary headers...
+//
+
+#include <FL/filename.H>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include "flstring.h"
+#ifdef WIN32
+# include <windows.h>
+# include <shellapi.h>
+#else
+# include <sys/wait.h>
+# include <signal.h>
+# include <fcntl.h>
+# include <unistd.h>
+#endif // WIN32
+
+
+//
+// Local functions...
+//
+
+#if !defined(WIN32) && !defined(__APPLE__)
+static char *path_find(const char *program, char *filename, int filesize);
+#endif // !WIN32 && !__APPLE__
+#ifndef WIN32
+static int run_program(const char *program, char **argv, char *msg, int msglen);
+#endif // !WIN32
+
+
+/**
+ * Open the specified URI.
+ *
+ * fl_open_uri() opens the specified Uniform Resource Identifier (URI)
+ * using an operating-system dependent program or interface. For URIs
+ * using the "ftp", "http", or "https" schemes, the system default web
+ * browser is used to open the URI, while "mailto" and "news" URIs are
+ * typically opened using the system default mail reader and "file" URIs
+ * are opened using the file system navigator.
+ *
+ * On success, the (optional) msg buffer is filled with the command that
+ * was run to open the URI; on Windows, this will always be "open uri".
+ *
+ * On failure, the msg buffer is filled with an English error message.
+ *
+ * @param uri The URI to open
+ * @param msg Optional buffer which contains the command or error message
+ * @param msglen Length of optional buffer
+ * @return 1 on success, 0 on failure
+ */
+
+int
+fl_open_uri(const char *uri, char *msg, int msglen) {
+ // Supported URI schemes...
+ static const char * const schemes[] = {
+ "file://",
+ "ftp://",
+ "http://",
+ "https://",
+ "mailto:",
+ "news://",
+ NULL
+ };
+
+ // Validate the URI scheme...
+ int i;
+ for (i = 0; schemes[i]; i ++)
+ if (!strncmp(uri, schemes[i], strlen(schemes[i])))
+ break;
+
+ if (!schemes[i]) {
+ if (msg) {
+ char scheme[255];
+ if (sscanf(uri, "%254[^:]", scheme) == 1) {
+ snprintf(msg, msglen, "URI scheme \"%s\" not supported.", scheme);
+ } else {
+ snprintf(msg, msglen, "Bad URI \"%s\"", uri);
+ }
+ }
+
+ return 0;
+ }
+
+#ifdef WIN32
+ if (msg) snprintf(msg, msglen, "open %s", uri);
+
+ return (int)ShellExecute(HWND_DESKTOP, "open", uri, NULL, NULL, SW_SHOW) > 32;
+
+#elif defined(__APPLE__)
+ char *argv[3]; // Command-line arguments
+
+ argv[0] = "open";
+ argv[1] = (char *)uri;
+ argv[2] = 0;
+
+ if (msg) snprintf(msg, msglen, "open %s", uri);
+
+ return run_program("/usr/bin/open", argv, msg, msglen) != 0;
+
+#else // !WIN32 && !__APPLE__
+ // Run any of several well-known commands to open the URI.
+ //
+ // We give preference to the Portland group's xdg-utils
+ // programs which run the user's preferred web browser, etc.
+ // based on the current desktop environment in use. We fall
+ // back on older standards and then finally test popular programs
+ // until we find one we can use.
+ //
+ // Note that we specifically do not support the MAILER and
+ // BROWSER environment variables because we have no idea whether
+ // we need to run the listed commands in a terminal program.
+
+ char command[1024], // Command to run...
+ *argv[4], // Command-line arguments
+ remote[1024]; // Remote-mode command...
+ const char * const *commands; // Array of commands to check...
+ static const char * const browsers[] = {
+ "xdg-open", // Portland
+ "htmlview", // Freedesktop.org
+ "firefox",
+ "mozilla",
+ "netscape",
+ "konqueror", // KDE
+ "opera",
+ "hotjava", // Solaris
+ "mosaic",
+ NULL
+ };
+ static const char * const readers[] = {
+ "xdg-email", // Portland
+ "thunderbird",
+ "mozilla",
+ "netscape",
+ "evolution", // GNOME
+ "kmailservice", // KDE
+ NULL
+ };
+ static const char * const managers[] = {
+ "xdg-open", // Portland
+ "fm", // IRIX
+ "dtaction", // CDE
+ "nautilus", // GNOME
+ "konqueror", // KDE
+ NULL
+ };
+
+ // Figure out which commands to check for...
+ if (!strncmp(uri, "file://", 7)) commands = managers;
+ else if (!strncmp(uri, "mailto:", 7) ||
+ !strncmp(uri, "news:", 5)) commands = readers;
+ else commands = browsers;
+
+ // Find the command to run...
+ for (i = 0; commands[i]; i ++)
+ if (path_find(commands[i], command, sizeof(command))) break;
+
+ if (!commands[i]) {
+ if (msg) {
+ snprintf(msg, msglen, "No helper application found for \"%s\"", uri);
+ }
+
+ return 0;
+ }
+
+ // Handle command-specific arguments...
+ argv[0] = (char *)commands[i];
+
+ if (!strcmp(commands[i], "firefox") ||
+ !strcmp(commands[i], "mozilla") ||
+ !strcmp(commands[i], "netscape") ||
+ !strcmp(commands[i], "thunderbird")) {
+ // program -remote openURL(uri)
+ snprintf(remote, sizeof(remote), "openURL(%s)", uri);
+
+ argv[1] = (char *)"-remote";
+ argv[2] = remote;
+ argv[3] = 0;
+ } else if (!strcmp(commands[i], "dtaction")) {
+ // dtaction open uri
+ argv[1] = (char *)"open";
+ argv[2] = (char *)uri;
+ argv[3] = 0;
+ } else {
+ // program uri
+ argv[1] = (char *)uri;
+ argv[2] = 0;
+ }
+
+ if (msg) {
+ strlcpy(msg, argv[0], msglen);
+
+ for (i = 1; argv[i]; i ++) {
+ strlcat(msg, " ", msglen);
+ strlcat(msg, argv[i], msglen);
+ }
+ }
+
+ return run_program(command, argv, msg, msglen) != 0;
+#endif // WIN32
+}
+
+
+#if !defined(WIN32) && !defined(__APPLE__)
+// Find a program in the path...
+static char *path_find(const char *program, char *filename, int filesize) {
+ const char *path; // Search path
+ char *ptr, // Pointer into filename
+ *end; // End of filename buffer
+
+
+ if ((path = getenv("PATH")) == NULL) path = "/bin:/usr/bin";
+
+ for (ptr = filename, end = filename + filesize - 1; *path; path ++) {
+ if (*path == ':') {
+ if (ptr > filename && ptr[-1] != '/' && ptr < end) *ptr++ = '/';
+
+ strlcpy(ptr, program, end - ptr + 1);
+
+ if (!access(filename, X_OK)) return filename;
+
+ ptr = filename;
+ } else if (ptr < end) *ptr++ = *path;
+ }
+
+ if (ptr > filename) {
+ if (ptr[-1] != '/' && ptr < end) *ptr++ = '/';
+
+ strlcpy(ptr, program, end - ptr + 1);
+
+ if (!access(filename, X_OK)) return filename;
+ }
+
+ return 0;
+}
+#endif // !WIN32 && !__APPLE__
+
+
+#ifndef WIN32
+// Run the specified program, returning 1 on success and 0 on failure
+static int
+run_program(const char *program, char **argv, char *msg, int msglen) {
+ pid_t pid; // Process ID of first child
+ int status; // Exit status from first child
+ sigset_t set, oldset; // Signal masks
+
+
+ // Block SIGCHLD while we run the program...
+ //
+ // Note that I only use the POSIX signal APIs, however older operating
+ // systems may either not support POSIX signals or have side effects.
+ // IRIX, for example, provides three separate and incompatible signal
+ // APIs, so it is possible that an application setting a signal handler
+ // via signal() or sigset() will not have its SIGCHLD signals blocked...
+
+ sigemptyset(&set);
+ sigaddset(&set, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &set, &oldset);
+
+ // Create child processes that actually run the program for us...
+ if ((pid = fork()) == 0) {
+ // First child comes here, fork a second child and exit...
+ if (!fork()) {
+ // Second child comes here, redirect stdin/out/err to /dev/null...
+ close(0);
+ open("/dev/null", O_RDONLY);
+
+ close(1);
+ open("/dev/null", O_WRONLY);
+
+ close(2);
+ open("/dev/null", O_WRONLY);
+
+ // Detach from the current process group...
+ setsid();
+
+ // Run the program...
+ execv(program, argv);
+ _exit(0);
+ } else {
+ // First child gets here, exit immediately...
+ _exit(0);
+ }
+ } else if (pid < 0) {
+ // Restore signal handling...
+ sigprocmask(SIG_SETMASK, &oldset, NULL);
+
+ // Return indicating failure...
+ return 0;
+ }
+
+ // Wait for the first child to exit...
+ while (waitpid(pid, &status, 0) < 0) {
+ if (errno != EINTR) {
+ // Someone else grabbed the child status...
+ if (msg) snprintf(msg, msglen, "waitpid(%ld) failed: %s", (long)pid,
+ strerror(errno));
+
+ // Restore signal handling...
+ sigprocmask(SIG_SETMASK, &oldset, NULL);
+
+ // Return indicating failure...
+ return 0;
+ }
+ }
+
+ // Restore signal handling...
+ sigprocmask(SIG_SETMASK, &oldset, NULL);
+
+ // Return indicating success...
+ return 1;
+}
+#endif // !WIN32
+
+
+#ifdef TEST
+//
+// Test code...
+//
+
+// Open the URI on the command-line...
+int main(int argc, char **argv) {
+ char msg[1024];
+
+
+ if (argc != 2) {
+ puts("Usage: fl_open_uri URI");
+ return 1;
+ }
+
+ if (!fl_open_uri(argv[1], msg, sizeof(msg))) {
+ puts(msg);
+ return 1;
+ } else return 0;
+}
+#endif // TEST
+
+
+//
+// End of "$Id: fl_open_uri.cxx 5636 2007-01-23 20:45:28Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_oval_box.cxx b/third_party/windows/fltk-1.1.10/src/fl_oval_box.cxx new file mode 100644 index 0000000..06132de --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_oval_box.cxx @@ -0,0 +1,66 @@ +//
+// "$Id: fl_oval_box.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Oval box drawing code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+
+// Less-used box types are in seperate files so they are not linked
+// in if not used.
+
+#include <FL/Fl.H>
+#include <FL/fl_draw.H>
+
+static void fl_oval_flat_box(int x, int y, int w, int h, Fl_Color c) {
+ fl_color(c);
+ fl_pie(x, y, w, h, 0, 360);
+}
+
+static void fl_oval_frame(int x, int y, int w, int h, Fl_Color c) {
+ fl_color(c);
+ fl_arc(x, y, w, h, 0, 360);
+}
+
+static void fl_oval_box(int x, int y, int w, int h, Fl_Color c) {
+ fl_oval_flat_box(x,y,w,h,c);
+ fl_oval_frame(x,y,w,h,FL_BLACK);
+}
+
+static void fl_oval_shadow_box(int x, int y, int w, int h, Fl_Color c) {
+ fl_oval_flat_box(x+3,y+3,w,h,FL_DARK3);
+ fl_oval_box(x,y,w,h,c);
+}
+
+extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*);
+Fl_Boxtype fl_define_FL_OVAL_BOX() {
+ fl_internal_boxtype(_FL_OSHADOW_BOX,fl_oval_shadow_box);
+ fl_internal_boxtype(_FL_OVAL_FRAME,fl_oval_frame);
+ fl_internal_boxtype(_FL_OFLAT_BOX,fl_oval_flat_box);
+ fl_internal_boxtype(_FL_OVAL_BOX,fl_oval_box);
+ return _FL_OVAL_BOX;
+}
+
+//
+// End of "$Id: fl_oval_box.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_overlay.cxx b/third_party/windows/fltk-1.1.10/src/fl_overlay.cxx new file mode 100644 index 0000000..6082b69 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_overlay.cxx @@ -0,0 +1,125 @@ +//
+// "$Id: fl_overlay.cxx 5614 2007-01-18 15:25:09Z matt $"
+//
+// Overlay support for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Extremely limited "overlay" support. You can use this to drag out
+// a rectangle in response to mouse events. It is your responsibility
+// to erase the overlay before drawing anything that might intersect
+// it.
+
+#include <FL/x.H>
+#include <FL/fl_draw.H>
+#ifdef __APPLE__
+#include <config.h>
+#endif
+
+//#define USE_XOR
+
+static int px,py,pw,ph;
+
+#ifndef USE_XOR
+#include <stdlib.h>
+static uchar *bgN = 0L, *bgS = 0L, *bgE = 0L, *bgW = 0L;
+static int bgx, bgy, bgw, bgh;
+#endif
+
+static void draw_current_rect() {
+#ifdef USE_XOR
+# ifdef WIN32
+ int old = SetROP2(fl_gc, R2_NOT);
+ fl_rect(px, py, pw, ph);
+ SetROP2(fl_gc, old);
+# elif defined(__APPLE_QD__)
+ PenMode( patXor );
+ fl_rect(px, py, pw, ph);
+ PenMode( patCopy );
+# elif defined(__APPLE_QUARTZ__)
+ // warning: Quartz does not support xor drawing
+ // Use the Fl_Overlay_Window instead.
+ fl_color(FL_WHITE);
+ fl_rect(px, py, pw, ph);
+# else
+ XSetFunction(fl_display, fl_gc, GXxor);
+ XSetForeground(fl_display, fl_gc, 0xffffffff);
+ XDrawRectangle(fl_display, fl_window, fl_gc, px, py, pw, ph);
+ XSetFunction(fl_display, fl_gc, GXcopy);
+# endif
+#else
+ if (bgN) { free(bgN); bgN = 0L; }
+ if (bgS) { free(bgS); bgS = 0L; }
+ if (bgE) { free(bgE); bgE = 0L; }
+ if (bgW) { free(bgW); bgW = 0L; }
+ if (pw>0 && ph>0) {
+ bgE = fl_read_image(0L, px+pw-1, py, 1, ph);
+ bgW = fl_read_image(0L, px, py, 1, ph);
+ bgS = fl_read_image(0L, px, py+ph-1, pw, 1);
+ bgN = fl_read_image(0L, px, py, pw, 1);
+ bgx = px; bgy = py;
+ bgw = pw; bgh = ph;
+ }
+ fl_color(FL_WHITE);
+ fl_line_style(FL_SOLID);
+ fl_rect(px, py, pw, ph);
+ fl_color(FL_BLACK);
+ fl_line_style(FL_DOT);
+ fl_rect(px, py, pw, ph);
+ fl_line_style(FL_SOLID);
+#endif
+}
+
+static void erase_current_rect() {
+#ifdef USE_XOR
+# ifdef __APPLE_QUARTZ__
+ fl_rect(px, py, pw, ph);
+# else
+ draw_current_rect();
+# endif
+#else
+ if (bgN) fl_draw_image(bgN, bgx, bgy, bgw, 1);
+ if (bgS) fl_draw_image(bgS, bgx, bgy+bgh-1, bgw, 1);
+ if (bgW) fl_draw_image(bgW, bgx, bgy, 1, bgh);
+ if (bgE) fl_draw_image(bgE, bgx+bgw-1, bgy, 1, bgh);
+#endif
+}
+
+void fl_overlay_clear() {
+ if (pw > 0) {erase_current_rect(); pw = 0;}
+}
+
+void fl_overlay_rect(int x, int y, int w, int h) {
+ if (w < 0) {x += w; w = -w;} else if (!w) w = 1;
+ if (h < 0) {y += h; h = -h;} else if (!h) h = 1;
+ if (pw > 0) {
+ if (x==px && y==py && w==pw && h==ph) return;
+ erase_current_rect();
+ }
+ px = x; py = y; pw = w; ph = h;
+ draw_current_rect();
+}
+
+//
+// End of "$Id: fl_overlay.cxx 5614 2007-01-18 15:25:09Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_overlay_visual.cxx b/third_party/windows/fltk-1.1.10/src/fl_overlay_visual.cxx new file mode 100644 index 0000000..4c72fb1 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_overlay_visual.cxx @@ -0,0 +1,105 @@ +//
+// "$Id: fl_overlay_visual.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// X overlay support for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Return an overlay visual, if any. Also allocate a colormap and
+// record the depth for fl_color() to use.
+// Another disgusting X interface, based on code extracted and
+// purified with great difficulty from XLayerUtil.cxx:
+
+#include <config.h>
+#if HAVE_OVERLAY
+#include <FL/Fl.H>
+#include <FL/x.H>
+
+// SERVER_OVERLAY_VISUALS property element:
+struct OverlayInfo {
+ long overlay_visual;
+ long transparent_type;
+ long value;
+ long layer;
+};
+
+extern Colormap fl_overlay_colormap;
+extern XVisualInfo* fl_overlay_visual;
+extern ulong fl_transparent_pixel;
+
+XVisualInfo *fl_find_overlay_visual() {
+ static char beenhere;
+ if (beenhere) return fl_overlay_visual;
+ beenhere = 1;
+
+ fl_open_display();
+ Atom overlayVisualsAtom =
+ XInternAtom(fl_display,"SERVER_OVERLAY_VISUALS",1);
+ if (!overlayVisualsAtom) return 0;
+ OverlayInfo *overlayInfo;
+ ulong sizeData, bytesLeft;
+ Atom actualType;
+ int actualFormat;
+ if (XGetWindowProperty(fl_display, RootWindow(fl_display, fl_screen),
+ overlayVisualsAtom, 0L, 10000L, False,
+ overlayVisualsAtom, &actualType, &actualFormat,
+ &sizeData, &bytesLeft,
+ (unsigned char **) &overlayInfo)) return 0;
+
+ if (actualType == overlayVisualsAtom && actualFormat == 32) {
+ int n = int(sizeData/4);
+ XVisualInfo* v = 0;
+ // find the greatest depth that has a transparent pixel:
+ for (int i = 0; i < n; i++) {
+ if (overlayInfo[i].transparent_type != 1) continue;
+ if (overlayInfo[i].layer <= 0) continue;
+ XVisualInfo templt;
+ templt.visualid = overlayInfo[i].overlay_visual;
+ int num;
+ XVisualInfo *v1=XGetVisualInfo(fl_display, VisualIDMask, &templt, &num);
+ if (v1->screen == fl_screen && v1->c_class == PseudoColor
+ && (!v || v1->depth > v->depth && v1->depth <= 8)) {
+ if (v) XFree((char*)v);
+ v = v1;
+ fl_transparent_pixel = overlayInfo[i].value;
+ } else {
+ XFree((char*)v1);
+ }
+ }
+ if (v) {
+ fl_overlay_visual = v;
+ fl_overlay_colormap =
+ XCreateColormap(fl_display, RootWindow(fl_display, fl_screen),
+ v->visual, AllocNone);
+ }
+ }
+ XFree((char*)overlayInfo);
+ //printf("overlay visual %ld selected\n", fl_overlay_visual->visualid);
+ return fl_overlay_visual;
+}
+
+#endif
+
+//
+// End of "$Id: fl_overlay_visual.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_plastic.cxx b/third_party/windows/fltk-1.1.10/src/fl_plastic.cxx new file mode 100644 index 0000000..af09ed9 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_plastic.cxx @@ -0,0 +1,381 @@ +//
+// "$Id: fl_plastic.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// "Plastic" drawing routines for the Fast Light Tool Kit (FLTK).
+//
+// These box types provide a cross between Aqua and KDE buttons; kindof
+// like translucent plastic buttons...
+//
+// Copyright 2001-2005 by Michael Sweet.
+//
+// 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
+//
+
+// Box drawing code for an obscure box type.
+// These box types are in seperate files so they are not linked
+// in if not used.
+
+#include <FL/Fl.H>
+#include <FL/fl_draw.H>
+#include "flstring.h"
+
+//
+// Uncomment the following line to restore the old plastic box type
+// appearance.
+//
+
+//#define USE_OLD_PLASTIC_BOX
+#define USE_OLD_PLASTIC_COLOR
+
+extern uchar *fl_gray_ramp();
+
+inline Fl_Color shade_color(uchar gc, Fl_Color bc) {
+#ifdef USE_OLD_PLASTIC_COLOR
+ return fl_color_average((Fl_Color)gc, bc, 0.75f);
+#else
+ unsigned grgb = Fl::get_color((Fl_Color)gc),
+ brgb = Fl::get_color(bc);
+ int red, green, blue, gray;
+
+
+ gray = ((grgb >> 24) & 255);
+ red = gray * ((brgb >> 24) & 255) / 255 + gray * gray / 510;
+ gray = ((grgb >> 16) & 255);
+ green = gray * ((brgb >> 16) & 255) / 255 + gray * gray / 510;
+ gray = ((grgb >> 8) & 255);
+ blue = gray * ((brgb >> 8) & 255) / 255 + gray * gray / 510;
+
+ if (red > 255)
+ red = 255;
+
+ if (green > 255)
+ green = 255;
+
+ if (blue > 255)
+ blue = 255;
+
+ if (Fl::draw_box_active())
+ return fl_rgb_color(red, green, blue);
+ else
+ return fl_color_average(FL_GRAY, fl_rgb_color(red, green, blue), 0.75f);
+#endif // USE_OLD_PLASTIC_COLOR
+}
+
+
+static void frame_rect(int x, int y, int w, int h, const char *c, Fl_Color bc) {
+ uchar *g = fl_gray_ramp();
+ int b = strlen(c) / 4 + 1;
+
+ for (x += b, y += b, w -= 2 * b, h -= 2 * b; b > 1; b --)
+ {
+ // Draw lines around the perimeter of the button, 4 colors per
+ // circuit.
+ fl_color(shade_color(g[*c++], bc));
+ fl_line(x, y + h + b, x + w - 1, y + h + b, x + w + b - 1, y + h);
+ fl_color(shade_color(g[*c++], bc));
+ fl_line(x + w + b - 1, y + h, x + w + b - 1, y, x + w - 1, y - b);
+ fl_color(shade_color(g[*c++], bc));
+ fl_line(x + w - 1, y - b, x, y - b, x - b, y);
+ fl_color(shade_color(g[*c++], bc));
+ fl_line(x - b, y, x - b, y + h, x, y + h + b);
+ }
+}
+
+
+static void frame_round(int x, int y, int w, int h, const char *c, Fl_Color bc) {
+ uchar *g = fl_gray_ramp();
+ int b = strlen(c) / 4 + 1;
+
+ if (w==h) {
+ for (; b > 1; b --, x ++, y ++, w -= 2, h -= 2)
+ {
+ fl_color(shade_color(g[*c++], bc));
+ fl_arc(x, y, w, h, 45.0, 135.0);
+ fl_color(shade_color(g[*c++], bc));
+ fl_arc(x, y, w, h, 315.0, 405.0);
+ fl_color(shade_color(g[*c++], bc));
+ fl_arc(x, y, w, h, 225.0, 315.0);
+ fl_color(shade_color(g[*c++], bc));
+ fl_arc(x, y, w, h, 135.0, 225.0);
+ }
+ } else if (w>h) {
+ int d = h/2;
+ for (; b > 1; d--, b --, x ++, y ++, w -= 2, h -= 2)
+ {
+ fl_color(shade_color(g[*c++], bc));
+ fl_arc(x, y, h, h, 90.0, 135.0);
+ fl_xyline(x+d, y, x+w-d);
+ fl_arc(x+w-h, y, h, h, 45.0, 90.0);
+ fl_color(shade_color(g[*c++], bc));
+ fl_arc(x+w-h, y, h, h, 315.0, 405.0);
+ fl_color(shade_color(g[*c++], bc));
+ fl_arc(x+w-h, y, h, h, 270.0, 315.0);
+ fl_xyline(x+d, y+h-1, x+w-d);
+ fl_arc(x, y, h, h, 225.0, 270.0);
+ fl_color(shade_color(g[*c++], bc));
+ fl_arc(x, y, h, h, 135.0, 225.0);
+ }
+ } else if (w<h) {
+ int d = w/2;
+ for (; b > 1; d--, b --, x ++, y ++, w -= 2, h -= 2)
+ {
+ fl_color(shade_color(g[*c++], bc));
+ fl_arc(x, y, w, w, 45.0, 135.0);
+ fl_color(shade_color(g[*c++], bc));
+ fl_arc(x, y, w, w, 0.0, 45.0);
+ fl_yxline(x+w-1, y+d, y+h-d);
+ fl_arc(x, y+h-w, w, w, 315.0, 360.0);
+ fl_color(shade_color(g[*c++], bc));
+ fl_arc(x, y+h-w, w, w, 225.0, 315.0);
+ fl_color(shade_color(g[*c++], bc));
+ fl_arc(x, y+h-w, w, w, 180.0, 225.0);
+ fl_yxline(x, y+d, y+h-d);
+ fl_arc(x, y, w, w, 135.0, 180.0);
+ }
+ }
+}
+
+
+static void shade_rect(int x, int y, int w, int h, const char *c, Fl_Color bc) {
+ uchar *g = fl_gray_ramp();
+ int i, j;
+ int clen = strlen(c) - 1;
+ int chalf = clen / 2;
+ int cstep = 1;
+
+ if (h < (w * 2)) {
+ // Horizontal shading...
+ if (clen >= h) cstep = 2;
+
+ for (i = 0, j = 0; j < chalf; i ++, j += cstep) {
+ // Draw the top line and points...
+ fl_color(shade_color(g[c[i]], bc));
+ fl_xyline(x + 1, y + i, x + w - 2);
+
+ fl_color(shade_color(g[c[i] - 2], bc));
+ fl_point(x, y + i + 1);
+ fl_point(x + w - 1, y + i + 1);
+
+ // Draw the bottom line and points...
+ fl_color(shade_color(g[c[clen - i]], bc));
+ fl_xyline(x + 1, y + h - i, x + w - 2);
+
+ fl_color(shade_color(g[c[clen - i] - 2], bc));
+ fl_point(x, y + h - i);
+ fl_point(x + w - 1, y + h - i);
+ }
+
+ // Draw the interior and sides...
+ i = chalf / cstep;
+
+ fl_color(shade_color(g[c[chalf]], bc));
+ fl_rectf(x + 1, y + i, w - 2, h - 2 * i + 1);
+
+ fl_color(shade_color(g[c[chalf] - 2], bc));
+ fl_yxline(x, y + i, y + h - i);
+ fl_yxline(x + w - 1, y + i, y + h - i);
+ } else {
+ // Vertical shading...
+ if (clen >= w) cstep = 2;
+
+ for (i = 0, j = 0; j < chalf; i ++, j += cstep) {
+ // Draw the left line and points...
+ fl_color(shade_color(g[c[i]], bc));
+ fl_yxline(x + i, y + 1, y + h - 1);
+
+ fl_color(shade_color(g[c[i] - 2], bc));
+ fl_point(x + i + 1, y);
+ fl_point(x + i + 1, y + h);
+
+ // Draw the right line and points...
+ fl_color(shade_color(g[c[clen - i]], bc));
+ fl_yxline(x + w - 1 - i, y + 1, y + h - 1);
+
+ fl_color(shade_color(g[c[clen - i] - 2], bc));
+ fl_point(x + w - 2 - i, y);
+ fl_point(x + w - 2 - i, y + h);
+ }
+
+ // Draw the interior, top, and bottom...
+ i = chalf / cstep;
+
+ fl_color(shade_color(g[c[chalf]], bc));
+ fl_rectf(x + i, y + 1, w - 2 * i, h - 1);
+
+ fl_color(shade_color(g[c[chalf] - 2], bc));
+ fl_xyline(x + i, y, x + w - i);
+ fl_xyline(x + i, y + h, x + w - i);
+ }
+}
+
+static void shade_round(int x, int y, int w, int h, const char *c, Fl_Color bc) {
+ uchar *g = fl_gray_ramp();
+ int i;
+ int clen = strlen(c) - 1;
+ int chalf = clen / 2;
+
+ if (w>h) {
+ int d = h/2;
+ const int na = 8;
+ for (i=0; i<chalf; i++, d--, x++, y++, w-=2, h-=2)
+ {
+ fl_color(shade_color(g[c[i]], bc));
+ fl_pie(x, y, h, h, 90.0, 135.0+i*na);
+ fl_xyline(x+d, y, x+w-d);
+ fl_pie(x+w-h, y, h, h, 45.0+i*na, 90.0);
+ fl_color(shade_color(g[c[i] - 2], bc));
+ fl_pie(x+w-h, y, h, h, 315.0+i*na, 405.0+i*na);
+ fl_color(shade_color(g[c[clen - i]], bc));
+ fl_pie(x+w-h, y, h, h, 270.0, 315.0+i*na);
+ fl_xyline(x+d, y+h-1, x+w-d);
+ fl_pie(x, y, h, h, 225.0+i*na, 270.0);
+ fl_color(shade_color(g[c[clen - i] - 2], bc));
+ fl_pie(x, y, h, h, 135.0+i*na, 225.0+i*na);
+ }
+ fl_color(shade_color(g[c[chalf]], bc));
+ fl_rectf(x+d, y, w-h+1, h+1);
+ fl_pie(x, y, h, h, 90.0, 270.0);
+ fl_pie(x+w-h, y, h, h, 270.0, 90.0);
+ } else {
+ int d = w/2;
+ const int na = 8;
+ for (i=0; i<chalf; i++, d--, x++, y++, w-=2, h-=2)
+ {
+ fl_color(shade_color(g[c[i]], bc));
+ fl_pie(x, y, w, w, 45.0+i*na, 135.0+i*na);
+ fl_color(shade_color(g[c[i] - 2], bc));
+ fl_pie(x, y, w, w, 0.0, 45.0+i*na);
+ fl_yxline(x+w-1, y+d, y+h-d);
+ fl_pie(x, y+h-w, w, w, 315.0+i*na, 360.0);
+ fl_color(shade_color(g[c[clen - i]], bc));
+ fl_pie(x, y+h-w, w, w, 225.0+i*na, 315.0+i*na);
+ fl_color(shade_color(g[c[clen - i] - 2], bc));
+ fl_pie(x, y+h-w, w, w, 180.0, 225.0+i*na);
+ fl_yxline(x, y+d, y+h-d);
+ fl_pie(x, y, w, w, 135.0+i*na, 180.0);
+ }
+ fl_color(shade_color(g[c[chalf]], bc));
+ fl_rectf(x, y+d, w+1, h-w+1);
+ fl_pie(x, y, w, w, 0.0, 180.0);
+ fl_pie(x, y+h-w, w, w, 180.0, 360.0);
+ }
+}
+
+
+static void up_frame(int x, int y, int w, int h, Fl_Color c) {
+ frame_rect(x, y, w, h - 1, "KLDIIJLM", c);
+}
+
+
+static void narrow_thin_box(int x, int y, int w, int h, Fl_Color c) {
+ if (h<=0 || w<=0) return;
+ uchar *g = fl_gray_ramp();
+ fl_color(shade_color(g['R'], c));
+ fl_rectf(x+1, y+1, w-2, h-2);
+ fl_color(shade_color(g['I'], c));
+ if (w > 1) {
+ fl_xyline(x+1, y, x+w-2);
+ fl_xyline(x+1, y+h-1, x+w-2);
+ }
+ if (h > 1) {
+ fl_yxline(x, y+1, y+h-2);
+ fl_yxline(x+w-1, y+1, y+h-2);
+ }
+}
+
+
+static void thin_up_box(int x, int y, int w, int h, Fl_Color c) {
+#ifdef USE_OLD_PLASTIC_BOX
+ shade_rect(x + 2, y + 2, w - 4, h - 5, "RVQNOPQRSTUVWVQ", c);
+ up_frame(x, y, w, h, c);
+#else
+ if (w > 4 && h > 4) {
+ shade_rect(x + 1, y + 1, w - 2, h - 3, "RQOQSUWQ", c);
+ frame_rect(x, y, w, h - 1, "IJLM", c);
+ } else {
+ narrow_thin_box(x, y, w, h, c);
+ }
+#endif // USE_OLD_PLASTIC_BOX
+}
+
+
+static void up_box(int x, int y, int w, int h, Fl_Color c) {
+#ifdef USE_OLD_PLASTIC_BOX
+ shade_rect(x + 2, y + 2, w - 4, h - 5, "RVQNOPQRSTUVWVQ", c);
+ up_frame(x, y, w, h, c);
+#else
+ if (w > 8 && h > 8) {
+ shade_rect(x + 1, y + 1, w - 2, h - 3, "RVQNOPQRSTUVWVQ", c);
+ frame_rect(x, y, w, h - 1, "IJLM", c);
+ } else {
+ thin_up_box(x, y, w, h, c);
+ }
+#endif // USE_OLD_PLASTIC_BOX
+}
+
+
+static void up_round(int x, int y, int w, int h, Fl_Color c) {
+ shade_round(x, y, w, h, "RVQNOPQRSTUVWVQ", c);
+ frame_round(x, y, w, h, "IJLM", c);
+}
+
+
+static void down_frame(int x, int y, int w, int h, Fl_Color c) {
+ frame_rect(x, y, w, h - 1, "LLLLTTRR", c);
+}
+
+
+static void down_box(int x, int y, int w, int h, Fl_Color c) {
+ if (w > 6 && h > 6) {
+ shade_rect(x + 2, y + 2, w - 4, h - 5, "STUVWWWVT", c);
+ down_frame(x, y, w, h, c);
+ }
+ else {
+ narrow_thin_box(x, y, w, h, c);
+ }
+}
+
+
+static void down_round(int x, int y, int w, int h, Fl_Color c) {
+ shade_round(x, y, w, h, "STUVWWWVT", c);
+ frame_round(x, y, w, h, "IJLM", c);
+}
+
+
+extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*);
+
+
+Fl_Boxtype fl_define_FL_PLASTIC_UP_BOX() {
+ fl_internal_boxtype(_FL_PLASTIC_UP_BOX, up_box);
+ fl_internal_boxtype(_FL_PLASTIC_DOWN_BOX, down_box);
+ fl_internal_boxtype(_FL_PLASTIC_UP_FRAME, up_frame);
+ fl_internal_boxtype(_FL_PLASTIC_DOWN_FRAME, down_frame);
+ fl_internal_boxtype(_FL_PLASTIC_THIN_UP_BOX, thin_up_box);
+ fl_internal_boxtype(_FL_PLASTIC_THIN_DOWN_BOX, down_box);
+ fl_internal_boxtype(_FL_PLASTIC_ROUND_UP_BOX, up_round);
+ fl_internal_boxtype(_FL_PLASTIC_ROUND_DOWN_BOX, down_round);
+
+ return _FL_PLASTIC_UP_BOX;
+}
+
+
+//
+// End of "$Id: fl_plastic.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_read_image.cxx b/third_party/windows/fltk-1.1.10/src/fl_read_image.cxx new file mode 100644 index 0000000..44e5545 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_read_image.cxx @@ -0,0 +1,503 @@ +//
+// "$Id: fl_read_image.cxx 6475 2008-10-19 20:35:32Z matt $"
+//
+// X11 image reading routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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/x.H>
+#include <FL/Fl.H>
+#include <FL/fl_draw.H>
+#include "flstring.h"
+
+#ifdef DEBUG
+# include <stdio.h>
+#endif // DEBUG
+
+#ifdef WIN32
+# include "fl_read_image_win32.cxx"
+#elif defined(__APPLE__)
+# include "fl_read_image_mac.cxx"
+#else
+# include <X11/Xutil.h>
+# ifdef __sgi
+# include <X11/extensions/readdisplay.h>
+# else
+# include <stdlib.h>
+# endif // __sgi
+
+// Defined in fl_color.cxx
+extern uchar fl_redmask, fl_greenmask, fl_bluemask;
+extern int fl_redshift, fl_greenshift, fl_blueshift, fl_extrashift;
+
+//
+// 'fl_subimage_offsets()' - Calculate subimage offsets for an axis
+static inline int
+fl_subimage_offsets(int a, int aw, int b, int bw, int &obw)
+{
+ int off;
+ int ob;
+
+ if (b >= a) {
+ ob = b;
+ off = 0;
+ } else {
+ ob = a;
+ off = a - b;
+ }
+
+ bw -= off;
+
+ if (ob + bw <= a + aw) {
+ obw = bw;
+ } else {
+ obw = (a + aw) - ob;
+ }
+
+ return off;
+}
+
+// this handler will catch and ignore exceptions during XGetImage
+// to avoid an application crash
+static int xgetimageerrhandler(Display *display, XErrorEvent *error) {
+ return 0;
+}
+
+//
+// 'fl_read_image()' - Read an image from the current window.
+//
+
+uchar * // O - Pixel buffer or NULL if failed
+fl_read_image(uchar *p, // I - Pixel buffer or NULL to allocate
+ int X, // I - Left position
+ int Y, // I - Top position
+ int w, // I - Width of area to read
+ int h, // I - Height of area to read
+ int alpha) { // I - Alpha value for image (0 for none)
+ XImage *image; // Captured image
+ int i, maxindex; // Looping vars
+ int x, y; // Current X & Y in image
+ int d; // Depth of image
+ unsigned char *line, // Array to hold image row
+ *line_ptr; // Pointer to current line image
+ unsigned char *pixel; // Current color value
+ XColor colors[4096]; // Colors from the colormap...
+ unsigned char cvals[4096][3]; // Color values from the colormap...
+ unsigned index_mask,
+ index_shift,
+ red_mask,
+ red_shift,
+ green_mask,
+ green_shift,
+ blue_mask,
+ blue_shift;
+
+
+ //
+ // Under X11 we have the option of the XGetImage() interface or SGI's
+ // ReadDisplay extension which does all of the really hard work for
+ // us...
+ //
+
+# ifdef __sgi
+ if (XReadDisplayQueryExtension(fl_display, &i, &i)) {
+ image = XReadDisplay(fl_display, fl_window, X, Y, w, h, 0, NULL);
+ } else
+# else
+ image = 0;
+# endif // __sgi
+
+ if (!image) {
+ // fetch absolute coordinates
+ int dx, dy, sx, sy, sw, sh;
+ Window child_win;
+ Fl_Window *win = fl_find(fl_window);
+ if (win) {
+ XTranslateCoordinates(fl_display, fl_window,
+ RootWindow(fl_display, fl_screen), X, Y, &dx, &dy, &child_win);
+ // screen dimensions
+ Fl::screen_xywh(sx, sy, sw, sh, fl_screen);
+ }
+ if (!win || (dx >= sx && dy >= sy && dx + w <= sw && dy + h <= sh)) {
+ // the image is fully contained, we can use the traditional method
+ // however, if the window is obscured etc. the function will still fail. Make sure we
+ // catch the error and continue, otherwise an exception will be thrown.
+ XErrorHandler old_handler = XSetErrorHandler(xgetimageerrhandler);
+ image = XGetImage(fl_display, fl_window, X, Y, w, h, AllPlanes, ZPixmap);
+ XSetErrorHandler(old_handler);
+ } else {
+ // image is crossing borders, determine visible region
+ int nw, nh, noffx, noffy;
+ noffx = fl_subimage_offsets(sx, sw, dx, w, nw);
+ noffy = fl_subimage_offsets(sy, sh, dy, h, nh);
+ if (nw <= 0 || nh <= 0) return 0;
+
+ // allocate the image
+ int bpp = fl_visual->depth + ((fl_visual->depth / 8) % 2) * 8;
+ char* buf = (char*)malloc(bpp / 8 * w * h);
+ image = XCreateImage(fl_display, fl_visual->visual,
+ fl_visual->depth, ZPixmap, 0, buf, w, h, bpp, 0);
+ if (!image) {
+ if (buf) free(buf);
+ return 0;
+ }
+
+ XErrorHandler old_handler = XSetErrorHandler(xgetimageerrhandler);
+ XImage *subimg = XGetSubImage(fl_display, fl_window, X + noffx, Y + noffy,
+ nw, nh, AllPlanes, ZPixmap, image, noffx, noffy);
+ XSetErrorHandler(old_handler);
+ if (!subimg) {
+ XDestroyImage(image);
+ return 0;
+ }
+ }
+ }
+
+ if (!image) return 0;
+
+#ifdef DEBUG
+ printf("width = %d\n", image->width);
+ printf("height = %d\n", image->height);
+ printf("xoffset = %d\n", image->xoffset);
+ printf("format = %d\n", image->format);
+ printf("data = %p\n", image->data);
+ printf("byte_order = %d\n", image->byte_order);
+ printf("bitmap_unit = %d\n", image->bitmap_unit);
+ printf("bitmap_bit_order = %d\n", image->bitmap_bit_order);
+ printf("bitmap_pad = %d\n", image->bitmap_pad);
+ printf("depth = %d\n", image->depth);
+ printf("bytes_per_line = %d\n", image->bytes_per_line);
+ printf("bits_per_pixel = %d\n", image->bits_per_pixel);
+ printf("red_mask = %08x\n", image->red_mask);
+ printf("green_mask = %08x\n", image->green_mask);
+ printf("blue_mask = %08x\n", image->blue_mask);
+ printf("map_entries = %d\n", fl_visual->visual->map_entries);
+#endif // DEBUG
+
+ d = alpha ? 4 : 3;
+
+ // Allocate the image data array as needed...
+ if (!p) p = new uchar[w * h * d];
+
+ // Initialize the default colors/alpha in the whole image...
+ memset(p, alpha, w * h * d);
+
+ // Check that we have valid mask/shift values...
+ if (!image->red_mask && image->bits_per_pixel > 12) {
+ // Greater than 12 bits must be TrueColor...
+ image->red_mask = fl_visual->visual->red_mask;
+ image->green_mask = fl_visual->visual->green_mask;
+ image->blue_mask = fl_visual->visual->blue_mask;
+
+#ifdef DEBUG
+ puts("\n---- UPDATED ----");
+ printf("fl_redmask = %08x\n", fl_redmask);
+ printf("fl_redshift = %d\n", fl_redshift);
+ printf("fl_greenmask = %08x\n", fl_greenmask);
+ printf("fl_greenshift = %d\n", fl_greenshift);
+ printf("fl_bluemask = %08x\n", fl_bluemask);
+ printf("fl_blueshift = %d\n", fl_blueshift);
+ printf("red_mask = %08x\n", image->red_mask);
+ printf("green_mask = %08x\n", image->green_mask);
+ printf("blue_mask = %08x\n", image->blue_mask);
+#endif // DEBUG
+ }
+
+ // Check if we have colormap image...
+ if (!image->red_mask) {
+ // Get the colormap entries for this window...
+ maxindex = fl_visual->visual->map_entries;
+
+ for (i = 0; i < maxindex; i ++) colors[i].pixel = i;
+
+ XQueryColors(fl_display, fl_colormap, colors, maxindex);
+
+ for (i = 0; i < maxindex; i ++) {
+ cvals[i][0] = colors[i].red >> 8;
+ cvals[i][1] = colors[i].green >> 8;
+ cvals[i][2] = colors[i].blue >> 8;
+ }
+
+ // Read the pixels and output an RGB image...
+ for (y = 0; y < image->height; y ++) {
+ pixel = (unsigned char *)(image->data + y * image->bytes_per_line);
+ line = p + y * w * d;
+
+ switch (image->bits_per_pixel) {
+ case 1 :
+ for (x = image->width, line_ptr = line, index_mask = 128;
+ x > 0;
+ x --, line_ptr += d) {
+ if (*pixel & index_mask) {
+ line_ptr[0] = cvals[1][0];
+ line_ptr[1] = cvals[1][1];
+ line_ptr[2] = cvals[1][2];
+ } else {
+ line_ptr[0] = cvals[0][0];
+ line_ptr[1] = cvals[0][1];
+ line_ptr[2] = cvals[0][2];
+ }
+
+ if (index_mask > 1) {
+ index_mask >>= 1;
+ } else {
+ index_mask = 128;
+ pixel ++;
+ }
+ }
+ break;
+
+ case 2 :
+ for (x = image->width, line_ptr = line, index_shift = 6;
+ x > 0;
+ x --, line_ptr += d) {
+ i = (*pixel >> index_shift) & 3;
+
+ line_ptr[0] = cvals[i][0];
+ line_ptr[1] = cvals[i][1];
+ line_ptr[2] = cvals[i][2];
+
+ if (index_shift > 0) {
+ index_mask >>= 2;
+ index_shift -= 2;
+ } else {
+ index_mask = 192;
+ index_shift = 6;
+ pixel ++;
+ }
+ }
+ break;
+
+ case 4 :
+ for (x = image->width, line_ptr = line, index_shift = 4;
+ x > 0;
+ x --, line_ptr += d) {
+ if (index_shift == 4) i = (*pixel >> 4) & 15;
+ else i = *pixel & 15;
+
+ line_ptr[0] = cvals[i][0];
+ line_ptr[1] = cvals[i][1];
+ line_ptr[2] = cvals[i][2];
+
+ if (index_shift > 0) {
+ index_shift = 0;
+ } else {
+ index_shift = 4;
+ pixel ++;
+ }
+ }
+ break;
+
+ case 8 :
+ for (x = image->width, line_ptr = line;
+ x > 0;
+ x --, line_ptr += d, pixel ++) {
+ line_ptr[0] = cvals[*pixel][0];
+ line_ptr[1] = cvals[*pixel][1];
+ line_ptr[2] = cvals[*pixel][2];
+ }
+ break;
+
+ case 12 :
+ for (x = image->width, line_ptr = line, index_shift = 0;
+ x > 0;
+ x --, line_ptr += d) {
+ if (index_shift == 0) {
+ i = ((pixel[0] << 4) | (pixel[1] >> 4)) & 4095;
+ } else {
+ i = ((pixel[1] << 8) | pixel[2]) & 4095;
+ }
+
+ line_ptr[0] = cvals[i][0];
+ line_ptr[1] = cvals[i][1];
+ line_ptr[2] = cvals[i][2];
+
+ if (index_shift == 0) {
+ index_shift = 4;
+ } else {
+ index_shift = 0;
+ pixel += 3;
+ }
+ }
+ break;
+ }
+ }
+ } else {
+ // RGB(A) image, so figure out the shifts & masks...
+ red_mask = image->red_mask;
+ red_shift = 0;
+
+ while ((red_mask & 1) == 0) {
+ red_mask >>= 1;
+ red_shift ++;
+ }
+
+ green_mask = image->green_mask;
+ green_shift = 0;
+
+ while ((green_mask & 1) == 0) {
+ green_mask >>= 1;
+ green_shift ++;
+ }
+
+ blue_mask = image->blue_mask;
+ blue_shift = 0;
+
+ while ((blue_mask & 1) == 0) {
+ blue_mask >>= 1;
+ blue_shift ++;
+ }
+
+ // Read the pixels and output an RGB image...
+ for (y = 0; y < image->height; y ++) {
+ pixel = (unsigned char *)(image->data + y * image->bytes_per_line);
+ line = p + y * w * d;
+
+ switch (image->bits_per_pixel) {
+ case 8 :
+ for (x = image->width, line_ptr = line;
+ x > 0;
+ x --, line_ptr += d, pixel ++) {
+ i = *pixel;
+
+ line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask;
+ line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask;
+ line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask;
+ }
+ break;
+
+ case 12 :
+ for (x = image->width, line_ptr = line, index_shift = 0;
+ x > 0;
+ x --, line_ptr += d) {
+ if (index_shift == 0) {
+ i = ((pixel[0] << 4) | (pixel[1] >> 4)) & 4095;
+ } else {
+ i = ((pixel[1] << 8) | pixel[2]) & 4095;
+ }
+
+ line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask;
+ line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask;
+ line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask;
+
+ if (index_shift == 0) {
+ index_shift = 4;
+ } else {
+ index_shift = 0;
+ pixel += 3;
+ }
+ }
+ break;
+
+ case 16 :
+ if (image->byte_order == LSBFirst) {
+ // Little-endian...
+ for (x = image->width, line_ptr = line;
+ x > 0;
+ x --, line_ptr += d, pixel += 2) {
+ i = (pixel[1] << 8) | pixel[0];
+
+ line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask;
+ line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask;
+ line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask;
+ }
+ } else {
+ // Big-endian...
+ for (x = image->width, line_ptr = line;
+ x > 0;
+ x --, line_ptr += d, pixel += 2) {
+ i = (pixel[0] << 8) | pixel[1];
+
+ line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask;
+ line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask;
+ line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask;
+ }
+ }
+ break;
+
+ case 24 :
+ if (image->byte_order == LSBFirst) {
+ // Little-endian...
+ for (x = image->width, line_ptr = line;
+ x > 0;
+ x --, line_ptr += d, pixel += 3) {
+ i = (((pixel[2] << 8) | pixel[1]) << 8) | pixel[0];
+
+ line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask;
+ line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask;
+ line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask;
+ }
+ } else {
+ // Big-endian...
+ for (x = image->width, line_ptr = line;
+ x > 0;
+ x --, line_ptr += d, pixel += 3) {
+ i = (((pixel[0] << 8) | pixel[1]) << 8) | pixel[2];
+
+ line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask;
+ line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask;
+ line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask;
+ }
+ }
+ break;
+
+ case 32 :
+ if (image->byte_order == LSBFirst) {
+ // Little-endian...
+ for (x = image->width, line_ptr = line;
+ x > 0;
+ x --, line_ptr += d, pixel += 4) {
+ i = (((((pixel[3] << 8) | pixel[2]) << 8) | pixel[1]) << 8) | pixel[0];
+
+ line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask;
+ line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask;
+ line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask;
+ }
+ } else {
+ // Big-endian...
+ for (x = image->width, line_ptr = line;
+ x > 0;
+ x --, line_ptr += d, pixel += 4) {
+ i = (((((pixel[0] << 8) | pixel[1]) << 8) | pixel[2]) << 8) | pixel[3];
+
+ line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask;
+ line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask;
+ line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ // Destroy the X image we've read and return the RGB(A) image...
+ XDestroyImage(image);
+
+ return p;
+}
+
+#endif
+
+//
+// End of "$Id: fl_read_image.cxx 6475 2008-10-19 20:35:32Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_read_image_mac.cxx b/third_party/windows/fltk-1.1.10/src/fl_read_image_mac.cxx new file mode 100644 index 0000000..80f467a --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_read_image_mac.cxx @@ -0,0 +1,137 @@ +//
+// "$Id: fl_read_image_mac.cxx 5614 2007-01-18 15:25:09Z matt $"
+//
+// WIN32 image reading routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2006 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 <config.h>
+
+// warning: this function is only implemented in Quickdraw. The function
+// below may not work If FLTK is compiled with Quartz enabled
+
+//
+// 'fl_read_image()' - Read an image from the current window.
+//
+
+uchar * // O - Pixel buffer or NULL if failed
+fl_read_image(uchar *p, // I - Pixel buffer or NULL to allocate
+ int x, // I - Left position
+ int y, // I - Top position
+ int w, // I - Width of area to read
+ int h, // I - Height of area to read
+ int alpha) { // I - Alpha value for image (0 for none)
+ Rect src, // Source rectangle
+ dst; // Destination rectangle
+ GWorldPtr osbuffer; // Temporary off-screen buffer for copy
+ GrafPtr srcPort; // Source port
+ RGBColor rgb; // RGB colors for copy mask...
+ PixMapHandle pm; // Pixmap handle for off-screen buffer
+ uchar *base, // Base address of off-screen buffer
+ *psrc, // Pointer into off-screen buffer
+ *pdst; // Pointer into pixel buffer
+ int idx, idy; // Current X & Y in image
+ int d; // Depth of image
+ int rowBytes; // Number of bytes per row...
+
+ // Set the source and destination rectangles...
+ src.top = y;
+ src.left = x;
+ src.bottom = y + h;
+ src.right = x + w;
+
+ dst.top = 0;
+ dst.left = 0;
+ dst.bottom = h;
+ dst.right = w;
+
+ // Get an off-screen buffer for copying the image...
+ QDErr err = NewGWorld(&osbuffer, 0, &dst, 0L, 0L, 0);
+ if (!osbuffer) return 0;
+ if (err!=noErr) {
+ DisposeGWorld(osbuffer);
+ return 0;
+ }
+
+ // Get the source port...
+ GetPort(&srcPort);
+
+ // Set the RGB copy mask via the foreground/background colors...
+ rgb.red = 0xffff;
+ rgb.green = 0xffff;
+ rgb.blue = 0xffff;
+ RGBBackColor(&rgb);
+
+ rgb.red = 0x0000;
+ rgb.green = 0x0000;
+ rgb.blue = 0x0000;
+ RGBForeColor(&rgb);
+
+ // Copy the screen image to the off-screen buffer...
+ CopyBits(GetPortBitMapForCopyBits(srcPort),
+ GetPortBitMapForCopyBits(osbuffer), &src, &dst, srcCopy, 0L);
+
+ // Allocate the image data array as needed...
+ d = alpha ? 4 : 3;
+
+ if (!p) p = new uchar[w * h * d];
+
+ // Initialize the default colors/alpha in the whole image...
+ memset(p, alpha, w * h * d);
+
+ // Set the correct port for the off-screen buffer and lock the buffer
+ SetGWorld(osbuffer, 0);
+
+ pm = GetGWorldPixMap(osbuffer);
+ LockPixels(pm);
+
+ base = (uchar *)GetPixBaseAddr(pm);
+ rowBytes = (*pm)->rowBytes & 0x3fff;
+
+ // Copy the image from the off-screen buffer to the memory buffer.
+ for (idy = 0, pdst = p; idy < h; idy ++)
+#ifdef __i386__
+ for (idx = 0, psrc = base + idy * rowBytes; idx < w; idx ++, psrc += 4, pdst += d) {
+ pdst[0] = psrc[2];
+ pdst[1] = psrc[1];
+ pdst[2] = psrc[0];
+ }
+#else
+ for (idx = 0, psrc = base + idy * rowBytes + 1; idx < w; idx ++, psrc += 4, pdst += d) {
+ pdst[0] = psrc[0];
+ pdst[1] = psrc[1];
+ pdst[2] = psrc[2];
+ }
+#endif // __i386__
+ // Unlock and delete the off-screen buffer, then return...
+ UnlockPixels(pm);
+ DisposeGWorld(osbuffer);
+
+ SetPort(srcPort);
+ return p;
+}
+
+
+//
+// End of "$Id: fl_read_image_mac.cxx 5614 2007-01-18 15:25:09Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_read_image_win32.cxx b/third_party/windows/fltk-1.1.10/src/fl_read_image_win32.cxx new file mode 100644 index 0000000..cf4731c --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_read_image_win32.cxx @@ -0,0 +1,72 @@ +//
+// "$Id: fl_read_image_win32.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// WIN32 image reading routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+//
+// 'fl_read_image()' - Read an image from the current window.
+//
+
+uchar * // O - Pixel buffer or NULL if failed
+fl_read_image(uchar *p, // I - Pixel buffer or NULL to allocate
+ int X, // I - Left position
+ int Y, // I - Top position
+ int w, // I - Width of area to read
+ int h, // I - Height of area to read
+ int alpha) { // I - Alpha value for image (0 for none)
+ int x, y; // Looping vars
+ int d; // Depth of image
+ uchar *ptr; // Pointer in image data
+
+
+ // Allocate the image data array as needed...
+ d = alpha ? 4 : 3;
+
+ if (!p) p = new uchar[w * h * d];
+
+ // Initialize the default colors/alpha in the whole image...
+ memset(p, alpha, w * h * d);
+
+ // Grab all of the pixels in the image, one at a time...
+ // MRS: there has to be a better way than this!
+ for (y = 0, ptr = p; y < h; y ++) {
+ for (x = 0; x < w; x ++, ptr += d) {
+ COLORREF c = GetPixel(fl_gc, X + x, Y + y);
+
+ ptr[0] = (uchar)c;
+ c >>= 8;
+ ptr[1] = (uchar)c;
+ c >>= 8;
+ ptr[2] = (uchar)c;
+ }
+ }
+
+ return p;
+}
+
+
+//
+// End of "$Id: fl_read_image_win32.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_rect.cxx b/third_party/windows/fltk-1.1.10/src/fl_rect.cxx new file mode 100644 index 0000000..b4b6351 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_rect.cxx @@ -0,0 +1,685 @@ +//
+// "$Id: fl_rect.cxx 5692 2007-02-12 16:41:41Z matt $"
+//
+// Rectangle drawing routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// These routines from fl_draw.H are used by the standard boxtypes
+// and thus are always linked into an fltk program.
+// Also all fl_clip routines, since they are always linked in so
+// that minimal update works.
+
+#include <config.h>
+#include <FL/Fl.H>
+#include <FL/Fl_Widget.H>
+#include <FL/fl_draw.H>
+#include <FL/x.H>
+
+#ifdef __APPLE_QUARTZ__
+extern float fl_quartz_line_width_;
+#endif
+
+void fl_rect(int x, int y, int w, int h) {
+ if (w<=0 || h<=0) return;
+#ifdef WIN32
+ MoveToEx(fl_gc, x, y, 0L);
+ LineTo(fl_gc, x+w-1, y);
+ LineTo(fl_gc, x+w-1, y+h-1);
+ LineTo(fl_gc, x, y+h-1);
+ LineTo(fl_gc, x, y);
+#elif defined(__APPLE_QD__)
+ Rect rect;
+ SetRect(&rect, x, y, x+w, y+h);
+ FrameRect(&rect);
+#elif defined(__APPLE_QUARTZ__)
+ if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, false);
+ CGRect rect = CGRectMake(x, y, w-1, h-1);
+ CGContextStrokeRect(fl_gc, rect);
+ if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, true);
+#else
+ XDrawRectangle(fl_display, fl_window, fl_gc, x, y, w-1, h-1);
+#endif
+}
+
+void fl_rectf(int x, int y, int w, int h) {
+ if (w<=0 || h<=0) return;
+#ifdef WIN32
+ RECT rect;
+ rect.left = x; rect.top = y;
+ rect.right = x + w; rect.bottom = y + h;
+ FillRect(fl_gc, &rect, fl_brush());
+#elif defined(__APPLE_QD__)
+ Rect rect;
+ SetRect(&rect, x, y, x+w, y+h);
+ PaintRect(&rect);
+#elif defined(__APPLE_QUARTZ__)
+ if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, false);
+ CGRect rect = CGRectMake(x, y, w-1, h-1);
+ CGContextFillRect(fl_gc, rect);
+ if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, true);
+#else
+ if (w && h) XFillRectangle(fl_display, fl_window, fl_gc, x, y, w, h);
+#endif
+}
+
+void fl_xyline(int x, int y, int x1) {
+#ifdef WIN32
+ MoveToEx(fl_gc, x, y, 0L); LineTo(fl_gc, x1+1, y);
+#elif defined(__APPLE_QD__)
+ MoveTo(x, y); LineTo(x1, y);
+#elif defined(__APPLE_QUARTZ__)
+ if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, false);
+ CGContextMoveToPoint(fl_gc, x, y);
+ CGContextAddLineToPoint(fl_gc, x1, y);
+ CGContextStrokePath(fl_gc);
+ if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, true);
+#else
+ XDrawLine(fl_display, fl_window, fl_gc, x, y, x1, y);
+#endif
+}
+
+void fl_xyline(int x, int y, int x1, int y2) {
+#ifdef WIN32
+ if (y2 < y) y2--;
+ else y2++;
+ MoveToEx(fl_gc, x, y, 0L);
+ LineTo(fl_gc, x1, y);
+ LineTo(fl_gc, x1, y2);
+#elif defined(__APPLE_QD__)
+ MoveTo(x, y);
+ LineTo(x1, y);
+ LineTo(x1, y2);
+#elif defined(__APPLE_QUARTZ__)
+ if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, false);
+ CGContextMoveToPoint(fl_gc, x, y);
+ CGContextAddLineToPoint(fl_gc, x1, y);
+ CGContextAddLineToPoint(fl_gc, x1, y2);
+ CGContextStrokePath(fl_gc);
+ if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, true);
+#else
+ XPoint p[3];
+ p[0].x = x; p[0].y = p[1].y = y;
+ p[1].x = p[2].x = x1; p[2].y = y2;
+ XDrawLines(fl_display, fl_window, fl_gc, p, 3, 0);
+#endif
+}
+
+void fl_xyline(int x, int y, int x1, int y2, int x3) {
+#ifdef WIN32
+ if(x3 < x1) x3--;
+ else x3++;
+ MoveToEx(fl_gc, x, y, 0L);
+ LineTo(fl_gc, x1, y);
+ LineTo(fl_gc, x1, y2);
+ LineTo(fl_gc, x3, y2);
+#elif defined(__APPLE_QD__)
+ MoveTo(x, y);
+ LineTo(x1, y);
+ LineTo(x1, y2);
+ LineTo(x3, y2);
+#elif defined(__APPLE_QUARTZ__)
+ if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, false);
+ CGContextMoveToPoint(fl_gc, x, y);
+ CGContextAddLineToPoint(fl_gc, x1, y);
+ CGContextAddLineToPoint(fl_gc, x1, y2);
+ CGContextAddLineToPoint(fl_gc, x3, y2);
+ CGContextStrokePath(fl_gc);
+ if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, true);
+#else
+ XPoint p[4];
+ p[0].x = x; p[0].y = p[1].y = y;
+ p[1].x = p[2].x = x1; p[2].y = p[3].y = y2;
+ p[3].x = x3;
+ XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0);
+#endif
+}
+
+void fl_yxline(int x, int y, int y1) {
+#ifdef WIN32
+ if (y1 < y) y1--;
+ else y1++;
+ MoveToEx(fl_gc, x, y, 0L); LineTo(fl_gc, x, y1);
+#elif defined(__APPLE_QD__)
+ MoveTo(x, y); LineTo(x, y1);
+#elif defined(__APPLE_QUARTZ__)
+ if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, false);
+ CGContextMoveToPoint(fl_gc, x, y);
+ CGContextAddLineToPoint(fl_gc, x, y1);
+ CGContextStrokePath(fl_gc);
+ if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, true);
+#else
+ XDrawLine(fl_display, fl_window, fl_gc, x, y, x, y1);
+#endif
+}
+
+void fl_yxline(int x, int y, int y1, int x2) {
+#ifdef WIN32
+ if (x2 > x) x2++;
+ else x2--;
+ MoveToEx(fl_gc, x, y, 0L);
+ LineTo(fl_gc, x, y1);
+ LineTo(fl_gc, x2, y1);
+#elif defined(__APPLE_QD__)
+ MoveTo(x, y);
+ LineTo(x, y1);
+ LineTo(x2, y1);
+#elif defined(__APPLE_QUARTZ__)
+ if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, false);
+ CGContextMoveToPoint(fl_gc, x, y);
+ CGContextAddLineToPoint(fl_gc, x, y1);
+ CGContextAddLineToPoint(fl_gc, x2, y1);
+ CGContextStrokePath(fl_gc);
+ if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, true);
+#else
+ XPoint p[3];
+ p[0].x = p[1].x = x; p[0].y = y;
+ p[1].y = p[2].y = y1; p[2].x = x2;
+ XDrawLines(fl_display, fl_window, fl_gc, p, 3, 0);
+#endif
+}
+
+void fl_yxline(int x, int y, int y1, int x2, int y3) {
+#ifdef WIN32
+ if(y3<y1) y3--;
+ else y3++;
+ MoveToEx(fl_gc, x, y, 0L);
+ LineTo(fl_gc, x, y1);
+ LineTo(fl_gc, x2, y1);
+ LineTo(fl_gc, x2, y3);
+#elif defined(__APPLE_QD__)
+ MoveTo(x, y);
+ LineTo(x, y1);
+ LineTo(x2, y1);
+ LineTo(x2, y3);
+#elif defined(__APPLE_QUARTZ__)
+ if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, false);
+ CGContextMoveToPoint(fl_gc, x, y);
+ CGContextAddLineToPoint(fl_gc, x, y1);
+ CGContextAddLineToPoint(fl_gc, x2, y1);
+ CGContextAddLineToPoint(fl_gc, x2, y3);
+ CGContextStrokePath(fl_gc);
+ if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, true);
+#else
+ XPoint p[4];
+ p[0].x = p[1].x = x; p[0].y = y;
+ p[1].y = p[2].y = y1; p[2].x = p[3].x = x2;
+ p[3].y = y3;
+ XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0);
+#endif
+}
+
+void fl_line(int x, int y, int x1, int y1) {
+#ifdef WIN32
+ MoveToEx(fl_gc, x, y, 0L);
+ LineTo(fl_gc, x1, y1);
+ // Draw the last point *again* because the GDI line drawing
+ // functions will not draw the last point ("it's a feature!"...)
+ SetPixel(fl_gc, x1, y1, fl_RGB());
+#elif defined(__APPLE_QD__)
+ MoveTo(x, y);
+ LineTo(x1, y1);
+#elif defined(__APPLE_QUARTZ__)
+ if (fl_quartz_line_width_==1.0f ) CGContextSetShouldAntialias(fl_gc, false);
+ CGContextMoveToPoint(fl_gc, x, y);
+ CGContextAddLineToPoint(fl_gc, x1, y1);
+ CGContextStrokePath(fl_gc);
+ if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, true);
+#else
+ XDrawLine(fl_display, fl_window, fl_gc, x, y, x1, y1);
+#endif
+}
+
+void fl_line(int x, int y, int x1, int y1, int x2, int y2) {
+#ifdef WIN32
+ MoveToEx(fl_gc, x, y, 0L);
+ LineTo(fl_gc, x1, y1);
+ LineTo(fl_gc, x2, y2);
+ // Draw the last point *again* because the GDI line drawing
+ // functions will not draw the last point ("it's a feature!"...)
+ SetPixel(fl_gc, x2, y2, fl_RGB());
+#elif defined(__APPLE_QD__)
+ MoveTo(x, y);
+ LineTo(x1, y1);
+ LineTo(x2, y2);
+#elif defined(__APPLE_QUARTZ__)
+ if (fl_quartz_line_width_==1.0f ) CGContextSetShouldAntialias(fl_gc, false);
+ CGContextMoveToPoint(fl_gc, x, y);
+ CGContextAddLineToPoint(fl_gc, x1, y1);
+ CGContextAddLineToPoint(fl_gc, x2, y2);
+ CGContextStrokePath(fl_gc);
+ if (fl_quartz_line_width_==1.0f ) CGContextSetShouldAntialias(fl_gc, true);
+#else
+ XPoint p[3];
+ p[0].x = x; p[0].y = y;
+ p[1].x = x1; p[1].y = y1;
+ p[2].x = x2; p[2].y = y2;
+ XDrawLines(fl_display, fl_window, fl_gc, p, 3, 0);
+#endif
+}
+
+void fl_loop(int x, int y, int x1, int y1, int x2, int y2) {
+#ifdef WIN32
+ MoveToEx(fl_gc, x, y, 0L);
+ LineTo(fl_gc, x1, y1);
+ LineTo(fl_gc, x2, y2);
+ LineTo(fl_gc, x, y);
+#elif defined(__APPLE_QD__)
+ MoveTo(x, y);
+ LineTo(x1, y1);
+ LineTo(x2, y2);
+ LineTo(x, y);
+#elif defined(__APPLE_QUARTZ__)
+ CGContextMoveToPoint(fl_gc, x, y);
+ CGContextAddLineToPoint(fl_gc, x1, y1);
+ CGContextAddLineToPoint(fl_gc, x2, y2);
+ CGContextClosePath(fl_gc);
+ CGContextStrokePath(fl_gc);
+#else
+ XPoint p[4];
+ p[0].x = x; p[0].y = y;
+ p[1].x = x1; p[1].y = y1;
+ p[2].x = x2; p[2].y = y2;
+ p[3].x = x; p[3].y = y;
+ XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0);
+#endif
+}
+
+void fl_loop(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
+#ifdef WIN32
+ MoveToEx(fl_gc, x, y, 0L);
+ LineTo(fl_gc, x1, y1);
+ LineTo(fl_gc, x2, y2);
+ LineTo(fl_gc, x3, y3);
+ LineTo(fl_gc, x, y);
+#elif defined(__APPLE_QD__)
+ MoveTo(x, y);
+ LineTo(x1, y1);
+ LineTo(x2, y2);
+ LineTo(x3, y3);
+ LineTo(x, y);
+#elif defined(__APPLE_QUARTZ__)
+ CGContextMoveToPoint(fl_gc, x, y);
+ CGContextAddLineToPoint(fl_gc, x1, y1);
+ CGContextAddLineToPoint(fl_gc, x2, y2);
+ CGContextAddLineToPoint(fl_gc, x3, y3);
+ CGContextClosePath(fl_gc);
+ CGContextStrokePath(fl_gc);
+#else
+ XPoint p[5];
+ p[0].x = x; p[0].y = y;
+ p[1].x = x1; p[1].y = y1;
+ p[2].x = x2; p[2].y = y2;
+ p[3].x = x3; p[3].y = y3;
+ p[4].x = x; p[4].y = y;
+ XDrawLines(fl_display, fl_window, fl_gc, p, 5, 0);
+#endif
+}
+
+void fl_polygon(int x, int y, int x1, int y1, int x2, int y2) {
+ XPoint p[4];
+ p[0].x = x; p[0].y = y;
+ p[1].x = x1; p[1].y = y1;
+ p[2].x = x2; p[2].y = y2;
+#ifdef WIN32
+ SelectObject(fl_gc, fl_brush());
+ Polygon(fl_gc, p, 3);
+#elif defined(__APPLE_QD__)
+ PolyHandle poly = OpenPoly();
+ MoveTo(x, y);
+ LineTo(x1, y1);
+ LineTo(x2, y2);
+ LineTo(x, y);
+ ClosePoly();
+ PaintPoly(poly);
+ FramePoly(poly);
+ KillPoly(poly);
+#elif defined(__APPLE_QUARTZ__)
+ CGContextMoveToPoint(fl_gc, x, y);
+ CGContextAddLineToPoint(fl_gc, x1, y1);
+ CGContextAddLineToPoint(fl_gc, x2, y2);
+ CGContextClosePath(fl_gc);
+ CGContextFillPath(fl_gc);
+#else
+ p[3].x = x; p[3].y = y;
+ XFillPolygon(fl_display, fl_window, fl_gc, p, 3, Convex, 0);
+ XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0);
+#endif
+}
+
+void fl_polygon(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
+ XPoint p[5];
+ p[0].x = x; p[0].y = y;
+ p[1].x = x1; p[1].y = y1;
+ p[2].x = x2; p[2].y = y2;
+ p[3].x = x3; p[3].y = y3;
+#ifdef WIN32
+ SelectObject(fl_gc, fl_brush());
+ Polygon(fl_gc, p, 4);
+#elif defined(__APPLE_QD__)
+ PolyHandle poly = OpenPoly();
+ MoveTo(x, y);
+ LineTo(x1, y1);
+ LineTo(x2, y2);
+ LineTo(x3, y3);
+ LineTo(x, y);
+ ClosePoly();
+ PaintPoly(poly);
+ FramePoly(poly);
+ KillPoly(poly);
+#elif defined(__APPLE_QUARTZ__)
+ CGContextMoveToPoint(fl_gc, x, y);
+ CGContextAddLineToPoint(fl_gc, x1, y1);
+ CGContextAddLineToPoint(fl_gc, x2, y2);
+ CGContextAddLineToPoint(fl_gc, x3, y3);
+ CGContextClosePath(fl_gc);
+ CGContextFillPath(fl_gc);
+#else
+ p[4].x = x; p[4].y = y;
+ XFillPolygon(fl_display, fl_window, fl_gc, p, 4, Convex, 0);
+ XDrawLines(fl_display, fl_window, fl_gc, p, 5, 0);
+#endif
+}
+
+void fl_point(int x, int y) {
+#ifdef WIN32
+ SetPixel(fl_gc, x, y, fl_RGB());
+#elif defined(__APPLE_QD__)
+ MoveTo(x, y); Line(0, 0);
+#elif defined(__APPLE_QUARTZ__)
+ if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, false);
+ CGContextMoveToPoint(fl_gc, x, y);
+ CGContextAddLineToPoint(fl_gc, x, y);
+ CGContextStrokePath(fl_gc);
+ if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, true);
+#else
+ XDrawPoint(fl_display, fl_window, fl_gc, x, y);
+#endif
+}
+
+////////////////////////////////////////////////////////////////
+
+#define STACK_SIZE 10
+#define STACK_MAX (STACK_SIZE - 1)
+static Fl_Region rstack[STACK_SIZE];
+static int rstackptr=0;
+int fl_clip_state_number=0; // used by gl_begin.cxx to update GL clip
+
+#if !defined(WIN32) && !defined(__APPLE__)
+// Missing X call: (is this the fastest way to init a 1-rectangle region?)
+// MSWindows equivalent exists, implemented inline in win32.H
+Fl_Region XRectangleRegion(int x, int y, int w, int h) {
+ XRectangle R;
+ R.x = x; R.y = y; R.width = w; R.height = h;
+ Fl_Region r = XCreateRegion();
+ XUnionRectWithRegion(&R, r, r);
+ return r;
+}
+#endif
+
+#ifdef __APPLE_QD__
+extern Fl_Region fl_window_region;
+#elif defined(__APPLE_QUARTZ__)
+// warning: the Quartz implementation currently uses Quickdraw calls to achieve
+// clipping. A future version should instead use 'CGContectClipToRect'
+// and friends.
+extern Fl_Region fl_window_region;
+#endif
+
+// undo any clobbering of clip done by your program:
+void fl_restore_clip() {
+ fl_clip_state_number++;
+ Fl_Region r = rstack[rstackptr];
+#ifdef WIN32
+ SelectClipRgn(fl_gc, r); //if r is NULL, clip is automatically cleared
+#elif defined(__APPLE_QD__)
+# if 1
+ // This code is required to allow true subwindows to work on Mac.
+ // During regular operation however, this seems overkill.
+ // See also: Fl_Window::make_current()
+ if ( fl_window ) {
+ GrafPtr port = GetWindowPort( fl_window );
+ if ( port ) { // port will be NULL if we are using a GWorld (and fl_window_region is invalid)
+ RgnHandle portClip = NewRgn();
+ CopyRgn( fl_window_region, portClip ); // changed
+ if ( r )
+ SectRgn( portClip, r, portClip );
+ SetPortClipRegion( port, portClip );
+ DisposeRgn( portClip );
+ }
+ } else {
+ if (r)
+ SetClip(r);
+ else {
+ Rect rect; rect.left=0; rect.top=0; rect.right=0x7fff; rect.bottom=0x7fff;
+ ClipRect(&rect);
+ }
+ }
+# else
+ if (r) SetClip(r);
+ else {
+ Rect rect; rect.left=0; rect.top=0; rect.right=0x7fff; rect.bottom=0x7fff;
+ ClipRect(&rect);
+ }
+# endif
+#elif defined(__APPLE_QUARTZ__)
+ if ( fl_window ) // clipping for a true window
+ {
+ GrafPtr port = GetWindowPort( fl_window );
+ if ( port ) {
+ RgnHandle portClip = NewRgn();
+ CopyRgn( fl_window_region, portClip ); // changed
+ if ( r )
+ SectRgn( portClip, r, portClip );
+ Rect portRect; GetPortBounds(port, &portRect);
+ Fl_X::q_clear_clipping();
+ ClipCGContextToRegion(fl_gc, &portRect, portClip );
+ Fl_X::q_fill_context();
+ DisposeRgn( portClip );
+ }
+ } else if (fl_gc) { // clipping for an offscreen drawing world (CGBitmap)
+ Rect portRect;
+ portRect.top = 0;
+ portRect.left = 0;
+ portRect.bottom = CGBitmapContextGetHeight(fl_gc);
+ portRect.right = CGBitmapContextGetWidth(fl_gc);
+ Fl_X::q_clear_clipping();
+ if (r)
+ ClipCGContextToRegion(fl_gc, &portRect, r);
+ Fl_X::q_fill_context();
+ }
+#else
+ if (r) XSetRegion(fl_display, fl_gc, r);
+ else XSetClipMask(fl_display, fl_gc, 0);
+#endif
+}
+
+// Replace the top of the clip stack:
+void fl_clip_region(Fl_Region r) {
+ Fl_Region oldr = rstack[rstackptr];
+ if (oldr) XDestroyRegion(oldr);
+ rstack[rstackptr] = r;
+ fl_restore_clip();
+}
+
+// Return the current clip region...
+Fl_Region fl_clip_region() {
+ return rstack[rstackptr];
+}
+
+// Intersect & push a new clip rectangle:
+void fl_push_clip(int x, int y, int w, int h) {
+ Fl_Region r;
+ if (w > 0 && h > 0) {
+ r = XRectangleRegion(x,y,w,h);
+ Fl_Region current = rstack[rstackptr];
+ if (current) {
+#ifdef WIN32
+ CombineRgn(r,r,current,RGN_AND);
+#elif defined(__APPLE_QD__)
+ SectRgn(r, current, r);
+#elif defined(__APPLE_QUARTZ__)
+ SectRgn(r, current, r);
+#else
+ Fl_Region temp = XCreateRegion();
+ XIntersectRegion(current, r, temp);
+ XDestroyRegion(r);
+ r = temp;
+#endif
+ }
+ } else { // make empty clip region:
+#ifdef WIN32
+ r = CreateRectRgn(0,0,0,0);
+#elif defined(__APPLE_QD__)
+ r = NewRgn();
+ SetEmptyRgn(r);
+#elif defined(__APPLE_QUARTZ__)
+ r = NewRgn();
+ SetEmptyRgn(r);
+#else
+ r = XCreateRegion();
+#endif
+ }
+ if (rstackptr < STACK_MAX) rstack[++rstackptr] = r;
+ else Fl::warning("fl_push_clip: clip stack overflow!\n");
+ fl_restore_clip();
+}
+
+// make there be no clip (used by fl_begin_offscreen() only!)
+void fl_push_no_clip() {
+ if (rstackptr < STACK_MAX) rstack[++rstackptr] = 0;
+ else Fl::warning("fl_push_no_clip: clip stack overflow!\n");
+ fl_restore_clip();
+}
+
+// pop back to previous clip:
+void fl_pop_clip() {
+ if (rstackptr > 0) {
+ Fl_Region oldr = rstack[rstackptr--];
+ if (oldr) XDestroyRegion(oldr);
+ } else Fl::warning("fl_pop_clip: clip stack underflow!\n");
+ fl_restore_clip();
+}
+
+// does this rectangle intersect current clip?
+int fl_not_clipped(int x, int y, int w, int h) {
+ if (x+w <= 0 || y+h <= 0) return 0;
+ Fl_Region r = rstack[rstackptr];
+#ifdef WIN32
+ if (!r) return 1;
+ RECT rect;
+ rect.left = x; rect.top = y; rect.right = x+w; rect.bottom = y+h;
+ return RectInRegion(r,&rect);
+#elif defined(__APPLE_QD__)
+ if (!r) return 1;
+ Rect rect;
+ rect.left = x; rect.top = y; rect.right = x+w; rect.bottom = y+h;
+ return RectInRgn(&rect, r);
+#elif defined(__APPLE_QUARTZ__)
+ if (!r) return 1;
+ Rect rect;
+ rect.left = x; rect.top = y; rect.right = x+w; rect.bottom = y+h;
+ return RectInRgn(&rect, r);
+#else
+ return r ? XRectInRegion(r, x, y, w, h) : 1;
+#endif
+}
+
+// return rectangle surrounding intersection of this rectangle and clip:
+int fl_clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H){
+ X = x; Y = y; W = w; H = h;
+ Fl_Region r = rstack[rstackptr];
+ if (!r) return 0;
+#ifdef WIN32
+// The win32 API makes no distinction between partial and complete
+// intersection, so we have to check for partial intersection ourselves.
+// However, given that the regions may be composite, we have to do
+// some voodoo stuff...
+ Fl_Region rr = XRectangleRegion(x,y,w,h);
+ Fl_Region temp = CreateRectRgn(0,0,0,0);
+ int ret;
+ if (CombineRgn(temp, rr, r, RGN_AND) == NULLREGION) { // disjoint
+ W = H = 0;
+ ret = 2;
+ } else if (EqualRgn(temp, rr)) { // complete
+ ret = 0;
+ } else { // parital intersection
+ RECT rect;
+ GetRgnBox(temp, &rect);
+ X = rect.left; Y = rect.top; W = rect.right - X; H = rect.bottom - Y;
+ ret = 1;
+ }
+ DeleteObject(temp);
+ DeleteObject(rr);
+ return ret;
+#elif defined(__APPLE_QD__)
+ RgnHandle rr = NewRgn();
+ SetRectRgn( rr, x, y, x+w, y+h );
+ SectRgn( r, rr, rr );
+ Rect rp; GetRegionBounds(rr, &rp);
+ X = rp.left;
+ Y = rp.top;
+ W = rp.right - X;
+ H = rp.bottom - Y;
+ DisposeRgn( rr );
+ if ( H==0 ) return 2;
+ if ( h==H && w==W ) return 0;
+ return 0;
+#elif defined(__APPLE_QUARTZ__)
+ RgnHandle rr = NewRgn();
+ SetRectRgn( rr, x, y, x+w, y+h );
+ SectRgn( r, rr, rr );
+ Rect rp; GetRegionBounds(rr, &rp);
+ X = rp.left;
+ Y = rp.top;
+ W = rp.right - X;
+ H = rp.bottom - Y;
+ DisposeRgn( rr );
+ if ( H==0 ) return 2;
+ if ( h==H && w==W ) return 0;
+ return 0;
+#else
+ switch (XRectInRegion(r, x, y, w, h)) {
+ case 0: // completely outside
+ W = H = 0;
+ return 2;
+ case 1: // completely inside:
+ return 0;
+ default: // partial:
+ break;
+ }
+ Fl_Region rr = XRectangleRegion(x,y,w,h);
+ Fl_Region temp = XCreateRegion();
+ XIntersectRegion(r, rr, temp);
+ XRectangle rect;
+ XClipBox(temp, &rect);
+ X = rect.x; Y = rect.y; W = rect.width; H = rect.height;
+ XDestroyRegion(temp);
+ XDestroyRegion(rr);
+ return 1;
+#endif
+}
+
+//
+// End of "$Id: fl_rect.cxx 5692 2007-02-12 16:41:41Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_round_box.cxx b/third_party/windows/fltk-1.1.10/src/fl_round_box.cxx new file mode 100644 index 0000000..babff30 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_round_box.cxx @@ -0,0 +1,122 @@ +//
+// "$Id: fl_round_box.cxx 6537 2008-12-02 17:21:36Z matt $"
+//
+// Round box drawing routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Box drawing code for an obscure box type.
+// These box types are in seperate files so they are not linked
+// in if not used.
+
+#include <FL/Fl.H>
+#include <FL/fl_draw.H>
+
+// A compiler from a certain very large software company will not compile
+// the function pointer assignment due to the name conflict with fl_arc.
+// This function is to fix that:
+void fl_arc_i(int x,int y,int w,int h,double a1,double a2) {
+ fl_arc(x,y,w,h,a1,a2);
+}
+
+enum {UPPER_LEFT, LOWER_RIGHT, CLOSED, FILL};
+
+static void draw(int which, int x,int y,int w,int h, int inset, unsigned int color)
+{
+ if (inset*2 >= w) inset = (w-1)/2;
+ if (inset*2 >= h) inset = (h-1)/2;
+ x += inset;
+ y += inset;
+ w -= 2*inset;
+ h -= 2*inset;
+ int d = w <= h ? w : h;
+ if (d <= 1) return;
+ fl_color(color);
+ void (*f)(int,int,int,int,double,double);
+ f = (which==FILL) ? fl_pie : fl_arc_i;
+ if (which >= CLOSED) {
+ f(x+w-d, y, d, d, w<=h ? 0 : -90, w<=h ? 180 : 90);
+ f(x, y+h-d, d, d, w<=h ? 180 : 90, w<=h ? 360 : 270);
+ } else if (which == UPPER_LEFT) {
+ f(x+w-d, y, d, d, 45, w<=h ? 180 : 90);
+ f(x, y+h-d, d, d, w<=h ? 180 : 90, 225);
+ } else { // LOWER_RIGHT
+ f(x, y+h-d, d, d, 225, w<=h ? 360 : 270);
+ f(x+w-d, y, d, d, w<=h ? 360 : 270, 360+45);
+ }
+ if (which == FILL) {
+ if (w < h)
+ fl_rectf(x, y+d/2, w, h-(d&-2));
+ else if (w > h)
+ fl_rectf(x+d/2, y, w-(d&-2), h);
+ } else {
+ if (w < h) {
+ if (which != UPPER_LEFT) fl_yxline(x+w-1, y+d/2-1, y+h-d/2+1);
+ if (which != LOWER_RIGHT) fl_yxline(x, y+d/2-1, y+h-d/2+1);
+ } else if (w > h) {
+ if (which != UPPER_LEFT) fl_xyline(x+d/2-1, y+h-1, x+w-d/2+1);
+ if (which != LOWER_RIGHT) fl_xyline(x+d/2-1, y, x+w-d/2+1);
+ }
+ }
+}
+
+extern uchar* fl_gray_ramp();
+
+void fl_round_down_box(int x, int y, int w, int h, Fl_Color bgcolor) {
+ uchar *g = fl_gray_ramp();
+ draw(FILL, x, y, w, h, 2, bgcolor);
+ draw(UPPER_LEFT, x+1, y, w-2, h, 0, g['N']);
+ draw(UPPER_LEFT, x+1, y, w-2, h, 1, g['H']);
+ draw(UPPER_LEFT, x, y, w, h, 0, g['N']);
+ draw(UPPER_LEFT, x, y, w, h, 1, g['H']);
+ draw(LOWER_RIGHT, x, y, w, h, 0, g['S']);
+ draw(LOWER_RIGHT, x+1, y, w-2, h, 0, g['U']);
+ draw(LOWER_RIGHT, x, y, w, h, 1, g['U']);
+ draw(LOWER_RIGHT, x+1, y, w-2, h, 1, g['W']);
+ draw(CLOSED, x, y, w, h, 2, g['A']);
+}
+
+void fl_round_up_box(int x, int y, int w, int h, Fl_Color bgcolor) {
+ uchar *g = fl_gray_ramp();
+ draw(FILL, x, y, w, h, 2, bgcolor);
+ draw(LOWER_RIGHT, x+1, y, w-2, h, 0, g['H']);
+ draw(LOWER_RIGHT, x+1, y, w-2, h, 1, g['N']);
+ draw(LOWER_RIGHT, x, y, w, h, 1, g['H']);
+ draw(LOWER_RIGHT, x, y, w, h, 2, g['N']);
+ draw(UPPER_LEFT, x, y, w, h, 2, g['U']);
+ draw(UPPER_LEFT, x+1, y, w-2, h, 1, g['S']);
+ draw(UPPER_LEFT, x, y, w, h, 1, g['W']);
+ draw(UPPER_LEFT, x+1, y, w-2, h, 0, g['U']);
+ draw(CLOSED, x, y, w, h, 0, g['A']);
+}
+
+extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*);
+Fl_Boxtype fl_define_FL_ROUND_UP_BOX() {
+ fl_internal_boxtype(_FL_ROUND_DOWN_BOX, fl_round_down_box);
+ fl_internal_boxtype(_FL_ROUND_UP_BOX, fl_round_up_box);
+ return _FL_ROUND_UP_BOX;
+}
+
+//
+// End of "$Id: fl_round_box.cxx 6537 2008-12-02 17:21:36Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_rounded_box.cxx b/third_party/windows/fltk-1.1.10/src/fl_rounded_box.cxx new file mode 100644 index 0000000..33f0d7a --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_rounded_box.cxx @@ -0,0 +1,99 @@ +//
+// "$Id: fl_rounded_box.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Rounded box drawing routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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_draw.H>
+
+#define RN 5
+#define RS 15
+#define BW 3
+
+static double offset[RN] = { 0.0, 0.07612, 0.29289, 0.61732, 1.0};
+
+static void rbox(int fill, int x, int y, int w, int h) {
+ int i;
+ int rsx ,rsy, rs;
+ rsx = w*2/5; rsy = h*2/5;
+ if (rsx > rsy) rs = rsy; else rs = rsx;
+ if (rs > RS) rs = RS;
+ rsx = rs; rsy = rs;
+
+ if (fill) fl_begin_polygon(); else fl_begin_loop();
+ for (i=0; i<RN; i++)
+ fl_vertex(x + offset[RN-i-1]*rsx, y + offset[i] * rsy);
+ for (i=0; i<RN; i++)
+ fl_vertex(x + offset[i]*rsx, y + h-1 - offset[RN-i-1] * rsy);
+ for (i=0; i<RN; i++)
+ fl_vertex(x + w-1 - offset[RN-i-1]*rsx, y + h-1 - offset[i] * rsy);
+ for (i=0; i<RN; i++)
+ fl_vertex(x + w-1 - offset[i]*rsx, y + offset[RN-i-1] * rsy);
+ if (fill) fl_end_polygon(); else fl_end_loop();
+}
+
+static void fl_rflat_box(int x, int y, int w, int h, Fl_Color c) {
+ fl_color(c); rbox(1, x, y, w, h); rbox(0, x, y, w, h);
+}
+
+static void fl_rounded_frame(int x, int y, int w, int h, Fl_Color c) {
+ fl_color(c); rbox(0, x, y, w, h);
+}
+
+static void fl_rounded_box(int x, int y, int w, int h, Fl_Color c) {
+ fl_color(c); rbox(1, x, y, w, h);
+ fl_color(FL_BLACK); rbox(0, x, y, w, h);
+}
+
+static void fl_rshadow_box(int x, int y, int w, int h, Fl_Color c) {
+ // draw shadow:
+ fl_color(FL_DARK3);
+ rbox(1, x+BW, y+BW, w, h);
+ rbox(0, x+BW, y+BW, w, h);
+ // draw the box:
+ fl_rounded_box(x, y, w, h, c);
+}
+
+extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*);
+
+Fl_Boxtype fl_define_FL_ROUNDED_BOX() {
+ fl_internal_boxtype(_FL_ROUNDED_FRAME, fl_rounded_frame);
+ fl_internal_boxtype(_FL_ROUNDED_BOX, fl_rounded_box);
+ return _FL_ROUNDED_BOX;
+}
+
+Fl_Boxtype fl_define_FL_RFLAT_BOX() {
+ fl_internal_boxtype(_FL_RFLAT_BOX, fl_rflat_box);
+ return _FL_RFLAT_BOX;
+}
+
+Fl_Boxtype fl_define_FL_RSHADOW_BOX() {
+ fl_internal_boxtype(_FL_RSHADOW_BOX, fl_rshadow_box);
+ return _FL_RSHADOW_BOX;
+}
+
+//
+// End of "$Id: fl_rounded_box.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_scroll_area.cxx b/third_party/windows/fltk-1.1.10/src/fl_scroll_area.cxx new file mode 100644 index 0000000..5373a51 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_scroll_area.cxx @@ -0,0 +1,166 @@ +//
+// "$Id: fl_scroll_area.cxx 5714 2007-02-25 00:00:49Z matt $"
+//
+// Scrolling routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Drawing function to move the contents of a rectangle. This is passed
+// a "callback" which is called to draw rectangular areas that are moved
+// into the drawing area.
+
+#include <config.h>
+#include <FL/Fl.H>
+#include <FL/x.H>
+#include <FL/fl_draw.H>
+
+// scroll a rectangle and redraw the newly exposed portions:
+void fl_scroll(int X, int Y, int W, int H, int dx, int dy,
+ void (*draw_area)(void*, int,int,int,int), void* data)
+{
+ if (!dx && !dy) return;
+ if (dx <= -W || dx >= W || dy <= -H || dy >= H) {
+ // no intersection of old an new scroll
+ draw_area(data,X,Y,W,H);
+ return;
+ }
+ int src_x, src_w, dest_x, clip_x, clip_w;
+ if (dx > 0) {
+ src_x = X;
+ dest_x = X+dx;
+ src_w = W-dx;
+ clip_x = X;
+ clip_w = dx;
+ } else {
+ src_x = X-dx;
+ dest_x = X;
+ src_w = W+dx;
+ clip_x = X+src_w;
+ clip_w = W-src_w;
+ }
+ int src_y, src_h, dest_y, clip_y, clip_h;
+ if (dy > 0) {
+ src_y = Y;
+ dest_y = Y+dy;
+ src_h = H-dy;
+ clip_y = Y;
+ clip_h = dy;
+ } else {
+ src_y = Y-dy;
+ dest_y = Y;
+ src_h = H+dy;
+ clip_y = Y+src_h;
+ clip_h = H-src_h;
+ }
+#ifdef WIN32
+ typedef int (WINAPI* fl_GetRandomRgn_func)(HDC, HRGN, INT);
+ static fl_GetRandomRgn_func fl_GetRandomRgn = 0L;
+ static char first_time = 1;
+
+ // We will have to do some Region magic now, so let's see if the
+ // required function is available (and it should be staring w/Win95)
+ if (first_time) {
+ HMODULE hMod = GetModuleHandle("GDI32.DLL");
+ if (hMod) {
+ fl_GetRandomRgn = (fl_GetRandomRgn_func)GetProcAddress(hMod, "GetRandomRgn");
+ }
+ first_time = 0;
+ }
+
+ // Now check if the source scrolling area is fully visible.
+ // If it is, we will do a quick scroll and just update the
+ // newly exposed area. If it is not, we go the safe route and
+ // re-render the full area instead.
+ // Note 1: we could go and find the areas that are actually
+ // obscured and recursively call fl_scroll for the newly found
+ // rectangles. However, this practice would rely on the
+ // elements of the undocumented Rgn structure.
+ // Note 2: although this method should take care of most
+ // multi-screen solutions, it will not solve issues scrolling
+ // from a different resolution screen onto another.
+ // Note 3: this has been tested with image maps, too.
+ if (fl_GetRandomRgn) {
+ // get the DC region minus all overlapping windows
+ HRGN sys_rgn = CreateRectRgn(0, 0, 0, 0);
+ fl_GetRandomRgn(fl_gc, sys_rgn, 4);
+ // now get the source scrolling rectangle
+ HRGN src_rgn = CreateRectRgn(src_x, src_y, src_x+src_w, src_y+src_h);
+ POINT offset = { 0, 0 };
+ if (GetDCOrgEx(fl_gc, &offset)) {
+ OffsetRgn(src_rgn, offset.x, offset.y);
+ }
+ // see if all source pixels are available in the system region
+ // Note: we could be a bit more merciful and subtract the
+ // scroll destination region as well.
+ HRGN dst_rgn = CreateRectRgn(0, 0, 0, 0);
+ int r = CombineRgn(dst_rgn, src_rgn, sys_rgn, RGN_DIFF);
+ DeleteObject(dst_rgn);
+ DeleteObject(src_rgn);
+ DeleteObject(sys_rgn);
+ if (r!=NULLREGION) {
+ draw_area(data,X,Y,W,H);
+ return;
+ }
+ }
+
+ // Great, we can do an accelerated scroll insteasd of re-rendering
+ BitBlt(fl_gc, dest_x, dest_y, src_w, src_h, fl_gc, src_x, src_y,SRCCOPY);
+
+#elif defined(__APPLE_QD__)
+ Rect src = { src_y, src_x, src_y+src_h, src_x+src_w };
+ Rect dst = { dest_y, dest_x, dest_y+src_h, dest_x+src_w };
+ static RGBColor bg = { 0xffff, 0xffff, 0xffff }; RGBBackColor( &bg );
+ static RGBColor fg = { 0x0000, 0x0000, 0x0000 }; RGBForeColor( &fg );
+ CopyBits( GetPortBitMapForCopyBits( GetWindowPort(fl_window) ),
+ GetPortBitMapForCopyBits( GetWindowPort(fl_window) ), &src, &dst, srcCopy, 0L);
+#elif defined(__APPLE_QUARTZ__)
+ // warning: there does not seem to be an equivalent to this function in Quartz
+ // ScrollWindowRect is a QuickDraw function and won't work here.
+ // Since on OS X all windows are fully double buffered, we need not
+ // worry about offscreen or obscured areas
+ Rect src = { src_y, src_x, src_y+src_h, src_x+src_w };
+ Rect dst = { dest_y, dest_x, dest_y+src_h, dest_x+src_w };
+ static RGBColor bg = { 0xffff, 0xffff, 0xffff }; RGBBackColor( &bg );
+ static RGBColor fg = { 0x0000, 0x0000, 0x0000 }; RGBForeColor( &fg );
+ CopyBits( GetPortBitMapForCopyBits( GetWindowPort(fl_window) ),
+ GetPortBitMapForCopyBits( GetWindowPort(fl_window) ), &src, &dst, srcCopy, 0L);
+#else
+ XCopyArea(fl_display, fl_window, fl_window, fl_gc,
+ src_x, src_y, src_w, src_h, dest_x, dest_y);
+ // we have to sync the display and get the GraphicsExpose events! (sigh)
+ for (;;) {
+ XEvent e; XWindowEvent(fl_display, fl_window, ExposureMask, &e);
+ if (e.type == NoExpose) break;
+ // otherwise assumme it is a GraphicsExpose event:
+ draw_area(data, e.xexpose.x, e.xexpose.y,
+ e.xexpose.width, e.xexpose.height);
+ if (!e.xgraphicsexpose.count) break;
+ }
+#endif
+ if (dx) draw_area(data, clip_x, dest_y, clip_w, src_h);
+ if (dy) draw_area(data, X, clip_y, W, clip_h);
+}
+
+//
+// End of "$Id: fl_scroll_area.cxx 5714 2007-02-25 00:00:49Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_set_font.cxx b/third_party/windows/fltk-1.1.10/src/fl_set_font.cxx new file mode 100644 index 0000000..c4f6d8b --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_set_font.cxx @@ -0,0 +1,90 @@ +//
+// "$Id: fl_set_font.cxx 5420 2006-09-05 11:16:15Z matt $"
+//
+// Font utilities for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Add a font to the internal table.
+// Also see fl_set_fonts.cxx which adds all possible fonts.
+
+#include <FL/Fl.H>
+#include <FL/x.H>
+#include <FL/fl_draw.H>
+#include "flstring.h"
+#include "Fl_Font.H"
+#include <stdlib.h>
+
+static int table_size;
+
+void Fl::set_font(Fl_Font fnum, const char* name) {
+ while (fnum >= table_size) {
+ int i = table_size;
+ if (!i) { // don't realloc the built-in table
+ table_size = 2*FL_FREE_FONT;
+ i = FL_FREE_FONT;
+ Fl_Fontdesc* t = (Fl_Fontdesc*)malloc(table_size*sizeof(Fl_Fontdesc));
+ memcpy(t, fl_fonts, FL_FREE_FONT*sizeof(Fl_Fontdesc));
+ fl_fonts = t;
+ } else {
+ table_size = 2*table_size;
+ fl_fonts=(Fl_Fontdesc*)realloc(fl_fonts, table_size*sizeof(Fl_Fontdesc));
+ }
+ for (; i < table_size; i++) {
+ fl_fonts[i].fontname[0] = 0;
+ fl_fonts[i].name = 0;
+#if !defined(WIN32) && !defined(__APPLE__)
+ fl_fonts[i].xlist = 0;
+ fl_fonts[i].n = 0;
+#endif // !WIN32 && !__APPLE__
+ }
+ }
+ Fl_Fontdesc* s = fl_fonts+fnum;
+ if (s->name) {
+ if (!strcmp(s->name, name)) {s->name = name; return;}
+#if !defined(WIN32) && !defined(__APPLE__)
+ if (s->xlist && s->n >= 0) XFreeFontNames(s->xlist);
+#endif
+ for (Fl_FontSize* f = s->first; f;) {
+ Fl_FontSize* n = f->next; delete f; f = n;
+ }
+ s->first = 0;
+ }
+ s->name = name;
+ s->fontname[0] = 0;
+#if !defined(WIN32) && !defined(__APPLE__)
+ s->xlist = 0;
+#endif
+ s->first = 0;
+ fl_font(-1, 0);
+}
+
+void Fl::set_font(Fl_Font fnum, Fl_Font from) {
+ Fl::set_font(fnum, get_font(from));
+}
+
+const char* Fl::get_font(Fl_Font fnum) {return fl_fonts[fnum].name;}
+
+//
+// End of "$Id: fl_set_font.cxx 5420 2006-09-05 11:16:15Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_set_fonts.cxx b/third_party/windows/fltk-1.1.10/src/fl_set_fonts.cxx new file mode 100644 index 0000000..faafec4 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_set_fonts.cxx @@ -0,0 +1,46 @@ +//
+// "$Id: fl_set_fonts.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// More font utilities for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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/x.H>
+#include "Fl_Font.H"
+#include "flstring.h"
+#include <stdlib.h>
+
+#ifdef WIN32
+# include "fl_set_fonts_win32.cxx"
+#elif defined(__APPLE__)
+# include "fl_set_fonts_mac.cxx"
+#elif USE_XFT
+# include "fl_set_fonts_xft.cxx"
+#else
+# include "fl_set_fonts_x.cxx"
+#endif // WIN32
+
+//
+// End of "$Id: fl_set_fonts.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_set_fonts_mac.cxx b/third_party/windows/fltk-1.1.10/src/fl_set_fonts_mac.cxx new file mode 100644 index 0000000..b4c0246 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_set_fonts_mac.cxx @@ -0,0 +1,213 @@ +//
+// "$Id: fl_set_fonts_mac.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// MacOS font utilities for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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 <config.h>
+
+// This function fills in the fltk font table with all the fonts that
+// are found on the X server. It tries to place the fonts into families
+// and to sort them so the first 4 in a family are normal, bold, italic,
+// and bold italic.
+
+// Bug: older versions calculated the value for *ap as a side effect of
+// making the name, and then forgot about it. To avoid having to change
+// the header files I decided to store this value in the last character
+// of the font name array.
+#define ENDOFBUFFER 127 // sizeof(Fl_Font.fontname)-1
+
+// turn a stored font name into a pretty name:
+const char* Fl::get_font_name(Fl_Font fnum, int* ap) {
+#ifdef __APPLE_QD__
+ Fl_Fontdesc *f = fl_fonts + fnum;
+ if (!f->fontname[0]) {
+ const char* p = f->name;
+ if (!p || !*p) {if (ap) *ap = 0; return "";}
+ int type;
+ switch (*p) {
+ case 'B': type = FL_BOLD; break;
+ case 'I': type = FL_ITALIC; break;
+ case 'P': type = FL_BOLD | FL_ITALIC; break;
+ default: type = 0; break;
+ }
+ strlcpy(f->fontname, p+1, ENDOFBUFFER);
+ if (type & FL_BOLD) strlcat(f->fontname, " bold", ENDOFBUFFER);
+ if (type & FL_ITALIC) strlcat(f->fontname, " italic", ENDOFBUFFER);
+ f->fontname[ENDOFBUFFER] = (char)type;
+ }
+ if (ap) *ap = f->fontname[ENDOFBUFFER];
+ return f->fontname;
+#elif defined(__APPLE_QUARTZ__)
+ Fl_Fontdesc *f = fl_fonts + fnum;
+ if (!f->fontname[0]) {
+ const char* p = f->name;
+ if (!p || !*p) {if (ap) *ap = 0; return "";}
+ strlcpy(f->fontname, p, ENDOFBUFFER);
+ int type = 0;
+ if (strstr(f->name, "Bold")) type |= FL_BOLD;
+ if (strstr(f->name, "Italic")) type |= FL_ITALIC;
+ f->fontname[ENDOFBUFFER] = (char)type;
+ }
+ if (ap) *ap = f->fontname[ENDOFBUFFER];
+ return f->fontname;
+#endif
+}
+
+static int fl_free_font = FL_FREE_FONT;
+
+Fl_Font Fl::set_fonts(const char* xstarname) {
+#pragma unused ( xstarname )
+#ifdef __APPLE_QD__
+ if (fl_free_font != FL_FREE_FONT)
+ return (Fl_Font)fl_free_font;
+ static char styleLU[] = " BIP";
+ FMFontFamilyInstanceIterator ffiIterator;
+ FMFontFamilyIterator ffIterator;
+ FMFontFamily family;
+ FMFont font;
+ FMFontStyle style; // bits 0..6: bold, italic underline, outline, shadow, condens, extended (FLTK supports 0 and 1 )
+ FMFontSize size;
+ //FMFilter filter; // do we need to set a specific (or multiple) filter(s) to get ALL fonts?
+
+ Str255 buf;
+ //filter.format = kFMCurrentFilterFormat;
+ //filter.selector = kFMGenerationFilterSelector;
+ //filter.filter.generationFilter =
+ FMCreateFontFamilyIterator( NULL, NULL, kFMUseGlobalScopeOption, &ffIterator );
+ OSStatus listFamilies, listInstances;
+ for (;;)
+ {
+ listFamilies = FMGetNextFontFamily( &ffIterator, &family );
+ if ( listFamilies != 0 ) break;
+ FMGetFontFamilyName( family, buf );
+ buf[ buf[0]+1 ] = 0;
+ //printf( "Font Family: %s\n", buf+1 );
+ int i;
+ for (i=0; i<FL_FREE_FONT; i++) // skip if one of our built-in fonts
+ if (!strcmp(Fl::get_font_name((Fl_Font)i),(char*)buf+1)) break;
+ if ( i < FL_FREE_FONT ) continue;
+ FMCreateFontFamilyInstanceIterator( family, &ffiIterator );
+ char pStyle = 0, nStyle;
+ for (;;)
+ {
+ listInstances = FMGetNextFontFamilyInstance( &ffiIterator, &font, &style, &size );
+ if ( listInstances != 0 ) break;
+ // printf(" %d %d %d\n", font, style, size );
+ nStyle = styleLU[style&0x03];
+ if ( ( pStyle & ( 1<<(style&0x03) ) ) == 0 )
+ {
+ buf[0] = nStyle;
+ Fl::set_font((Fl_Font)(fl_free_font++), strdup((char*)buf));
+ pStyle |= ( 1<<(style&0x03) );
+ }
+ }
+ FMDisposeFontFamilyInstanceIterator( &ffiIterator );
+ }
+ FMDisposeFontFamilyIterator( &ffIterator );
+ return (Fl_Font)fl_free_font;
+#elif defined(__APPLE_QUARTZ__)
+ ATSFontIterator it;
+ ATSFontIteratorCreate(kATSFontContextGlobal, 0L, 0L, kATSOptionFlagsRestrictedScope, &it);
+ for (;;) {
+ ATSFontRef font;
+ CFStringRef fname = 0;
+ OSStatus err = ATSFontIteratorNext(it, &font);
+ if (err!=noErr) break;
+ ATSFontGetName(font, kATSOptionFlagsDefault, &fname);
+ char buf[1024];
+ CFStringGetCString(fname, buf, 1024, kCFStringEncodingASCII);
+ int i;
+ for (i=0; i<FL_FREE_FONT; i++) // skip if one of our built-in fonts
+ if (!strcmp(Fl::get_font_name((Fl_Font)i),buf)) break;
+ if ( i < FL_FREE_FONT ) continue;
+ Fl::set_font((Fl_Font)(fl_free_font++), strdup((char*)buf));
+ }
+ ATSFontIteratorRelease(&it);
+ return (Fl_Font)fl_free_font;
+#endif
+}
+
+static int array[128];
+int Fl::get_font_sizes(Fl_Font fnum, int*& sizep) {
+ Fl_Fontdesc *s = fl_fonts+fnum;
+ if (!s->name) s = fl_fonts; // empty slot in table, use entry 0
+ int cnt = 0;
+
+#ifdef __APPLE_QD__
+ Str255 name;
+ int len = strlen( s->name );
+ memcpy(((char*)name)+1, s->name+1, len );
+ name[0] = len-1;
+ FMFontFamily family = FMGetFontFamilyFromName( name );
+ if ( family == kInvalidFontFamily ) return 0;
+
+ sizep = array;
+ FMFont font;
+ FMFontStyle style, fStyle;
+ switch ( s->name[0] ) {
+ default :
+ fStyle=0;
+ break;
+ case 'B' :
+ fStyle=1;
+ break;
+ case 'I' :
+ fStyle=2;
+ break;
+ case 'P' :
+ fStyle=3;
+ break;
+ }
+ FMFontSize size, pSize = -1;
+ FMFontFamilyInstanceIterator ffiIterator;
+ FMCreateFontFamilyInstanceIterator( family, &ffiIterator );
+ OSStatus listInstances;
+ for (;;)
+ {
+ listInstances = FMGetNextFontFamilyInstance( &ffiIterator, &font, &style, &size );
+ if ( listInstances != 0 ) break;
+ if ( style==fStyle )
+ {
+ if ( size>pSize )
+ {
+ array[ cnt++ ] = size;
+ pSize = size;
+ }
+ }
+ }
+ FMDisposeFontFamilyInstanceIterator( &ffiIterator );
+#elif defined(__APPLE_QUARTZ__)
+ // ATS supports all font size
+ array[0] = 0;
+ sizep = array;
+ cnt = 1;
+#endif
+
+ return cnt;
+}
+
+//
+// End of "$Id: fl_set_fonts_mac.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_set_fonts_win32.cxx b/third_party/windows/fltk-1.1.10/src/fl_set_fonts_win32.cxx new file mode 100644 index 0000000..923f563 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_set_fonts_win32.cxx @@ -0,0 +1,149 @@ +//
+// "$Id: fl_set_fonts_win32.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// WIN32 font utilities for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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 this7 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
+//
+
+// This function fills in the FLTK font table with all the fonts that
+// are found on the X server. It tries to place the fonts into families
+// and to sort them so the first 4 in a family are normal, bold, italic,
+// and bold italic.
+
+// Bug: older versions calculated the value for *ap as a side effect of
+// making the name, and then forgot about it. To avoid having to change
+// the header files I decided to store this value in the last character
+// of the font name array.
+#define ENDOFBUFFER 127 // sizeof(Fl_Font.fontname)-1
+
+// turn a stored font name into a pretty name:
+const char* Fl::get_font_name(Fl_Font fnum, int* ap) {
+ Fl_Fontdesc *f = fl_fonts + fnum;
+ if (!f->fontname[0]) {
+ const char* p = f->name;
+ if (!p || !*p) {if (ap) *ap = 0; return "";}
+ int type;
+ switch (*p) {
+ case 'B': type = FL_BOLD; break;
+ case 'I': type = FL_ITALIC; break;
+ case 'P': type = FL_BOLD | FL_ITALIC; break;
+ default: type = 0; break;
+ }
+ strlcpy(f->fontname, p+1, ENDOFBUFFER);
+ if (type & FL_BOLD) strlcat(f->fontname, " bold", ENDOFBUFFER);
+ if (type & FL_ITALIC) strlcat(f->fontname, " italic", ENDOFBUFFER);
+ f->fontname[ENDOFBUFFER] = (char)type;
+ }
+ if (ap) *ap = f->fontname[ENDOFBUFFER];
+ return f->fontname;
+}
+
+static int fl_free_font = FL_FREE_FONT;
+
+static int CALLBACK
+enumcb(CONST LOGFONT *lpelf,
+ CONST TEXTMETRIC * /*lpntm*/,
+ DWORD /*FontType*/,
+ LPARAM p) {
+ if (!p && lpelf->lfCharSet != ANSI_CHARSET) return 1;
+ const char *n = lpelf->lfFaceName;
+ for (int i=0; i<FL_FREE_FONT; i++) // skip if one of our built-in fonts
+ if (!strcmp(Fl::get_font_name((Fl_Font)i),n)) return 1;
+ char buffer[LF_FACESIZE + 1];
+ strcpy(buffer+1, n);
+ buffer[0] = ' '; Fl::set_font((Fl_Font)(fl_free_font++), strdup(buffer));
+ if (lpelf->lfWeight <= 400)
+ buffer[0] = 'B', Fl::set_font((Fl_Font)(fl_free_font++), strdup(buffer));
+ buffer[0] = 'I'; Fl::set_font((Fl_Font)(fl_free_font++), strdup(buffer));
+ if (lpelf->lfWeight <= 400)
+ buffer[0] = 'P', Fl::set_font((Fl_Font)(fl_free_font++), strdup(buffer));
+ return 1;
+}
+
+Fl_Font Fl::set_fonts(const char* xstarname) {
+ if (fl_free_font == FL_FREE_FONT) {// if not already been called
+ if (!fl_gc) fl_GetDC(0);
+ EnumFontFamilies(fl_gc, NULL, (FONTENUMPROC)enumcb, xstarname != 0);
+ }
+ return (Fl_Font)fl_free_font;
+}
+
+
+static int nbSize;
+static int cyPerInch;
+static int sizes[128];
+
+static int CALLBACK
+EnumSizeCb(CONST LOGFONT * /*lpelf*/,
+ CONST TEXTMETRIC *lpntm,
+ DWORD fontType,
+ LPARAM /*p*/) {
+ if ((fontType & RASTER_FONTTYPE) == 0) {
+ sizes[0] = 0;
+ nbSize = 1;
+
+ // Scalable font
+ return 0;
+ }
+
+ int add = lpntm->tmHeight - lpntm->tmInternalLeading;
+ add = MulDiv(add, 72, cyPerInch);
+
+ int start = 0;
+ while ((start < nbSize) && (sizes[start] < add)) {
+ start++;
+ }
+
+ if ((start < nbSize) && (sizes[start] == add)) {
+ return 1;
+ }
+
+ for (int i=nbSize; i>start; i--) sizes[i] = sizes[i - 1];
+
+ sizes[start] = add;
+ nbSize++;
+
+ // Stop enum if buffer overflow
+ return nbSize < 128;
+}
+
+
+int
+Fl::get_font_sizes(Fl_Font fnum, int*& sizep) {
+ nbSize = 0;
+ Fl_Fontdesc *s = fl_fonts+fnum;
+ if (!s->name) s = fl_fonts; // empty slot in table, use entry 0
+
+ if (!fl_gc) fl_GetDC(0);
+ cyPerInch = GetDeviceCaps(fl_gc, LOGPIXELSY);
+ if (cyPerInch < 1) cyPerInch = 1;
+ EnumFontFamilies(fl_gc, s->name+1, (FONTENUMPROC)EnumSizeCb, 0);
+
+ sizep = sizes;
+ return nbSize;
+}
+
+
+//
+// End of "$Id: fl_set_fonts_win32.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_set_fonts_x.cxx b/third_party/windows/fltk-1.1.10/src/fl_set_fonts_x.cxx new file mode 100644 index 0000000..ca8709a --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_set_fonts_x.cxx @@ -0,0 +1,350 @@ +//
+// "$Id: fl_set_fonts_x.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// X11 font utilities for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// This function fills in the fltk font table with all the fonts that
+// are found on the X server. It tries to place the fonts into families
+// and to sort them so the first 4 in a family are normal, bold, italic,
+// and bold italic.
+
+// Standard X fonts are matched by a pattern that is always of
+// this form, and this pattern is put in the table:
+// "-*-family-weight-slant-width1-style-*-registry-encoding"
+
+// Non-standard font names (those not starting with '-') are matched
+// by a pattern of the form "prefix*suffix", where the '*' is where
+// fltk thinks the point size is, or by the actual font name if no
+// point size is found.
+
+// Fltk knows how to pull an "attribute" out of a font name, such as
+// bold or italic, by matching known x font field values. All words
+// that don't match a known attribute are combined into the "name"
+// of the font. Names are compared before attributes for sorting, this
+// makes the bold and plain version of a font come out next to each
+// other despite the poor X font naming scheme.
+
+// By default fl_set_fonts() only does iso8859-1 encoded fonts. You can
+// do all normal X fonts by passing "-*" or every possible font with "*".
+
+// Fl::set_font will take strings other than the ones this stores
+// and can identify any font on X that way. You may want to write your
+// own system of font management and not use this code.
+
+// turn word N of a X font name into either some attribute bits
+// (right now 0, FL_BOLD, or FL_ITALIC), or into -1 indicating that
+// the word should be put into the name:
+
+static int attribute(int n, const char *p) {
+ // don't put blank things into name:
+ if (!*p || *p=='-' || *p=='*') return 0;
+ if (n == 3) { // weight
+ if (!strncmp(p,"normal",6) ||
+ !strncmp(p,"light",5) ||
+ !strncmp(p,"medium",6) ||
+ !strncmp(p,"book",4)) return 0;
+ if (!strncmp(p,"bold",4) || !strncmp(p,"demi",4)) return FL_BOLD;
+ } else if (n == 4) { // slant
+ if (*p == 'r') return 0;
+ if (*p == 'i' || *p == 'o') return FL_ITALIC;
+ } else if (n == 5) { // sWidth
+ if (!strncmp(p,"normal",6)) return 0;
+ }
+ return -1;
+}
+
+// return non-zero if the registry-encoding should be used:
+extern const char* fl_encoding;
+static int use_registry(const char *p) {
+ return *p && *p!='*' && strcmp(p,fl_encoding);
+}
+
+// Bug: older versions calculated the value for *ap as a side effect of
+// making the name, and then forgot about it. To avoid having to change
+// the header files I decided to store this value in the last character
+// of the font name array.
+#define ENDOFBUFFER 127 // sizeof(Fl_Font.fontname)-1
+
+// turn a stored (with *'s) X font name into a pretty name:
+const char* Fl::get_font_name(Fl_Font fnum, int* ap) {
+ Fl_Fontdesc *f = fl_fonts + fnum;
+ if (!f->fontname[0]) {
+ int type = 0;
+ const char* p = f->name;
+ if (!p) {
+ if (ap) *ap = 0;
+ return "";
+ }
+ char *o = f->fontname;
+
+ if (*p != '-') { // non-standard font, just replace * with spaces:
+ if (strstr(p,"bold")) type = FL_BOLD;
+ if (strstr(p,"ital")) type |= FL_ITALIC;
+ for (;*p; p++) {
+ if (*p == '*' || *p == ' ' || *p == '-') {
+ do p++; while (*p == '*' || *p == ' ' || *p == '-');
+ if (!*p) break;
+ if (o < (f->fontname + ENDOFBUFFER - 1)) *o++ = ' ';
+ }
+ if (o < (f->fontname + ENDOFBUFFER - 1)) *o++ = *p;
+ }
+ *o = 0;
+
+ } else { // standard dash-seperated font:
+
+ // get the family:
+ const char *x = fl_font_word(p,2); if (*x) x++; if (*x=='*') x++;
+ if (!*x) {
+ if (ap) *ap = 0;
+ return p;
+ }
+ const char *e = fl_font_word(x,1);
+ if ((e - x) < (int)(ENDOFBUFFER - 1)) {
+ // MRS: we want strncpy here, not strlcpy...
+ strncpy(o,x,e-x);
+ o += e-x;
+ } else {
+ strlcpy(f->fontname, x, ENDOFBUFFER);
+ o = f->fontname+ENDOFBUFFER-1;
+ }
+
+ // collect all the attribute words:
+ for (int n = 3; n <= 6; n++) {
+ // get the next word:
+ if (*e) e++; x = e; e = fl_font_word(x,1);
+ int t = attribute(n,x);
+ if (t < 0) {
+ if (o < (f->fontname + ENDOFBUFFER - 1)) *o++ = ' ';
+ if ((e - x) < (int)(ENDOFBUFFER - (o - f->fontname) - 1)) {
+ // MRS: we want strncpy here, not strlcpy...
+ strncpy(o,x,e-x);
+ o += e-x;
+ } else {
+ strlcpy(o,x, ENDOFBUFFER - (o - f->fontname) - 1);
+ o = f->fontname+ENDOFBUFFER-1;
+ }
+ } else type |= t;
+ }
+
+ // skip over the '*' for the size and get the registry-encoding:
+ x = fl_font_word(e,2);
+ if (*x) {x++; *o++ = '('; while (*x) *o++ = *x++; *o++ = ')';}
+
+ *o = 0;
+ if (type & FL_BOLD) strlcat(f->fontname, " bold", ENDOFBUFFER);
+ if (type & FL_ITALIC) strlcat(f->fontname, " italic", ENDOFBUFFER);
+ }
+ f->fontname[ENDOFBUFFER] = (char)type;
+ }
+ if (ap) *ap = f->fontname[ENDOFBUFFER];
+ return f->fontname;
+}
+
+extern "C" {
+// sort raw (non-'*') X font names into perfect order:
+
+static int ultrasort(const void *aa, const void *bb) {
+ const char *a = *(char **)aa;
+ const char *b = *(char **)bb;
+
+ // sort all non x-fonts at the end:
+ if (*a != '-') {
+ if (*b == '-') return 1;
+ // 2 non-x fonts are matched by "numeric sort"
+ int ret = 0;
+ for (;;) {
+ if (isdigit(*a) && isdigit(*b)) {
+ int na = strtol(a, (char **)&a, 10);
+ int nb = strtol(b, (char **)&b, 10);
+ if (!ret) ret = na-nb;
+ } else if (*a != *b) {
+ return (*a-*b);
+ } else if (!*a) {
+ return ret;
+ } else {
+ a++; b++;
+ }
+ }
+ } else {
+ if (*b != '-') return -1;
+ }
+
+ // skip the foundry (assumme equal):
+ for (a++; *a && *a++!='-';);
+ for (b++; *b && *b++!='-';);
+
+ // compare the family and all the attribute words:
+ int atype = 0;
+ int btype = 0;
+ for (int n = 2; n <= 6; n++) {
+ int at = attribute(n,a);
+ int bt = attribute(n,b);
+ if (at < 0) {
+ if (bt >= 0) return 1;
+ for (;;) {if (*a!=*b) return *a-*b; b++; if (!*a || *a++=='-') break;}
+ } else {
+ if (bt < 0) return -1;
+ a = fl_font_word(a,1); if (*a) a++;
+ b = fl_font_word(b,1); if (*b) b++;
+ atype |= at; btype |= bt;
+ }
+ }
+
+ // remember the pixel size:
+ int asize = atoi(a);
+ int bsize = atoi(b);
+
+ // compare the registry/encoding:
+ a = fl_font_word(a,6); if (*a) a++;
+ b = fl_font_word(b,6); if (*b) b++;
+ if (use_registry(a)) {
+ if (!use_registry(b)) return 1;
+ int r = strcmp(a,b); if (r) return r;
+ } else {
+ if (use_registry(b)) return -1;
+ }
+
+ if (atype != btype) return atype-btype;
+ if (asize != bsize) return asize-bsize;
+
+ // something wrong, just do a string compare...
+ return strcmp(*(char**)aa, *(char**)bb);
+}
+}
+
+// converts a X font name to a standard starname, returns point size:
+static int to_canonical(char *to, const char *from, size_t tolen) {
+ char* c = fl_find_fontsize((char*)from);
+ if (!c) return -1; // no point size found...
+ const char* endptr;
+ int size = strtol(c,(char**)&endptr,10);
+ if (from[0] == '-') {
+ // replace the "foundry" with -*-:
+ *to++ = '-'; *to++ = '*';
+ for (from++; *from && *from != '-'; from++);
+ // skip to the registry-encoding:
+ endptr = (char*)fl_font_word(endptr,6);
+ if (*endptr && !use_registry(endptr+1)) endptr = "";
+ }
+ int n = c-from;
+ // MRS: we want strncpy here, not strlcpy...
+ if (n > (int)(tolen - 1)) return -1;
+ strncpy(to,from,n);
+ to[n++] = '*';
+ strlcpy(to+n,endptr, tolen - n);
+ return size;
+}
+
+static int fl_free_font = FL_FREE_FONT;
+
+Fl_Font Fl::set_fonts(const char* xstarname) {
+ if (fl_free_font > FL_FREE_FONT) // already been here
+ return (Fl_Font)fl_free_font;
+ fl_open_display();
+ int xlistsize;
+ char buf[20];
+ if (!xstarname) {
+ strcpy(buf,"-*-"); strcpy(buf+3,fl_encoding);
+ xstarname = buf;
+ }
+ char **xlist = XListFonts(fl_display, xstarname, 10000, &xlistsize);
+ if (!xlist) return (Fl_Font)fl_free_font;
+ qsort(xlist, xlistsize, sizeof(*xlist), ultrasort);
+ int used_xlist = 0;
+ for (int i=0; i<xlistsize;) {
+ int first_xlist = i;
+ const char *p = xlist[i++];
+ char canon[1024];
+ int size = to_canonical(canon, p, sizeof(canon));
+ if (size >= 0) {
+ for (;;) { // find all matching fonts:
+ if (i >= xlistsize) break;
+ const char *q = xlist[i];
+ char this_canon[1024];
+ if (to_canonical(this_canon, q, sizeof(this_canon)) < 0) break;
+ if (strcmp(canon, this_canon)) break;
+ i++;
+ }
+ /*if (*p=='-' || i > first_xlist+1)*/ p = canon;
+ }
+ int j;
+ for (j = 0;; j++) {
+ if (j < FL_FREE_FONT) {
+ // see if it is one of our built-in fonts:
+ // if so, set the list of x fonts, since we have it anyway
+ if (fl_fonts[j].name && !strcmp(fl_fonts[j].name, p)) break;
+ } else {
+ j = fl_free_font++;
+ if (p == canon) p = strdup(p); else used_xlist = 1;
+ Fl::set_font((Fl_Font)j, p);
+ break;
+ }
+ }
+ if (!fl_fonts[j].xlist) {
+ fl_fonts[j].xlist = xlist+first_xlist;
+ fl_fonts[j].n = -(i-first_xlist);
+ used_xlist = 1;
+ }
+ }
+ if (!used_xlist) XFreeFontNames(xlist);
+ return (Fl_Font)fl_free_font;
+}
+
+int Fl::get_font_sizes(Fl_Font fnum, int*& sizep) {
+ Fl_Fontdesc *s = fl_fonts+fnum;
+ if (!s->name) s = fl_fonts; // empty slot in table, use entry 0
+ if (!s->xlist) {
+ fl_open_display();
+ s->xlist = XListFonts(fl_display, s->name, 100, &(s->n));
+ if (!s->xlist) return 0;
+ }
+ int listsize = s->n; if (listsize<0) listsize = -listsize;
+ static int sizes[128];
+ int numsizes = 0;
+ for (int i = 0; i < listsize; i++) {
+ char *q = s->xlist[i];
+ char *d = fl_find_fontsize(q);
+ if (!d) continue;
+ int s = strtol(d,0,10);
+ if (!numsizes || sizes[numsizes-1] < s) {
+ sizes[numsizes++] = s;
+ } else {
+ // insert-sort the new size into list:
+ int n;
+ for (n = numsizes-1; n > 0; n--) if (sizes[n-1] < s) break;
+ if (sizes[n] != s) {
+ for (int m = numsizes; m > n; m--) sizes[m] = sizes[m-1];
+ sizes[n] = s;
+ numsizes++;
+ }
+ }
+ }
+ sizep = sizes;
+ return numsizes;
+}
+
+//
+// End of "$Id: fl_set_fonts_x.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_set_fonts_xft.cxx b/third_party/windows/fltk-1.1.10/src/fl_set_fonts_xft.cxx new file mode 100644 index 0000000..5192fda --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_set_fonts_xft.cxx @@ -0,0 +1,366 @@ +//
+// "$Id: fl_set_fonts_xft.cxx 6832 2009-07-23 22:36:04Z AlbrechtS $"
+//
+// More font utilities for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2006 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 <X11/Xft/Xft.h>
+
+// This function fills in the fltk font table with all the fonts that
+// are found on the X server. It tries to place the fonts into families
+// and to sort them so the first 4 in a family are normal, bold, italic,
+// and bold italic.
+
+// Bug: older versions calculated the value for *ap as a side effect of
+// making the name, and then forgot about it. To avoid having to change
+// the header files I decided to store this value in the last character
+// of the font name array.
+#define ENDOFBUFFER 127 // sizeof(Fl_Font.fontname)-1
+
+// turn a stored font name into a pretty name:
+const char* Fl::get_font_name(Fl_Font fnum, int* ap) {
+ Fl_Fontdesc *f = fl_fonts + fnum;
+ if (!f->fontname[0]) {
+ const char* p = f->name;
+ int type;
+ switch (p[0]) {
+ case 'B': type = FL_BOLD; break;
+ case 'I': type = FL_ITALIC; break;
+ case 'P': type = FL_BOLD | FL_ITALIC; break;
+ default: type = 0; break;
+ }
+
+ // NOTE: This can cause duplications in fonts that already have Bold or Italic in
+ // their "name". Maybe we need to find a cleverer way?
+ strlcpy(f->fontname, p+1, ENDOFBUFFER);
+ if (type & FL_BOLD) strlcat(f->fontname, " bold", ENDOFBUFFER);
+ if (type & FL_ITALIC) strlcat(f->fontname, " italic", ENDOFBUFFER);
+ f->fontname[ENDOFBUFFER] = (char)type;
+ }
+ if (ap) *ap = f->fontname[ENDOFBUFFER];
+ return f->fontname;
+}
+
+///////////////////////////////////////////////////////////
+#define LOCAL_RAW_NAME_MAX 256
+
+extern "C" {
+// sort returned fontconfig font names
+static int name_sort(const void *aa, const void *bb) {
+ // What should we do here? Just do a string compare for now...
+ // NOTE: This yeilds some oddities - in particular a Blah Bold font will be
+ // listed before Blah...
+ // Also - the fontconfig listing returns some faces that are effectively duplicates
+ // as far as fltk is concerned, e.g. where there are ko or ja variants that we
+ // can't distinguish (since we are not yet fully UTF-*) - should we strip them here?
+ return strcasecmp(*(char**)aa, *(char**)bb);
+} // end of name_sort
+} // end of extern C section
+
+
+// Read the "pretty" name we have derived from fontconfig then convert
+// it into the format fltk uses internally for Xft names...
+// This is just a mess - I should have tokenised the strings and gone from there,
+// but I really thought this would be easier!
+static void make_raw_name(char *raw, char *pretty)
+{
+ // Input name will be "Some Name:style = Bold Italic" or whatever
+ // The plan is this:
+ // - the first char in the "raw" name becomes either I, B, P or " " for
+ // italic, bold, bold italic or normal - this seems to be the fltk way...
+
+ char *style = strchr(pretty, ':');
+ char *last = style + strlen(style) - 2;
+
+ if (style)
+ {
+ *style = 0; // Terminate "name" string
+ style ++; // point to start of style section
+ }
+ raw[0] = ' '; raw[1] = 0; // Default start of "raw name" text
+ strncat(raw, pretty, LOCAL_RAW_NAME_MAX);
+ // At this point, the name is "marked" as regular...
+ if (style)
+ {
+#define PLAIN 0
+#define BOLD 1
+#define ITALIC 2
+#define BITALIC (BOLD | ITALIC)
+ int mods = PLAIN;
+ // Now try and parse the style string - look for the "=" sign
+ style = strchr(style, '=');
+ while ((style) && (style < last))
+ {
+ int type;
+ while ((*style == '=') || (*style == ' ') || (*style == '\t'))
+ {
+ style++; // Start of Style string
+ if ((style >= last) || (*style == 0)) continue;
+ }
+ type = toupper(style[0]);
+ switch (type)
+ {
+ // Things we might see: Regular Normal Bold Italic Oblique (??what??) Medium
+ // Roman Light Demi Sans SemiCondensed SuperBold Book... etc...
+ // Things we actually care about: Bold Italic Oblique SuperBold - Others???
+ case 'I':
+ if (strncasecmp(style, "Italic", 6) == 0)
+ {
+ mods |= ITALIC;
+ }
+ goto NEXT_STYLE;
+
+ case 'B':
+ if (strncasecmp(style, "Bold", 4) == 0)
+ {
+ mods |= BOLD;
+ }
+ goto NEXT_STYLE;
+
+ case 'O':
+ if (strncasecmp(style, "Oblique", 7) == 0)
+ {
+ mods |= ITALIC;
+ }
+ goto NEXT_STYLE;
+
+ case 's':
+ if (strncasecmp(style, "SuperBold", 9) == 0)
+ {
+ mods |= BOLD;
+ }
+ goto NEXT_STYLE;
+
+ default: // find the next gap
+ goto NEXT_STYLE;
+ } // switch end
+NEXT_STYLE:
+ while ((*style != ' ') && (*style != '\t'))
+ {
+ style++;
+ if ((style >= last) || (*style == 0)) goto STYLE_DONE;
+ }
+ }
+STYLE_DONE:
+ // Set the "modifier" character in the raw string
+ switch(mods)
+ {
+ case BOLD: raw[0] = 'B';
+ break;
+ case ITALIC: raw[0] = 'I';
+ break;
+ case BITALIC: raw[0] = 'P';
+ break;
+ default: raw[0] = ' ';
+ break;
+ }
+ }
+} // make_raw_name
+
+///////////////////////////////////////////////////////////
+
+static int fl_free_font = FL_FREE_FONT;
+
+// Uses the fontconfig lib to construct a list of all installed fonts.
+// I tried using XftListFonts for this, but the API is tricky - and when
+// I looked at the XftList* code, it calls the Fc* functions anyway, so...
+//
+// Also, for now I'm ignoring the "pattern_name" and just getting everything...
+// AND I don't try and skip the fonts we've already loaded in the defaults.
+// Blimey! What a hack!
+Fl_Font Fl::set_fonts(const char* pattern_name)
+{
+ FcFontSet *fnt_set; // Will hold the list of fonts we find
+ FcPattern *fnt_pattern; // Holds the generic "match all names" pattern
+ FcObjectSet *fnt_obj_set = 0; // Holds the generic "match all objects"
+
+ int j; // loop iterator variable
+ int font_count; // Total number of fonts found to process
+ char **full_list; // The list of font names we build
+
+ if (fl_free_font > FL_FREE_FONT) // already been here
+ return (Fl_Font)fl_free_font;
+
+ fl_open_display(); // Just in case...
+
+ // Make sure fontconfig is ready... is this necessary? The docs say it is
+ // safe to call it multiple times, so just go for it anyway!
+ if (!FcInit())
+ {
+ // What to do? Just return defaults...
+ return FL_FREE_FONT;
+ }
+
+ // Create a search pattern that will match every font name - I think this
+ // does the Right Thing, but am not certain...
+ //
+ // This could possibly be "enhanced" to pay attention to the requested
+ // "pattern_name"?
+ fnt_pattern = FcPatternCreate();
+ fnt_obj_set = FcObjectSetBuild(FC_FAMILY, FC_STYLE, (void *)0);
+
+ // Hopefully, this is a set of all the fonts...
+ fnt_set = FcFontList(0, fnt_pattern, fnt_obj_set);
+
+ // We don't need the fnt_pattern any more, release it
+ FcPatternDestroy(fnt_pattern);
+
+ // Now, if we got any fonts, iterate through them...
+ if (fnt_set)
+ {
+ char *stop;
+ char *start;
+ char *first;
+
+ font_count = fnt_set->nfont; // How many fonts?
+
+ // Allocate array of char*'s to hold the name strings
+ full_list = (char **)malloc(sizeof(char *) * font_count);
+
+ // iterate through all the font patterns and get the names out...
+ for (j = 0; j < font_count; j++)
+ {
+ // NOTE: FcChar8 is a typedef of "unsigned char"...
+ FcChar8 *font; // String to hold the font's name
+
+ // Convert from fontconfig internal pattern to human readable name
+ // NOTE: This WILL malloc storage, so we need to free it later...
+ font = FcNameUnparse(fnt_set->fonts[j]);
+
+ // The returned strings look like this...
+ // Century Schoolbook:style=Bold Italic,fed kursiv,Fett Kursiv,...
+ // So the bit we want is up to the first comma - BUT some strings have
+ // more than one name, separated by, guess what?, a comma...
+ stop = start = first = 0;
+ stop = strchr((char *)font, ',');
+ start = strchr((char *)font, ':');
+ if ((stop) && (start) && (stop < start))
+ {
+ first = stop + 1; // discard first version of name
+ // find first comma *after* the end of the name
+ stop = strchr((char *)start, ',');
+ }
+ else
+ {
+ first = (char *)font; // name is just what was returned
+ }
+ // Truncate the name after the (english) modifiers description
+ if (stop)
+ {
+ *stop = 0; // Terminate the string at the first comma, if there is one
+ }
+
+ // Copy the font description into our list
+ if (first == (char *)font)
+ { // The listed name is still OK
+ full_list[j] = (char *)font;
+ }
+ else
+ { // The listed name has been modified
+ full_list[j] = strdup(first);
+ // Free the font name storage
+ free (font);
+ }
+ // replace "style=Regular" so strcmp sorts it first
+ if (start) {
+ char *reg = strstr(full_list[j], "=Regular");
+ if (reg) reg[1]='.';
+ }
+ }
+
+ // Release the fnt_set - we don't need it any more
+ FcFontSetDestroy(fnt_set);
+
+ // Sort the list into alphabetic order
+ qsort(full_list, font_count, sizeof(*full_list), name_sort);
+
+ // Now let us add the names we got to fltk's font list...
+ for (j = 0; j < font_count; j++)
+ {
+ if (full_list[j])
+ {
+ char xft_name[LOCAL_RAW_NAME_MAX];
+ char *stored_name;
+ // Parse the strings into FLTK-XFT style..
+ make_raw_name(xft_name, full_list[j]);
+ // NOTE: This just adds on AFTER the default fonts - no attempt is made
+ // to identify already loaded fonts. Is this bad?
+ stored_name = strdup(xft_name);
+ Fl::set_font((Fl_Font)(j + FL_FREE_FONT), stored_name);
+ fl_free_font ++;
+
+ free(full_list[j]); // release that name from our internal array
+ }
+ }
+ // Now we are done with the list, release it fully
+ free(full_list);
+ }
+ return (Fl_Font)fl_free_font;
+} // ::set_fonts
+////////////////////////////////////////////////////////////////
+
+
+extern "C" {
+static int int_sort(const void *aa, const void *bb) {
+ return (*(int*)aa)-(*(int*)bb);
+}
+}
+
+////////////////////////////////////////////////////////////////
+
+// Return all the point sizes supported by this font:
+// Suprisingly enough Xft works exactly like fltk does and returns
+// the same list. Except there is no way to tell if the font is scalable.
+int Fl::get_font_sizes(Fl_Font fnum, int*& sizep) {
+ Fl_Fontdesc *s = fl_fonts+fnum;
+ if (!s->name) s = fl_fonts; // empty slot in table, use entry 0
+
+ fl_open_display();
+ XftFontSet* fs = XftListFonts(fl_display, fl_screen,
+ XFT_FAMILY, XftTypeString, s->name+1,
+ (void *)0,
+ XFT_PIXEL_SIZE,
+ (void *)0);
+ static int* array = 0;
+ static int array_size = 0;
+ if (fs->nfont >= array_size) {
+ delete[] array;
+ array = new int[array_size = fs->nfont+1];
+ }
+ array[0] = 0; int j = 1; // claim all fonts are scalable
+ for (int i = 0; i < fs->nfont; i++) {
+ double v;
+ if (XftPatternGetDouble(fs->fonts[i], XFT_PIXEL_SIZE, 0, &v) == XftResultMatch) {
+ array[j++] = int(v);
+ }
+ }
+ qsort(array+1, j-1, sizeof(int), int_sort);
+ XftFontSetDestroy(fs);
+ sizep = array;
+ return j;
+}
+
+//
+// End of "$Id: fl_set_fonts_xft.cxx 6832 2009-07-23 22:36:04Z AlbrechtS $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_shadow_box.cxx b/third_party/windows/fltk-1.1.10/src/fl_shadow_box.cxx new file mode 100644 index 0000000..808b874 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_shadow_box.cxx @@ -0,0 +1,56 @@ +//
+// "$Id: fl_shadow_box.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Shadow box drawing routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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_draw.H>
+
+#define BW 3
+
+static void fl_shadow_frame(int x, int y, int w, int h, Fl_Color c) {
+ fl_color(FL_DARK3);
+ fl_rectf(x+BW, y+h-BW, w - BW, BW);
+ fl_rectf(x+w-BW, y+BW, BW, h - BW);
+ fl_color(c);
+ fl_rect(x,y,w-BW,h-BW);
+}
+
+static void fl_shadow_box(int x, int y, int w, int h, Fl_Color c) {
+ fl_color(c);
+ fl_rectf(x+1,y+1,w-2-BW,h-2-BW);
+ fl_shadow_frame(x,y,w,h,FL_GRAY0);
+}
+
+extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*);
+Fl_Boxtype fl_define_FL_SHADOW_BOX() {
+ fl_internal_boxtype(_FL_SHADOW_FRAME, fl_shadow_frame);
+ fl_internal_boxtype(_FL_SHADOW_BOX, fl_shadow_box);
+ return _FL_SHADOW_BOX;
+}
+
+//
+// End of "$Id: fl_shadow_box.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_shortcut.cxx b/third_party/windows/fltk-1.1.10/src/fl_shortcut.cxx new file mode 100644 index 0000000..221b4bd --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_shortcut.cxx @@ -0,0 +1,243 @@ +//
+// "$Id: fl_shortcut.cxx 6803 2009-06-28 22:25:51Z matt $"
+//
+// Shortcut support routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Code to test and parse fltk shortcut numbers.
+//
+// A shortcut is a keysym or'd with shift flags. In the simplest
+// sense a shortcut is matched if the shift state is exactly as
+// given and the key returning that keysym is pressed.
+//
+// To make it easier to match some things it is more complex:
+//
+// Only FL_META, FL_ALT, FL_SHIFT, and FL_CTRL must be "off". A
+// zero in the other shift flags indicates "dont care".
+//
+// It also checks against the first character of Fl::event_text(),
+// and zero for FL_SHIFT means "don't care".
+// This allows punctuation shortcuts like "#" to work (rather than
+// calling it "shift+3")
+
+#include <FL/Fl.H>
+#include <FL/Fl_Widget.H>
+#include <FL/Fl_Button.H>
+#include <FL/fl_draw.H>
+#include <ctype.h>
+#include "flstring.h"
+#if !defined(WIN32) && !defined(__APPLE__)
+#include <FL/x.H>
+#endif
+
+int Fl::test_shortcut(int shortcut) {
+ if (!shortcut) return 0;
+
+ int v = shortcut & 0xffff;
+#ifdef __APPLE__
+ if (v > 32 && v < 0x7f || v >= 0x80 && v <= 0xff) {
+#else
+ // most X11 use MSWindows Latin-1 if set to Western encoding, so 0x80 to 0xa0 are defined
+ if (v > 32 && v < 0x7f || v >= 0x80 && v <= 0xff) {
+#endif
+ if (isupper(v)) {
+ shortcut |= FL_SHIFT;
+ }
+ }
+
+ int shift = Fl::event_state();
+ // see if any required shift flags are off:
+ if ((shortcut&shift) != (shortcut&0x7fff0000)) return 0;
+ // record shift flags that are wrong:
+ int mismatch = (shortcut^shift)&0x7fff0000;
+ // these three must always be correct:
+ if (mismatch&(FL_META|FL_ALT|FL_CTRL)) return 0;
+
+ int key = shortcut & 0xffff;
+
+ // if shift is also correct, check for exactly equal keysyms:
+ if (!(mismatch&(FL_SHIFT)) && key == Fl::event_key()) return 1;
+
+ // try matching ascii, ignore shift:
+ if (key == event_text()[0]) return 1;
+
+ // kludge so that Ctrl+'_' works (as opposed to Ctrl+'^_'):
+ if ((shift&FL_CTRL) && key >= 0x3f && key <= 0x5F
+ && event_text()[0]==(key^0x40)) return 1;
+ return 0;
+}
+
+#if defined(WIN32) || defined(__APPLE__) // if not X
+// This table must be in numeric order by fltk (X) keysym number:
+struct Keyname {int key; const char* name;};
+static Keyname table[] = {
+ {' ', "Space"},
+ {FL_BackSpace, "Backspace"},
+ {FL_Tab, "Tab"},
+ {0xff0b/*XK_Clear*/, "Clear"},
+ {FL_Enter, "Enter"}, // X says "Enter"
+ {FL_Pause, "Pause"},
+ {FL_Scroll_Lock, "Scroll_Lock"},
+ {FL_Escape, "Escape"},
+ {FL_Home, "Home"},
+ {FL_Left, "Left"},
+ {FL_Up, "Up"},
+ {FL_Right, "Right"},
+ {FL_Down, "Down"},
+ {FL_Page_Up, "Page_Up"}, // X says "Prior"
+ {FL_Page_Down,"Page_Down"}, // X says "Next"
+ {FL_End, "End"},
+ {FL_Print, "Print"},
+ {FL_Insert, "Insert"},
+ {FL_Menu, "Menu"},
+ {FL_Num_Lock, "Num_Lock"},
+ {FL_KP_Enter, "KP_Enter"},
+ {FL_Shift_L, "Shift_L"},
+ {FL_Shift_R, "Shift_R"},
+ {FL_Control_L,"Control_L"},
+ {FL_Control_R,"Control_R"},
+ {FL_Caps_Lock,"Caps_Lock"},
+ {FL_Meta_L, "Meta_L"},
+ {FL_Meta_R, "Meta_R"},
+ {FL_Alt_L, "Alt_L"},
+ {FL_Alt_R, "Alt_R"},
+ {FL_Delete, "Delete"}
+};
+#endif
+
+const char * fl_shortcut_label(int shortcut) {
+ static char buf[20];
+ char *p = buf;
+ if (!shortcut) {*p = 0; return buf;}
+ // fix upper case shortcuts
+ int v = shortcut & 0xffff;
+#ifdef __APPLE__
+ if (v > 32 && v < 0x7f || v >= 0x80 && v <= 0xff) {
+#else
+ if (v > 32 && v < 0x7f || v >= 0xa0 && v <= 0xff) {
+#endif
+ if (isupper(v)) {
+ shortcut |= FL_SHIFT;
+ }
+ }
+#ifdef __APPLE__
+ // \todo Mac : we might want to change the symbols for Mac users - consider drawing Apple Symbols... .
+ if (shortcut & FL_SHIFT) {strcpy(p,"Shift+"); p += 6;} //: Mac hollow up arrow
+ if (shortcut & FL_META) {strcpy(p,"Cmd+"); p += 4;} //: Mac 'Apple' key
+ if (shortcut & FL_ALT) {strcpy(p,"Option+"); p += 7;} //: Mac 'Alt/Option' or fancy switch symbol
+ if (shortcut & FL_CTRL) {strcpy(p,"Ctrl+"); p += 5;} //: Mac ctrl key
+#else
+ if (shortcut & FL_META) {strcpy(p,"Meta+"); p += 5;}
+ if (shortcut & FL_ALT) {strcpy(p,"Alt+"); p += 4;}
+ if (shortcut & FL_SHIFT) {strcpy(p,"Shift+"); p += 6;}
+ if (shortcut & FL_CTRL) {strcpy(p,"Ctrl+"); p += 5;}
+#endif // __APPLE__
+ int key = shortcut & 0xFFFF;
+#if defined(WIN32) || defined(__APPLE__) // if not X
+ if (key >= FL_F && key <= FL_F_Last) {
+ *p++ = 'F';
+ if (key > FL_F+9) *p++ = (key-FL_F)/10+'0';
+ *p++ = (key-FL_F)%10 + '0';
+ } else {
+ // binary search the table for a match:
+ int a = 0;
+ int b = sizeof(table)/sizeof(*table);
+ while (a < b) {
+ int c = (a+b)/2;
+ if (table[c].key == key) {
+ if (p > buf) {strcpy(p,table[c].name); return buf;}
+ return table[c].name;
+ }
+ if (table[c].key < key) a = c+1;
+ else b = c;
+ }
+ if (key >= FL_KP && key <= FL_KP_Last) {
+ // mark keypad keys with KP_ prefix
+ strcpy(p,"KP_"); p += 3;
+ *p++ = uchar(key & 127);
+ } else {
+ // if none found, use the keystroke as a match:
+ *p++ = uchar(toupper(key & 255));
+ }
+ }
+ *p = 0;
+ return buf;
+#else
+ const char* q;
+ if (key == FL_Enter || key == '\r') q="Enter"; // don't use Xlib's "Return":
+ else if (key > 32 && key < 0x100) q = 0;
+ else q = XKeysymToString(key);
+ if (!q) {*p++ = uchar(toupper(key & 255)); *p = 0; return buf;}
+ if (p > buf) {strcpy(p,q); return buf;} else return q;
+#endif
+}
+
+// Emulation of XForms named shortcuts
+#include <stdlib.h>
+int fl_old_shortcut(const char* s) {
+ if (!s || !*s) return 0;
+ int n = 0;
+ if (*s == '#') {n |= FL_ALT; s++;}
+ if (*s == '+') {n |= FL_SHIFT; s++;}
+ if (*s == '^') {n |= FL_CTRL; s++;}
+ if (*s && s[1]) return n | (int)strtol(s,0,0); // allow 0xf00 to get any key
+ return n | *s;
+}
+
+// Tests for &x shortcuts in button labels:
+
+char Fl_Widget::label_shortcut(const char *t) {
+ if (!t) return 0;
+ for (;;) {
+ if (*t==0) return 0;
+ if (*t=='&') {
+ char s = t[1];
+ if (s==0) return 0;
+ else if (s=='&') t++;
+ else return s;
+ }
+ t++;
+ }
+}
+
+int Fl_Widget::test_shortcut(const char *t) {
+ #ifdef WIN32
+ // on MSWindows, users expect shortcuts to work only when the Alt modifier is pressed
+ if (Fl::event_state(FL_ALT)==0) return 0;
+ #endif
+ char c = Fl::event_text()[0];
+ if (!c || !t) return 0;
+ if (c == label_shortcut(t))
+ return 1;
+ return 0;
+}
+
+int Fl_Widget::test_shortcut() {
+ if (!(flags()&SHORTCUT_LABEL)) return 0;
+ return test_shortcut(label());
+}
+
+//
+// End of "$Id: fl_shortcut.cxx 6803 2009-06-28 22:25:51Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_show_colormap.cxx b/third_party/windows/fltk-1.1.10/src/fl_show_colormap.cxx new file mode 100644 index 0000000..ea56a67 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_show_colormap.cxx @@ -0,0 +1,162 @@ +//
+// "$Id: fl_show_colormap.cxx 6926 2009-11-07 21:01:08Z matt $"
+//
+// Colormap color selection dialog for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Select a color from the colormap.
+// Pretty much unchanged from Forms.
+
+#include <FL/Fl.H>
+#include <FL/Fl_Single_Window.H>
+#include <FL/fl_draw.H>
+#include <FL/fl_show_colormap.H>
+#include <config.h>
+
+#define BOXSIZE 14
+#define BORDER 4
+
+class ColorMenu : public Fl_Window {
+ Fl_Color initial;
+ Fl_Color which, previous;
+ int done;
+ void drawbox(Fl_Color);
+ void draw();
+ int handle(int);
+public:
+ ColorMenu(Fl_Color oldcol);
+ Fl_Color run();
+};
+
+ColorMenu::ColorMenu(Fl_Color oldcol) :
+ Fl_Window(BOXSIZE*8+1+2*BORDER, BOXSIZE*32+1+2*BORDER) {
+ clear_border();
+ set_modal();
+ initial = which = previous = oldcol;
+ done = 0;
+}
+
+void ColorMenu::drawbox(Fl_Color c) {
+ if (c < 0 || c > 255) return;
+ int X = (c%8)*BOXSIZE+BORDER;
+ int Y = (c/8)*BOXSIZE+BORDER;
+#if BORDER_WIDTH < 3
+ if (c == which) fl_draw_box(FL_DOWN_BOX, X+1, Y+1, BOXSIZE-1, BOXSIZE-1, c);
+ else fl_draw_box(FL_BORDER_BOX, X, Y, BOXSIZE+1, BOXSIZE+1, c);
+#else
+ fl_draw_box(c == which ? FL_DOWN_BOX : FL_BORDER_BOX,
+ X, Y, BOXSIZE+1, BOXSIZE+1, c);
+#endif
+}
+
+void ColorMenu::draw() {
+ if (damage() != FL_DAMAGE_CHILD) {
+ fl_draw_box(FL_UP_BOX,0,0,w(),h(),color());
+ for (int c = 0; c < 256; c++) drawbox((Fl_Color)c);
+ } else {
+ drawbox(previous);
+ drawbox(which);
+ }
+ previous = which;
+}
+
+int ColorMenu::handle(int e) {
+ int c = which;
+ switch (e) {
+ case FL_PUSH:
+ case FL_DRAG: {
+ int X = (Fl::event_x_root() - x() - BORDER);
+ if (X >= 0) X = X/BOXSIZE;
+ int Y = (Fl::event_y_root() - y() - BORDER);
+ if (Y >= 0) Y = Y/BOXSIZE;
+ if (X >= 0 && X < 8 && Y >= 0 && Y < 32)
+ c = 8*Y + X;
+ else
+ c = initial;
+ } break;
+ case FL_RELEASE:
+ done = 1;
+ return 1;
+ case FL_KEYBOARD:
+ switch (Fl::event_key()) {
+ case FL_Up: if (c > 7) c -= 8; break;
+ case FL_Down: if (c < 256-8) c += 8; break;
+ case FL_Left: if (c > 0) c--; break;
+ case FL_Right: if (c < 255) c++; break;
+ case FL_Escape: which = initial; done = 1; return 1;
+ case FL_KP_Enter:
+ case FL_Enter: done = 1; return 1;
+ default: return 0;
+ }
+ break;
+ default:
+ return 0;
+ }
+ if (c != which) {
+ which = (Fl_Color)c; damage(FL_DAMAGE_CHILD);
+ int bx = (c%8)*BOXSIZE+BORDER;
+ int by = (c/8)*BOXSIZE+BORDER;
+ int px = x();
+ int py = y();
+ int scr_x, scr_y, scr_w, scr_h;
+ Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h);
+ if (px < scr_x) px = scr_x;
+ if (px+bx+BOXSIZE+BORDER >= scr_x+scr_w) px = scr_x+scr_w-bx-BOXSIZE-BORDER;
+ if (py < scr_y) py = scr_y;
+ if (py+by+BOXSIZE+BORDER >= scr_y+scr_h) py = scr_y+scr_h-by-BOXSIZE-BORDER;
+ if (px+bx < BORDER) px = BORDER-bx;
+ if (py+by < BORDER) py = BORDER-by;
+ position(px,py);
+ }
+ return 1;
+}
+
+extern char fl_override_redirect; // hack for menus
+
+#ifdef _MSC_VER
+#pragma optimize("a",off) // needed to get the done check to work
+#endif
+Fl_Color ColorMenu::run() {
+ if (which < 0 || which > 255) {
+ position(Fl::event_x_root()-w()/2, Fl::event_y_root()-y()/2);
+ } else {
+ position(Fl::event_x_root()-(initial%8)*BOXSIZE-BOXSIZE/2-BORDER,
+ Fl::event_y_root()-(initial/8)*BOXSIZE-BOXSIZE/2-BORDER);
+ }
+ show();
+ Fl::grab(*this);
+ done = 0;
+ while (!done) Fl::wait();
+ Fl::release();
+ return which;
+}
+
+Fl_Color fl_show_colormap(Fl_Color oldcol) {
+ ColorMenu m(oldcol);
+ return m.run();
+}
+
+//
+// End of "$Id: fl_show_colormap.cxx 6926 2009-11-07 21:01:08Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_symbols.cxx b/third_party/windows/fltk-1.1.10/src/fl_symbols.cxx new file mode 100644 index 0000000..75abcdc --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_symbols.cxx @@ -0,0 +1,700 @@ +//
+// "$Id: fl_symbols.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Symbol drawing code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// These are small graphics drawn by the normal label-drawing
+// code when the string starts with an '@' sign.
+
+// Adapted from original code written by:
+
+// Written by Mark Overmars
+// Version 2.1 a
+// Date: Oct 2, 1992
+
+#include <FL/Fl.H>
+#include <FL/fl_draw.H>
+#include <FL/math.h>
+#include "flstring.h"
+
+typedef struct {
+ const char *name;
+ void (*drawit)(Fl_Color);
+ char scalable;
+ char notempty;
+} SYMBOL;
+
+#define MAXSYMBOL 211
+ /* Maximal number of symbols in table. Only half of them are
+ used. Should be prime. */
+
+static SYMBOL symbols[MAXSYMBOL]; /* The symbols */
+static int symbnumb = -1; /* Their number */
+
+static int find(const char *name) {
+// returns hash entry if it exists, or first empty slot:
+ int pos = name[0] ? (
+ name[1] ? (
+ name[2] ? 71*name[0]+31*name[1]+name[2] : 31*name[0]+name[1]
+ ) :
+ name[0]
+ ) : 0;
+ pos %= MAXSYMBOL;
+ int hh2 = name[0] ? (
+ (name[1]) ? 51*name[0]+3*name[1] : 3*name[0]
+ ) : 1;
+ hh2 %= MAXSYMBOL; if (!hh2) hh2 = 1;
+ for (;;) {
+ if (!symbols[pos].notempty) return pos;
+ if (!strcmp(symbols[pos].name,name)) return pos;
+ pos = (pos + hh2) % MAXSYMBOL;
+ }
+}
+
+static void fl_init_symbols(void);
+
+/**************** The routines seen by the user *************************/
+
+int fl_add_symbol(const char *name, void (*drawit)(Fl_Color), int scalable)
+/* Adds a symbol to the system. Returns whether correct. */
+{
+ fl_init_symbols();
+ int pos;
+ if (symbnumb > MAXSYMBOL / 2) return 0; // table is full
+ pos = find(name);
+ symbols[pos].name = name;
+ symbols[pos].drawit = drawit;
+ symbols[pos].notempty = 1;
+ symbols[pos].scalable = scalable;
+ symbnumb++;
+ return 1;
+}
+
+int fl_return_arrow(int x,int y,int w,int h);
+
+// provided for back compatability:
+int fl_draw_symbol(const char *label,int x,int y,int w,int h,Fl_Color col) {
+ const char *p = label;
+ if (*p++ != '@') return 0;
+ fl_init_symbols();
+ int equalscale = 0;
+ if (*p == '#') {equalscale = 1; p++;}
+ if (*p == '-' && p[1]>='1' && p[1]<='9') {
+ int n = p[1]-'0';
+ x += n; y += n; w -= 2*n; h -= 2*n;
+ p += 2;
+ } else if (*p == '+' && p[1]>='1' && p[1]<='9') {
+ int n = p[1]-'0';
+ x -= n; y -= n; w += 2*n; h += 2*n;
+ p += 2;
+ }
+ if (w < 10) {x -= (10-w)/2; w = 10;}
+ if (h < 10) {y -= (10-h)/2; h = 10;}
+ w = (w-1)|1; h = (h-1)|1;
+ char flip_x = 0, flip_y = 0;
+ if (*p=='$') {
+ flip_x = 1;
+ p++;
+ }
+ if (*p=='%') {
+ flip_y = 1;
+ p++;
+ }
+ int rotangle;
+ switch (*p++) {
+ case '0':
+ rotangle = 1000*(p[1]-'0') + 100*(p[2]-'0') + 10*(p[3]-'0');
+ p += 4;
+ break;
+ case '1': rotangle = 2250; break;
+ case '2': rotangle = 2700; break;
+ case '3': rotangle = 3150; break;
+ case '4': rotangle = 1800; break;
+ case '5':
+ case '6': rotangle = 0; break;
+ case '7': rotangle = 1350; break;
+ case '8': rotangle = 900; break;
+ case '9': rotangle = 450; break;
+ default: rotangle = 0; p--; break;
+ }
+ int pos = find(p);
+ if (!symbols[pos].notempty) return 0;
+ if (symbols[pos].scalable == 3) { // kludge to detect return arrow
+ fl_return_arrow(x,y,w,h);
+ return 1;
+ }
+ fl_push_matrix();
+ fl_translate(x+w/2,y+h/2);
+ if (symbols[pos].scalable) {
+ if (equalscale) {if (w<h) h = w; else w = h;}
+ fl_scale(0.5*w, 0.5*h);
+ fl_rotate(rotangle/10.0);
+ if (flip_x) fl_scale(-1.0, 1.0);
+ if (flip_y) fl_scale(1.0, -1.0);
+ }
+ (symbols[pos].drawit)(col);
+ fl_pop_matrix();
+ return 1;
+}
+
+/******************** THE DEFAULT SYMBOLS ****************************/
+
+/* Some help stuff */
+
+#define BP fl_begin_polygon()
+#define EP fl_end_polygon()
+#define BCP fl_begin_complex_polygon()
+#define ECP fl_end_complex_polygon()
+#define BL fl_begin_line()
+#define EL fl_end_line()
+#define BC fl_begin_loop()
+#define EC fl_end_loop()
+#define vv(x,y) fl_vertex(x,y)
+
+//for the outline color
+static void set_outline_color(Fl_Color c) {
+ fl_color(fl_darker(c));
+}
+
+static void rectangle(double x,double y,double x2,double y2,Fl_Color col) {
+ fl_color(col);
+ BP; vv(x,y); vv(x2,y); vv(x2,y2); vv(x,y2); EP;
+ set_outline_color(col);
+ BC; vv(x,y); vv(x2,y); vv(x2,y2); vv(x,y2); EC;
+}
+
+/* The drawing routines */
+
+static void draw_fltk(Fl_Color col)
+{
+ fl_color(col);
+ // F fill
+ BCP; vv(-2.0, -0.5); vv(-1.0, -0.5); vv(-1.0, -0.3); vv(-1.8, -0.3);
+ vv(-1.8, -0.1); vv(-1.2, -0.1); vv(-1.2, 0.1); vv(-1.8, 0.1);
+ vv(-1.8, 0.5); vv(-2.0, 0.5); ECP;
+ // L fill
+ BCP; vv(-1.0, -0.5); vv(-0.8, -0.5); vv(-0.8, 0.3); vv(0.0, 0.3);
+ vv(0.0, 0.5); vv(-1.0, 0.5); ECP;
+ // T outline
+ BCP; vv(-0.1, -0.5); vv(1.1, -0.5); vv(1.1, -0.3); vv(0.6, -0.3);
+ vv(0.6, 0.5); vv(0.4, 0.5); vv(0.4, -0.3); vv(-0.1, -0.3); ECP;
+ // K outline
+ BCP; vv(1.1, -0.5); vv(1.3, -0.5); vv(1.3, -0.15); vv(1.70, -0.5);
+ vv(2.0, -0.5); vv(1.43, 0.0); vv(2.0, 0.5); vv(1.70, 0.5);
+ vv(1.3, 0.15); vv(1.3, 0.5); vv(1.1, 0.5); ECP;
+ set_outline_color(col);
+ // F outline
+ BC; vv(-2.0, -0.5); vv(-1.0, -0.5); vv(-1.0, -0.3); vv(-1.8, -0.3);
+ vv(-1.8, -0.1); vv(-1.2, -0.1); vv(-1.2, 0.1); vv(-1.8, 0.1);
+ vv(-1.8, 0.5); vv(-2.0, 0.5); EC;
+ // L outline
+ BC; vv(-1.0, -0.5); vv(-0.8, -0.5); vv(-0.8, 0.3); vv(0.0, 0.3);
+ vv(0.0, 0.5); vv(-1.0, 0.5); EC;
+ // T outline
+ BC; vv(-0.1, -0.5); vv(1.1, -0.5); vv(1.1, -0.3); vv(0.6, -0.3);
+ vv(0.6, 0.5); vv(0.4, 0.5); vv(0.4, -0.3); vv(-0.1, -0.3); EC;
+ // K outline
+ BC; vv(1.1, -0.5); vv(1.3, -0.5); vv(1.3, -0.15); vv(1.70, -0.5);
+ vv(2.0, -0.5); vv(1.43, 0.0); vv(2.0, 0.5); vv(1.70, 0.5);
+ vv(1.3, 0.15); vv(1.3, 0.5); vv(1.1, 0.5); EC;
+}
+
+static void draw_search(Fl_Color col)
+{
+ fl_color(col);
+ BP; vv(-.4, .13); vv(-1.0, .73); vv(-.73, 1.0); vv(-.13, .4); EP;
+ set_outline_color(col);
+ fl_line_style(FL_SOLID, 3, 0);
+ BC; fl_circle(.2, -.2, .6); EC;
+ fl_line_style(FL_SOLID, 1, 0);
+ BC; vv(-.4, .13); vv(-1.0, .73); vv(-.73, 1.0); vv(-.13, .4); EC;
+}
+
+static void draw_arrow1(Fl_Color col)
+{
+ fl_color(col);
+ BP; vv(-0.8,-0.4); vv(-0.8,0.4); vv(0.0,0.4); vv(0.0,-0.4); EP;
+ BP; vv(0.0,0.8); vv(0.8,0.0); vv(0.0,-0.8); vv(0.0,-0.4); vv(0.0,0.4); EP;
+ set_outline_color(col);
+ BC; vv(-0.8,-0.4); vv(-0.8,0.4); vv(0.0,0.4); vv(0.0,0.8); vv(0.8,0.0);
+ vv(0.0,-0.8); vv(0.0,-0.4); EC;
+}
+
+static void draw_arrow1bar(Fl_Color col)
+{
+ draw_arrow1(col);
+ rectangle(.6,-.8,.9,.8,col);
+}
+
+static void draw_arrow2(Fl_Color col)
+{
+ fl_color(col);
+ BP; vv(-0.3,0.8); vv(0.50,0.0); vv(-0.3,-0.8); EP;
+ set_outline_color(col);
+ BC; vv(-0.3,0.8); vv(0.50,0.0); vv(-0.3,-0.8); EC;
+}
+
+static void draw_arrow3(Fl_Color col)
+{
+ fl_color(col);
+ BP; vv(0.1,0.8); vv(0.9,0.0); vv(0.1,-0.8); EP;
+ BP; vv(-0.7,0.8); vv(0.1,0.0); vv(-0.7,-0.8); EP;
+ set_outline_color(col);
+ BC; vv(0.1,0.8); vv(0.9,0.0); vv(0.1,-0.8); EC;
+ BC; vv(-0.7,0.8); vv(0.1,0.0); vv(-0.7,-0.8); EC;
+}
+
+static void draw_arrowbar(Fl_Color col)
+{
+ fl_color(col);
+ BP; vv(0.2,0.8); vv(0.6,0.8); vv(0.6,-0.8); vv(0.2,-0.8); EP;
+ BP; vv(-0.6,0.8); vv(0.2,0.0); vv(-0.6,-0.8); EP;
+ set_outline_color(col);
+ BC; vv(0.2,0.8); vv(0.6,0.8); vv(0.6,-0.8); vv(0.2,-0.8); EC;
+ BC; vv(-0.6,0.8); vv(0.2,0.0); vv(-0.6,-0.8); EC;
+}
+
+static void draw_arrowbox(Fl_Color col)
+{
+ fl_color(col);
+ BP; vv(-0.6,0.8); vv(0.2,0.0); vv(-0.6,-0.8); EP;
+ BC; vv(0.2,0.8); vv(0.6,0.8); vv(0.6,-0.8); vv(0.2,-0.8); EC;
+ set_outline_color(col);
+ BC; vv(0.2,0.8); vv(0.6,0.8); vv(0.6,-0.8); vv(0.2,-0.8); EC;
+ BC; vv(-0.6,0.8); vv(0.2,0.0); vv(-0.6,-0.8); EC;
+}
+
+static void draw_bararrow(Fl_Color col)
+{
+ fl_color(col);
+ BP; vv(0.1,0.8); vv(0.9,0.0); vv(0.1,-0.8); EP;
+ BP; vv(-0.5,0.8); vv(-0.1,0.8); vv(-0.1,-0.8); vv(-0.5,-0.8); EP;
+ set_outline_color(col);
+ BC; vv(0.1,0.8); vv(0.9,0.0); vv(0.1,-0.8); EC;
+ BC; vv(-0.5,0.8); vv(-0.1,0.8); vv(-0.1,-0.8); vv(-0.5,-0.8); EC;
+}
+
+static void draw_doublebar(Fl_Color col) {
+ rectangle(-0.6,-0.8,-.1,.8,col);
+ rectangle(.1,-0.8,.6,.8,col);
+}
+
+static void draw_arrow01(Fl_Color col)
+ { fl_rotate(180); draw_arrow1(col); }
+
+static void draw_arrow02(Fl_Color col)
+ { fl_rotate(180); draw_arrow2(col); }
+
+static void draw_arrow03(Fl_Color col)
+ { fl_rotate(180); draw_arrow3(col); }
+
+static void draw_0arrowbar(Fl_Color col)
+ { fl_rotate(180); draw_arrowbar(col); }
+
+static void draw_0arrowbox(Fl_Color col)
+ { fl_rotate(180); draw_arrowbox(col); }
+
+static void draw_0bararrow(Fl_Color col)
+ { fl_rotate(180); draw_bararrow(col); }
+
+static void draw_doublearrow(Fl_Color col)
+{
+ fl_color(col);
+ BP; vv(-0.35,-0.4); vv(-0.35,0.4); vv(0.35,0.4); vv(0.35,-0.4); EP;
+ BP; vv(0.15,0.8); vv(0.95,0.0); vv(0.15,-0.8); EP;
+ BP; vv(-0.15,0.8); vv(-0.95,0.0); vv(-0.15,-0.8); EP;
+ set_outline_color(col);
+ BC; vv(-0.15,0.4); vv(0.15,0.4); vv(0.15,0.8); vv(0.95,0.0);
+ vv(0.15,-0.8); vv(0.15,-0.4); vv(-0.15,-0.4); vv(-0.15,-0.8);
+ vv(-0.95,0.0); vv(-0.15,0.8); EC;
+}
+
+static void draw_arrow(Fl_Color col)
+{
+ fl_color(col);
+ BP; vv(0.65,0.1); vv(1.0,0.0); vv(0.65,-0.1); EP;
+ BL; vv(-1.0,0.0); vv(0.65,0.0); EL;
+ set_outline_color(col);
+ BL; vv(-1.0,0.0); vv(0.65,0.0); EL;
+ BC; vv(0.65,0.1); vv(1.0,0.0); vv(0.65,-0.1); EC;
+}
+
+static void draw_square(Fl_Color col)
+ { rectangle(-1,-1,1,1,col); }
+
+static void draw_circle(Fl_Color col) {
+ fl_color(col); BP; fl_circle(0,0,1); EP;
+ set_outline_color(col);
+ BC; fl_circle(0,0,1); EC;
+}
+
+static void draw_line(Fl_Color col)
+ { fl_color(col); BL; vv(-1.0,0.0); vv(1.0,0.0); EL; }
+
+static void draw_plus(Fl_Color col)
+{
+ fl_color(col);
+ BP; vv(-0.9,-0.15); vv(-0.9,0.15); vv(0.9,0.15); vv(0.9,-0.15); EP;
+ BP; vv(-0.15,-0.9); vv(-0.15,0.9); vv(0.15,0.9); vv(0.15,-0.9); EP;
+ set_outline_color(col);
+ BC;
+ vv(-0.9,-0.15); vv(-0.9,0.15); vv(-0.15,0.15); vv(-0.15,0.9);
+ vv(0.15,0.9); vv(0.15,0.15); vv(0.9,0.15); vv(0.9,-0.15);
+ vv(0.15,-0.15); vv(0.15,-0.9); vv(-0.15,-0.9); vv(-0.15,-0.15);
+ EC;
+}
+
+static void draw_uparrow(Fl_Color) {
+ fl_color(FL_LIGHT3);
+ BL; vv(-.8,.8); vv(-.8,-.8); vv(.8,0); EL;
+ fl_color(FL_DARK3);
+ BL; vv(-.8,.8); vv(.8, 0); EL;
+}
+
+static void draw_downarrow(Fl_Color) {
+ fl_color(FL_DARK3);
+ BL; vv(-.8,.8); vv(-.8,-.8); vv(.8,0); EL;
+ fl_color(FL_LIGHT3);
+ BL; vv(-.8,.8); vv(.8, 0); EL;
+}
+
+static void draw_menu(Fl_Color col)
+{
+ rectangle(-0.65, 0.85, 0.65, -0.25, col);
+ rectangle(-0.65, -0.6, 0.65, -1.0, col);
+}
+
+// Standard UI icons...
+static void draw_filenew(Fl_Color c) {
+ fl_color(c);
+ BCP;
+ vv(-0.7, -1.0);
+ vv(0.1, -1.0);
+ vv(0.1, -0.4);
+ vv(0.7, -0.4);
+ vv(0.7, 1.0);
+ vv(-0.7, 1.0);
+ ECP;
+
+ fl_color(fl_lighter(c));
+ BP;
+ vv(0.1, -1.0);
+ vv(0.1, -0.4);
+ vv(0.7, -0.4);
+ EP;
+
+ fl_color(fl_darker(c));
+ BC;
+ vv(-0.7, -1.0);
+ vv(0.1, -1.0);
+ vv(0.1, -0.4);
+ vv(0.7, -0.4);
+ vv(0.7, 1.0);
+ vv(-0.7, 1.0);
+ EC;
+
+ BL;
+ vv(0.1, -1.0);
+ vv(0.7, -0.4);
+ EL;
+}
+
+static void draw_fileopen(Fl_Color c) {
+ fl_color(c);
+ BP;
+ vv(-1.0, -0.7);
+ vv(-0.9, -0.8);
+ vv(-0.4, -0.8);
+ vv(-0.3, -0.7);
+ vv(0.6, -0.7);
+ vv(0.6, 0.7);
+ vv(-1.0, 0.7);
+ EP;
+
+ fl_color(fl_darker(c));
+ BC;
+ vv(-1.0, -0.7);
+ vv(-0.9, -0.8);
+ vv(-0.4, -0.8);
+ vv(-0.3, -0.7);
+ vv(0.6, -0.7);
+ vv(0.6, 0.7);
+ vv(-1.0, 0.7);
+ EC;
+
+ fl_color(fl_lighter(c));
+ BP;
+ vv(-1.0, 0.7);
+ vv(-0.6, -0.3);
+ vv(1.0, -0.3);
+ vv(0.6, 0.7);
+ EP;
+
+ fl_color(fl_darker(c));
+ BC;
+ vv(-1.0, 0.7);
+ vv(-0.6, -0.3);
+ vv(1.0, -0.3);
+ vv(0.6, 0.7);
+ EC;
+}
+
+static void draw_filesave(Fl_Color c) {
+ fl_color(c);
+ BP;
+ vv(-0.9, -1.0);
+ vv(0.9, -1.0);
+ vv(1.0, -0.9);
+ vv(1.0, 0.9);
+ vv(0.9, 1.0);
+ vv(-0.9, 1.0);
+ vv(-1.0, 0.9);
+ vv(-1.0, -0.9);
+ EP;
+
+ fl_color(fl_lighter(c));
+ BP;
+ vv(-0.7, -1.0);
+ vv(0.7, -1.0);
+ vv(0.7, -0.4);
+ vv(-0.7, -0.4);
+ EP;
+
+ BP;
+ vv(-0.7, 0.0);
+ vv(0.7, 0.0);
+ vv(0.7, 1.0);
+ vv(-0.7, 1.0);
+ EP;
+
+ fl_color(c);
+ BP;
+ vv(-0.5, -0.9);
+ vv(-0.3, -0.9);
+ vv(-0.3, -0.5);
+ vv(-0.5, -0.5);
+ EP;
+
+ fl_color(fl_darker(c));
+ BC;
+ vv(-0.9, -1.0);
+ vv(0.9, -1.0);
+ vv(1.0, -0.9);
+ vv(1.0, 0.9);
+ vv(0.9, 1.0);
+ vv(-0.9, 1.0);
+ vv(-1.0, 0.9);
+ vv(-1.0, -0.9);
+ EC;
+}
+
+static void draw_filesaveas(Fl_Color c) {
+ draw_filesave(c);
+
+ fl_color(fl_color_average(c, FL_WHITE, 0.25f));
+ BP;
+ vv(0.6, -0.8);
+ vv(1.0, -0.4);
+ vv(0.0, 0.6);
+ vv(-0.4, 0.6);
+ vv(-0.4, 0.2);
+ EP;
+
+ fl_color(fl_darker(c));
+ BC;
+ vv(0.6, -0.8);
+ vv(1.0, -0.4);
+ vv(0.0, 0.6);
+ vv(-0.4, 0.6);
+ vv(-0.4, 0.2);
+ EC;
+
+ BP;
+ vv(-0.1, 0.6);
+ vv(-0.4, 0.6);
+ vv(-0.4, 0.3);
+ EP;
+}
+
+static void draw_fileprint(Fl_Color c) {
+ fl_color(c);
+ BP;
+ vv(-0.8, 0.0);
+ vv(0.8, 0.0);
+ vv(1.0, 0.2);
+ vv(1.0, 1.0);
+ vv(-1.0, 1.0);
+ vv(-1.0, 0.2);
+ EP;
+
+ fl_color(fl_color_average(c, FL_WHITE, 0.25f));
+ BP;
+ vv(-0.6, 0.0);
+ vv(-0.6, -1.0);
+ vv(0.6, -1.0);
+ vv(0.6, 0.0);
+ EP;
+
+ fl_color(fl_lighter(c));
+ BP;
+ vv(-0.6, 0.6);
+ vv(0.6, 0.6);
+ vv(0.6, 1.0);
+ vv(-0.6, 1.0);
+ EP;
+
+ fl_color(fl_darker(c));
+ BC;
+ vv(-0.8, 0.0);
+ vv(-0.6, 0.0);
+ vv(-0.6, -1.0);
+ vv(0.6, -1.0);
+ vv(0.6, 0.0);
+ vv(0.8, 0.0);
+ vv(1.0, 0.2);
+ vv(1.0, 1.0);
+ vv(-1.0, 1.0);
+ vv(-1.0, 0.2);
+ EC;
+
+ BC;
+ vv(-0.6, 0.6);
+ vv(0.6, 0.6);
+ vv(0.6, 1.0);
+ vv(-0.6, 1.0);
+ EC;
+}
+
+static void draw_round_arrow(Fl_Color c, float da=5.0) {
+ double a, r, dr1=0.005, dr2=0.015;
+ int i, j;
+ for (j=0; j<2; j++) {
+ if (j&1) {
+ fl_color(c);
+ set_outline_color(c);
+ BC;
+ } else {
+ fl_color(c);
+ BCP;
+ }
+ vv(-0.1, 0.0);
+ vv(-1.0, 0.0);
+ vv(-1.0, 0.9);
+ for (i=27, a=140.0, r=1.0; i>0; i--, a-=da, r-=dr1) {
+ double ar = a/180.0 * M_PI;
+ vv(cos(ar)*r, sin(ar)*r);
+ }
+ for (i=27; i>=0; a+=da, i--, r-=dr2) {
+ double ar = a/180.0 * M_PI;
+ vv(cos(ar)*r, sin(ar)*r);
+ }
+ if (j&1) {
+ EC;
+ } else {
+ ECP;
+ }
+ }
+}
+
+static void draw_refresh(Fl_Color c) {
+ draw_round_arrow(c);
+ fl_rotate(180.0);
+ draw_round_arrow(c);
+ fl_rotate(-180.0);
+}
+
+static void draw_reload(Fl_Color c) {
+ fl_rotate(-135.0);
+ draw_round_arrow(c, 10);
+ fl_rotate(135.0);
+}
+
+static void draw_undo(Fl_Color c) {
+ fl_translate(0.0, 0.2);
+ fl_scale(1.0, -1.0);
+ draw_round_arrow(c, 6);
+ fl_scale(1.0, -1.0);
+ fl_translate(0.0, -0.2);
+}
+
+static void draw_redo(Fl_Color c) {
+ fl_scale(-1.0, 1.0);
+ draw_undo(c);
+ fl_scale(-1.0, 1.0);
+}
+
+static void fl_init_symbols(void) {
+ static char beenhere;
+ if (beenhere) return;
+ beenhere = 1;
+ symbnumb = 0;
+
+ fl_add_symbol("", draw_arrow1, 1);
+ fl_add_symbol("->", draw_arrow1, 1);
+ fl_add_symbol(">", draw_arrow2, 1);
+ fl_add_symbol(">>", draw_arrow3, 1);
+ fl_add_symbol(">|", draw_arrowbar, 1);
+ fl_add_symbol(">[]", draw_arrowbox, 1);
+ fl_add_symbol("|>", draw_bararrow, 1);
+ fl_add_symbol("<-", draw_arrow01, 1);
+ fl_add_symbol("<", draw_arrow02, 1);
+ fl_add_symbol("<<", draw_arrow03, 1);
+ fl_add_symbol("|<", draw_0arrowbar, 1);
+ fl_add_symbol("[]<", draw_0arrowbox, 1);
+ fl_add_symbol("<|", draw_0bararrow, 1);
+ fl_add_symbol("<->", draw_doublearrow, 1);
+ fl_add_symbol("-->", draw_arrow, 1);
+ fl_add_symbol("+", draw_plus, 1);
+ fl_add_symbol("->|", draw_arrow1bar, 1);
+ fl_add_symbol("arrow", draw_arrow, 1);
+ fl_add_symbol("returnarrow", 0, 3);
+ fl_add_symbol("square", draw_square, 1);
+ fl_add_symbol("circle", draw_circle, 1);
+ fl_add_symbol("line", draw_line, 1);
+ fl_add_symbol("plus", draw_plus, 1);
+ fl_add_symbol("menu", draw_menu, 1);
+ fl_add_symbol("UpArrow", draw_uparrow, 1);
+ fl_add_symbol("DnArrow", draw_downarrow, 1);
+ fl_add_symbol("||", draw_doublebar, 1);
+ fl_add_symbol("search", draw_search, 1);
+ fl_add_symbol("FLTK", draw_fltk, 1);
+
+ fl_add_symbol("filenew", draw_filenew, 1);
+ fl_add_symbol("fileopen", draw_fileopen, 1);
+ fl_add_symbol("filesave", draw_filesave, 1);
+ fl_add_symbol("filesaveas", draw_filesaveas, 1);
+ fl_add_symbol("fileprint", draw_fileprint, 1);
+
+ fl_add_symbol("refresh", draw_refresh, 1);
+ fl_add_symbol("reload", draw_reload, 1);
+ fl_add_symbol("undo", draw_undo, 1);
+ fl_add_symbol("redo", draw_redo, 1);
+
+// fl_add_symbol("file", draw_file, 1);
+}
+
+//
+// End of "$Id: fl_symbols.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/fl_vertex.cxx b/third_party/windows/fltk-1.1.10/src/fl_vertex.cxx new file mode 100644 index 0000000..9ced185 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/fl_vertex.cxx @@ -0,0 +1,325 @@ +//
+// "$Id: fl_vertex.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Portable drawing routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Portable drawing code for drawing arbitrary shapes with
+// simple 2D transformations. See also fl_arc.cxx
+
+// matt: the Quartz implementation purposly doesn't use the Quartz matrix
+// operations for reasons of compatibility and maintainability
+
+#include <config.h>
+#include <FL/fl_draw.H>
+#include <FL/x.H>
+#include <FL/Fl.H>
+#include <FL/math.h>
+#include <stdlib.h>
+
+struct matrix {double a, b, c, d, x, y;};
+
+static matrix m = {1, 0, 0, 1, 0, 0};
+
+static matrix stack[32];
+static int sptr = 0;
+
+void fl_push_matrix() {
+ if (sptr==32)
+ Fl::error("fl_push_matrix(): matrix stack overflow.");
+ else
+ stack[sptr++] = m;
+}
+
+void fl_pop_matrix() {
+ if (sptr==0)
+ Fl::error("fl_pop_matrix(): matrix stack underflow.");
+ else
+ m = stack[--sptr];
+}
+
+void fl_mult_matrix(double a, double b, double c, double d, double x, double y) {
+ matrix o;
+ o.a = a*m.a + b*m.c;
+ o.b = a*m.b + b*m.d;
+ o.c = c*m.a + d*m.c;
+ o.d = c*m.b + d*m.d;
+ o.x = x*m.a + y*m.c + m.x;
+ o.y = x*m.b + y*m.d + m.y;
+ m = o;
+}
+
+void fl_scale(double x,double y) {fl_mult_matrix(x,0,0,y,0,0);}
+
+void fl_scale(double x) {fl_mult_matrix(x,0,0,x,0,0);}
+
+void fl_translate(double x,double y) {fl_mult_matrix(1,0,0,1,x,y);}
+
+void fl_rotate(double d) {
+ if (d) {
+ double s, c;
+ if (d == 0) {s = 0; c = 1;}
+ else if (d == 90) {s = 1; c = 0;}
+ else if (d == 180) {s = 0; c = -1;}
+ else if (d == 270 || d == -90) {s = -1; c = 0;}
+ else {s = sin(d*M_PI/180); c = cos(d*M_PI/180);}
+ fl_mult_matrix(c,-s,s,c,0,0);
+ }
+}
+
+// typedef what the x,y fields in a point are:
+#ifdef WIN32
+typedef int COORD_T;
+# define XPOINT XPoint
+#elif defined(__APPLE_QUARTZ__)
+typedef float COORD_T;
+typedef struct { float x; float y; } QPoint;
+# define XPOINT QPoint
+extern float fl_quartz_line_width_;
+#else
+typedef short COORD_T;
+# define XPOINT XPoint
+#endif
+
+static XPOINT *p = (XPOINT *)0;
+
+static int p_size;
+static int n;
+static int what;
+enum {LINE, LOOP, POLYGON, POINT_};
+
+void fl_begin_points() {n = 0; what = POINT_;}
+
+void fl_begin_line() {n = 0; what = LINE;}
+
+void fl_begin_loop() {n = 0; what = LOOP;}
+
+void fl_begin_polygon() {n = 0; what = POLYGON;}
+
+double fl_transform_x(double x, double y) {return x*m.a + y*m.c + m.x;}
+
+double fl_transform_y(double x, double y) {return x*m.b + y*m.d + m.y;}
+
+double fl_transform_dx(double x, double y) {return x*m.a + y*m.c;}
+
+double fl_transform_dy(double x, double y) {return x*m.b + y*m.d;}
+
+static void fl_transformed_vertex(COORD_T x, COORD_T y) {
+ if (!n || x != p[n-1].x || y != p[n-1].y) {
+ if (n >= p_size) {
+ p_size = p ? 2*p_size : 16;
+ p = (XPOINT*)realloc((void*)p, p_size*sizeof(*p));
+ }
+ p[n].x = x;
+ p[n].y = y;
+ n++;
+ }
+}
+
+void fl_transformed_vertex(double xf, double yf) {
+#ifdef __APPLE_QUARTZ__
+ fl_transformed_vertex(COORD_T(xf), COORD_T(yf));
+#else
+ fl_transformed_vertex(COORD_T(rint(xf)), COORD_T(rint(yf)));
+#endif
+}
+
+void fl_vertex(double x,double y) {
+ fl_transformed_vertex(x*m.a + y*m.c + m.x, x*m.b + y*m.d + m.y);
+}
+
+void fl_end_points() {
+#ifdef WIN32
+ for (int i=0; i<n; i++) SetPixel(fl_gc, p[i].x, p[i].y, fl_RGB());
+#elif defined(__APPLE_QD__)
+ for (int i=0; i<n; i++) { MoveTo(p[i].x, p[i].y); Line(0, 0); }
+#elif defined(__APPLE_QUARTZ__)
+ if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, false);
+ for (int i=0; i<n; i++) {
+ CGContextMoveToPoint(fl_gc, p[i].x, p[i].y);
+ CGContextAddLineToPoint(fl_gc, p[i].x, p[i].y);
+ CGContextStrokePath(fl_gc);
+ }
+ if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, false);
+#else
+ if (n>1) XDrawPoints(fl_display, fl_window, fl_gc, p, n, 0);
+#endif
+}
+
+void fl_end_line() {
+ if (n < 2) {
+ fl_end_points();
+ return;
+ }
+#ifdef WIN32
+ if (n>1) Polyline(fl_gc, p, n);
+#elif defined(__APPLE_QD__)
+ if (n<=1) return;
+ MoveTo(p[0].x, p[0].y);
+ for (int i=1; i<n; i++) LineTo(p[i].x, p[i].y);
+#elif defined(__APPLE_QUARTZ__)
+ if (n<=1) return;
+ CGContextMoveToPoint(fl_gc, p[0].x, p[0].y);
+ for (int i=1; i<n; i++)
+ CGContextAddLineToPoint(fl_gc, p[i].x, p[i].y);
+ CGContextStrokePath(fl_gc);
+#else
+ if (n>1) XDrawLines(fl_display, fl_window, fl_gc, p, n, 0);
+#endif
+}
+
+static void fixloop() { // remove equal points from closed path
+ while (n>2 && p[n-1].x == p[0].x && p[n-1].y == p[0].y) n--;
+}
+
+void fl_end_loop() {
+ fixloop();
+ if (n>2) fl_transformed_vertex((COORD_T)p[0].x, (COORD_T)p[0].y);
+ fl_end_line();
+}
+
+void fl_end_polygon() {
+ fixloop();
+ if (n < 3) {
+ fl_end_line();
+ return;
+ }
+#ifdef WIN32
+ if (n>2) {
+ SelectObject(fl_gc, fl_brush());
+ Polygon(fl_gc, p, n);
+ }
+#elif defined(__APPLE_QD__)
+ if (n<=1) return;
+ PolyHandle ph = OpenPoly();
+ MoveTo(p[0].x, p[0].y);
+ for (int i=1; i<n; i++) LineTo(p[i].x, p[i].y);
+ ClosePoly();
+ PaintPoly(ph);
+ KillPoly(ph);
+#elif defined(__APPLE_QUARTZ__)
+ if (n<=1) return;
+ CGContextMoveToPoint(fl_gc, p[0].x, p[0].y);
+ for (int i=1; i<n; i++)
+ CGContextAddLineToPoint(fl_gc, p[i].x, p[i].y);
+ CGContextClosePath(fl_gc);
+ CGContextFillPath(fl_gc);
+#else
+ if (n>2) XFillPolygon(fl_display, fl_window, fl_gc, p, n, Convex, 0);
+#endif
+}
+
+static int gap;
+#ifdef WIN32
+static int counts[20];
+static int numcount;
+#endif
+
+void fl_begin_complex_polygon() {
+ fl_begin_polygon();
+ gap = 0;
+#ifdef WIN32
+ numcount = 0;
+#endif
+}
+
+void fl_gap() {
+ while (n>gap+2 && p[n-1].x == p[gap].x && p[n-1].y == p[gap].y) n--;
+ if (n > gap+2) {
+ fl_transformed_vertex((COORD_T)p[gap].x, (COORD_T)p[gap].y);
+#ifdef WIN32
+ counts[numcount++] = n-gap;
+#endif
+ gap = n;
+ } else {
+ n = gap;
+ }
+}
+
+void fl_end_complex_polygon() {
+ fl_gap();
+ if (n < 3) {
+ fl_end_line();
+ return;
+ }
+#ifdef WIN32
+ if (n>2) {
+ SelectObject(fl_gc, fl_brush());
+ PolyPolygon(fl_gc, p, counts, numcount);
+ }
+#elif defined(__APPLE_QD__)
+ if (n<=1) return;
+ PolyHandle ph = OpenPoly();
+ MoveTo(p[0].x, p[0].y);
+ for (int i=1; i<n; i++) LineTo(p[i].x, p[i].y);
+ ClosePoly();
+ PaintPoly(ph);
+ KillPoly(ph);
+#elif defined(__APPLE_QUARTZ__)
+ if (n<=1) return;
+ CGContextMoveToPoint(fl_gc, p[0].x, p[0].y);
+ for (int i=1; i<n; i++)
+ CGContextAddLineToPoint(fl_gc, p[i].x, p[i].y);
+ CGContextClosePath(fl_gc);
+ CGContextFillPath(fl_gc);
+#else
+ if (n>2) XFillPolygon(fl_display, fl_window, fl_gc, p, n, 0, 0);
+#endif
+}
+
+// shortcut the closed circles so they use XDrawArc:
+// warning: these do not draw rotated ellipses correctly!
+// See fl_arc.c for portable version.
+
+void fl_circle(double x, double y,double r) {
+ double xt = fl_transform_x(x,y);
+ double yt = fl_transform_y(x,y);
+ double rx = r * (m.c ? sqrt(m.a*m.a+m.c*m.c) : fabs(m.a));
+ double ry = r * (m.b ? sqrt(m.b*m.b+m.d*m.d) : fabs(m.d));
+ int llx = (int)rint(xt-rx);
+ int w = (int)rint(xt+rx)-llx;
+ int lly = (int)rint(yt-ry);
+ int h = (int)rint(yt+ry)-lly;
+#ifdef WIN32
+ if (what==POLYGON) {
+ SelectObject(fl_gc, fl_brush());
+ Pie(fl_gc, llx, lly, llx+w, lly+h, 0,0, 0,0);
+ } else
+ Arc(fl_gc, llx, lly, llx+w, lly+h, 0,0, 0,0);
+#elif defined(__APPLE_QD__)
+ Rect rt; rt.left=llx; rt.right=llx+w; rt.top=lly; rt.bottom=lly+h;
+ (what == POLYGON ? PaintOval : FrameOval)(&rt);
+#elif defined(__APPLE_QUARTZ__)
+ // Quartz warning : circle won't scale to current matrix!
+ CGContextAddArc(fl_gc, xt, yt, (w+h)*0.25f, 0, 2.0f*M_PI, 1);
+ (what == POLYGON ? CGContextFillPath : CGContextStrokePath)(fl_gc);
+#else
+ (what == POLYGON ? XFillArc : XDrawArc)
+ (fl_display, fl_window, fl_gc, llx, lly, w, h, 0, 360*64);
+#endif
+}
+
+//
+// End of "$Id: fl_vertex.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/flstring.c b/third_party/windows/fltk-1.1.10/src/flstring.c new file mode 100644 index 0000000..34c01d6 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/flstring.c @@ -0,0 +1,105 @@ +/*
+ * "$Id: flstring.c 4288 2005-04-16 00:13:17Z mike $"
+ *
+ * BSD string functions for the Fast Light Tool Kit (FLTK).
+ *
+ * Copyright 1998-2005 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 "flstring.h"
+
+
+/*
+ * 'fl_strlcat()' - Safely concatenate two strings.
+ */
+
+size_t /* O - Length of string */
+fl_strlcat(char *dst, /* O - Destination string */
+ const char *src, /* I - Source string */
+ size_t size) { /* I - Size of destination string buffer */
+ size_t srclen; /* Length of source string */
+ size_t dstlen; /* Length of destination string */
+
+
+ /*
+ * Figure out how much room is left...
+ */
+
+ dstlen = strlen(dst);
+ size -= dstlen + 1;
+
+ if (!size) return (dstlen); /* No room, return immediately... */
+
+ /*
+ * Figure out how much room is needed...
+ */
+
+ srclen = strlen(src);
+
+ /*
+ * Copy the appropriate amount...
+ */
+
+ if (srclen > size) srclen = size;
+
+ memcpy(dst + dstlen, src, srclen);
+ dst[dstlen + srclen] = '\0';
+
+ return (dstlen + srclen);
+}
+
+
+/*
+ * 'fl_strlcpy()' - Safely copy two strings.
+ */
+
+size_t /* O - Length of string */
+fl_strlcpy(char *dst, /* O - Destination string */
+ const char *src, /* I - Source string */
+ size_t size) { /* I - Size of destination string buffer */
+ size_t srclen; /* Length of source string */
+
+
+ /*
+ * Figure out how much room is needed...
+ */
+
+ size --;
+
+ srclen = strlen(src);
+
+ /*
+ * Copy the appropriate amount...
+ */
+
+ if (srclen > size) srclen = size;
+
+ memcpy(dst, src, srclen);
+ dst[srclen] = '\0';
+
+ return (srclen);
+}
+
+
+/*
+ * End of "$Id: flstring.c 4288 2005-04-16 00:13:17Z mike $".
+ */
diff --git a/third_party/windows/fltk-1.1.10/src/flstring.h b/third_party/windows/fltk-1.1.10/src/flstring.h new file mode 100644 index 0000000..1a676f6 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/flstring.h @@ -0,0 +1,115 @@ +/*
+ * "$Id: flstring.h 5701 2007-02-20 18:43:10Z mike $"
+ *
+ * Common string header file for the Fast Light Tool Kit (FLTK).
+ *
+ * Copyright 1998-2007 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
+ */
+
+#ifndef flstring_h
+# define flstring_h
+
+# include <FL/Fl_Export.H>
+# include <config.h>
+# include <stdio.h>
+# include <stdarg.h>
+# include <string.h>
+# ifdef HAVE_STRINGS_H
+# include <strings.h>
+# endif /* HAVE_STRINGS_H */
+# include <ctype.h>
+
+/*
+ * Apparently Unixware defines "index" to strchr (!) rather than
+ * providing a proper entry point or not providing the (obsolete)
+ * BSD function. Make sure index is not defined...
+ */
+
+# ifdef index
+# undef index
+# endif /* index */
+
+# if defined(WIN32) && !defined(__CYGWIN__)
+# define strcasecmp(s,t) _stricmp((s), (t))
+# define strncasecmp(s,t,n) _strnicmp((s), (t), (n))
+// Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs
+// on Windows, which is supposed to be POSIX compliant... Some of these
+// functions are also defined in ISO C99...
+# ifndef __WATCOMC__
+# define strdup _strdup
+# define unlink _unlink
+# endif // !__WATCOMC__
+# elif defined(__EMX__)
+# define strcasecmp(s,t) stricmp((s), (t))
+# define strncasecmp(s,t,n) strnicmp((s), (t), (n))
+# endif /* WIN32 */
+
+# ifdef __cplusplus
+extern "C" {
+# endif /* __cplusplus */
+
+/*
+ * MetroWerks' CodeWarrior put thes "non-standard" functions in
+ * <extras.h> which unfortunatly does not play well otherwise
+ * when included - to be resolved...
+ */
+
+# if defined(__APPLE__) && defined(__MWERKS__) && defined(_MSL_USING_MW_C_HEADERS)
+int strcasecmp(const char*,const char*);
+int strncasecmp(const char*,const char*,int);
+char *strdup(const char*);
+# endif
+
+FL_EXPORT extern int fl_snprintf(char *, size_t, const char *, ...);
+# if !HAVE_SNPRINTF
+# define snprintf fl_snprintf
+# endif /* !HAVE_SNPRINTF */
+
+FL_EXPORT extern int fl_vsnprintf(char *, size_t, const char *, va_list ap);
+# if !HAVE_VSNPRINTF
+# define vsnprintf fl_vsnprintf
+# endif /* !HAVE_VSNPRINTF */
+
+/*
+ * strlcpy() and strlcat() are some really useful BSD string functions
+ * that work the way strncpy() and strncat() *should* have worked.
+ */
+
+FL_EXPORT extern size_t fl_strlcat(char *, const char *, size_t);
+# if !HAVE_STRLCAT
+# define strlcat fl_strlcat
+# endif /* !HAVE_STRLCAT */
+
+FL_EXPORT extern size_t fl_strlcpy(char *, const char *, size_t);
+# if !HAVE_STRLCPY
+# define strlcpy fl_strlcpy
+# endif /* !HAVE_STRLCPY */
+
+# ifdef __cplusplus
+}
+# endif /* __cplusplus */
+#endif /* !flstring_h */
+
+
+/*
+ * End of "$Id: flstring.h 5701 2007-02-20 18:43:10Z mike $".
+ */
diff --git a/third_party/windows/fltk-1.1.10/src/forms_bitmap.cxx b/third_party/windows/fltk-1.1.10/src/forms_bitmap.cxx new file mode 100644 index 0000000..f7e497e --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/forms_bitmap.cxx @@ -0,0 +1,52 @@ +//
+// "$Id: forms_bitmap.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Forms compatible bitmap function for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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/forms.H>
+
+Fl_FormsBitmap::Fl_FormsBitmap(
+ Fl_Boxtype t, int X, int Y, int W, int H, const char* l)
+: Fl_Widget(X, Y, W, H, l) {
+ box(t);
+ b = 0;
+ color(FL_BLACK);
+ align(FL_ALIGN_BOTTOM);
+}
+
+void Fl_FormsBitmap::set(int W, int H, const uchar *bits) {
+ delete b;
+ bitmap(new Fl_Bitmap(bits, W, H));
+}
+
+void Fl_FormsBitmap::draw() {
+ draw_box(box(), selection_color());
+ if (b) {fl_color(color()); b->draw(x(), y(), w(), h());}
+ draw_label();
+}
+
+//
+// End of "$Id: forms_bitmap.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/forms_compatability.cxx b/third_party/windows/fltk-1.1.10/src/forms_compatability.cxx new file mode 100644 index 0000000..0608f30 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/forms_compatability.cxx @@ -0,0 +1,211 @@ +//
+// "$Id: forms_compatability.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Forms compatibility functions for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Forms library compatability functions.
+// Many more functions are defined as inlines in forms.h!
+
+#include <FL/forms.H>
+#include <stdlib.h>
+
+char fl_flip = 2;
+void fl_end_form() {
+ while (Fl_Group::current()) Fl_Group::current()->forms_end();
+}
+void Fl_Group::forms_end() {
+ // set the dimensions of a group to surround contents
+ if (children() && !w()) {
+ Fl_Widget*const* a = array();
+ Fl_Widget* o = *a++;
+ int rx = o->x();
+ int ry = o->y();
+ int rw = rx+o->w();
+ int rh = ry+o->h();
+ for (int i=children_-1; i--;) {
+ o = *a++;
+ if (o->x() < rx) rx = o->x();
+ if (o->y() < ry) ry = o->y();
+ if (o->x()+o->w() > rw) rw = o->x()+o->w();
+ if (o->y()+o->h() > rh) rh = o->y()+o->h();
+ }
+ x(rx);
+ y(ry);
+ w(rw-rx);
+ h(rh-ry);
+ }
+ // flip all the children's coordinate systems:
+ if (fl_flip) {
+ Fl_Widget* o = (type()>=FL_WINDOW) ? this : window();
+ int Y = o->h();
+ Fl_Widget*const* a = array();
+ for (int i=children(); i--;) {
+ Fl_Widget* ow = *a++;
+ int newy = Y-ow->y()-ow->h();
+ ow->y(newy);
+ }
+ }
+ end();
+}
+
+static int initargc;
+static char **initargv;
+
+void fl_initialize(int *argc, char **argv, const char *, FL_CMD_OPT *, int) {
+ initargc = *argc;
+ initargv = new char*[*argc+1];
+ int i,j;
+ for (i=0; i<=*argc; i++) initargv[i] = argv[i];
+ for (i=j=1; i<*argc; ) {
+ if (Fl::arg(*argc,argv,i));
+ else argv[j++] = argv[i++];
+ }
+ argv[j] = 0;
+ *argc = j;
+ if (fl_flip==2) fl_flip = 0;
+}
+
+char fl_modal_next; // set by fl_freeze_forms()
+
+void fl_show_form(Fl_Window *f,int place,int b,const char *n) {
+
+ f->label(n);
+ if (!b) f->clear_border();
+ if (fl_modal_next || b==FL_TRANSIENT) {f->set_modal(); fl_modal_next = 0;}
+
+ if (place & FL_PLACE_MOUSE) f->hotspot(f);
+
+ if (place & FL_PLACE_CENTER) {
+ int scr_x, scr_y, scr_w, scr_h;
+ Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h);
+ f->position(scr_x+(scr_w-f->w())/2, scr_y+(scr_h-f->h())/2);
+ }
+
+ if (place & FL_PLACE_FULLSCREEN)
+ f->fullscreen();
+
+ if (place & (FL_PLACE_POSITION | FL_PLACE_GEOMETRY))
+ f->position(
+ (f->x() < 0) ? Fl::w()-f->w()+f->x()-1 : f->x(),
+ (f->y() < 0) ? Fl::h()-f->h()+f->y()-1 : f->y());
+
+// if (place & FL_PLACE_ASPECT) {
+// this is not yet implemented
+// it can be done by setting size_range().
+
+ if (place == FL_PLACE_FREE || place == FL_PLACE_SIZE)
+ f->free_position();
+
+ if (place == FL_PLACE_FREE || place & FL_FREE_SIZE)
+ if (!f->resizable()) f->resizable(f);
+
+ if (initargc) {f->show(initargc,initargv); initargc = 0;}
+ else f->show();
+}
+
+Fl_Widget *fl_do_forms(void) {
+ Fl_Widget *obj;
+ while (!(obj = Fl::readqueue())) if (!Fl::wait()) exit(0);
+ return obj;
+}
+
+Fl_Widget *fl_check_forms() {
+ Fl::check();
+ return Fl::readqueue();
+}
+
+void fl_set_graphics_mode(int /*r*/,int /*d*/) {}
+
+void Fl_FormsText::draw() {
+ draw_box();
+ align(align()|FL_ALIGN_INSIDE); // questionable method of compatability
+ draw_label();
+}
+
+// Create a forms button by selecting correct fltk subclass:
+
+#include <FL/Fl_Return_Button.H>
+#include <FL/Fl_Repeat_Button.H>
+
+Fl_Button *fl_add_button(uchar t,int x,int y,int w,int h,const char *l) {
+ Fl_Button *b;
+ switch (t) {
+ case FL_RETURN_BUTTON:
+ case FL_HIDDEN_RET_BUTTON:
+ b = new Fl_Return_Button(x,y,w,h,l);
+ break;
+ case FL_TOUCH_BUTTON:
+ b = new Fl_Repeat_Button(x,y,w,h,l);
+ break;
+ default:
+ b = new Fl_Button(x,y,w,h,l);
+ }
+ switch (t) {
+ case FL_TOGGLE_BUTTON:
+ case FL_RADIO_BUTTON:
+ b->type(t);
+ break;
+ case FL_HIDDEN_BUTTON:
+ case FL_HIDDEN_RET_BUTTON:
+ b->type(FL_HIDDEN_BUTTON);
+ break;
+ case FL_INOUT_BUTTON:
+ b->when(FL_WHEN_CHANGED);
+ break;
+ }
+ return b;
+}
+
+void fl_show_message(const char *q1,const char *q2,const char *q3) {
+ fl_message("%s\n%s\n%s", q1?q1:"", q2?q2:"", q3?q3:"");
+}
+
+void fl_show_alert(const char *q1,const char *q2,const char *q3,int) {
+ fl_alert("%s\n%s\n%s", q1?q1:"", q2?q2:"", q3?q3:"");
+}
+
+int fl_show_question(const char *q1,const char *q2,const char *q3) {
+ return fl_choice("%s\n%s\n%s", "No", "Yes", 0L, q1?q1:"", q2?q2:"", q3?q3:"");
+}
+
+int fl_show_choice(
+ const char *q1,
+ const char *q2,
+ const char *q3,
+ int, // number of buttons, ignored
+ const char *b0,
+ const char *b1,
+ const char *b2) {
+ return fl_choice("%s\n%s\n%s", q1?q1:"", q2?q2:"", q3?q3:"", b0,b1,b2)+1;
+}
+
+char *fl_show_simple_input(const char *str1, const char *defstr) {
+ const char *r = fl_input(str1, defstr);
+ return (char *)(r ? r : defstr);
+}
+
+//
+// End of "$Id: forms_compatability.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/forms_free.cxx b/third_party/windows/fltk-1.1.10/src/forms_free.cxx new file mode 100644 index 0000000..7b589e5 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/forms_free.cxx @@ -0,0 +1,81 @@ +//
+// "$Id: forms_free.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Forms free widget routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Emulation of the Forms "free" widget.
+// This emulation allows the free demo to run, and has allowed
+// me to port several other programs, but it is in no way
+// complete.
+
+#include <FL/Fl.H>
+#include <FL/Fl_Free.H>
+
+void Fl_Free::step(void *v) {
+ Fl_Free *f = (Fl_Free *)v;
+ int old_event = Fl::e_number;
+ f->handle(Fl::e_number == FL_STEP);
+ Fl::e_number = old_event;
+ Fl::add_timeout(.01,step,v);
+}
+
+Fl_Free::Fl_Free(uchar t,int X, int Y, int W, int H,const char *l,
+ FL_HANDLEPTR hdl) :
+Fl_Widget(X,Y,W,H,l) {
+ type(t);
+ hfunc = hdl;
+ if (t == FL_SLEEPING_FREE) set_flag(INACTIVE);
+ if (t == FL_CONTINUOUS_FREE || t == FL_ALL_FREE)
+ Fl::add_timeout(.01,step,this);
+}
+
+Fl_Free::~Fl_Free() {
+ Fl::remove_timeout(step,this);
+ hfunc(this,FL_FREEMEM,0,0,0);
+}
+
+void Fl_Free::draw() {hfunc(this,FL_DRAW,0,0,0);}
+
+int Fl_Free::handle(int e) {
+ char key = Fl::event_key();
+ switch (e) {
+ case FL_FOCUS:
+ if (type()!=FL_INPUT_FREE && type()!=FL_ALL_FREE) return 0;
+ break;
+ case FL_PUSH:
+ case FL_DRAG:
+ case FL_RELEASE:
+ key = 4-Fl::event_button();
+ break;
+ case FL_SHORTCUT:
+ return 0;
+ }
+ if (hfunc(this, e, float(Fl::event_x()), float(Fl::event_y()), key)) do_callback();
+ return 1;
+}
+
+//
+// End of "$Id: forms_free.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/forms_fselect.cxx b/third_party/windows/fltk-1.1.10/src/forms_fselect.cxx new file mode 100644 index 0000000..5bad0f8 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/forms_fselect.cxx @@ -0,0 +1,67 @@ +//
+// "$Id: forms_fselect.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Forms file selection routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Emulate the Forms file chooser using the fltk file chooser.
+
+#include <FL/forms.H>
+#include "flstring.h"
+
+static char fl_directory[1024];
+static const char *fl_pattern; // assummed passed value is static
+static char fl_filename[1024];
+
+char* fl_show_file_selector(const char *message,const char *dir,
+ const char *pat,const char *fname) {
+ if (dir && dir[0]) strlcpy(fl_directory,dir,sizeof(fl_directory));
+ if (pat && pat[0]) fl_pattern = pat;
+ if (fname && fname[0]) strlcpy(fl_filename,fname,sizeof(fl_filename));
+ char *p = fl_directory+strlen(fl_directory);
+ if (p > fl_directory && *(p-1)!='/'
+#ifdef WIN32
+ && *(p-1)!='\\' && *(p-1)!=':'
+#endif
+ ) *p++ = '/';
+ strlcpy(p,fl_filename,sizeof(fl_directory) - (p - fl_directory));
+ const char *q = fl_file_chooser(message,fl_pattern,fl_directory);
+ if (!q) return 0;
+ strlcpy(fl_directory, q, sizeof(fl_directory));
+ p = (char *)fl_filename_name(fl_directory);
+ strlcpy(fl_filename, p, sizeof(fl_filename));
+ if (p > fl_directory+1) p--;
+ *p = 0;
+ return (char *)q;
+}
+
+char* fl_get_directory() {return fl_directory;}
+
+char* fl_get_pattern() {return (char *)fl_pattern;}
+
+char* fl_get_filename() {return fl_filename;}
+
+//
+// End of "$Id: forms_fselect.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/forms_pixmap.cxx b/third_party/windows/fltk-1.1.10/src/forms_pixmap.cxx new file mode 100644 index 0000000..6259a21 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/forms_pixmap.cxx @@ -0,0 +1,52 @@ +//
+// "$Id: forms_pixmap.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// Forms pixmap drawing routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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/forms.H>
+
+Fl_FormsPixmap::Fl_FormsPixmap(
+ Fl_Boxtype t, int X, int Y, int W, int H, const char* l)
+: Fl_Widget(X, Y, W, H, l) {
+ box(t);
+ b = 0;
+ color(FL_BLACK);
+ align(FL_ALIGN_BOTTOM);
+}
+
+void Fl_FormsPixmap::set(char*const* bits) {
+ delete b;
+ b = new Fl_Pixmap(bits);
+}
+
+void Fl_FormsPixmap::draw() {
+ draw_box(box(), selection_color());
+ if (b) {fl_color(color()); b->draw(x(), y(), w(), h());}
+ draw_label();
+}
+
+//
+// End of "$Id: forms_pixmap.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/forms_timer.cxx b/third_party/windows/fltk-1.1.10/src/forms_timer.cxx new file mode 100644 index 0000000..6dd41dc --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/forms_timer.cxx @@ -0,0 +1,170 @@ +//
+// "$Id: forms_timer.cxx 6928 2009-11-07 21:11:16Z matt $"
+//
+// Forms timer object for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Emulate the Forms Timer object
+// You don't want to use this if you just want a timeout, call
+// Fl::add_timeout directly!
+
+#include <FL/Fl.H>
+#include <FL/Fl_Timer.H>
+#include <FL/fl_draw.H>
+#ifdef WIN32
+# ifdef __MWERKS__
+# include <time.h>
+# else
+# include <sys/types.h>
+# include <sys/timeb.h>
+# endif
+#else
+# include <time.h>
+# include <sys/time.h>
+#endif
+#include <stdio.h>
+
+#define FL_TIMER_BLINKRATE 0.2
+
+void fl_gettime(long* sec, long* usec) {
+#ifdef WIN32
+# ifdef __MWERKS__
+ time_t localTime = time(NULL);
+ struct tm *now = localtime(&localTime);
+ *sec = now->tm_sec + 60*now->tm_min + 3600*now->tm_hour + 24*3600*now->tm_yday;
+ *usec = 0;
+# else
+ struct timeb tp;
+ ftime(&tp);
+ *sec = tp.time;
+ *usec = tp.millitm * 1000;
+# endif
+#else
+ struct timeval tp;
+ struct timezone tzp;
+ gettimeofday(&tp, &tzp);
+ *sec = tp.tv_sec;
+ *usec = tp.tv_usec;
+#endif
+}
+
+void Fl_Timer::draw() {
+ int tt;
+ Fl_Color col;
+ char str[32];
+ if (!on || delay>0.0)
+ col = color();
+ else if ((int) (delay / FL_TIMER_BLINKRATE) % 2)
+ col = color();
+ else
+ col = selection_color();
+ draw_box(box(), col);
+ if (type() == FL_VALUE_TIMER && delay>0.0) {
+ double d = direction_ ? total-delay : delay;
+ if (d < 60.0)
+ sprintf(str, "%.1f", d);
+ else {
+ tt = (int) ((d+0.05) / 60.0);
+ sprintf(str, "%d:%04.1f", tt, d - 60.0 * tt);
+ }
+ fl_font(labelfont(), labelsize());
+ fl_color(labelcolor());
+ fl_draw(str, x(), y(), w(), h(), FL_ALIGN_CENTER);
+ } else
+ draw_label();
+}
+
+void Fl_Timer::stepcb(void* v) {
+ ((Fl_Timer*)v)->step();
+}
+
+void Fl_Timer::step() {
+ if (!on) return;
+ double lastdelay = delay;
+ long sec, usec; fl_gettime(&sec, &usec);
+ delay -= (double) (sec - lastsec) + (double) (usec - lastusec) / 1000000.0;
+ lastsec = sec; lastusec = usec;
+ if (lastdelay > 0.0 && delay <= 0.0) {
+ if (type() == FL_HIDDEN_TIMER) {
+ on = 0;
+ delay = 0;
+ } else {
+ redraw();
+ Fl::add_timeout(FL_TIMER_BLINKRATE, stepcb, this);
+ }
+ set_changed();
+ do_callback();
+ } else {
+ if (type() == FL_VALUE_TIMER) redraw();
+ Fl::add_timeout(FL_TIMER_BLINKRATE, stepcb, this);
+ }
+}
+
+int Fl_Timer::handle(int event) {
+ if (event == FL_RELEASE && delay <= 0) value(0.0);
+ return 0;
+}
+
+Fl_Timer::~Fl_Timer() {
+ Fl::remove_timeout(stepcb, this);
+}
+
+Fl_Timer::Fl_Timer(uchar t, int X, int Y, int W, int H, const char* l)
+: Fl_Widget(X, Y, W, H, l) {
+ box(FL_DOWN_BOX);
+ selection_color(FL_RED);
+ delay = 0;
+ on = 0;
+ direction_ = 0;
+ lastsec = lastusec = total = 0;
+ type(t);
+ if (t == FL_HIDDEN_TIMER) clear_visible();
+ if (t == FL_VALUE_TIMER) align(FL_ALIGN_LEFT);
+}
+
+void Fl_Timer::value(double d) {
+ delay = total = d;
+ on = (d > 0.0);
+ fl_gettime(&(lastsec), &(lastusec));
+ if (type() != FL_HIDDEN_TIMER) redraw();
+ Fl::remove_timeout(stepcb, this);
+ if (on) Fl::add_timeout(FL_TIMER_BLINKRATE, stepcb, this);
+}
+
+void Fl_Timer::suspended(char d) {
+ if (!d) {
+ if (on) return;
+ on = (delay > 0.0);
+ fl_gettime(&(lastsec), &(lastusec));
+ if (on) Fl::add_timeout(FL_TIMER_BLINKRATE, stepcb, this);
+ } else {
+ if (!on) return;
+ on = 0;
+ Fl::remove_timeout(stepcb, this);
+ }
+}
+
+//
+// End of "$Id: forms_timer.cxx 6928 2009-11-07 21:11:16Z matt $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/freeglut_geometry.cxx b/third_party/windows/fltk-1.1.10/src/freeglut_geometry.cxx new file mode 100644 index 0000000..91bd9e3 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/freeglut_geometry.cxx @@ -0,0 +1,1110 @@ +/*
+ * freeglut_geometry.c
+ *
+ * Freeglut geometry rendering methods.
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta@sourceforge.net>
+ * Creation date: Fri Dec 3 1999
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <FL/glut.H>
+#include <FL/math.h>
+#include <stdlib.h>
+
+/*
+ * TODO BEFORE THE STABLE RELEASE:
+ *
+ * Following functions have been contributed by Andreas Umbach.
+ *
+ * glutWireCube() -- looks OK
+ * glutSolidCube() -- OK
+ *
+ * Those functions have been implemented by John Fay.
+ *
+ * glutWireTorus() -- looks OK
+ * glutSolidTorus() -- looks OK
+ * glutWireDodecahedron() -- looks OK
+ * glutSolidDodecahedron() -- looks OK
+ * glutWireOctahedron() -- looks OK
+ * glutSolidOctahedron() -- looks OK
+ * glutWireTetrahedron() -- looks OK
+ * glutSolidTetrahedron() -- looks OK
+ * glutWireIcosahedron() -- looks OK
+ * glutSolidIcosahedron() -- looks OK
+ *
+ * The Following functions have been updated by Nigel Stewart, based
+ * on FreeGLUT 2.0.0 implementations:
+ *
+ * glutWireSphere() -- looks OK
+ * glutSolidSphere() -- looks OK
+ * glutWireCone() -- looks OK
+ * glutSolidCone() -- looks OK
+ */
+
+
+/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
+
+/*
+ * Draws a wireframed cube. Code contributed by Andreas Umbach <marvin@dataway.ch>
+ */
+void glutWireCube( GLdouble dSize )
+{
+ double size = dSize * 0.5;
+
+# define V(a,b,c) glVertex3d( a size, b size, c size );
+# define N(a,b,c) glNormal3d( a, b, c );
+
+ /* PWO: I dared to convert the code to use macros... */
+ glBegin( GL_LINE_LOOP ); N( 1.0, 0.0, 0.0); V(+,-,+); V(+,-,-); V(+,+,-); V(+,+,+); glEnd();
+ glBegin( GL_LINE_LOOP ); N( 0.0, 1.0, 0.0); V(+,+,+); V(+,+,-); V(-,+,-); V(-,+,+); glEnd();
+ glBegin( GL_LINE_LOOP ); N( 0.0, 0.0, 1.0); V(+,+,+); V(-,+,+); V(-,-,+); V(+,-,+); glEnd();
+ glBegin( GL_LINE_LOOP ); N(-1.0, 0.0, 0.0); V(-,-,+); V(-,+,+); V(-,+,-); V(-,-,-); glEnd();
+ glBegin( GL_LINE_LOOP ); N( 0.0,-1.0, 0.0); V(-,-,+); V(-,-,-); V(+,-,-); V(+,-,+); glEnd();
+ glBegin( GL_LINE_LOOP ); N( 0.0, 0.0,-1.0); V(-,-,-); V(-,+,-); V(+,+,-); V(+,-,-); glEnd();
+
+# undef V
+# undef N
+}
+
+/*
+ * Draws a solid cube. Code contributed by Andreas Umbach <marvin@dataway.ch>
+ */
+void glutSolidCube( GLdouble dSize )
+{
+ double size = dSize * 0.5;
+
+# define V(a,b,c) glVertex3d( a size, b size, c size );
+# define N(a,b,c) glNormal3d( a, b, c );
+
+ /* PWO: Again, I dared to convert the code to use macros... */
+ glBegin( GL_QUADS );
+ N( 1.0, 0.0, 0.0); V(+,-,+); V(+,-,-); V(+,+,-); V(+,+,+);
+ N( 0.0, 1.0, 0.0); V(+,+,+); V(+,+,-); V(-,+,-); V(-,+,+);
+ N( 0.0, 0.0, 1.0); V(+,+,+); V(-,+,+); V(-,-,+); V(+,-,+);
+ N(-1.0, 0.0, 0.0); V(-,-,+); V(-,+,+); V(-,+,-); V(-,-,-);
+ N( 0.0,-1.0, 0.0); V(-,-,+); V(-,-,-); V(+,-,-); V(+,-,+);
+ N( 0.0, 0.0,-1.0); V(-,-,-); V(-,+,-); V(+,+,-); V(+,-,-);
+ glEnd();
+
+# undef V
+# undef N
+}
+
+/*
+ * Compute lookup table of cos and sin values forming a cirle
+ *
+ * Notes:
+ * It is the responsibility of the caller to free these tables
+ * The size of the table is (n+1) to form a connected loop
+ * The last entry is exactly the same as the first
+ * The sign of n can be flipped to get the reverse loop
+ */
+
+static void fghCircleTable(double **sint,double **cost,const int n)
+{
+ int i;
+
+ /* Table size, the sign of n flips the circle direction */
+
+ const int size = abs(n);
+
+ /* Determine the angle between samples */
+
+ const double angle = 2*M_PI/(double)( ( n == 0 ) ? 1 : n );
+
+ /* Allocate memory for n samples, plus duplicate of first entry at the end */
+
+ *sint = (double *) calloc(sizeof(double), size+1);
+ *cost = (double *) calloc(sizeof(double), size+1);
+
+ /* Bail out if memory allocation fails, fgError never returns */
+
+ if (!(*sint) || !(*cost))
+ {
+ if (*sint) free(*sint);
+ if (*cost) free(*cost);
+ return;
+ }
+
+ /* Compute cos and sin around the circle */
+
+ (*sint)[0] = 0.0;
+ (*cost)[0] = 1.0;
+
+ for (i=1; i<size; i++)
+ {
+ (*sint)[i] = sin(angle*i);
+ (*cost)[i] = cos(angle*i);
+ }
+
+ /* Last sample is duplicate of the first */
+
+ (*sint)[size] = (*sint)[0];
+ (*cost)[size] = (*cost)[0];
+}
+
+/*
+ * Draws a solid sphere
+ */
+void glutSolidSphere(GLdouble radius, GLint slices, GLint stacks)
+{
+ int i,j;
+
+ /* Adjust z and radius as stacks are drawn. */
+
+ double z0,z1;
+ double r0,r1;
+
+ /* Pre-computed circle */
+
+ double *sint1,*cost1;
+ double *sint2,*cost2;
+
+ fghCircleTable(&sint1,&cost1,-slices);
+ fghCircleTable(&sint2,&cost2,stacks*2);
+
+ /* The top stack is covered with a triangle fan */
+
+ z0 = 1.0;
+ z1 = cost2[(stacks>0)?1:0];
+ r0 = 0.0;
+ r1 = sint2[(stacks>0)?1:0];
+
+ glBegin(GL_TRIANGLE_FAN);
+
+ glNormal3d(0,0,1);
+ glVertex3d(0,0,radius);
+
+ for (j=slices; j>=0; j--)
+ {
+ glNormal3d(cost1[j]*r1, sint1[j]*r1, z1 );
+ glVertex3d(cost1[j]*r1*radius, sint1[j]*r1*radius, z1*radius);
+ }
+
+ glEnd();
+
+ /* Cover each stack with a quad strip, except the top and bottom stacks */
+
+ for( i=1; i<stacks-1; i++ )
+ {
+ z0 = z1; z1 = cost2[i+1];
+ r0 = r1; r1 = sint2[i+1];
+
+ glBegin(GL_QUAD_STRIP);
+
+ for(j=0; j<=slices; j++)
+ {
+ glNormal3d(cost1[j]*r1, sint1[j]*r1, z1 );
+ glVertex3d(cost1[j]*r1*radius, sint1[j]*r1*radius, z1*radius);
+ glNormal3d(cost1[j]*r0, sint1[j]*r0, z0 );
+ glVertex3d(cost1[j]*r0*radius, sint1[j]*r0*radius, z0*radius);
+ }
+
+ glEnd();
+ }
+
+ /* The bottom stack is covered with a triangle fan */
+
+ z0 = z1;
+ r0 = r1;
+
+ glBegin(GL_TRIANGLE_FAN);
+
+ glNormal3d(0,0,-1);
+ glVertex3d(0,0,-radius);
+
+ for (j=0; j<=slices; j++)
+ {
+ glNormal3d(cost1[j]*r0, sint1[j]*r0, z0 );
+ glVertex3d(cost1[j]*r0*radius, sint1[j]*r0*radius, z0*radius);
+ }
+
+ glEnd();
+
+ /* Release sin and cos tables */
+
+ free(sint1);
+ free(cost1);
+ free(sint2);
+ free(cost2);
+}
+
+/*
+ * Draws a wire sphere
+ */
+void glutWireSphere(GLdouble radius, GLint slices, GLint stacks)
+{
+ int i,j;
+
+ /* Adjust z and radius as stacks and slices are drawn. */
+
+ double r;
+ double x,y,z;
+
+ /* Pre-computed circle */
+
+ double *sint1,*cost1;
+ double *sint2,*cost2;
+
+ fghCircleTable(&sint1,&cost1,-slices );
+ fghCircleTable(&sint2,&cost2, stacks*2);
+
+ /* Draw a line loop for each stack */
+
+ for (i=1; i<stacks; i++)
+ {
+ z = cost2[i];
+ r = sint2[i];
+
+ glBegin(GL_LINE_LOOP);
+
+ for(j=0; j<=slices; j++)
+ {
+ x = cost1[j];
+ y = sint1[j];
+
+ glNormal3d(x,y,z);
+ glVertex3d(x*r*radius,y*r*radius,z*radius);
+ }
+
+ glEnd();
+ }
+
+ /* Draw a line loop for each slice */
+
+ for (i=0; i<slices; i++)
+ {
+ glBegin(GL_LINE_STRIP);
+
+ for(j=0; j<=stacks; j++)
+ {
+ x = cost1[i]*sint2[j];
+ y = sint1[i]*sint2[j];
+ z = cost2[j];
+
+ glNormal3d(x,y,z);
+ glVertex3d(x*radius,y*radius,z*radius);
+ }
+
+ glEnd();
+ }
+
+ /* Release sin and cos tables */
+
+ free(sint1);
+ free(cost1);
+ free(sint2);
+ free(cost2);
+}
+
+/*
+ * Draws a solid cone
+ */
+void glutSolidCone( GLdouble base, GLdouble height, GLint slices, GLint stacks )
+{
+ int i,j;
+
+ /* Step in z and radius as stacks are drawn. */
+
+ double z0,z1;
+ double r0,r1;
+
+ const double zStep = height / ( ( stacks > 0 ) ? stacks : 1 );
+ const double rStep = base / ( ( stacks > 0 ) ? stacks : 1 );
+
+ /* Scaling factors for vertex normals */
+
+ const double cosn = ( height / sqrt ( height * height + base * base ));
+ const double sinn = ( base / sqrt ( height * height + base * base ));
+
+ /* Pre-computed circle */
+
+ double *sint,*cost;
+
+ fghCircleTable(&sint,&cost,-slices);
+
+ /* Cover the circular base with a triangle fan... */
+
+ z0 = 0.0;
+ z1 = zStep;
+
+ r0 = base;
+ r1 = r0 - rStep;
+
+ glBegin(GL_TRIANGLE_FAN);
+
+ glNormal3d(0.0,0.0,-1.0);
+ glVertex3d(0.0,0.0, z0 );
+
+ for (j=0; j<=slices; j++)
+ glVertex3d(cost[j]*r0, sint[j]*r0, z0);
+
+ glEnd();
+
+ /* Cover each stack with a quad strip, except the top stack */
+
+ for( i=0; i<stacks-1; i++ )
+ {
+ glBegin(GL_QUAD_STRIP);
+
+ for(j=0; j<=slices; j++)
+ {
+ glNormal3d(cost[j]*sinn, sint[j]*sinn, cosn);
+ glVertex3d(cost[j]*r0, sint[j]*r0, z0 );
+ glVertex3d(cost[j]*r1, sint[j]*r1, z1 );
+ }
+
+ z0 = z1; z1 += zStep;
+ r0 = r1; r1 -= rStep;
+
+ glEnd();
+ }
+
+ /* The top stack is covered with individual triangles */
+
+ glBegin(GL_TRIANGLES);
+
+ glNormal3d(cost[0]*sinn, sint[0]*sinn, cosn);
+
+ for (j=0; j<slices; j++)
+ {
+ glVertex3d(cost[j+0]*r0, sint[j+0]*r0, z0 );
+ glVertex3d(0, 0, height);
+ glNormal3d(cost[j+1]*sinn, sint[j+1]*sinn, cosn );
+ glVertex3d(cost[j+1]*r0, sint[j+1]*r0, z0 );
+ }
+
+ glEnd();
+
+ /* Release sin and cos tables */
+
+ free(sint);
+ free(cost);
+}
+
+/*
+ * Draws a wire cone
+ */
+void glutWireCone( GLdouble base, GLdouble height, GLint slices, GLint stacks)
+{
+ int i,j;
+
+ /* Step in z and radius as stacks are drawn. */
+
+ double z = 0.0;
+ double r = base;
+
+ const double zStep = height / ( ( stacks > 0 ) ? stacks : 1 );
+ const double rStep = base / ( ( stacks > 0 ) ? stacks : 1 );
+
+ /* Scaling factors for vertex normals */
+
+ const double cosn = ( height / sqrt ( height * height + base * base ));
+ const double sinn = ( base / sqrt ( height * height + base * base ));
+
+ /* Pre-computed circle */
+
+ double *sint,*cost;
+
+ fghCircleTable(&sint,&cost,-slices);
+
+ /* Draw the stacks... */
+
+ for (i=0; i<stacks; i++)
+ {
+ glBegin(GL_LINE_LOOP);
+
+ for( j=0; j<slices; j++ )
+ {
+ glNormal3d(cost[j]*sinn, sint[j]*sinn, cosn);
+ glVertex3d(cost[j]*r, sint[j]*r, z );
+ }
+
+ glEnd();
+
+ z += zStep;
+ r -= rStep;
+ }
+
+ /* Draw the slices */
+
+ r = base;
+
+ glBegin(GL_LINES);
+
+ for (j=0; j<slices; j++)
+ {
+ glNormal3d(cost[j]*sinn, sint[j]*sinn, cosn );
+ glVertex3d(cost[j]*r, sint[j]*r, 0.0 );
+ glVertex3d(0.0, 0.0, height);
+ }
+
+ glEnd();
+
+ /* Release sin and cos tables */
+
+ free(sint);
+ free(cost);
+}
+
+
+/*
+ * Draws a solid cylinder
+ */
+void glutSolidCylinder(GLdouble radius, GLdouble height, GLint slices, GLint stacks)
+{
+ int i,j;
+
+ /* Step in z and radius as stacks are drawn. */
+
+ double z0,z1;
+ const double zStep = height / ( ( stacks > 0 ) ? stacks : 1 );
+
+ /* Pre-computed circle */
+
+ double *sint,*cost;
+
+ fghCircleTable(&sint,&cost,-slices);
+
+ /* Cover the base and top */
+
+ glBegin(GL_TRIANGLE_FAN);
+ glNormal3d(0.0, 0.0, -1.0 );
+ glVertex3d(0.0, 0.0, 0.0 );
+ for (j=0; j<=slices; j++)
+ glVertex3d(cost[j]*radius, sint[j]*radius, 0.0);
+ glEnd();
+
+ glBegin(GL_TRIANGLE_FAN);
+ glNormal3d(0.0, 0.0, 1.0 );
+ glVertex3d(0.0, 0.0, height);
+ for (j=slices; j>=0; j--)
+ glVertex3d(cost[j]*radius, sint[j]*radius, height);
+ glEnd();
+
+ /* Do the stacks */
+
+ z0 = 0.0;
+ z1 = zStep;
+
+ for (i=1; i<=stacks; i++)
+ {
+ if (i==stacks)
+ z1 = height;
+
+ glBegin(GL_QUAD_STRIP);
+ for (j=0; j<=slices; j++ )
+ {
+ glNormal3d(cost[j], sint[j], 0.0 );
+ glVertex3d(cost[j]*radius, sint[j]*radius, z0 );
+ glVertex3d(cost[j]*radius, sint[j]*radius, z1 );
+ }
+ glEnd();
+
+ z0 = z1; z1 += zStep;
+ }
+
+ /* Release sin and cos tables */
+
+ free(sint);
+ free(cost);
+}
+
+/*
+ * Draws a wire cylinder
+ */
+void glutWireCylinder(GLdouble radius, GLdouble height, GLint slices, GLint stacks)
+{
+ int i,j;
+
+ /* Step in z and radius as stacks are drawn. */
+
+ double z = 0.0;
+ const double zStep = height / ( ( stacks > 0 ) ? stacks : 1 );
+
+ /* Pre-computed circle */
+
+ double *sint,*cost;
+
+ fghCircleTable(&sint,&cost,-slices);
+
+ /* Draw the stacks... */
+
+ for (i=0; i<=stacks; i++)
+ {
+ if (i==stacks)
+ z = height;
+
+ glBegin(GL_LINE_LOOP);
+
+ for( j=0; j<slices; j++ )
+ {
+ glNormal3d(cost[j], sint[j], 0.0);
+ glVertex3d(cost[j]*radius, sint[j]*radius, z );
+ }
+
+ glEnd();
+
+ z += zStep;
+ }
+
+ /* Draw the slices */
+
+ glBegin(GL_LINES);
+
+ for (j=0; j<slices; j++)
+ {
+ glNormal3d(cost[j], sint[j], 0.0 );
+ glVertex3d(cost[j]*radius, sint[j]*radius, 0.0 );
+ glVertex3d(cost[j]*radius, sint[j]*radius, height);
+ }
+
+ glEnd();
+
+ /* Release sin and cos tables */
+
+ free(sint);
+ free(cost);
+}
+
+/*
+ * Draws a wire torus
+ */
+void glutWireTorus( GLdouble dInnerRadius, GLdouble dOuterRadius, GLint nSides, GLint nRings )
+{
+ double iradius = dInnerRadius, oradius = dOuterRadius, phi, psi, dpsi, dphi;
+ double *vertex, *normal;
+ int i, j;
+ double spsi, cpsi, sphi, cphi ;
+
+ if ( nSides < 1 ) nSides = 1;
+ if ( nRings < 1 ) nRings = 1;
+
+ /* Allocate the vertices array */
+ vertex = (double *)calloc( sizeof(double), 3 * nSides * nRings );
+ normal = (double *)calloc( sizeof(double), 3 * nSides * nRings );
+
+ glPushMatrix();
+
+ dpsi = 2.0 * M_PI / (double)nRings ;
+ dphi = -2.0 * M_PI / (double)nSides ;
+ psi = 0.0;
+
+ for( j=0; j<nRings; j++ )
+ {
+ cpsi = cos ( psi ) ;
+ spsi = sin ( psi ) ;
+ phi = 0.0;
+
+ for( i=0; i<nSides; i++ )
+ {
+ int offset = 3 * ( j * nSides + i ) ;
+ cphi = cos ( phi ) ;
+ sphi = sin ( phi ) ;
+ *(vertex + offset + 0) = cpsi * ( oradius + cphi * iradius ) ;
+ *(vertex + offset + 1) = spsi * ( oradius + cphi * iradius ) ;
+ *(vertex + offset + 2) = sphi * iradius ;
+ *(normal + offset + 0) = cpsi * cphi ;
+ *(normal + offset + 1) = spsi * cphi ;
+ *(normal + offset + 2) = sphi ;
+ phi += dphi;
+ }
+
+ psi += dpsi;
+ }
+
+ for( i=0; i<nSides; i++ )
+ {
+ glBegin( GL_LINE_LOOP );
+
+ for( j=0; j<nRings; j++ )
+ {
+ int offset = 3 * ( j * nSides + i ) ;
+ glNormal3dv( normal + offset );
+ glVertex3dv( vertex + offset );
+ }
+
+ glEnd();
+ }
+
+ for( j=0; j<nRings; j++ )
+ {
+ glBegin(GL_LINE_LOOP);
+
+ for( i=0; i<nSides; i++ )
+ {
+ int offset = 3 * ( j * nSides + i ) ;
+ glNormal3dv( normal + offset );
+ glVertex3dv( vertex + offset );
+ }
+
+ glEnd();
+ }
+
+ free ( vertex ) ;
+ free ( normal ) ;
+ glPopMatrix();
+}
+
+/*
+ * Draws a solid torus
+ */
+void glutSolidTorus( GLdouble dInnerRadius, GLdouble dOuterRadius, GLint nSides, GLint nRings )
+{
+ double iradius = dInnerRadius, oradius = dOuterRadius, phi, psi, dpsi, dphi;
+ double *vertex, *normal;
+ int i, j;
+ double spsi, cpsi, sphi, cphi ;
+
+ if ( nSides < 1 ) nSides = 1;
+ if ( nRings < 1 ) nRings = 1;
+
+ /* Increment the number of sides and rings to allow for one more point than surface */
+ nSides ++ ;
+ nRings ++ ;
+
+ /* Allocate the vertices array */
+ vertex = (double *)calloc( sizeof(double), 3 * nSides * nRings );
+ normal = (double *)calloc( sizeof(double), 3 * nSides * nRings );
+
+ glPushMatrix();
+
+ dpsi = 2.0 * M_PI / (double)(nRings - 1) ;
+ dphi = -2.0 * M_PI / (double)(nSides - 1) ;
+ psi = 0.0;
+
+ for( j=0; j<nRings; j++ )
+ {
+ cpsi = cos ( psi ) ;
+ spsi = sin ( psi ) ;
+ phi = 0.0;
+
+ for( i=0; i<nSides; i++ )
+ {
+ int offset = 3 * ( j * nSides + i ) ;
+ cphi = cos ( phi ) ;
+ sphi = sin ( phi ) ;
+ *(vertex + offset + 0) = cpsi * ( oradius + cphi * iradius ) ;
+ *(vertex + offset + 1) = spsi * ( oradius + cphi * iradius ) ;
+ *(vertex + offset + 2) = sphi * iradius ;
+ *(normal + offset + 0) = cpsi * cphi ;
+ *(normal + offset + 1) = spsi * cphi ;
+ *(normal + offset + 2) = sphi ;
+ phi += dphi;
+ }
+
+ psi += dpsi;
+ }
+
+ glBegin( GL_QUADS );
+ for( i=0; i<nSides-1; i++ )
+ {
+ for( j=0; j<nRings-1; j++ )
+ {
+ int offset = 3 * ( j * nSides + i ) ;
+ glNormal3dv( normal + offset );
+ glVertex3dv( vertex + offset );
+ glNormal3dv( normal + offset + 3 );
+ glVertex3dv( vertex + offset + 3 );
+ glNormal3dv( normal + offset + 3 * nSides + 3 );
+ glVertex3dv( vertex + offset + 3 * nSides + 3 );
+ glNormal3dv( normal + offset + 3 * nSides );
+ glVertex3dv( vertex + offset + 3 * nSides );
+ }
+ }
+
+ glEnd();
+
+ free ( vertex ) ;
+ free ( normal ) ;
+ glPopMatrix();
+}
+
+/*
+ *
+ */
+void glutWireDodecahedron( void )
+{
+ /* Magic Numbers: It is possible to create a dodecahedron by attaching two pentagons to each face of
+ * of a cube. The coordinates of the points are:
+ * (+-x,0, z); (+-1, 1, 1); (0, z, x )
+ * where x = (-1 + sqrt(5))/2, z = (1 + sqrt(5))/2 or
+ * x = 0.61803398875 and z = 1.61803398875.
+ */
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3d ( 0.0, 0.525731112119, 0.850650808354 ) ; glVertex3d ( 0.0, 1.61803398875, 0.61803398875 ) ; glVertex3d ( -1.0, 1.0, 1.0 ) ; glVertex3d ( -0.61803398875, 0.0, 1.61803398875 ) ; glVertex3d ( 0.61803398875, 0.0, 1.61803398875 ) ; glVertex3d ( 1.0, 1.0, 1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3d ( 0.0, 0.525731112119, -0.850650808354 ) ; glVertex3d ( 0.0, 1.61803398875, -0.61803398875 ) ; glVertex3d ( 1.0, 1.0, -1.0 ) ; glVertex3d ( 0.61803398875, 0.0, -1.61803398875 ) ; glVertex3d ( -0.61803398875, 0.0, -1.61803398875 ) ; glVertex3d ( -1.0, 1.0, -1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3d ( 0.0, -0.525731112119, 0.850650808354 ) ; glVertex3d ( 0.0, -1.61803398875, 0.61803398875 ) ; glVertex3d ( 1.0, -1.0, 1.0 ) ; glVertex3d ( 0.61803398875, 0.0, 1.61803398875 ) ; glVertex3d ( -0.61803398875, 0.0, 1.61803398875 ) ; glVertex3d ( -1.0, -1.0, 1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3d ( 0.0, -0.525731112119, -0.850650808354 ) ; glVertex3d ( 0.0, -1.61803398875, -0.61803398875 ) ; glVertex3d ( -1.0, -1.0, -1.0 ) ; glVertex3d ( -0.61803398875, 0.0, -1.61803398875 ) ; glVertex3d ( 0.61803398875, 0.0, -1.61803398875 ) ; glVertex3d ( 1.0, -1.0, -1.0 ) ;
+ glEnd () ;
+
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3d ( 0.850650808354, 0.0, 0.525731112119 ) ; glVertex3d ( 0.61803398875, 0.0, 1.61803398875 ) ; glVertex3d ( 1.0, -1.0, 1.0 ) ; glVertex3d ( 1.61803398875, -0.61803398875, 0.0 ) ; glVertex3d ( 1.61803398875, 0.61803398875, 0.0 ) ; glVertex3d ( 1.0, 1.0, 1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3d ( -0.850650808354, 0.0, 0.525731112119 ) ; glVertex3d ( -0.61803398875, 0.0, 1.61803398875 ) ; glVertex3d ( -1.0, 1.0, 1.0 ) ; glVertex3d ( -1.61803398875, 0.61803398875, 0.0 ) ; glVertex3d ( -1.61803398875, -0.61803398875, 0.0 ) ; glVertex3d ( -1.0, -1.0, 1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3d ( 0.850650808354, 0.0, -0.525731112119 ) ; glVertex3d ( 0.61803398875, 0.0, -1.61803398875 ) ; glVertex3d ( 1.0, 1.0, -1.0 ) ; glVertex3d ( 1.61803398875, 0.61803398875, 0.0 ) ; glVertex3d ( 1.61803398875, -0.61803398875, 0.0 ) ; glVertex3d ( 1.0, -1.0, -1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3d ( -0.850650808354, 0.0, -0.525731112119 ) ; glVertex3d ( -0.61803398875, 0.0, -1.61803398875 ) ; glVertex3d ( -1.0, -1.0, -1.0 ) ; glVertex3d ( -1.61803398875, -0.61803398875, 0.0 ) ; glVertex3d ( -1.61803398875, 0.61803398875, 0.0 ) ; glVertex3d ( -1.0, 1.0, -1.0 ) ;
+ glEnd () ;
+
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3d ( 0.525731112119, 0.850650808354, 0.0 ) ; glVertex3d ( 1.61803398875, 0.61803398875, 0.0 ) ; glVertex3d ( 1.0, 1.0, -1.0 ) ; glVertex3d ( 0.0, 1.61803398875, -0.61803398875 ) ; glVertex3d ( 0.0, 1.61803398875, 0.61803398875 ) ; glVertex3d ( 1.0, 1.0, 1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3d ( 0.525731112119, -0.850650808354, 0.0 ) ; glVertex3d ( 1.61803398875, -0.61803398875, 0.0 ) ; glVertex3d ( 1.0, -1.0, 1.0 ) ; glVertex3d ( 0.0, -1.61803398875, 0.61803398875 ) ; glVertex3d ( 0.0, -1.61803398875, -0.61803398875 ) ; glVertex3d ( 1.0, -1.0, -1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3d ( -0.525731112119, 0.850650808354, 0.0 ) ; glVertex3d ( -1.61803398875, 0.61803398875, 0.0 ) ; glVertex3d ( -1.0, 1.0, 1.0 ) ; glVertex3d ( 0.0, 1.61803398875, 0.61803398875 ) ; glVertex3d ( 0.0, 1.61803398875, -0.61803398875 ) ; glVertex3d ( -1.0, 1.0, -1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3d ( -0.525731112119, -0.850650808354, 0.0 ) ; glVertex3d ( -1.61803398875, -0.61803398875, 0.0 ) ; glVertex3d ( -1.0, -1.0, -1.0 ) ; glVertex3d ( 0.0, -1.61803398875, -0.61803398875 ) ; glVertex3d ( 0.0, -1.61803398875, 0.61803398875 ) ; glVertex3d ( -1.0, -1.0, 1.0 ) ;
+ glEnd () ;
+}
+
+/*
+ *
+ */
+void glutSolidDodecahedron( void )
+{
+ /* Magic Numbers: It is possible to create a dodecahedron by attaching two pentagons to each face of
+ * of a cube. The coordinates of the points are:
+ * (+-x,0, z); (+-1, 1, 1); (0, z, x )
+ * where x = (-1 + sqrt(5))/2, z = (1 + sqrt(5))/2 or
+ * x = 0.61803398875 and z = 1.61803398875.
+ */
+ glBegin ( GL_POLYGON ) ;
+ glNormal3d ( 0.0, 0.525731112119, 0.850650808354 ) ; glVertex3d ( 0.0, 1.61803398875, 0.61803398875 ) ; glVertex3d ( -1.0, 1.0, 1.0 ) ; glVertex3d ( -0.61803398875, 0.0, 1.61803398875 ) ; glVertex3d ( 0.61803398875, 0.0, 1.61803398875 ) ; glVertex3d ( 1.0, 1.0, 1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_POLYGON ) ;
+ glNormal3d ( 0.0, 0.525731112119, -0.850650808354 ) ; glVertex3d ( 0.0, 1.61803398875, -0.61803398875 ) ; glVertex3d ( 1.0, 1.0, -1.0 ) ; glVertex3d ( 0.61803398875, 0.0, -1.61803398875 ) ; glVertex3d ( -0.61803398875, 0.0, -1.61803398875 ) ; glVertex3d ( -1.0, 1.0, -1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_POLYGON ) ;
+ glNormal3d ( 0.0, -0.525731112119, 0.850650808354 ) ; glVertex3d ( 0.0, -1.61803398875, 0.61803398875 ) ; glVertex3d ( 1.0, -1.0, 1.0 ) ; glVertex3d ( 0.61803398875, 0.0, 1.61803398875 ) ; glVertex3d ( -0.61803398875, 0.0, 1.61803398875 ) ; glVertex3d ( -1.0, -1.0, 1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_POLYGON ) ;
+ glNormal3d ( 0.0, -0.525731112119, -0.850650808354 ) ; glVertex3d ( 0.0, -1.61803398875, -0.61803398875 ) ; glVertex3d ( -1.0, -1.0, -1.0 ) ; glVertex3d ( -0.61803398875, 0.0, -1.61803398875 ) ; glVertex3d ( 0.61803398875, 0.0, -1.61803398875 ) ; glVertex3d ( 1.0, -1.0, -1.0 ) ;
+ glEnd () ;
+
+ glBegin ( GL_POLYGON ) ;
+ glNormal3d ( 0.850650808354, 0.0, 0.525731112119 ) ; glVertex3d ( 0.61803398875, 0.0, 1.61803398875 ) ; glVertex3d ( 1.0, -1.0, 1.0 ) ; glVertex3d ( 1.61803398875, -0.61803398875, 0.0 ) ; glVertex3d ( 1.61803398875, 0.61803398875, 0.0 ) ; glVertex3d ( 1.0, 1.0, 1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_POLYGON ) ;
+ glNormal3d ( -0.850650808354, 0.0, 0.525731112119 ) ; glVertex3d ( -0.61803398875, 0.0, 1.61803398875 ) ; glVertex3d ( -1.0, 1.0, 1.0 ) ; glVertex3d ( -1.61803398875, 0.61803398875, 0.0 ) ; glVertex3d ( -1.61803398875, -0.61803398875, 0.0 ) ; glVertex3d ( -1.0, -1.0, 1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_POLYGON ) ;
+ glNormal3d ( 0.850650808354, 0.0, -0.525731112119 ) ; glVertex3d ( 0.61803398875, 0.0, -1.61803398875 ) ; glVertex3d ( 1.0, 1.0, -1.0 ) ; glVertex3d ( 1.61803398875, 0.61803398875, 0.0 ) ; glVertex3d ( 1.61803398875, -0.61803398875, 0.0 ) ; glVertex3d ( 1.0, -1.0, -1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_POLYGON ) ;
+ glNormal3d ( -0.850650808354, 0.0, -0.525731112119 ) ; glVertex3d ( -0.61803398875, 0.0, -1.61803398875 ) ; glVertex3d ( -1.0, -1.0, -1.0 ) ; glVertex3d ( -1.61803398875, -0.61803398875, 0.0 ) ; glVertex3d ( -1.61803398875, 0.61803398875, 0.0 ) ; glVertex3d ( -1.0, 1.0, -1.0 ) ;
+ glEnd () ;
+
+ glBegin ( GL_POLYGON ) ;
+ glNormal3d ( 0.525731112119, 0.850650808354, 0.0 ) ; glVertex3d ( 1.61803398875, 0.61803398875, 0.0 ) ; glVertex3d ( 1.0, 1.0, -1.0 ) ; glVertex3d ( 0.0, 1.61803398875, -0.61803398875 ) ; glVertex3d ( 0.0, 1.61803398875, 0.61803398875 ) ; glVertex3d ( 1.0, 1.0, 1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_POLYGON ) ;
+ glNormal3d ( 0.525731112119, -0.850650808354, 0.0 ) ; glVertex3d ( 1.61803398875, -0.61803398875, 0.0 ) ; glVertex3d ( 1.0, -1.0, 1.0 ) ; glVertex3d ( 0.0, -1.61803398875, 0.61803398875 ) ; glVertex3d ( 0.0, -1.61803398875, -0.61803398875 ) ; glVertex3d ( 1.0, -1.0, -1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_POLYGON ) ;
+ glNormal3d ( -0.525731112119, 0.850650808354, 0.0 ) ; glVertex3d ( -1.61803398875, 0.61803398875, 0.0 ) ; glVertex3d ( -1.0, 1.0, 1.0 ) ; glVertex3d ( 0.0, 1.61803398875, 0.61803398875 ) ; glVertex3d ( 0.0, 1.61803398875, -0.61803398875 ) ; glVertex3d ( -1.0, 1.0, -1.0 ) ;
+ glEnd () ;
+ glBegin ( GL_POLYGON ) ;
+ glNormal3d ( -0.525731112119, -0.850650808354, 0.0 ) ; glVertex3d ( -1.61803398875, -0.61803398875, 0.0 ) ; glVertex3d ( -1.0, -1.0, -1.0 ) ; glVertex3d ( 0.0, -1.61803398875, -0.61803398875 ) ; glVertex3d ( 0.0, -1.61803398875, 0.61803398875 ) ; glVertex3d ( -1.0, -1.0, 1.0 ) ;
+ glEnd () ;
+}
+
+/*
+ *
+ */
+void glutWireOctahedron( void )
+{
+#define RADIUS 1.0f
+ glBegin( GL_LINE_LOOP );
+ glNormal3d( 0.577350269189, 0.577350269189, 0.577350269189); glVertex3d( RADIUS, 0.0, 0.0 ); glVertex3d( 0.0, RADIUS, 0.0 ); glVertex3d( 0.0, 0.0, RADIUS );
+ glNormal3d( 0.577350269189, 0.577350269189,-0.577350269189); glVertex3d( RADIUS, 0.0, 0.0 ); glVertex3d( 0.0, 0.0,-RADIUS ); glVertex3d( 0.0, RADIUS, 0.0 );
+ glNormal3d( 0.577350269189,-0.577350269189, 0.577350269189); glVertex3d( RADIUS, 0.0, 0.0 ); glVertex3d( 0.0, 0.0, RADIUS ); glVertex3d( 0.0,-RADIUS, 0.0 );
+ glNormal3d( 0.577350269189,-0.577350269189,-0.577350269189); glVertex3d( RADIUS, 0.0, 0.0 ); glVertex3d( 0.0,-RADIUS, 0.0 ); glVertex3d( 0.0, 0.0,-RADIUS );
+ glNormal3d(-0.577350269189, 0.577350269189, 0.577350269189); glVertex3d(-RADIUS, 0.0, 0.0 ); glVertex3d( 0.0, 0.0, RADIUS ); glVertex3d( 0.0, RADIUS, 0.0 );
+ glNormal3d(-0.577350269189, 0.577350269189,-0.577350269189); glVertex3d(-RADIUS, 0.0, 0.0 ); glVertex3d( 0.0, RADIUS, 0.0 ); glVertex3d( 0.0, 0.0,-RADIUS );
+ glNormal3d(-0.577350269189,-0.577350269189, 0.577350269189); glVertex3d(-RADIUS, 0.0, 0.0 ); glVertex3d( 0.0,-RADIUS, 0.0 ); glVertex3d( 0.0, 0.0, RADIUS );
+ glNormal3d(-0.577350269189,-0.577350269189,-0.577350269189); glVertex3d(-RADIUS, 0.0, 0.0 ); glVertex3d( 0.0, 0.0,-RADIUS ); glVertex3d( 0.0,-RADIUS, 0.0 );
+ glEnd();
+#undef RADIUS
+}
+
+/*
+ *
+ */
+void glutSolidOctahedron( void )
+{
+#define RADIUS 1.0f
+ glBegin( GL_TRIANGLES );
+ glNormal3d( 0.577350269189, 0.577350269189, 0.577350269189); glVertex3d( RADIUS, 0.0, 0.0 ); glVertex3d( 0.0, RADIUS, 0.0 ); glVertex3d( 0.0, 0.0, RADIUS );
+ glNormal3d( 0.577350269189, 0.577350269189,-0.577350269189); glVertex3d( RADIUS, 0.0, 0.0 ); glVertex3d( 0.0, 0.0,-RADIUS ); glVertex3d( 0.0, RADIUS, 0.0 );
+ glNormal3d( 0.577350269189,-0.577350269189, 0.577350269189); glVertex3d( RADIUS, 0.0, 0.0 ); glVertex3d( 0.0, 0.0, RADIUS ); glVertex3d( 0.0,-RADIUS, 0.0 );
+ glNormal3d( 0.577350269189,-0.577350269189,-0.577350269189); glVertex3d( RADIUS, 0.0, 0.0 ); glVertex3d( 0.0,-RADIUS, 0.0 ); glVertex3d( 0.0, 0.0,-RADIUS );
+ glNormal3d(-0.577350269189, 0.577350269189, 0.577350269189); glVertex3d(-RADIUS, 0.0, 0.0 ); glVertex3d( 0.0, 0.0, RADIUS ); glVertex3d( 0.0, RADIUS, 0.0 );
+ glNormal3d(-0.577350269189, 0.577350269189,-0.577350269189); glVertex3d(-RADIUS, 0.0, 0.0 ); glVertex3d( 0.0, RADIUS, 0.0 ); glVertex3d( 0.0, 0.0,-RADIUS );
+ glNormal3d(-0.577350269189,-0.577350269189, 0.577350269189); glVertex3d(-RADIUS, 0.0, 0.0 ); glVertex3d( 0.0,-RADIUS, 0.0 ); glVertex3d( 0.0, 0.0, RADIUS );
+ glNormal3d(-0.577350269189,-0.577350269189,-0.577350269189); glVertex3d(-RADIUS, 0.0, 0.0 ); glVertex3d( 0.0, 0.0,-RADIUS ); glVertex3d( 0.0,-RADIUS, 0.0 );
+ glEnd();
+#undef RADIUS
+}
+
+/* Magic Numbers: r0 = ( 1, 0, 0 )
+ * r1 = ( -1/3, 2 sqrt(2) / 3, 0 )
+ * r2 = ( -1/3, -sqrt(2) / 3, sqrt(6) / 3 )
+ * r3 = ( -1/3, -sqrt(2) / 3, -sqrt(6) / 3 )
+ * |r0| = |r1| = |r2| = |r3| = 1
+ * Distance between any two points is 2 sqrt(6) / 3
+ *
+ * Normals: The unit normals are simply the negative of the coordinates of the point not on the surface.
+ */
+
+#define NUM_TETR_FACES 4
+
+static GLdouble tet_r[4][3] = { { 1.0, 0.0, 0.0 },
+ { -0.333333333333, 0.942809041582, 0.0 },
+ { -0.333333333333, -0.471404520791, 0.816496580928 },
+ { -0.333333333333, -0.471404520791, -0.816496580928 } } ;
+
+static GLint tet_i[4][3] = /* Vertex indices */
+{
+ { 1, 3, 2 }, { 0, 2, 3 }, { 0, 3, 1 }, { 0, 1, 2 }
+} ;
+
+/*
+ *
+ */
+void glutWireTetrahedron( void )
+{
+ glBegin( GL_LINE_LOOP ) ;
+ glNormal3d ( -tet_r[0][0], -tet_r[0][1], -tet_r[0][2] ) ; glVertex3dv ( tet_r[1] ) ; glVertex3dv ( tet_r[3] ) ; glVertex3dv ( tet_r[2] ) ;
+ glNormal3d ( -tet_r[1][0], -tet_r[1][1], -tet_r[1][2] ) ; glVertex3dv ( tet_r[0] ) ; glVertex3dv ( tet_r[2] ) ; glVertex3dv ( tet_r[3] ) ;
+ glNormal3d ( -tet_r[2][0], -tet_r[2][1], -tet_r[2][2] ) ; glVertex3dv ( tet_r[0] ) ; glVertex3dv ( tet_r[3] ) ; glVertex3dv ( tet_r[1] ) ;
+ glNormal3d ( -tet_r[3][0], -tet_r[3][1], -tet_r[3][2] ) ; glVertex3dv ( tet_r[0] ) ; glVertex3dv ( tet_r[1] ) ; glVertex3dv ( tet_r[2] ) ;
+ glEnd() ;
+}
+
+/*
+ *
+ */
+void glutSolidTetrahedron( void )
+{
+ glBegin( GL_TRIANGLES ) ;
+ glNormal3d ( -tet_r[0][0], -tet_r[0][1], -tet_r[0][2] ) ; glVertex3dv ( tet_r[1] ) ; glVertex3dv ( tet_r[3] ) ; glVertex3dv ( tet_r[2] ) ;
+ glNormal3d ( -tet_r[1][0], -tet_r[1][1], -tet_r[1][2] ) ; glVertex3dv ( tet_r[0] ) ; glVertex3dv ( tet_r[2] ) ; glVertex3dv ( tet_r[3] ) ;
+ glNormal3d ( -tet_r[2][0], -tet_r[2][1], -tet_r[2][2] ) ; glVertex3dv ( tet_r[0] ) ; glVertex3dv ( tet_r[3] ) ; glVertex3dv ( tet_r[1] ) ;
+ glNormal3d ( -tet_r[3][0], -tet_r[3][1], -tet_r[3][2] ) ; glVertex3dv ( tet_r[0] ) ; glVertex3dv ( tet_r[1] ) ; glVertex3dv ( tet_r[2] ) ;
+ glEnd() ;
+}
+
+/*
+ *
+ */
+double icos_r[12][3] = { { 1.0, 0.0, 0.0 },
+ { 0.447213595500, 0.894427191000, 0.0 }, { 0.447213595500, 0.276393202252, 0.850650808354 }, { 0.447213595500, -0.723606797748, 0.525731112119 }, { 0.447213595500, -0.723606797748, -0.525731112119 }, { 0.447213595500, 0.276393202252, -0.850650808354 },
+ { -0.447213595500, -0.894427191000, 0.0 }, { -0.447213595500, -0.276393202252, 0.850650808354 }, { -0.447213595500, 0.723606797748, 0.525731112119 }, { -0.447213595500, 0.723606797748, -0.525731112119 }, { -0.447213595500, -0.276393202252, -0.850650808354 },
+ { -1.0, 0.0, 0.0 } } ;
+int icos_v [20][3] = { { 0, 1, 2 }, { 0, 2, 3 }, { 0, 3, 4 }, { 0, 4, 5 }, { 0, 5, 1 },
+ { 1, 8, 2 }, { 2, 7, 3 }, { 3, 6, 4 }, { 4, 10, 5 }, { 5, 9, 1 },
+ { 1, 9, 8 }, { 2, 8, 7 }, { 3, 7, 6 }, { 4, 6, 10 }, { 5, 10, 9 },
+ { 11, 9, 10 }, { 11, 8, 9 }, { 11, 7, 8 }, { 11, 6, 7 }, { 11, 10, 6 } } ;
+
+void glutWireIcosahedron( void )
+{
+ int i ;
+
+ for ( i = 0; i < 20; i++ )
+ {
+ double normal[3] ;
+ normal[0] = ( icos_r[icos_v[i][1]][1] - icos_r[icos_v[i][0]][1] ) * ( icos_r[icos_v[i][2]][2] - icos_r[icos_v[i][0]][2] ) - ( icos_r[icos_v[i][1]][2] - icos_r[icos_v[i][0]][2] ) * ( icos_r[icos_v[i][2]][1] - icos_r[icos_v[i][0]][1] ) ;
+ normal[1] = ( icos_r[icos_v[i][1]][2] - icos_r[icos_v[i][0]][2] ) * ( icos_r[icos_v[i][2]][0] - icos_r[icos_v[i][0]][0] ) - ( icos_r[icos_v[i][1]][0] - icos_r[icos_v[i][0]][0] ) * ( icos_r[icos_v[i][2]][2] - icos_r[icos_v[i][0]][2] ) ;
+ normal[2] = ( icos_r[icos_v[i][1]][0] - icos_r[icos_v[i][0]][0] ) * ( icos_r[icos_v[i][2]][1] - icos_r[icos_v[i][0]][1] ) - ( icos_r[icos_v[i][1]][1] - icos_r[icos_v[i][0]][1] ) * ( icos_r[icos_v[i][2]][0] - icos_r[icos_v[i][0]][0] ) ;
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3dv ( normal ) ;
+ glVertex3dv ( icos_r[icos_v[i][0]] ) ;
+ glVertex3dv ( icos_r[icos_v[i][1]] ) ;
+ glVertex3dv ( icos_r[icos_v[i][2]] ) ;
+ glEnd () ;
+ }
+}
+
+/*
+ *
+ */
+void glutSolidIcosahedron( void )
+{
+ int i ;
+
+ glBegin ( GL_TRIANGLES ) ;
+ for ( i = 0; i < 20; i++ )
+ {
+ double normal[3] ;
+ normal[0] = ( icos_r[icos_v[i][1]][1] - icos_r[icos_v[i][0]][1] ) * ( icos_r[icos_v[i][2]][2] - icos_r[icos_v[i][0]][2] ) - ( icos_r[icos_v[i][1]][2] - icos_r[icos_v[i][0]][2] ) * ( icos_r[icos_v[i][2]][1] - icos_r[icos_v[i][0]][1] ) ;
+ normal[1] = ( icos_r[icos_v[i][1]][2] - icos_r[icos_v[i][0]][2] ) * ( icos_r[icos_v[i][2]][0] - icos_r[icos_v[i][0]][0] ) - ( icos_r[icos_v[i][1]][0] - icos_r[icos_v[i][0]][0] ) * ( icos_r[icos_v[i][2]][2] - icos_r[icos_v[i][0]][2] ) ;
+ normal[2] = ( icos_r[icos_v[i][1]][0] - icos_r[icos_v[i][0]][0] ) * ( icos_r[icos_v[i][2]][1] - icos_r[icos_v[i][0]][1] ) - ( icos_r[icos_v[i][1]][1] - icos_r[icos_v[i][0]][1] ) * ( icos_r[icos_v[i][2]][0] - icos_r[icos_v[i][0]][0] ) ;
+ glNormal3dv ( normal ) ;
+ glVertex3dv ( icos_r[icos_v[i][0]] ) ;
+ glVertex3dv ( icos_r[icos_v[i][1]] ) ;
+ glVertex3dv ( icos_r[icos_v[i][2]] ) ;
+ }
+
+ glEnd () ;
+}
+
+/*
+ *
+ */
+double rdod_r[14][3] = { { 0.0, 0.0, 1.0 },
+ { 0.707106781187, 0.000000000000, 0.5 }, { 0.000000000000, 0.707106781187, 0.5 }, { -0.707106781187, 0.000000000000, 0.5 }, { 0.000000000000, -0.707106781187, 0.5 },
+ { 0.707106781187, 0.707106781187, 0.0 }, { -0.707106781187, 0.707106781187, 0.0 }, { -0.707106781187, -0.707106781187, 0.0 }, { 0.707106781187, -0.707106781187, 0.0 },
+ { 0.707106781187, 0.000000000000, -0.5 }, { 0.000000000000, 0.707106781187, -0.5 }, { -0.707106781187, 0.000000000000, -0.5 }, { 0.000000000000, -0.707106781187, -0.5 },
+ { 0.0, 0.0, -1.0 } } ;
+int rdod_v [12][4] = { { 0, 1, 5, 2 }, { 0, 2, 6, 3 }, { 0, 3, 7, 4 }, { 0, 4, 8, 1 },
+ { 5, 10, 6, 2 }, { 6, 11, 7, 3 }, { 7, 12, 8, 4 }, { 8, 9, 5, 1 },
+ { 5, 9, 13, 10 }, { 6, 10, 13, 11 }, { 7, 11, 13, 12 }, { 8, 12, 13, 9 } } ;
+double rdod_n[12][3] = {
+ { 0.353553390594, 0.353553390594, 0.5 }, { -0.353553390594, 0.353553390594, 0.5 }, { -0.353553390594, -0.353553390594, 0.5 }, { 0.353553390594, -0.353553390594, 0.5 },
+ { 0.000000000000, 1.000000000000, 0.0 }, { -1.000000000000, 0.000000000000, 0.0 }, { 0.000000000000, -1.000000000000, 0.0 }, { 1.000000000000, 0.000000000000, 0.0 },
+ { 0.353553390594, 0.353553390594, -0.5 }, { -0.353553390594, 0.353553390594, -0.5 }, { -0.353553390594, -0.353553390594, -0.5 }, { 0.353553390594, -0.353553390594, -0.5 }
+ } ;
+
+void glutWireRhombicDodecahedron( void )
+{
+ int i ;
+
+ for ( i = 0; i < 12; i++ )
+ {
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3dv ( rdod_n[i] ) ;
+ glVertex3dv ( rdod_r[rdod_v[i][0]] ) ;
+ glVertex3dv ( rdod_r[rdod_v[i][1]] ) ;
+ glVertex3dv ( rdod_r[rdod_v[i][2]] ) ;
+ glVertex3dv ( rdod_r[rdod_v[i][3]] ) ;
+ glEnd () ;
+ }
+}
+
+/*
+ *
+ */
+void glutSolidRhombicDodecahedron( void )
+{
+ int i ;
+
+ glBegin ( GL_QUADS ) ;
+ for ( i = 0; i < 12; i++ )
+ {
+ glNormal3dv ( rdod_n[i] ) ;
+ glVertex3dv ( rdod_r[rdod_v[i][0]] ) ;
+ glVertex3dv ( rdod_r[rdod_v[i][1]] ) ;
+ glVertex3dv ( rdod_r[rdod_v[i][2]] ) ;
+ glVertex3dv ( rdod_r[rdod_v[i][3]] ) ;
+ }
+
+ glEnd () ;
+}
+
+void glutWireSierpinskiSponge ( int num_levels, GLdouble offset[3], GLdouble scale )
+{
+ int i, j ;
+
+ if ( num_levels == 0 )
+ {
+
+ for ( i = 0 ; i < NUM_TETR_FACES ; i++ )
+ {
+ glBegin ( GL_LINE_LOOP ) ;
+ glNormal3d ( -tet_r[i][0], -tet_r[i][1], -tet_r[i][2] ) ;
+ for ( j = 0; j < 3; j++ )
+ {
+ double x = offset[0] + scale * tet_r[tet_i[i][j]][0] ;
+ double y = offset[1] + scale * tet_r[tet_i[i][j]][1] ;
+ double z = offset[2] + scale * tet_r[tet_i[i][j]][2] ;
+ glVertex3d ( x, y, z ) ;
+ }
+
+ glEnd () ;
+ }
+ }
+ else
+ {
+ GLdouble local_offset[3] ; /* Use a local variable to avoid buildup of roundoff errors */
+ num_levels -- ;
+ scale /= 2.0 ;
+ for ( i = 0 ; i < NUM_TETR_FACES ; i++ )
+ {
+ local_offset[0] = offset[0] + scale * tet_r[i][0] ;
+ local_offset[1] = offset[1] + scale * tet_r[i][1] ;
+ local_offset[2] = offset[2] + scale * tet_r[i][2] ;
+ glutWireSierpinskiSponge ( num_levels, local_offset, scale ) ;
+ }
+ }
+}
+
+void glutSolidSierpinskiSponge ( int num_levels, GLdouble offset[3], GLdouble scale )
+{
+ int i, j ;
+
+ if ( num_levels == 0 )
+ {
+ glBegin ( GL_TRIANGLES ) ;
+
+ for ( i = 0 ; i < NUM_TETR_FACES ; i++ )
+ {
+ glNormal3d ( -tet_r[i][0], -tet_r[i][1], -tet_r[i][2] ) ;
+ for ( j = 0; j < 3; j++ )
+ {
+ double x = offset[0] + scale * tet_r[tet_i[i][j]][0] ;
+ double y = offset[1] + scale * tet_r[tet_i[i][j]][1] ;
+ double z = offset[2] + scale * tet_r[tet_i[i][j]][2] ;
+ glVertex3d ( x, y, z ) ;
+ }
+ }
+
+ glEnd () ;
+ }
+ else
+ {
+ GLdouble local_offset[3] ; /* Use a local variable to avoid buildup of roundoff errors */
+ num_levels -- ;
+ scale /= 2.0 ;
+ for ( i = 0 ; i < NUM_TETR_FACES ; i++ )
+ {
+ local_offset[0] = offset[0] + scale * tet_r[i][0] ;
+ local_offset[1] = offset[1] + scale * tet_r[i][1] ;
+ local_offset[2] = offset[2] + scale * tet_r[i][2] ;
+ glutSolidSierpinskiSponge ( num_levels, local_offset, scale ) ;
+ }
+ }
+}
+
+/*** END OF FILE ***/
diff --git a/third_party/windows/fltk-1.1.10/src/freeglut_stroke_mono_roman.cxx b/third_party/windows/fltk-1.1.10/src/freeglut_stroke_mono_roman.cxx new file mode 100644 index 0000000..a3c9bb6 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/freeglut_stroke_mono_roman.cxx @@ -0,0 +1,2848 @@ +/*
+ * freeglut_stroke_mono_roman.c
+ *
+ * freeglut Monospace Roman stroke font definition
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta@sourceforge.net>
+ * Creation date: Thu Dec 16 1999
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/* This file has been automatically generated by the genstroke utility. */
+
+#include <FL/glut.H>
+
+/* char: 0x20 */
+
+static const Fl_Glut_StrokeStrip ch32st[] =
+{
+ { 0, 0 }
+};
+
+static const Fl_Glut_StrokeChar ch32 = {104.762f,0,ch32st};
+
+/* char: 0x21 */
+
+static const Fl_Glut_StrokeVertex ch33st0[] =
+{
+ {52.381f,100.0f},
+ {52.381f,33.3333f}
+};
+
+static const Fl_Glut_StrokeVertex ch33st1[] =
+{
+ {52.381f,9.5238f},
+ {47.6191f,4.7619f},
+ {52.381f,0.0f},
+ {57.1429f,4.7619f},
+ {52.381f,9.5238f}
+};
+
+static const Fl_Glut_StrokeStrip ch33st[] =
+{
+ {2,ch33st0},
+ {5,ch33st1}
+};
+
+static const Fl_Glut_StrokeChar ch33 = {104.762f,2,ch33st};
+
+/* char: 0x22 */
+
+static const Fl_Glut_StrokeVertex ch34st0[] =
+{
+ {33.3334f,100.0f},
+ {33.3334f,66.6667f}
+};
+
+static const Fl_Glut_StrokeVertex ch34st1[] =
+{
+ {71.4286f,100.0f},
+ {71.4286f,66.6667f}
+};
+
+static const Fl_Glut_StrokeStrip ch34st[] =
+{
+ {2,ch34st0},
+ {2,ch34st1}
+};
+
+static const Fl_Glut_StrokeChar ch34 = {104.762f,2,ch34st};
+
+/* char: 0x23 */
+
+static const Fl_Glut_StrokeVertex ch35st0[] =
+{
+ {54.7619f,119.048f},
+ {21.4286f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeVertex ch35st1[] =
+{
+ {83.3334f,119.048f},
+ {50.0f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeVertex ch35st2[] =
+{
+ {21.4286f,57.1429f},
+ {88.0952f,57.1429f}
+};
+
+static const Fl_Glut_StrokeVertex ch35st3[] =
+{
+ {16.6667f,28.5714f},
+ {83.3334f,28.5714f}
+};
+
+static const Fl_Glut_StrokeStrip ch35st[] =
+{
+ {2,ch35st0},
+ {2,ch35st1},
+ {2,ch35st2},
+ {2,ch35st3}
+};
+
+static const Fl_Glut_StrokeChar ch35 = {104.762f,4,ch35st};
+
+/* char: 0x24 */
+
+static const Fl_Glut_StrokeVertex ch36st0[] =
+{
+ {42.8571f,119.048f},
+ {42.8571f,-19.0476f}
+};
+
+static const Fl_Glut_StrokeVertex ch36st1[] =
+{
+ {61.9047f,119.048f},
+ {61.9047f,-19.0476f}
+};
+
+static const Fl_Glut_StrokeVertex ch36st2[] =
+{
+ {85.7143f,85.7143f},
+ {76.1905f,95.2381f},
+ {61.9047f,100.0f},
+ {42.8571f,100.0f},
+ {28.5714f,95.2381f},
+ {19.0476f,85.7143f},
+ {19.0476f,76.1905f},
+ {23.8095f,66.6667f},
+ {28.5714f,61.9048f},
+ {38.0952f,57.1429f},
+ {66.6666f,47.619f},
+ {76.1905f,42.8571f},
+ {80.9524f,38.0952f},
+ {85.7143f,28.5714f},
+ {85.7143f,14.2857f},
+ {76.1905f,4.7619f},
+ {61.9047f,0.0f},
+ {42.8571f,0.0f},
+ {28.5714f,4.7619f},
+ {19.0476f,14.2857f}
+};
+
+static const Fl_Glut_StrokeStrip ch36st[] =
+{
+ {2,ch36st0},
+ {2,ch36st1},
+ {20,ch36st2}
+};
+
+static const Fl_Glut_StrokeChar ch36 = {104.762f,3,ch36st};
+
+/* char: 0x25 */
+
+static const Fl_Glut_StrokeVertex ch37st0[] =
+{
+ {95.2381f,100.0f},
+ {9.5238f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch37st1[] =
+{
+ {33.3333f,100.0f},
+ {42.8571f,90.4762f},
+ {42.8571f,80.9524f},
+ {38.0952f,71.4286f},
+ {28.5714f,66.6667f},
+ {19.0476f,66.6667f},
+ {9.5238f,76.1905f},
+ {9.5238f,85.7143f},
+ {14.2857f,95.2381f},
+ {23.8095f,100.0f},
+ {33.3333f,100.0f},
+ {42.8571f,95.2381f},
+ {57.1428f,90.4762f},
+ {71.4286f,90.4762f},
+ {85.7143f,95.2381f},
+ {95.2381f,100.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch37st2[] =
+{
+ {76.1905f,33.3333f},
+ {66.6667f,28.5714f},
+ {61.9048f,19.0476f},
+ {61.9048f,9.5238f},
+ {71.4286f,0.0f},
+ {80.9524f,0.0f},
+ {90.4762f,4.7619f},
+ {95.2381f,14.2857f},
+ {95.2381f,23.8095f},
+ {85.7143f,33.3333f},
+ {76.1905f,33.3333f}
+};
+
+static const Fl_Glut_StrokeStrip ch37st[] =
+{
+ {2,ch37st0},
+ {16,ch37st1},
+ {11,ch37st2}
+};
+
+static const Fl_Glut_StrokeChar ch37 = {104.762f,3,ch37st};
+
+/* char: 0x26 */
+
+static const Fl_Glut_StrokeVertex ch38st0[] =
+{
+ {100.0f,57.1429f},
+ {100.0f,61.9048f},
+ {95.2381f,66.6667f},
+ {90.4762f,66.6667f},
+ {85.7143f,61.9048f},
+ {80.9524f,52.381f},
+ {71.4286f,28.5714f},
+ {61.9048f,14.2857f},
+ {52.3809f,4.7619f},
+ {42.8571f,0.0f},
+ {23.8095f,0.0f},
+ {14.2857f,4.7619f},
+ {9.5238f,9.5238f},
+ {4.7619f,19.0476f},
+ {4.7619f,28.5714f},
+ {9.5238f,38.0952f},
+ {14.2857f,42.8571f},
+ {47.619f,61.9048f},
+ {52.3809f,66.6667f},
+ {57.1429f,76.1905f},
+ {57.1429f,85.7143f},
+ {52.3809f,95.2381f},
+ {42.8571f,100.0f},
+ {33.3333f,95.2381f},
+ {28.5714f,85.7143f},
+ {28.5714f,76.1905f},
+ {33.3333f,61.9048f},
+ {42.8571f,47.619f},
+ {66.6667f,14.2857f},
+ {76.1905f,4.7619f},
+ {85.7143f,0.0f},
+ {95.2381f,0.0f},
+ {100.0f,4.7619f},
+ {100.0f,9.5238f}
+};
+
+static const Fl_Glut_StrokeStrip ch38st[] =
+{
+ {34,ch38st0}
+};
+
+static const Fl_Glut_StrokeChar ch38 = {104.762f,1,ch38st};
+
+/* char: 0x27 */
+
+static const Fl_Glut_StrokeVertex ch39st0[] =
+{
+ {52.381f,100.0f},
+ {52.381f,66.6667f}
+};
+
+static const Fl_Glut_StrokeStrip ch39st[] =
+{
+ {2,ch39st0}
+};
+
+static const Fl_Glut_StrokeChar ch39 = {104.762f,1,ch39st};
+
+/* char: 0x28 */
+
+static const Fl_Glut_StrokeVertex ch40st0[] =
+{
+ {69.0476f,119.048f},
+ {59.5238f,109.524f},
+ {50.0f,95.2381f},
+ {40.4762f,76.1905f},
+ {35.7143f,52.381f},
+ {35.7143f,33.3333f},
+ {40.4762f,9.5238f},
+ {50.0f,-9.5238f},
+ {59.5238f,-23.8095f},
+ {69.0476f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeStrip ch40st[] =
+{
+ {10,ch40st0}
+};
+
+static const Fl_Glut_StrokeChar ch40 = {104.762f,1,ch40st};
+
+/* char: 0x29 */
+
+static const Fl_Glut_StrokeVertex ch41st0[] =
+{
+ {35.7143f,119.048f},
+ {45.2381f,109.524f},
+ {54.7619f,95.2381f},
+ {64.2857f,76.1905f},
+ {69.0476f,52.381f},
+ {69.0476f,33.3333f},
+ {64.2857f,9.5238f},
+ {54.7619f,-9.5238f},
+ {45.2381f,-23.8095f},
+ {35.7143f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeStrip ch41st[] =
+{
+ {10,ch41st0}
+};
+
+static const Fl_Glut_StrokeChar ch41 = {104.762f,1,ch41st};
+
+/* char: 0x2a */
+
+static const Fl_Glut_StrokeVertex ch42st0[] =
+{
+ {52.381f,71.4286f},
+ {52.381f,14.2857f}
+};
+
+static const Fl_Glut_StrokeVertex ch42st1[] =
+{
+ {28.5715f,57.1429f},
+ {76.1905f,28.5714f}
+};
+
+static const Fl_Glut_StrokeVertex ch42st2[] =
+{
+ {76.1905f,57.1429f},
+ {28.5715f,28.5714f}
+};
+
+static const Fl_Glut_StrokeStrip ch42st[] =
+{
+ {2,ch42st0},
+ {2,ch42st1},
+ {2,ch42st2}
+};
+
+static const Fl_Glut_StrokeChar ch42 = {104.762f,3,ch42st};
+
+/* char: 0x2b */
+
+static const Fl_Glut_StrokeVertex ch43st0[] =
+{
+ {52.3809f,85.7143f},
+ {52.3809f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch43st1[] =
+{
+ {9.5238f,42.8571f},
+ {95.2381f,42.8571f}
+};
+
+static const Fl_Glut_StrokeStrip ch43st[] =
+{
+ {2,ch43st0},
+ {2,ch43st1}
+};
+
+static const Fl_Glut_StrokeChar ch43 = {104.762f,2,ch43st};
+
+/* char: 0x2c */
+
+static const Fl_Glut_StrokeVertex ch44st0[] =
+{
+ {57.1429f,4.7619f},
+ {52.381f,0.0f},
+ {47.6191f,4.7619f},
+ {52.381f,9.5238f},
+ {57.1429f,4.7619f},
+ {57.1429f,-4.7619f},
+ {52.381f,-14.2857f},
+ {47.6191f,-19.0476f}
+};
+
+static const Fl_Glut_StrokeStrip ch44st[] =
+{
+ {8,ch44st0}
+};
+
+static const Fl_Glut_StrokeChar ch44 = {104.762f,1,ch44st};
+
+/* char: 0x2d */
+
+static const Fl_Glut_StrokeVertex ch45st0[] =
+{
+ {9.5238f,42.8571f},
+ {95.2381f,42.8571f}
+};
+
+static const Fl_Glut_StrokeStrip ch45st[] =
+{
+ {2,ch45st0}
+};
+
+static const Fl_Glut_StrokeChar ch45 = {104.762f,1,ch45st};
+
+/* char: 0x2e */
+
+static const Fl_Glut_StrokeVertex ch46st0[] =
+{
+ {52.381f,9.5238f},
+ {47.6191f,4.7619f},
+ {52.381f,0.0f},
+ {57.1429f,4.7619f},
+ {52.381f,9.5238f}
+};
+
+static const Fl_Glut_StrokeStrip ch46st[] =
+{
+ {5,ch46st0}
+};
+
+static const Fl_Glut_StrokeChar ch46 = {104.762f,1,ch46st};
+
+/* char: 0x2f */
+
+static const Fl_Glut_StrokeVertex ch47st0[] =
+{
+ {19.0476f,-14.2857f},
+ {85.7143f,100.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch47st[] =
+{
+ {2,ch47st0}
+};
+
+static const Fl_Glut_StrokeChar ch47 = {104.762f,1,ch47st};
+
+/* char: 0x30 */
+
+static const Fl_Glut_StrokeVertex ch48st0[] =
+{
+ {47.619f,100.0f},
+ {33.3333f,95.2381f},
+ {23.8095f,80.9524f},
+ {19.0476f,57.1429f},
+ {19.0476f,42.8571f},
+ {23.8095f,19.0476f},
+ {33.3333f,4.7619f},
+ {47.619f,0.0f},
+ {57.1428f,0.0f},
+ {71.4286f,4.7619f},
+ {80.9524f,19.0476f},
+ {85.7143f,42.8571f},
+ {85.7143f,57.1429f},
+ {80.9524f,80.9524f},
+ {71.4286f,95.2381f},
+ {57.1428f,100.0f},
+ {47.619f,100.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch48st[] =
+{
+ {17,ch48st0}
+};
+
+static const Fl_Glut_StrokeChar ch48 = {104.762f,1,ch48st};
+
+/* char: 0x31 */
+
+static const Fl_Glut_StrokeVertex ch49st0[] =
+{
+ {40.4762f,80.9524f},
+ {50.0f,85.7143f},
+ {64.2857f,100.0f},
+ {64.2857f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch49st[] =
+{
+ {4,ch49st0}
+};
+
+static const Fl_Glut_StrokeChar ch49 = {104.762f,1,ch49st};
+
+/* char: 0x32 */
+
+static const Fl_Glut_StrokeVertex ch50st0[] =
+{
+ {23.8095f,76.1905f},
+ {23.8095f,80.9524f},
+ {28.5714f,90.4762f},
+ {33.3333f,95.2381f},
+ {42.8571f,100.0f},
+ {61.9047f,100.0f},
+ {71.4286f,95.2381f},
+ {76.1905f,90.4762f},
+ {80.9524f,80.9524f},
+ {80.9524f,71.4286f},
+ {76.1905f,61.9048f},
+ {66.6666f,47.619f},
+ {19.0476f,0.0f},
+ {85.7143f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch50st[] =
+{
+ {14,ch50st0}
+};
+
+static const Fl_Glut_StrokeChar ch50 = {104.762f,1,ch50st};
+
+/* char: 0x33 */
+
+static const Fl_Glut_StrokeVertex ch51st0[] =
+{
+ {28.5714f,100.0f},
+ {80.9524f,100.0f},
+ {52.3809f,61.9048f},
+ {66.6666f,61.9048f},
+ {76.1905f,57.1429f},
+ {80.9524f,52.381f},
+ {85.7143f,38.0952f},
+ {85.7143f,28.5714f},
+ {80.9524f,14.2857f},
+ {71.4286f,4.7619f},
+ {57.1428f,0.0f},
+ {42.8571f,0.0f},
+ {28.5714f,4.7619f},
+ {23.8095f,9.5238f},
+ {19.0476f,19.0476f}
+};
+
+static const Fl_Glut_StrokeStrip ch51st[] =
+{
+ {15,ch51st0}
+};
+
+static const Fl_Glut_StrokeChar ch51 = {104.762f,1,ch51st};
+
+/* char: 0x34 */
+
+static const Fl_Glut_StrokeVertex ch52st0[] =
+{
+ {64.2857f,100.0f},
+ {16.6667f,33.3333f},
+ {88.0952f,33.3333f}
+};
+
+static const Fl_Glut_StrokeVertex ch52st1[] =
+{
+ {64.2857f,100.0f},
+ {64.2857f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch52st[] =
+{
+ {3,ch52st0},
+ {2,ch52st1}
+};
+
+static const Fl_Glut_StrokeChar ch52 = {104.762f,2,ch52st};
+
+/* char: 0x35 */
+
+static const Fl_Glut_StrokeVertex ch53st0[] =
+{
+ {76.1905f,100.0f},
+ {28.5714f,100.0f},
+ {23.8095f,57.1429f},
+ {28.5714f,61.9048f},
+ {42.8571f,66.6667f},
+ {57.1428f,66.6667f},
+ {71.4286f,61.9048f},
+ {80.9524f,52.381f},
+ {85.7143f,38.0952f},
+ {85.7143f,28.5714f},
+ {80.9524f,14.2857f},
+ {71.4286f,4.7619f},
+ {57.1428f,0.0f},
+ {42.8571f,0.0f},
+ {28.5714f,4.7619f},
+ {23.8095f,9.5238f},
+ {19.0476f,19.0476f}
+};
+
+static const Fl_Glut_StrokeStrip ch53st[] =
+{
+ {17,ch53st0}
+};
+
+static const Fl_Glut_StrokeChar ch53 = {104.762f,1,ch53st};
+
+/* char: 0x36 */
+
+static const Fl_Glut_StrokeVertex ch54st0[] =
+{
+ {78.5714f,85.7143f},
+ {73.8096f,95.2381f},
+ {59.5238f,100.0f},
+ {50.0f,100.0f},
+ {35.7143f,95.2381f},
+ {26.1905f,80.9524f},
+ {21.4286f,57.1429f},
+ {21.4286f,33.3333f},
+ {26.1905f,14.2857f},
+ {35.7143f,4.7619f},
+ {50.0f,0.0f},
+ {54.7619f,0.0f},
+ {69.0476f,4.7619f},
+ {78.5714f,14.2857f},
+ {83.3334f,28.5714f},
+ {83.3334f,33.3333f},
+ {78.5714f,47.619f},
+ {69.0476f,57.1429f},
+ {54.7619f,61.9048f},
+ {50.0f,61.9048f},
+ {35.7143f,57.1429f},
+ {26.1905f,47.619f},
+ {21.4286f,33.3333f}
+};
+
+static const Fl_Glut_StrokeStrip ch54st[] =
+{
+ {23,ch54st0}
+};
+
+static const Fl_Glut_StrokeChar ch54 = {104.762f,1,ch54st};
+
+/* char: 0x37 */
+
+static const Fl_Glut_StrokeVertex ch55st0[] =
+{
+ {85.7143f,100.0f},
+ {38.0952f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch55st1[] =
+{
+ {19.0476f,100.0f},
+ {85.7143f,100.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch55st[] =
+{
+ {2,ch55st0},
+ {2,ch55st1}
+};
+
+static const Fl_Glut_StrokeChar ch55 = {104.762f,2,ch55st};
+
+/* char: 0x38 */
+
+static const Fl_Glut_StrokeVertex ch56st0[] =
+{
+ {42.8571f,100.0f},
+ {28.5714f,95.2381f},
+ {23.8095f,85.7143f},
+ {23.8095f,76.1905f},
+ {28.5714f,66.6667f},
+ {38.0952f,61.9048f},
+ {57.1428f,57.1429f},
+ {71.4286f,52.381f},
+ {80.9524f,42.8571f},
+ {85.7143f,33.3333f},
+ {85.7143f,19.0476f},
+ {80.9524f,9.5238f},
+ {76.1905f,4.7619f},
+ {61.9047f,0.0f},
+ {42.8571f,0.0f},
+ {28.5714f,4.7619f},
+ {23.8095f,9.5238f},
+ {19.0476f,19.0476f},
+ {19.0476f,33.3333f},
+ {23.8095f,42.8571f},
+ {33.3333f,52.381f},
+ {47.619f,57.1429f},
+ {66.6666f,61.9048f},
+ {76.1905f,66.6667f},
+ {80.9524f,76.1905f},
+ {80.9524f,85.7143f},
+ {76.1905f,95.2381f},
+ {61.9047f,100.0f},
+ {42.8571f,100.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch56st[] =
+{
+ {29,ch56st0}
+};
+
+static const Fl_Glut_StrokeChar ch56 = {104.762f,1,ch56st};
+
+/* char: 0x39 */
+
+static const Fl_Glut_StrokeVertex ch57st0[] =
+{
+ {83.3334f,66.6667f},
+ {78.5714f,52.381f},
+ {69.0476f,42.8571f},
+ {54.7619f,38.0952f},
+ {50.0f,38.0952f},
+ {35.7143f,42.8571f},
+ {26.1905f,52.381f},
+ {21.4286f,66.6667f},
+ {21.4286f,71.4286f},
+ {26.1905f,85.7143f},
+ {35.7143f,95.2381f},
+ {50.0f,100.0f},
+ {54.7619f,100.0f},
+ {69.0476f,95.2381f},
+ {78.5714f,85.7143f},
+ {83.3334f,66.6667f},
+ {83.3334f,42.8571f},
+ {78.5714f,19.0476f},
+ {69.0476f,4.7619f},
+ {54.7619f,0.0f},
+ {45.2381f,0.0f},
+ {30.9524f,4.7619f},
+ {26.1905f,14.2857f}
+};
+
+static const Fl_Glut_StrokeStrip ch57st[] =
+{
+ {23,ch57st0}
+};
+
+static const Fl_Glut_StrokeChar ch57 = {104.762f,1,ch57st};
+
+/* char: 0x3a */
+
+static const Fl_Glut_StrokeVertex ch58st0[] =
+{
+ {52.381f,66.6667f},
+ {47.6191f,61.9048f},
+ {52.381f,57.1429f},
+ {57.1429f,61.9048f},
+ {52.381f,66.6667f}
+};
+
+static const Fl_Glut_StrokeVertex ch58st1[] =
+{
+ {52.381f,9.5238f},
+ {47.6191f,4.7619f},
+ {52.381f,0.0f},
+ {57.1429f,4.7619f},
+ {52.381f,9.5238f}
+};
+
+static const Fl_Glut_StrokeStrip ch58st[] =
+{
+ {5,ch58st0},
+ {5,ch58st1}
+};
+
+static const Fl_Glut_StrokeChar ch58 = {104.762f,2,ch58st};
+
+/* char: 0x3b */
+
+static const Fl_Glut_StrokeVertex ch59st0[] =
+{
+ {52.381f,66.6667f},
+ {47.6191f,61.9048f},
+ {52.381f,57.1429f},
+ {57.1429f,61.9048f},
+ {52.381f,66.6667f}
+};
+
+static const Fl_Glut_StrokeVertex ch59st1[] =
+{
+ {57.1429f,4.7619f},
+ {52.381f,0.0f},
+ {47.6191f,4.7619f},
+ {52.381f,9.5238f},
+ {57.1429f,4.7619f},
+ {57.1429f,-4.7619f},
+ {52.381f,-14.2857f},
+ {47.6191f,-19.0476f}
+};
+
+static const Fl_Glut_StrokeStrip ch59st[] =
+{
+ {5,ch59st0},
+ {8,ch59st1}
+};
+
+static const Fl_Glut_StrokeChar ch59 = {104.762f,2,ch59st};
+
+/* char: 0x3c */
+
+static const Fl_Glut_StrokeVertex ch60st0[] =
+{
+ {90.4762f,85.7143f},
+ {14.2857f,42.8571f},
+ {90.4762f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch60st[] =
+{
+ {3,ch60st0}
+};
+
+static const Fl_Glut_StrokeChar ch60 = {104.762f,1,ch60st};
+
+/* char: 0x3d */
+
+static const Fl_Glut_StrokeVertex ch61st0[] =
+{
+ {9.5238f,57.1429f},
+ {95.2381f,57.1429f}
+};
+
+static const Fl_Glut_StrokeVertex ch61st1[] =
+{
+ {9.5238f,28.5714f},
+ {95.2381f,28.5714f}
+};
+
+static const Fl_Glut_StrokeStrip ch61st[] =
+{
+ {2,ch61st0},
+ {2,ch61st1}
+};
+
+static const Fl_Glut_StrokeChar ch61 = {104.762f,2,ch61st};
+
+/* char: 0x3e */
+
+static const Fl_Glut_StrokeVertex ch62st0[] =
+{
+ {14.2857f,85.7143f},
+ {90.4762f,42.8571f},
+ {14.2857f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch62st[] =
+{
+ {3,ch62st0}
+};
+
+static const Fl_Glut_StrokeChar ch62 = {104.762f,1,ch62st};
+
+/* char: 0x3f */
+
+static const Fl_Glut_StrokeVertex ch63st0[] =
+{
+ {23.8095f,76.1905f},
+ {23.8095f,80.9524f},
+ {28.5714f,90.4762f},
+ {33.3333f,95.2381f},
+ {42.8571f,100.0f},
+ {61.9047f,100.0f},
+ {71.4285f,95.2381f},
+ {76.1905f,90.4762f},
+ {80.9524f,80.9524f},
+ {80.9524f,71.4286f},
+ {76.1905f,61.9048f},
+ {71.4285f,57.1429f},
+ {52.3809f,47.619f},
+ {52.3809f,33.3333f}
+};
+
+static const Fl_Glut_StrokeVertex ch63st1[] =
+{
+ {52.3809f,9.5238f},
+ {47.619f,4.7619f},
+ {52.3809f,0.0f},
+ {57.1428f,4.7619f},
+ {52.3809f,9.5238f}
+};
+
+static const Fl_Glut_StrokeStrip ch63st[] =
+{
+ {14,ch63st0},
+ {5,ch63st1}
+};
+
+static const Fl_Glut_StrokeChar ch63 = {104.762f,2,ch63st};
+
+/* char: 0x40 */
+
+static const Fl_Glut_StrokeVertex ch64st0[] =
+{
+ {64.2857f,52.381f},
+ {54.7619f,57.1429f},
+ {45.2381f,57.1429f},
+ {40.4762f,47.619f},
+ {40.4762f,42.8571f},
+ {45.2381f,33.3333f},
+ {54.7619f,33.3333f},
+ {64.2857f,38.0952f}
+};
+
+static const Fl_Glut_StrokeVertex ch64st1[] =
+{
+ {64.2857f,57.1429f},
+ {64.2857f,38.0952f},
+ {69.0476f,33.3333f},
+ {78.5714f,33.3333f},
+ {83.3334f,42.8571f},
+ {83.3334f,47.619f},
+ {78.5714f,61.9048f},
+ {69.0476f,71.4286f},
+ {54.7619f,76.1905f},
+ {50.0f,76.1905f},
+ {35.7143f,71.4286f},
+ {26.1905f,61.9048f},
+ {21.4286f,47.619f},
+ {21.4286f,42.8571f},
+ {26.1905f,28.5714f},
+ {35.7143f,19.0476f},
+ {50.0f,14.2857f},
+ {54.7619f,14.2857f},
+ {69.0476f,19.0476f}
+};
+
+static const Fl_Glut_StrokeStrip ch64st[] =
+{
+ {8,ch64st0},
+ {19,ch64st1}
+};
+
+static const Fl_Glut_StrokeChar ch64 = {104.762f,2,ch64st};
+
+/* char: 0x41 */
+
+static const Fl_Glut_StrokeVertex ch65st0[] =
+{
+ {52.3809f,100.0f},
+ {14.2857f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch65st1[] =
+{
+ {52.3809f,100.0f},
+ {90.4762f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch65st2[] =
+{
+ {28.5714f,33.3333f},
+ {76.1905f,33.3333f}
+};
+
+static const Fl_Glut_StrokeStrip ch65st[] =
+{
+ {2,ch65st0},
+ {2,ch65st1},
+ {2,ch65st2}
+};
+
+static const Fl_Glut_StrokeChar ch65 = {104.762f,3,ch65st};
+
+/* char: 0x42 */
+
+static const Fl_Glut_StrokeVertex ch66st0[] =
+{
+ {19.0476f,100.0f},
+ {19.0476f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch66st1[] =
+{
+ {19.0476f,100.0f},
+ {61.9047f,100.0f},
+ {76.1905f,95.2381f},
+ {80.9524f,90.4762f},
+ {85.7143f,80.9524f},
+ {85.7143f,71.4286f},
+ {80.9524f,61.9048f},
+ {76.1905f,57.1429f},
+ {61.9047f,52.381f}
+};
+
+static const Fl_Glut_StrokeVertex ch66st2[] =
+{
+ {19.0476f,52.381f},
+ {61.9047f,52.381f},
+ {76.1905f,47.619f},
+ {80.9524f,42.8571f},
+ {85.7143f,33.3333f},
+ {85.7143f,19.0476f},
+ {80.9524f,9.5238f},
+ {76.1905f,4.7619f},
+ {61.9047f,0.0f},
+ {19.0476f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch66st[] =
+{
+ {2,ch66st0},
+ {9,ch66st1},
+ {10,ch66st2}
+};
+
+static const Fl_Glut_StrokeChar ch66 = {104.762f,3,ch66st};
+
+/* char: 0x43 */
+
+static const Fl_Glut_StrokeVertex ch67st0[] =
+{
+ {88.0952f,76.1905f},
+ {83.3334f,85.7143f},
+ {73.8096f,95.2381f},
+ {64.2857f,100.0f},
+ {45.2381f,100.0f},
+ {35.7143f,95.2381f},
+ {26.1905f,85.7143f},
+ {21.4286f,76.1905f},
+ {16.6667f,61.9048f},
+ {16.6667f,38.0952f},
+ {21.4286f,23.8095f},
+ {26.1905f,14.2857f},
+ {35.7143f,4.7619f},
+ {45.2381f,0.0f},
+ {64.2857f,0.0f},
+ {73.8096f,4.7619f},
+ {83.3334f,14.2857f},
+ {88.0952f,23.8095f}
+};
+
+static const Fl_Glut_StrokeStrip ch67st[] =
+{
+ {18,ch67st0}
+};
+
+static const Fl_Glut_StrokeChar ch67 = {104.762f,1,ch67st};
+
+/* char: 0x44 */
+
+static const Fl_Glut_StrokeVertex ch68st0[] =
+{
+ {19.0476f,100.0f},
+ {19.0476f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch68st1[] =
+{
+ {19.0476f,100.0f},
+ {52.3809f,100.0f},
+ {66.6666f,95.2381f},
+ {76.1905f,85.7143f},
+ {80.9524f,76.1905f},
+ {85.7143f,61.9048f},
+ {85.7143f,38.0952f},
+ {80.9524f,23.8095f},
+ {76.1905f,14.2857f},
+ {66.6666f,4.7619f},
+ {52.3809f,0.0f},
+ {19.0476f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch68st[] =
+{
+ {2,ch68st0},
+ {12,ch68st1}
+};
+
+static const Fl_Glut_StrokeChar ch68 = {104.762f,2,ch68st};
+
+/* char: 0x45 */
+
+static const Fl_Glut_StrokeVertex ch69st0[] =
+{
+ {21.4286f,100.0f},
+ {21.4286f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch69st1[] =
+{
+ {21.4286f,100.0f},
+ {83.3334f,100.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch69st2[] =
+{
+ {21.4286f,52.381f},
+ {59.5238f,52.381f}
+};
+
+static const Fl_Glut_StrokeVertex ch69st3[] =
+{
+ {21.4286f,0.0f},
+ {83.3334f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch69st[] =
+{
+ {2,ch69st0},
+ {2,ch69st1},
+ {2,ch69st2},
+ {2,ch69st3}
+};
+
+static const Fl_Glut_StrokeChar ch69 = {104.762f,4,ch69st};
+
+/* char: 0x46 */
+
+static const Fl_Glut_StrokeVertex ch70st0[] =
+{
+ {21.4286f,100.0f},
+ {21.4286f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch70st1[] =
+{
+ {21.4286f,100.0f},
+ {83.3334f,100.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch70st2[] =
+{
+ {21.4286f,52.381f},
+ {59.5238f,52.381f}
+};
+
+static const Fl_Glut_StrokeStrip ch70st[] =
+{
+ {2,ch70st0},
+ {2,ch70st1},
+ {2,ch70st2}
+};
+
+static const Fl_Glut_StrokeChar ch70 = {104.762f,3,ch70st};
+
+/* char: 0x47 */
+
+static const Fl_Glut_StrokeVertex ch71st0[] =
+{
+ {88.0952f,76.1905f},
+ {83.3334f,85.7143f},
+ {73.8096f,95.2381f},
+ {64.2857f,100.0f},
+ {45.2381f,100.0f},
+ {35.7143f,95.2381f},
+ {26.1905f,85.7143f},
+ {21.4286f,76.1905f},
+ {16.6667f,61.9048f},
+ {16.6667f,38.0952f},
+ {21.4286f,23.8095f},
+ {26.1905f,14.2857f},
+ {35.7143f,4.7619f},
+ {45.2381f,0.0f},
+ {64.2857f,0.0f},
+ {73.8096f,4.7619f},
+ {83.3334f,14.2857f},
+ {88.0952f,23.8095f},
+ {88.0952f,38.0952f}
+};
+
+static const Fl_Glut_StrokeVertex ch71st1[] =
+{
+ {64.2857f,38.0952f},
+ {88.0952f,38.0952f}
+};
+
+static const Fl_Glut_StrokeStrip ch71st[] =
+{
+ {19,ch71st0},
+ {2,ch71st1}
+};
+
+static const Fl_Glut_StrokeChar ch71 = {104.762f,2,ch71st};
+
+/* char: 0x48 */
+
+static const Fl_Glut_StrokeVertex ch72st0[] =
+{
+ {19.0476f,100.0f},
+ {19.0476f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch72st1[] =
+{
+ {85.7143f,100.0f},
+ {85.7143f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch72st2[] =
+{
+ {19.0476f,52.381f},
+ {85.7143f,52.381f}
+};
+
+static const Fl_Glut_StrokeStrip ch72st[] =
+{
+ {2,ch72st0},
+ {2,ch72st1},
+ {2,ch72st2}
+};
+
+static const Fl_Glut_StrokeChar ch72 = {104.762f,3,ch72st};
+
+/* char: 0x49 */
+
+static const Fl_Glut_StrokeVertex ch73st0[] =
+{
+ {52.381f,100.0f},
+ {52.381f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch73st[] =
+{
+ {2,ch73st0}
+};
+
+static const Fl_Glut_StrokeChar ch73 = {104.762f,1,ch73st};
+
+/* char: 0x4a */
+
+static const Fl_Glut_StrokeVertex ch74st0[] =
+{
+ {76.1905f,100.0f},
+ {76.1905f,23.8095f},
+ {71.4286f,9.5238f},
+ {66.6667f,4.7619f},
+ {57.1429f,0.0f},
+ {47.6191f,0.0f},
+ {38.0953f,4.7619f},
+ {33.3334f,9.5238f},
+ {28.5715f,23.8095f},
+ {28.5715f,33.3333f}
+};
+
+static const Fl_Glut_StrokeStrip ch74st[] =
+{
+ {10,ch74st0}
+};
+
+static const Fl_Glut_StrokeChar ch74 = {104.762f,1,ch74st};
+
+/* char: 0x4b */
+
+static const Fl_Glut_StrokeVertex ch75st0[] =
+{
+ {19.0476f,100.0f},
+ {19.0476f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch75st1[] =
+{
+ {85.7143f,100.0f},
+ {19.0476f,33.3333f}
+};
+
+static const Fl_Glut_StrokeVertex ch75st2[] =
+{
+ {42.8571f,57.1429f},
+ {85.7143f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch75st[] =
+{
+ {2,ch75st0},
+ {2,ch75st1},
+ {2,ch75st2}
+};
+
+static const Fl_Glut_StrokeChar ch75 = {104.762f,3,ch75st};
+
+/* char: 0x4c */
+
+static const Fl_Glut_StrokeVertex ch76st0[] =
+{
+ {23.8095f,100.0f},
+ {23.8095f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch76st1[] =
+{
+ {23.8095f,0.0f},
+ {80.9524f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch76st[] =
+{
+ {2,ch76st0},
+ {2,ch76st1}
+};
+
+static const Fl_Glut_StrokeChar ch76 = {104.762f,2,ch76st};
+
+/* char: 0x4d */
+
+static const Fl_Glut_StrokeVertex ch77st0[] =
+{
+ {14.2857f,100.0f},
+ {14.2857f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch77st1[] =
+{
+ {14.2857f,100.0f},
+ {52.3809f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch77st2[] =
+{
+ {90.4762f,100.0f},
+ {52.3809f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch77st3[] =
+{
+ {90.4762f,100.0f},
+ {90.4762f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch77st[] =
+{
+ {2,ch77st0},
+ {2,ch77st1},
+ {2,ch77st2},
+ {2,ch77st3}
+};
+
+static const Fl_Glut_StrokeChar ch77 = {104.762f,4,ch77st};
+
+/* char: 0x4e */
+
+static const Fl_Glut_StrokeVertex ch78st0[] =
+{
+ {19.0476f,100.0f},
+ {19.0476f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch78st1[] =
+{
+ {19.0476f,100.0f},
+ {85.7143f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch78st2[] =
+{
+ {85.7143f,100.0f},
+ {85.7143f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch78st[] =
+{
+ {2,ch78st0},
+ {2,ch78st1},
+ {2,ch78st2}
+};
+
+static const Fl_Glut_StrokeChar ch78 = {104.762f,3,ch78st};
+
+/* char: 0x4f */
+
+static const Fl_Glut_StrokeVertex ch79st0[] =
+{
+ {42.8571f,100.0f},
+ {33.3333f,95.2381f},
+ {23.8095f,85.7143f},
+ {19.0476f,76.1905f},
+ {14.2857f,61.9048f},
+ {14.2857f,38.0952f},
+ {19.0476f,23.8095f},
+ {23.8095f,14.2857f},
+ {33.3333f,4.7619f},
+ {42.8571f,0.0f},
+ {61.9047f,0.0f},
+ {71.4286f,4.7619f},
+ {80.9524f,14.2857f},
+ {85.7143f,23.8095f},
+ {90.4762f,38.0952f},
+ {90.4762f,61.9048f},
+ {85.7143f,76.1905f},
+ {80.9524f,85.7143f},
+ {71.4286f,95.2381f},
+ {61.9047f,100.0f},
+ {42.8571f,100.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch79st[] =
+{
+ {21,ch79st0}
+};
+
+static const Fl_Glut_StrokeChar ch79 = {104.762f,1,ch79st};
+
+/* char: 0x50 */
+
+static const Fl_Glut_StrokeVertex ch80st0[] =
+{
+ {19.0476f,100.0f},
+ {19.0476f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch80st1[] =
+{
+ {19.0476f,100.0f},
+ {61.9047f,100.0f},
+ {76.1905f,95.2381f},
+ {80.9524f,90.4762f},
+ {85.7143f,80.9524f},
+ {85.7143f,66.6667f},
+ {80.9524f,57.1429f},
+ {76.1905f,52.381f},
+ {61.9047f,47.619f},
+ {19.0476f,47.619f}
+};
+
+static const Fl_Glut_StrokeStrip ch80st[] =
+{
+ {2,ch80st0},
+ {10,ch80st1}
+};
+
+static const Fl_Glut_StrokeChar ch80 = {104.762f,2,ch80st};
+
+/* char: 0x51 */
+
+static const Fl_Glut_StrokeVertex ch81st0[] =
+{
+ {42.8571f,100.0f},
+ {33.3333f,95.2381f},
+ {23.8095f,85.7143f},
+ {19.0476f,76.1905f},
+ {14.2857f,61.9048f},
+ {14.2857f,38.0952f},
+ {19.0476f,23.8095f},
+ {23.8095f,14.2857f},
+ {33.3333f,4.7619f},
+ {42.8571f,0.0f},
+ {61.9047f,0.0f},
+ {71.4286f,4.7619f},
+ {80.9524f,14.2857f},
+ {85.7143f,23.8095f},
+ {90.4762f,38.0952f},
+ {90.4762f,61.9048f},
+ {85.7143f,76.1905f},
+ {80.9524f,85.7143f},
+ {71.4286f,95.2381f},
+ {61.9047f,100.0f},
+ {42.8571f,100.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch81st1[] =
+{
+ {57.1428f,19.0476f},
+ {85.7143f,-9.5238f}
+};
+
+static const Fl_Glut_StrokeStrip ch81st[] =
+{
+ {21,ch81st0},
+ {2,ch81st1}
+};
+
+static const Fl_Glut_StrokeChar ch81 = {104.762f,2,ch81st};
+
+/* char: 0x52 */
+
+static const Fl_Glut_StrokeVertex ch82st0[] =
+{
+ {19.0476f,100.0f},
+ {19.0476f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch82st1[] =
+{
+ {19.0476f,100.0f},
+ {61.9047f,100.0f},
+ {76.1905f,95.2381f},
+ {80.9524f,90.4762f},
+ {85.7143f,80.9524f},
+ {85.7143f,71.4286f},
+ {80.9524f,61.9048f},
+ {76.1905f,57.1429f},
+ {61.9047f,52.381f},
+ {19.0476f,52.381f}
+};
+
+static const Fl_Glut_StrokeVertex ch82st2[] =
+{
+ {52.3809f,52.381f},
+ {85.7143f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch82st[] =
+{
+ {2,ch82st0},
+ {10,ch82st1},
+ {2,ch82st2}
+};
+
+static const Fl_Glut_StrokeChar ch82 = {104.762f,3,ch82st};
+
+/* char: 0x53 */
+
+static const Fl_Glut_StrokeVertex ch83st0[] =
+{
+ {85.7143f,85.7143f},
+ {76.1905f,95.2381f},
+ {61.9047f,100.0f},
+ {42.8571f,100.0f},
+ {28.5714f,95.2381f},
+ {19.0476f,85.7143f},
+ {19.0476f,76.1905f},
+ {23.8095f,66.6667f},
+ {28.5714f,61.9048f},
+ {38.0952f,57.1429f},
+ {66.6666f,47.619f},
+ {76.1905f,42.8571f},
+ {80.9524f,38.0952f},
+ {85.7143f,28.5714f},
+ {85.7143f,14.2857f},
+ {76.1905f,4.7619f},
+ {61.9047f,0.0f},
+ {42.8571f,0.0f},
+ {28.5714f,4.7619f},
+ {19.0476f,14.2857f}
+};
+
+static const Fl_Glut_StrokeStrip ch83st[] =
+{
+ {20,ch83st0}
+};
+
+static const Fl_Glut_StrokeChar ch83 = {104.762f,1,ch83st};
+
+/* char: 0x54 */
+
+static const Fl_Glut_StrokeVertex ch84st0[] =
+{
+ {52.3809f,100.0f},
+ {52.3809f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch84st1[] =
+{
+ {19.0476f,100.0f},
+ {85.7143f,100.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch84st[] =
+{
+ {2,ch84st0},
+ {2,ch84st1}
+};
+
+static const Fl_Glut_StrokeChar ch84 = {104.762f,2,ch84st};
+
+/* char: 0x55 */
+
+static const Fl_Glut_StrokeVertex ch85st0[] =
+{
+ {19.0476f,100.0f},
+ {19.0476f,28.5714f},
+ {23.8095f,14.2857f},
+ {33.3333f,4.7619f},
+ {47.619f,0.0f},
+ {57.1428f,0.0f},
+ {71.4286f,4.7619f},
+ {80.9524f,14.2857f},
+ {85.7143f,28.5714f},
+ {85.7143f,100.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch85st[] =
+{
+ {10,ch85st0}
+};
+
+static const Fl_Glut_StrokeChar ch85 = {104.762f,1,ch85st};
+
+/* char: 0x56 */
+
+static const Fl_Glut_StrokeVertex ch86st0[] =
+{
+ {14.2857f,100.0f},
+ {52.3809f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch86st1[] =
+{
+ {90.4762f,100.0f},
+ {52.3809f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch86st[] =
+{
+ {2,ch86st0},
+ {2,ch86st1}
+};
+
+static const Fl_Glut_StrokeChar ch86 = {104.762f,2,ch86st};
+
+/* char: 0x57 */
+
+static const Fl_Glut_StrokeVertex ch87st0[] =
+{
+ {4.7619f,100.0f},
+ {28.5714f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch87st1[] =
+{
+ {52.3809f,100.0f},
+ {28.5714f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch87st2[] =
+{
+ {52.3809f,100.0f},
+ {76.1905f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch87st3[] =
+{
+ {100.0f,100.0f},
+ {76.1905f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch87st[] =
+{
+ {2,ch87st0},
+ {2,ch87st1},
+ {2,ch87st2},
+ {2,ch87st3}
+};
+
+static const Fl_Glut_StrokeChar ch87 = {104.762f,4,ch87st};
+
+/* char: 0x58 */
+
+static const Fl_Glut_StrokeVertex ch88st0[] =
+{
+ {19.0476f,100.0f},
+ {85.7143f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch88st1[] =
+{
+ {85.7143f,100.0f},
+ {19.0476f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch88st[] =
+{
+ {2,ch88st0},
+ {2,ch88st1}
+};
+
+static const Fl_Glut_StrokeChar ch88 = {104.762f,2,ch88st};
+
+/* char: 0x59 */
+
+static const Fl_Glut_StrokeVertex ch89st0[] =
+{
+ {14.2857f,100.0f},
+ {52.3809f,52.381f},
+ {52.3809f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch89st1[] =
+{
+ {90.4762f,100.0f},
+ {52.3809f,52.381f}
+};
+
+static const Fl_Glut_StrokeStrip ch89st[] =
+{
+ {3,ch89st0},
+ {2,ch89st1}
+};
+
+static const Fl_Glut_StrokeChar ch89 = {104.762f,2,ch89st};
+
+/* char: 0x5a */
+
+static const Fl_Glut_StrokeVertex ch90st0[] =
+{
+ {85.7143f,100.0f},
+ {19.0476f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch90st1[] =
+{
+ {19.0476f,100.0f},
+ {85.7143f,100.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch90st2[] =
+{
+ {19.0476f,0.0f},
+ {85.7143f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch90st[] =
+{
+ {2,ch90st0},
+ {2,ch90st1},
+ {2,ch90st2}
+};
+
+static const Fl_Glut_StrokeChar ch90 = {104.762f,3,ch90st};
+
+/* char: 0x5b */
+
+static const Fl_Glut_StrokeVertex ch91st0[] =
+{
+ {35.7143f,119.048f},
+ {35.7143f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeVertex ch91st1[] =
+{
+ {40.4762f,119.048f},
+ {40.4762f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeVertex ch91st2[] =
+{
+ {35.7143f,119.048f},
+ {69.0476f,119.048f}
+};
+
+static const Fl_Glut_StrokeVertex ch91st3[] =
+{
+ {35.7143f,-33.3333f},
+ {69.0476f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeStrip ch91st[] =
+{
+ {2,ch91st0},
+ {2,ch91st1},
+ {2,ch91st2},
+ {2,ch91st3}
+};
+
+static const Fl_Glut_StrokeChar ch91 = {104.762f,4,ch91st};
+
+/* char: 0x5c */
+
+static const Fl_Glut_StrokeVertex ch92st0[] =
+{
+ {19.0476f,100.0f},
+ {85.7143f,-14.2857f}
+};
+
+static const Fl_Glut_StrokeStrip ch92st[] =
+{
+ {2,ch92st0}
+};
+
+static const Fl_Glut_StrokeChar ch92 = {104.762f,1,ch92st};
+
+/* char: 0x5d */
+
+static const Fl_Glut_StrokeVertex ch93st0[] =
+{
+ {64.2857f,119.048f},
+ {64.2857f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeVertex ch93st1[] =
+{
+ {69.0476f,119.048f},
+ {69.0476f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeVertex ch93st2[] =
+{
+ {35.7143f,119.048f},
+ {69.0476f,119.048f}
+};
+
+static const Fl_Glut_StrokeVertex ch93st3[] =
+{
+ {35.7143f,-33.3333f},
+ {69.0476f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeStrip ch93st[] =
+{
+ {2,ch93st0},
+ {2,ch93st1},
+ {2,ch93st2},
+ {2,ch93st3}
+};
+
+static const Fl_Glut_StrokeChar ch93 = {104.762f,4,ch93st};
+
+/* char: 0x5e */
+
+static const Fl_Glut_StrokeVertex ch94st0[] =
+{
+ {52.3809f,109.524f},
+ {14.2857f,42.8571f}
+};
+
+static const Fl_Glut_StrokeVertex ch94st1[] =
+{
+ {52.3809f,109.524f},
+ {90.4762f,42.8571f}
+};
+
+static const Fl_Glut_StrokeStrip ch94st[] =
+{
+ {2,ch94st0},
+ {2,ch94st1}
+};
+
+static const Fl_Glut_StrokeChar ch94 = {104.762f,2,ch94st};
+
+/* char: 0x5f */
+
+static const Fl_Glut_StrokeVertex ch95st0[] =
+{
+ {0,-33.3333f},
+ {104.762f,-33.3333f},
+ {104.762f,-28.5714f},
+ {0,-28.5714f},
+ {0,-33.3333f}
+};
+
+static const Fl_Glut_StrokeStrip ch95st[] =
+{
+ {5,ch95st0}
+};
+
+static const Fl_Glut_StrokeChar ch95 = {104.762f,1,ch95st};
+
+/* char: 0x60 */
+
+static const Fl_Glut_StrokeVertex ch96st0[] =
+{
+ {42.8572f,100.0f},
+ {66.6667f,71.4286f}
+};
+
+static const Fl_Glut_StrokeVertex ch96st1[] =
+{
+ {42.8572f,100.0f},
+ {38.0953f,95.2381f},
+ {66.6667f,71.4286f}
+};
+
+static const Fl_Glut_StrokeStrip ch96st[] =
+{
+ {2,ch96st0},
+ {3,ch96st1}
+};
+
+static const Fl_Glut_StrokeChar ch96 = {104.762f,2,ch96st};
+
+/* char: 0x61 */
+
+static const Fl_Glut_StrokeVertex ch97st0[] =
+{
+ {80.9524f,66.6667f},
+ {80.9524f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch97st1[] =
+{
+ {80.9524f,52.381f},
+ {71.4285f,61.9048f},
+ {61.9047f,66.6667f},
+ {47.619f,66.6667f},
+ {38.0952f,61.9048f},
+ {28.5714f,52.381f},
+ {23.8095f,38.0952f},
+ {23.8095f,28.5714f},
+ {28.5714f,14.2857f},
+ {38.0952f,4.7619f},
+ {47.619f,0.0f},
+ {61.9047f,0.0f},
+ {71.4285f,4.7619f},
+ {80.9524f,14.2857f}
+};
+
+static const Fl_Glut_StrokeStrip ch97st[] =
+{
+ {2,ch97st0},
+ {14,ch97st1}
+};
+
+static const Fl_Glut_StrokeChar ch97 = {104.762f,2,ch97st};
+
+/* char: 0x62 */
+
+static const Fl_Glut_StrokeVertex ch98st0[] =
+{
+ {23.8095f,100.0f},
+ {23.8095f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch98st1[] =
+{
+ {23.8095f,52.381f},
+ {33.3333f,61.9048f},
+ {42.8571f,66.6667f},
+ {57.1428f,66.6667f},
+ {66.6666f,61.9048f},
+ {76.1905f,52.381f},
+ {80.9524f,38.0952f},
+ {80.9524f,28.5714f},
+ {76.1905f,14.2857f},
+ {66.6666f,4.7619f},
+ {57.1428f,0.0f},
+ {42.8571f,0.0f},
+ {33.3333f,4.7619f},
+ {23.8095f,14.2857f}
+};
+
+static const Fl_Glut_StrokeStrip ch98st[] =
+{
+ {2,ch98st0},
+ {14,ch98st1}
+};
+
+static const Fl_Glut_StrokeChar ch98 = {104.762f,2,ch98st};
+
+/* char: 0x63 */
+
+static const Fl_Glut_StrokeVertex ch99st0[] =
+{
+ {80.9524f,52.381f},
+ {71.4285f,61.9048f},
+ {61.9047f,66.6667f},
+ {47.619f,66.6667f},
+ {38.0952f,61.9048f},
+ {28.5714f,52.381f},
+ {23.8095f,38.0952f},
+ {23.8095f,28.5714f},
+ {28.5714f,14.2857f},
+ {38.0952f,4.7619f},
+ {47.619f,0.0f},
+ {61.9047f,0.0f},
+ {71.4285f,4.7619f},
+ {80.9524f,14.2857f}
+};
+
+static const Fl_Glut_StrokeStrip ch99st[] =
+{
+ {14,ch99st0}
+};
+
+static const Fl_Glut_StrokeChar ch99 = {104.762f,1,ch99st};
+
+/* char: 0x64 */
+
+static const Fl_Glut_StrokeVertex ch100st0[] =
+{
+ {80.9524f,100.0f},
+ {80.9524f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch100st1[] =
+{
+ {80.9524f,52.381f},
+ {71.4285f,61.9048f},
+ {61.9047f,66.6667f},
+ {47.619f,66.6667f},
+ {38.0952f,61.9048f},
+ {28.5714f,52.381f},
+ {23.8095f,38.0952f},
+ {23.8095f,28.5714f},
+ {28.5714f,14.2857f},
+ {38.0952f,4.7619f},
+ {47.619f,0.0f},
+ {61.9047f,0.0f},
+ {71.4285f,4.7619f},
+ {80.9524f,14.2857f}
+};
+
+static const Fl_Glut_StrokeStrip ch100st[] =
+{
+ {2,ch100st0},
+ {14,ch100st1}
+};
+
+static const Fl_Glut_StrokeChar ch100 = {104.762f,2,ch100st};
+
+/* char: 0x65 */
+
+static const Fl_Glut_StrokeVertex ch101st0[] =
+{
+ {23.8095f,38.0952f},
+ {80.9524f,38.0952f},
+ {80.9524f,47.619f},
+ {76.1905f,57.1429f},
+ {71.4285f,61.9048f},
+ {61.9047f,66.6667f},
+ {47.619f,66.6667f},
+ {38.0952f,61.9048f},
+ {28.5714f,52.381f},
+ {23.8095f,38.0952f},
+ {23.8095f,28.5714f},
+ {28.5714f,14.2857f},
+ {38.0952f,4.7619f},
+ {47.619f,0.0f},
+ {61.9047f,0.0f},
+ {71.4285f,4.7619f},
+ {80.9524f,14.2857f}
+};
+
+static const Fl_Glut_StrokeStrip ch101st[] =
+{
+ {17,ch101st0}
+};
+
+static const Fl_Glut_StrokeChar ch101 = {104.762f,1,ch101st};
+
+/* char: 0x66 */
+
+static const Fl_Glut_StrokeVertex ch102st0[] =
+{
+ {71.4286f,100.0f},
+ {61.9048f,100.0f},
+ {52.381f,95.2381f},
+ {47.6191f,80.9524f},
+ {47.6191f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch102st1[] =
+{
+ {33.3334f,66.6667f},
+ {66.6667f,66.6667f}
+};
+
+static const Fl_Glut_StrokeStrip ch102st[] =
+{
+ {5,ch102st0},
+ {2,ch102st1}
+};
+
+static const Fl_Glut_StrokeChar ch102 = {104.762f,2,ch102st};
+
+/* char: 0x67 */
+
+static const Fl_Glut_StrokeVertex ch103st0[] =
+{
+ {80.9524f,66.6667f},
+ {80.9524f,-9.5238f},
+ {76.1905f,-23.8095f},
+ {71.4285f,-28.5714f},
+ {61.9047f,-33.3333f},
+ {47.619f,-33.3333f},
+ {38.0952f,-28.5714f}
+};
+
+static const Fl_Glut_StrokeVertex ch103st1[] =
+{
+ {80.9524f,52.381f},
+ {71.4285f,61.9048f},
+ {61.9047f,66.6667f},
+ {47.619f,66.6667f},
+ {38.0952f,61.9048f},
+ {28.5714f,52.381f},
+ {23.8095f,38.0952f},
+ {23.8095f,28.5714f},
+ {28.5714f,14.2857f},
+ {38.0952f,4.7619f},
+ {47.619f,0.0f},
+ {61.9047f,0.0f},
+ {71.4285f,4.7619f},
+ {80.9524f,14.2857f}
+};
+
+static const Fl_Glut_StrokeStrip ch103st[] =
+{
+ {7,ch103st0},
+ {14,ch103st1}
+};
+
+static const Fl_Glut_StrokeChar ch103 = {104.762f,2,ch103st};
+
+/* char: 0x68 */
+
+static const Fl_Glut_StrokeVertex ch104st0[] =
+{
+ {26.1905f,100.0f},
+ {26.1905f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch104st1[] =
+{
+ {26.1905f,47.619f},
+ {40.4762f,61.9048f},
+ {50.0f,66.6667f},
+ {64.2857f,66.6667f},
+ {73.8095f,61.9048f},
+ {78.5715f,47.619f},
+ {78.5715f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch104st[] =
+{
+ {2,ch104st0},
+ {7,ch104st1}
+};
+
+static const Fl_Glut_StrokeChar ch104 = {104.762f,2,ch104st};
+
+/* char: 0x69 */
+
+static const Fl_Glut_StrokeVertex ch105st0[] =
+{
+ {47.6191f,100.0f},
+ {52.381f,95.2381f},
+ {57.1429f,100.0f},
+ {52.381f,104.762f},
+ {47.6191f,100.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch105st1[] =
+{
+ {52.381f,66.6667f},
+ {52.381f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch105st[] =
+{
+ {5,ch105st0},
+ {2,ch105st1}
+};
+
+static const Fl_Glut_StrokeChar ch105 = {104.762f,2,ch105st};
+
+/* char: 0x6a */
+
+static const Fl_Glut_StrokeVertex ch106st0[] =
+{
+ {57.1429f,100.0f},
+ {61.9048f,95.2381f},
+ {66.6667f,100.0f},
+ {61.9048f,104.762f},
+ {57.1429f,100.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch106st1[] =
+{
+ {61.9048f,66.6667f},
+ {61.9048f,-14.2857f},
+ {57.1429f,-28.5714f},
+ {47.6191f,-33.3333f},
+ {38.0953f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeStrip ch106st[] =
+{
+ {5,ch106st0},
+ {5,ch106st1}
+};
+
+static const Fl_Glut_StrokeChar ch106 = {104.762f,2,ch106st};
+
+/* char: 0x6b */
+
+static const Fl_Glut_StrokeVertex ch107st0[] =
+{
+ {26.1905f,100.0f},
+ {26.1905f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch107st1[] =
+{
+ {73.8095f,66.6667f},
+ {26.1905f,19.0476f}
+};
+
+static const Fl_Glut_StrokeVertex ch107st2[] =
+{
+ {45.2381f,38.0952f},
+ {78.5715f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch107st[] =
+{
+ {2,ch107st0},
+ {2,ch107st1},
+ {2,ch107st2}
+};
+
+static const Fl_Glut_StrokeChar ch107 = {104.762f,3,ch107st};
+
+/* char: 0x6c */
+
+static const Fl_Glut_StrokeVertex ch108st0[] =
+{
+ {52.381f,100.0f},
+ {52.381f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch108st[] =
+{
+ {2,ch108st0}
+};
+
+static const Fl_Glut_StrokeChar ch108 = {104.762f,1,ch108st};
+
+/* char: 0x6d */
+
+static const Fl_Glut_StrokeVertex ch109st0[] =
+{
+ {0,66.6667f},
+ {0,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch109st1[] =
+{
+ {0,47.619f},
+ {14.2857f,61.9048f},
+ {23.8095f,66.6667f},
+ {38.0952f,66.6667f},
+ {47.619f,61.9048f},
+ {52.381f,47.619f},
+ {52.381f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch109st2[] =
+{
+ {52.381f,47.619f},
+ {66.6667f,61.9048f},
+ {76.1905f,66.6667f},
+ {90.4762f,66.6667f},
+ {100.0f,61.9048f},
+ {104.762f,47.619f},
+ {104.762f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch109st[] =
+{
+ {2,ch109st0},
+ {7,ch109st1},
+ {7,ch109st2}
+};
+
+static const Fl_Glut_StrokeChar ch109 = {104.762f,3,ch109st};
+
+/* char: 0x6e */
+
+static const Fl_Glut_StrokeVertex ch110st0[] =
+{
+ {26.1905f,66.6667f},
+ {26.1905f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch110st1[] =
+{
+ {26.1905f,47.619f},
+ {40.4762f,61.9048f},
+ {50.0f,66.6667f},
+ {64.2857f,66.6667f},
+ {73.8095f,61.9048f},
+ {78.5715f,47.619f},
+ {78.5715f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch110st[] =
+{
+ {2,ch110st0},
+ {7,ch110st1}
+};
+
+static const Fl_Glut_StrokeChar ch110 = {104.762f,2,ch110st};
+
+/* char: 0x6f */
+
+static const Fl_Glut_StrokeVertex ch111st0[] =
+{
+ {45.2381f,66.6667f},
+ {35.7143f,61.9048f},
+ {26.1905f,52.381f},
+ {21.4286f,38.0952f},
+ {21.4286f,28.5714f},
+ {26.1905f,14.2857f},
+ {35.7143f,4.7619f},
+ {45.2381f,0.0f},
+ {59.5238f,0.0f},
+ {69.0476f,4.7619f},
+ {78.5714f,14.2857f},
+ {83.3334f,28.5714f},
+ {83.3334f,38.0952f},
+ {78.5714f,52.381f},
+ {69.0476f,61.9048f},
+ {59.5238f,66.6667f},
+ {45.2381f,66.6667f}
+};
+
+static const Fl_Glut_StrokeStrip ch111st[] =
+{
+ {17,ch111st0}
+};
+
+static const Fl_Glut_StrokeChar ch111 = {104.762f,1,ch111st};
+
+/* char: 0x70 */
+
+static const Fl_Glut_StrokeVertex ch112st0[] =
+{
+ {23.8095f,66.6667f},
+ {23.8095f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeVertex ch112st1[] =
+{
+ {23.8095f,52.381f},
+ {33.3333f,61.9048f},
+ {42.8571f,66.6667f},
+ {57.1428f,66.6667f},
+ {66.6666f,61.9048f},
+ {76.1905f,52.381f},
+ {80.9524f,38.0952f},
+ {80.9524f,28.5714f},
+ {76.1905f,14.2857f},
+ {66.6666f,4.7619f},
+ {57.1428f,0.0f},
+ {42.8571f,0.0f},
+ {33.3333f,4.7619f},
+ {23.8095f,14.2857f}
+};
+
+static const Fl_Glut_StrokeStrip ch112st[] =
+{
+ {2,ch112st0},
+ {14,ch112st1}
+};
+
+static const Fl_Glut_StrokeChar ch112 = {104.762f,2,ch112st};
+
+/* char: 0x71 */
+
+static const Fl_Glut_StrokeVertex ch113st0[] =
+{
+ {80.9524f,66.6667f},
+ {80.9524f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeVertex ch113st1[] =
+{
+ {80.9524f,52.381f},
+ {71.4285f,61.9048f},
+ {61.9047f,66.6667f},
+ {47.619f,66.6667f},
+ {38.0952f,61.9048f},
+ {28.5714f,52.381f},
+ {23.8095f,38.0952f},
+ {23.8095f,28.5714f},
+ {28.5714f,14.2857f},
+ {38.0952f,4.7619f},
+ {47.619f,0.0f},
+ {61.9047f,0.0f},
+ {71.4285f,4.7619f},
+ {80.9524f,14.2857f}
+};
+
+static const Fl_Glut_StrokeStrip ch113st[] =
+{
+ {2,ch113st0},
+ {14,ch113st1}
+};
+
+static const Fl_Glut_StrokeChar ch113 = {104.762f,2,ch113st};
+
+/* char: 0x72 */
+
+static const Fl_Glut_StrokeVertex ch114st0[] =
+{
+ {33.3334f,66.6667f},
+ {33.3334f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch114st1[] =
+{
+ {33.3334f,38.0952f},
+ {38.0953f,52.381f},
+ {47.6191f,61.9048f},
+ {57.1429f,66.6667f},
+ {71.4286f,66.6667f}
+};
+
+static const Fl_Glut_StrokeStrip ch114st[] =
+{
+ {2,ch114st0},
+ {5,ch114st1}
+};
+
+static const Fl_Glut_StrokeChar ch114 = {104.762f,2,ch114st};
+
+/* char: 0x73 */
+
+static const Fl_Glut_StrokeVertex ch115st0[] =
+{
+ {78.5715f,52.381f},
+ {73.8095f,61.9048f},
+ {59.5238f,66.6667f},
+ {45.2381f,66.6667f},
+ {30.9524f,61.9048f},
+ {26.1905f,52.381f},
+ {30.9524f,42.8571f},
+ {40.4762f,38.0952f},
+ {64.2857f,33.3333f},
+ {73.8095f,28.5714f},
+ {78.5715f,19.0476f},
+ {78.5715f,14.2857f},
+ {73.8095f,4.7619f},
+ {59.5238f,0.0f},
+ {45.2381f,0.0f},
+ {30.9524f,4.7619f},
+ {26.1905f,14.2857f}
+};
+
+static const Fl_Glut_StrokeStrip ch115st[] =
+{
+ {17,ch115st0}
+};
+
+static const Fl_Glut_StrokeChar ch115 = {104.762f,1,ch115st};
+
+/* char: 0x74 */
+
+static const Fl_Glut_StrokeVertex ch116st0[] =
+{
+ {47.6191f,100.0f},
+ {47.6191f,19.0476f},
+ {52.381f,4.7619f},
+ {61.9048f,0.0f},
+ {71.4286f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch116st1[] =
+{
+ {33.3334f,66.6667f},
+ {66.6667f,66.6667f}
+};
+
+static const Fl_Glut_StrokeStrip ch116st[] =
+{
+ {5,ch116st0},
+ {2,ch116st1}
+};
+
+static const Fl_Glut_StrokeChar ch116 = {104.762f,2,ch116st};
+
+/* char: 0x75 */
+
+static const Fl_Glut_StrokeVertex ch117st0[] =
+{
+ {26.1905f,66.6667f},
+ {26.1905f,19.0476f},
+ {30.9524f,4.7619f},
+ {40.4762f,0.0f},
+ {54.7619f,0.0f},
+ {64.2857f,4.7619f},
+ {78.5715f,19.0476f}
+};
+
+static const Fl_Glut_StrokeVertex ch117st1[] =
+{
+ {78.5715f,66.6667f},
+ {78.5715f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch117st[] =
+{
+ {7,ch117st0},
+ {2,ch117st1}
+};
+
+static const Fl_Glut_StrokeChar ch117 = {104.762f,2,ch117st};
+
+/* char: 0x76 */
+
+static const Fl_Glut_StrokeVertex ch118st0[] =
+{
+ {23.8095f,66.6667f},
+ {52.3809f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch118st1[] =
+{
+ {80.9524f,66.6667f},
+ {52.3809f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch118st[] =
+{
+ {2,ch118st0},
+ {2,ch118st1}
+};
+
+static const Fl_Glut_StrokeChar ch118 = {104.762f,2,ch118st};
+
+/* char: 0x77 */
+
+static const Fl_Glut_StrokeVertex ch119st0[] =
+{
+ {14.2857f,66.6667f},
+ {33.3333f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch119st1[] =
+{
+ {52.3809f,66.6667f},
+ {33.3333f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch119st2[] =
+{
+ {52.3809f,66.6667f},
+ {71.4286f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch119st3[] =
+{
+ {90.4762f,66.6667f},
+ {71.4286f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch119st[] =
+{
+ {2,ch119st0},
+ {2,ch119st1},
+ {2,ch119st2},
+ {2,ch119st3}
+};
+
+static const Fl_Glut_StrokeChar ch119 = {104.762f,4,ch119st};
+
+/* char: 0x78 */
+
+static const Fl_Glut_StrokeVertex ch120st0[] =
+{
+ {26.1905f,66.6667f},
+ {78.5715f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch120st1[] =
+{
+ {78.5715f,66.6667f},
+ {26.1905f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch120st[] =
+{
+ {2,ch120st0},
+ {2,ch120st1}
+};
+
+static const Fl_Glut_StrokeChar ch120 = {104.762f,2,ch120st};
+
+/* char: 0x79 */
+
+static const Fl_Glut_StrokeVertex ch121st0[] =
+{
+ {26.1905f,66.6667f},
+ {54.7619f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch121st1[] =
+{
+ {83.3334f,66.6667f},
+ {54.7619f,0.0f},
+ {45.2381f,-19.0476f},
+ {35.7143f,-28.5714f},
+ {26.1905f,-33.3333f},
+ {21.4286f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeStrip ch121st[] =
+{
+ {2,ch121st0},
+ {6,ch121st1}
+};
+
+static const Fl_Glut_StrokeChar ch121 = {104.762f,2,ch121st};
+
+/* char: 0x7a */
+
+static const Fl_Glut_StrokeVertex ch122st0[] =
+{
+ {78.5715f,66.6667f},
+ {26.1905f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch122st1[] =
+{
+ {26.1905f,66.6667f},
+ {78.5715f,66.6667f}
+};
+
+static const Fl_Glut_StrokeVertex ch122st2[] =
+{
+ {26.1905f,0.0f},
+ {78.5715f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch122st[] =
+{
+ {2,ch122st0},
+ {2,ch122st1},
+ {2,ch122st2}
+};
+
+static const Fl_Glut_StrokeChar ch122 = {104.762f,3,ch122st};
+
+/* char: 0x7b */
+
+static const Fl_Glut_StrokeVertex ch123st0[] =
+{
+ {64.2857f,119.048f},
+ {54.7619f,114.286f},
+ {50.0f,109.524f},
+ {45.2381f,100.0f},
+ {45.2381f,90.4762f},
+ {50.0f,80.9524f},
+ {54.7619f,76.1905f},
+ {59.5238f,66.6667f},
+ {59.5238f,57.1429f},
+ {50.0f,47.619f}
+};
+
+static const Fl_Glut_StrokeVertex ch123st1[] =
+{
+ {54.7619f,114.286f},
+ {50.0f,104.762f},
+ {50.0f,95.2381f},
+ {54.7619f,85.7143f},
+ {59.5238f,80.9524f},
+ {64.2857f,71.4286f},
+ {64.2857f,61.9048f},
+ {59.5238f,52.381f},
+ {40.4762f,42.8571f},
+ {59.5238f,33.3333f},
+ {64.2857f,23.8095f},
+ {64.2857f,14.2857f},
+ {59.5238f,4.7619f},
+ {54.7619f,0.0f},
+ {50.0f,-9.5238f},
+ {50.0f,-19.0476f},
+ {54.7619f,-28.5714f}
+};
+
+static const Fl_Glut_StrokeVertex ch123st2[] =
+{
+ {50.0f,38.0952f},
+ {59.5238f,28.5714f},
+ {59.5238f,19.0476f},
+ {54.7619f,9.5238f},
+ {50.0f,4.7619f},
+ {45.2381f,-4.7619f},
+ {45.2381f,-14.2857f},
+ {50.0f,-23.8095f},
+ {54.7619f,-28.5714f},
+ {64.2857f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeStrip ch123st[] =
+{
+ {10,ch123st0},
+ {17,ch123st1},
+ {10,ch123st2}
+};
+
+static const Fl_Glut_StrokeChar ch123 = {104.762f,3,ch123st};
+
+/* char: 0x7c */
+
+static const Fl_Glut_StrokeVertex ch124st0[] =
+{
+ {52.381f,119.048f},
+ {52.381f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeStrip ch124st[] =
+{
+ {2,ch124st0}
+};
+
+static const Fl_Glut_StrokeChar ch124 = {104.762f,1,ch124st};
+
+/* char: 0x7d */
+
+static const Fl_Glut_StrokeVertex ch125st0[] =
+{
+ {40.4762f,119.048f},
+ {50.0f,114.286f},
+ {54.7619f,109.524f},
+ {59.5238f,100.0f},
+ {59.5238f,90.4762f},
+ {54.7619f,80.9524f},
+ {50.0f,76.1905f},
+ {45.2381f,66.6667f},
+ {45.2381f,57.1429f},
+ {54.7619f,47.619f}
+};
+
+static const Fl_Glut_StrokeVertex ch125st1[] =
+{
+ {50.0f,114.286f},
+ {54.7619f,104.762f},
+ {54.7619f,95.2381f},
+ {50.0f,85.7143f},
+ {45.2381f,80.9524f},
+ {40.4762f,71.4286f},
+ {40.4762f,61.9048f},
+ {45.2381f,52.381f},
+ {64.2857f,42.8571f},
+ {45.2381f,33.3333f},
+ {40.4762f,23.8095f},
+ {40.4762f,14.2857f},
+ {45.2381f,4.7619f},
+ {50.0f,0.0f},
+ {54.7619f,-9.5238f},
+ {54.7619f,-19.0476f},
+ {50.0f,-28.5714f}
+};
+
+static const Fl_Glut_StrokeVertex ch125st2[] =
+{
+ {54.7619f,38.0952f},
+ {45.2381f,28.5714f},
+ {45.2381f,19.0476f},
+ {50.0f,9.5238f},
+ {54.7619f,4.7619f},
+ {59.5238f,-4.7619f},
+ {59.5238f,-14.2857f},
+ {54.7619f,-23.8095f},
+ {50.0f,-28.5714f},
+ {40.4762f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeStrip ch125st[] =
+{
+ {10,ch125st0},
+ {17,ch125st1},
+ {10,ch125st2}
+};
+
+static const Fl_Glut_StrokeChar ch125 = {104.762f,3,ch125st};
+
+/* char: 0x7e */
+
+static const Fl_Glut_StrokeVertex ch126st0[] =
+{
+ {9.5238f,28.5714f},
+ {9.5238f,38.0952f},
+ {14.2857f,52.381f},
+ {23.8095f,57.1429f},
+ {33.3333f,57.1429f},
+ {42.8571f,52.381f},
+ {61.9048f,38.0952f},
+ {71.4286f,33.3333f},
+ {80.9524f,33.3333f},
+ {90.4762f,38.0952f},
+ {95.2381f,47.619f}
+};
+
+static const Fl_Glut_StrokeVertex ch126st1[] =
+{
+ {9.5238f,38.0952f},
+ {14.2857f,47.619f},
+ {23.8095f,52.381f},
+ {33.3333f,52.381f},
+ {42.8571f,47.619f},
+ {61.9048f,33.3333f},
+ {71.4286f,28.5714f},
+ {80.9524f,28.5714f},
+ {90.4762f,33.3333f},
+ {95.2381f,47.619f},
+ {95.2381f,57.1429f}
+};
+
+static const Fl_Glut_StrokeStrip ch126st[] =
+{
+ {11,ch126st0},
+ {11,ch126st1}
+};
+
+static const Fl_Glut_StrokeChar ch126 = {104.762f,2,ch126st};
+
+/* char: 0x7f */
+
+static const Fl_Glut_StrokeVertex ch127st0[] =
+{
+ {71.4286f,100.0f},
+ {33.3333f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeVertex ch127st1[] =
+{
+ {47.619f,66.6667f},
+ {33.3333f,61.9048f},
+ {23.8095f,52.381f},
+ {19.0476f,38.0952f},
+ {19.0476f,23.8095f},
+ {23.8095f,14.2857f},
+ {33.3333f,4.7619f},
+ {47.619f,0.0f},
+ {57.1428f,0.0f},
+ {71.4286f,4.7619f},
+ {80.9524f,14.2857f},
+ {85.7143f,28.5714f},
+ {85.7143f,42.8571f},
+ {80.9524f,52.381f},
+ {71.4286f,61.9048f},
+ {57.1428f,66.6667f},
+ {47.619f,66.6667f}
+};
+
+static const Fl_Glut_StrokeStrip ch127st[] =
+{
+ {2,ch127st0},
+ {17,ch127st1}
+};
+
+static const Fl_Glut_StrokeChar ch127 = {104.762f,2,ch127st};
+
+static const Fl_Glut_StrokeChar *chars[] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ &ch32, &ch33, &ch34, &ch35, &ch36, &ch37, &ch38, &ch39,
+ &ch40, &ch41, &ch42, &ch43, &ch44, &ch45, &ch46, &ch47,
+ &ch48, &ch49, &ch50, &ch51, &ch52, &ch53, &ch54, &ch55,
+ &ch56, &ch57, &ch58, &ch59, &ch60, &ch61, &ch62, &ch63,
+ &ch64, &ch65, &ch66, &ch67, &ch68, &ch69, &ch70, &ch71,
+ &ch72, &ch73, &ch74, &ch75, &ch76, &ch77, &ch78, &ch79,
+ &ch80, &ch81, &ch82, &ch83, &ch84, &ch85, &ch86, &ch87,
+ &ch88, &ch89, &ch90, &ch91, &ch92, &ch93, &ch94, &ch95,
+ &ch96, &ch97, &ch98, &ch99, &ch100, &ch101, &ch102, &ch103,
+ &ch104, &ch105, &ch106, &ch107, &ch108, &ch109, &ch110, &ch111,
+ &ch112, &ch113, &ch114, &ch115, &ch116, &ch117, &ch118, &ch119,
+ &ch120, &ch121, &ch122, &ch123, &ch124, &ch125, &ch126, &ch127
+};
+
+Fl_Glut_StrokeFont glutStrokeMonoRoman = {(char *)"MonoRoman",128,152.381f,chars};
diff --git a/third_party/windows/fltk-1.1.10/src/freeglut_stroke_roman.cxx b/third_party/windows/fltk-1.1.10/src/freeglut_stroke_roman.cxx new file mode 100644 index 0000000..1267637 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/freeglut_stroke_roman.cxx @@ -0,0 +1,2848 @@ +/*
+ * freeglut_stroke_roman.c
+ *
+ * freeglut Roman stroke font definition
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta@sourceforge.net>
+ * Creation date: Thu Dec 16 1999
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/* This file has been automatically generated by the genstroke utility. */
+
+#include <FL/glut.H>
+
+/* char: 0x20 */
+
+static const Fl_Glut_StrokeStrip ch32st[] =
+{
+ { 0, 0 }
+};
+
+static const Fl_Glut_StrokeChar ch32 = {104.762f,0,ch32st};
+
+/* char: 0x21 */
+
+static const Fl_Glut_StrokeVertex ch33st0[] =
+{
+ {13.3819f,100.0f},
+ {13.3819f,33.3333f}
+};
+
+static const Fl_Glut_StrokeVertex ch33st1[] =
+{
+ {13.3819f,9.5238f},
+ {8.62f,4.7619f},
+ {13.3819f,0.0f},
+ {18.1438f,4.7619f},
+ {13.3819f,9.5238f}
+};
+
+static const Fl_Glut_StrokeStrip ch33st[] =
+{
+ {2,ch33st0},
+ {5,ch33st1}
+};
+
+static const Fl_Glut_StrokeChar ch33 = {26.6238f,2,ch33st};
+
+/* char: 0x22 */
+
+static const Fl_Glut_StrokeVertex ch34st0[] =
+{
+ {4.02f,100.0f},
+ {4.02f,66.6667f}
+};
+
+static const Fl_Glut_StrokeVertex ch34st1[] =
+{
+ {42.1152f,100.0f},
+ {42.1152f,66.6667f}
+};
+
+static const Fl_Glut_StrokeStrip ch34st[] =
+{
+ {2,ch34st0},
+ {2,ch34st1}
+};
+
+static const Fl_Glut_StrokeChar ch34 = {51.4352f,2,ch34st};
+
+/* char: 0x23 */
+
+static const Fl_Glut_StrokeVertex ch35st0[] =
+{
+ {41.2952f,119.048f},
+ {7.9619f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeVertex ch35st1[] =
+{
+ {69.8667f,119.048f},
+ {36.5333f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeVertex ch35st2[] =
+{
+ {7.9619f,57.1429f},
+ {74.6286f,57.1429f}
+};
+
+static const Fl_Glut_StrokeVertex ch35st3[] =
+{
+ {3.2f,28.5714f},
+ {69.8667f,28.5714f}
+};
+
+static const Fl_Glut_StrokeStrip ch35st[] =
+{
+ {2,ch35st0},
+ {2,ch35st1},
+ {2,ch35st2},
+ {2,ch35st3}
+};
+
+static const Fl_Glut_StrokeChar ch35 = {79.4886f,4,ch35st};
+
+/* char: 0x24 */
+
+static const Fl_Glut_StrokeVertex ch36st0[] =
+{
+ {28.6295f,119.048f},
+ {28.6295f,-19.0476f}
+};
+
+static const Fl_Glut_StrokeVertex ch36st1[] =
+{
+ {47.6771f,119.048f},
+ {47.6771f,-19.0476f}
+};
+
+static const Fl_Glut_StrokeVertex ch36st2[] =
+{
+ {71.4867f,85.7143f},
+ {61.9629f,95.2381f},
+ {47.6771f,100.0f},
+ {28.6295f,100.0f},
+ {14.3438f,95.2381f},
+ {4.82f,85.7143f},
+ {4.82f,76.1905f},
+ {9.5819f,66.6667f},
+ {14.3438f,61.9048f},
+ {23.8676f,57.1429f},
+ {52.439f,47.619f},
+ {61.9629f,42.8571f},
+ {66.7248f,38.0952f},
+ {71.4867f,28.5714f},
+ {71.4867f,14.2857f},
+ {61.9629f,4.7619f},
+ {47.6771f,0.0f},
+ {28.6295f,0.0f},
+ {14.3438f,4.7619f},
+ {4.82f,14.2857f}
+};
+
+static const Fl_Glut_StrokeStrip ch36st[] =
+{
+ {2,ch36st0},
+ {2,ch36st1},
+ {20,ch36st2}
+};
+
+static const Fl_Glut_StrokeChar ch36 = {76.2067f,3,ch36st};
+
+/* char: 0x25 */
+
+static const Fl_Glut_StrokeVertex ch37st0[] =
+{
+ {92.0743f,100.0f},
+ {6.36f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch37st1[] =
+{
+ {30.1695f,100.0f},
+ {39.6933f,90.4762f},
+ {39.6933f,80.9524f},
+ {34.9314f,71.4286f},
+ {25.4076f,66.6667f},
+ {15.8838f,66.6667f},
+ {6.36f,76.1905f},
+ {6.36f,85.7143f},
+ {11.1219f,95.2381f},
+ {20.6457f,100.0f},
+ {30.1695f,100.0f},
+ {39.6933f,95.2381f},
+ {53.979f,90.4762f},
+ {68.2648f,90.4762f},
+ {82.5505f,95.2381f},
+ {92.0743f,100.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch37st2[] =
+{
+ {73.0267f,33.3333f},
+ {63.5029f,28.5714f},
+ {58.741f,19.0476f},
+ {58.741f,9.5238f},
+ {68.2648f,0.0f},
+ {77.7886f,0.0f},
+ {87.3124f,4.7619f},
+ {92.0743f,14.2857f},
+ {92.0743f,23.8095f},
+ {82.5505f,33.3333f},
+ {73.0267f,33.3333f}
+};
+
+static const Fl_Glut_StrokeStrip ch37st[] =
+{
+ {2,ch37st0},
+ {16,ch37st1},
+ {11,ch37st2}
+};
+
+static const Fl_Glut_StrokeChar ch37 = {96.5743f,3,ch37st};
+
+/* char: 0x26 */
+
+static const Fl_Glut_StrokeVertex ch38st0[] =
+{
+ {101.218f,57.1429f},
+ {101.218f,61.9048f},
+ {96.4562f,66.6667f},
+ {91.6943f,66.6667f},
+ {86.9324f,61.9048f},
+ {82.1705f,52.381f},
+ {72.6467f,28.5714f},
+ {63.1229f,14.2857f},
+ {53.599f,4.7619f},
+ {44.0752f,0.0f},
+ {25.0276f,0.0f},
+ {15.5038f,4.7619f},
+ {10.7419f,9.5238f},
+ {5.98f,19.0476f},
+ {5.98f,28.5714f},
+ {10.7419f,38.0952f},
+ {15.5038f,42.8571f},
+ {48.8371f,61.9048f},
+ {53.599f,66.6667f},
+ {58.361f,76.1905f},
+ {58.361f,85.7143f},
+ {53.599f,95.2381f},
+ {44.0752f,100.0f},
+ {34.5514f,95.2381f},
+ {29.7895f,85.7143f},
+ {29.7895f,76.1905f},
+ {34.5514f,61.9048f},
+ {44.0752f,47.619f},
+ {67.8848f,14.2857f},
+ {77.4086f,4.7619f},
+ {86.9324f,0.0f},
+ {96.4562f,0.0f},
+ {101.218f,4.7619f},
+ {101.218f,9.5238f}
+};
+
+static const Fl_Glut_StrokeStrip ch38st[] =
+{
+ {34,ch38st0}
+};
+
+static const Fl_Glut_StrokeChar ch38 = {101.758f,1,ch38st};
+
+/* char: 0x27 */
+
+static const Fl_Glut_StrokeVertex ch39st0[] =
+{
+ {4.44f,100.0f},
+ {4.44f,66.6667f}
+};
+
+static const Fl_Glut_StrokeStrip ch39st[] =
+{
+ {2,ch39st0}
+};
+
+static const Fl_Glut_StrokeChar ch39 = {13.62f,1,ch39st};
+
+/* char: 0x28 */
+
+static const Fl_Glut_StrokeVertex ch40st0[] =
+{
+ {40.9133f,119.048f},
+ {31.3895f,109.524f},
+ {21.8657f,95.2381f},
+ {12.3419f,76.1905f},
+ {7.58f,52.381f},
+ {7.58f,33.3333f},
+ {12.3419f,9.5238f},
+ {21.8657f,-9.5238f},
+ {31.3895f,-23.8095f},
+ {40.9133f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeStrip ch40st[] =
+{
+ {10,ch40st0}
+};
+
+static const Fl_Glut_StrokeChar ch40 = {47.1733f,1,ch40st};
+
+/* char: 0x29 */
+
+static const Fl_Glut_StrokeVertex ch41st0[] =
+{
+ {5.28f,119.048f},
+ {14.8038f,109.524f},
+ {24.3276f,95.2381f},
+ {33.8514f,76.1905f},
+ {38.6133f,52.381f},
+ {38.6133f,33.3333f},
+ {33.8514f,9.5238f},
+ {24.3276f,-9.5238f},
+ {14.8038f,-23.8095f},
+ {5.28f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeStrip ch41st[] =
+{
+ {10,ch41st0}
+};
+
+static const Fl_Glut_StrokeChar ch41 = {47.5333f,1,ch41st};
+
+/* char: 0x2a */
+
+static const Fl_Glut_StrokeVertex ch42st0[] =
+{
+ {30.7695f,71.4286f},
+ {30.7695f,14.2857f}
+};
+
+static const Fl_Glut_StrokeVertex ch42st1[] =
+{
+ {6.96f,57.1429f},
+ {54.579f,28.5714f}
+};
+
+static const Fl_Glut_StrokeVertex ch42st2[] =
+{
+ {54.579f,57.1429f},
+ {6.96f,28.5714f}
+};
+
+static const Fl_Glut_StrokeStrip ch42st[] =
+{
+ {2,ch42st0},
+ {2,ch42st1},
+ {2,ch42st2}
+};
+
+static const Fl_Glut_StrokeChar ch42 = {59.439f,3,ch42st};
+
+/* char: 0x2b */
+
+static const Fl_Glut_StrokeVertex ch43st0[] =
+{
+ {48.8371f,85.7143f},
+ {48.8371f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch43st1[] =
+{
+ {5.98f,42.8571f},
+ {91.6943f,42.8571f}
+};
+
+static const Fl_Glut_StrokeStrip ch43st[] =
+{
+ {2,ch43st0},
+ {2,ch43st1}
+};
+
+static const Fl_Glut_StrokeChar ch43 = {97.2543f,2,ch43st};
+
+/* char: 0x2c */
+
+static const Fl_Glut_StrokeVertex ch44st0[] =
+{
+ {18.2838f,4.7619f},
+ {13.5219f,0.0f},
+ {8.76f,4.7619f},
+ {13.5219f,9.5238f},
+ {18.2838f,4.7619f},
+ {18.2838f,-4.7619f},
+ {13.5219f,-14.2857f},
+ {8.76f,-19.0476f}
+};
+
+static const Fl_Glut_StrokeStrip ch44st[] =
+{
+ {8,ch44st0}
+};
+
+static const Fl_Glut_StrokeChar ch44 = {26.0638f,1,ch44st};
+
+/* char: 0x2d */
+
+static const Fl_Glut_StrokeVertex ch45st0[] =
+{
+ {7.38f,42.8571f},
+ {93.0943f,42.8571f}
+};
+
+static const Fl_Glut_StrokeStrip ch45st[] =
+{
+ {2,ch45st0}
+};
+
+static const Fl_Glut_StrokeChar ch45 = {100.754f,1,ch45st};
+
+/* char: 0x2e */
+
+static const Fl_Glut_StrokeVertex ch46st0[] =
+{
+ {13.1019f,9.5238f},
+ {8.34f,4.7619f},
+ {13.1019f,0.0f},
+ {17.8638f,4.7619f},
+ {13.1019f,9.5238f}
+};
+
+static const Fl_Glut_StrokeStrip ch46st[] =
+{
+ {5,ch46st0}
+};
+
+static const Fl_Glut_StrokeChar ch46 = {26.4838f,1,ch46st};
+
+/* char: 0x2f */
+
+static const Fl_Glut_StrokeVertex ch47st0[] =
+{
+ {7.24f,-14.2857f},
+ {73.9067f,100.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch47st[] =
+{
+ {2,ch47st0}
+};
+
+static const Fl_Glut_StrokeChar ch47 = {82.1067f,1,ch47st};
+
+/* char: 0x30 */
+
+static const Fl_Glut_StrokeVertex ch48st0[] =
+{
+ {33.5514f,100.0f},
+ {19.2657f,95.2381f},
+ {9.7419f,80.9524f},
+ {4.98f,57.1429f},
+ {4.98f,42.8571f},
+ {9.7419f,19.0476f},
+ {19.2657f,4.7619f},
+ {33.5514f,0.0f},
+ {43.0752f,0.0f},
+ {57.361f,4.7619f},
+ {66.8848f,19.0476f},
+ {71.6467f,42.8571f},
+ {71.6467f,57.1429f},
+ {66.8848f,80.9524f},
+ {57.361f,95.2381f},
+ {43.0752f,100.0f},
+ {33.5514f,100.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch48st[] =
+{
+ {17,ch48st0}
+};
+
+static const Fl_Glut_StrokeChar ch48 = {77.0667f,1,ch48st};
+
+/* char: 0x31 */
+
+static const Fl_Glut_StrokeVertex ch49st0[] =
+{
+ {11.82f,80.9524f},
+ {21.3438f,85.7143f},
+ {35.6295f,100.0f},
+ {35.6295f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch49st[] =
+{
+ {4,ch49st0}
+};
+
+static const Fl_Glut_StrokeChar ch49 = {66.5295f,1,ch49st};
+
+/* char: 0x32 */
+
+static const Fl_Glut_StrokeVertex ch50st0[] =
+{
+ {10.1819f,76.1905f},
+ {10.1819f,80.9524f},
+ {14.9438f,90.4762f},
+ {19.7057f,95.2381f},
+ {29.2295f,100.0f},
+ {48.2771f,100.0f},
+ {57.801f,95.2381f},
+ {62.5629f,90.4762f},
+ {67.3248f,80.9524f},
+ {67.3248f,71.4286f},
+ {62.5629f,61.9048f},
+ {53.039f,47.619f},
+ {5.42f,0.0f},
+ {72.0867f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch50st[] =
+{
+ {14,ch50st0}
+};
+
+static const Fl_Glut_StrokeChar ch50 = {77.6467f,1,ch50st};
+
+/* char: 0x33 */
+
+static const Fl_Glut_StrokeVertex ch51st0[] =
+{
+ {14.5238f,100.0f},
+ {66.9048f,100.0f},
+ {38.3333f,61.9048f},
+ {52.619f,61.9048f},
+ {62.1429f,57.1429f},
+ {66.9048f,52.381f},
+ {71.6667f,38.0952f},
+ {71.6667f,28.5714f},
+ {66.9048f,14.2857f},
+ {57.381f,4.7619f},
+ {43.0952f,0.0f},
+ {28.8095f,0.0f},
+ {14.5238f,4.7619f},
+ {9.7619f,9.5238f},
+ {5.0f,19.0476f}
+};
+
+static const Fl_Glut_StrokeStrip ch51st[] =
+{
+ {15,ch51st0}
+};
+
+static const Fl_Glut_StrokeChar ch51 = {77.0467f,1,ch51st};
+
+/* char: 0x34 */
+
+static const Fl_Glut_StrokeVertex ch52st0[] =
+{
+ {51.499f,100.0f},
+ {3.88f,33.3333f},
+ {75.3086f,33.3333f}
+};
+
+static const Fl_Glut_StrokeVertex ch52st1[] =
+{
+ {51.499f,100.0f},
+ {51.499f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch52st[] =
+{
+ {3,ch52st0},
+ {2,ch52st1}
+};
+
+static const Fl_Glut_StrokeChar ch52 = {80.1686f,2,ch52st};
+
+/* char: 0x35 */
+
+static const Fl_Glut_StrokeVertex ch53st0[] =
+{
+ {62.0029f,100.0f},
+ {14.3838f,100.0f},
+ {9.6219f,57.1429f},
+ {14.3838f,61.9048f},
+ {28.6695f,66.6667f},
+ {42.9552f,66.6667f},
+ {57.241f,61.9048f},
+ {66.7648f,52.381f},
+ {71.5267f,38.0952f},
+ {71.5267f,28.5714f},
+ {66.7648f,14.2857f},
+ {57.241f,4.7619f},
+ {42.9552f,0.0f},
+ {28.6695f,0.0f},
+ {14.3838f,4.7619f},
+ {9.6219f,9.5238f},
+ {4.86f,19.0476f}
+};
+
+static const Fl_Glut_StrokeStrip ch53st[] =
+{
+ {17,ch53st0}
+};
+
+static const Fl_Glut_StrokeChar ch53 = {77.6867f,1,ch53st};
+
+/* char: 0x36 */
+
+static const Fl_Glut_StrokeVertex ch54st0[] =
+{
+ {62.7229f,85.7143f},
+ {57.961f,95.2381f},
+ {43.6752f,100.0f},
+ {34.1514f,100.0f},
+ {19.8657f,95.2381f},
+ {10.3419f,80.9524f},
+ {5.58f,57.1429f},
+ {5.58f,33.3333f},
+ {10.3419f,14.2857f},
+ {19.8657f,4.7619f},
+ {34.1514f,0.0f},
+ {38.9133f,0.0f},
+ {53.199f,4.7619f},
+ {62.7229f,14.2857f},
+ {67.4848f,28.5714f},
+ {67.4848f,33.3333f},
+ {62.7229f,47.619f},
+ {53.199f,57.1429f},
+ {38.9133f,61.9048f},
+ {34.1514f,61.9048f},
+ {19.8657f,57.1429f},
+ {10.3419f,47.619f},
+ {5.58f,33.3333f}
+};
+
+static const Fl_Glut_StrokeStrip ch54st[] =
+{
+ {23,ch54st0}
+};
+
+static const Fl_Glut_StrokeChar ch54 = {73.8048f,1,ch54st};
+
+/* char: 0x37 */
+
+static const Fl_Glut_StrokeVertex ch55st0[] =
+{
+ {72.2267f,100.0f},
+ {24.6076f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch55st1[] =
+{
+ {5.56f,100.0f},
+ {72.2267f,100.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch55st[] =
+{
+ {2,ch55st0},
+ {2,ch55st1}
+};
+
+static const Fl_Glut_StrokeChar ch55 = {77.2267f,2,ch55st};
+
+/* char: 0x38 */
+
+static const Fl_Glut_StrokeVertex ch56st0[] =
+{
+ {29.4095f,100.0f},
+ {15.1238f,95.2381f},
+ {10.3619f,85.7143f},
+ {10.3619f,76.1905f},
+ {15.1238f,66.6667f},
+ {24.6476f,61.9048f},
+ {43.6952f,57.1429f},
+ {57.981f,52.381f},
+ {67.5048f,42.8571f},
+ {72.2667f,33.3333f},
+ {72.2667f,19.0476f},
+ {67.5048f,9.5238f},
+ {62.7429f,4.7619f},
+ {48.4571f,0.0f},
+ {29.4095f,0.0f},
+ {15.1238f,4.7619f},
+ {10.3619f,9.5238f},
+ {5.6f,19.0476f},
+ {5.6f,33.3333f},
+ {10.3619f,42.8571f},
+ {19.8857f,52.381f},
+ {34.1714f,57.1429f},
+ {53.219f,61.9048f},
+ {62.7429f,66.6667f},
+ {67.5048f,76.1905f},
+ {67.5048f,85.7143f},
+ {62.7429f,95.2381f},
+ {48.4571f,100.0f},
+ {29.4095f,100.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch56st[] =
+{
+ {29,ch56st0}
+};
+
+static const Fl_Glut_StrokeChar ch56 = {77.6667f,1,ch56st};
+
+/* char: 0x39 */
+
+static const Fl_Glut_StrokeVertex ch57st0[] =
+{
+ {68.5048f,66.6667f},
+ {63.7429f,52.381f},
+ {54.219f,42.8571f},
+ {39.9333f,38.0952f},
+ {35.1714f,38.0952f},
+ {20.8857f,42.8571f},
+ {11.3619f,52.381f},
+ {6.6f,66.6667f},
+ {6.6f,71.4286f},
+ {11.3619f,85.7143f},
+ {20.8857f,95.2381f},
+ {35.1714f,100.0f},
+ {39.9333f,100.0f},
+ {54.219f,95.2381f},
+ {63.7429f,85.7143f},
+ {68.5048f,66.6667f},
+ {68.5048f,42.8571f},
+ {63.7429f,19.0476f},
+ {54.219f,4.7619f},
+ {39.9333f,0.0f},
+ {30.4095f,0.0f},
+ {16.1238f,4.7619f},
+ {11.3619f,14.2857f}
+};
+
+static const Fl_Glut_StrokeStrip ch57st[] =
+{
+ {23,ch57st0}
+};
+
+static const Fl_Glut_StrokeChar ch57 = {74.0648f,1,ch57st};
+
+/* char: 0x3a */
+
+static const Fl_Glut_StrokeVertex ch58st0[] =
+{
+ {14.0819f,66.6667f},
+ {9.32f,61.9048f},
+ {14.0819f,57.1429f},
+ {18.8438f,61.9048f},
+ {14.0819f,66.6667f}
+};
+
+static const Fl_Glut_StrokeVertex ch58st1[] =
+{
+ {14.0819f,9.5238f},
+ {9.32f,4.7619f},
+ {14.0819f,0.0f},
+ {18.8438f,4.7619f},
+ {14.0819f,9.5238f}
+};
+
+static const Fl_Glut_StrokeStrip ch58st[] =
+{
+ {5,ch58st0},
+ {5,ch58st1}
+};
+
+static const Fl_Glut_StrokeChar ch58 = {26.2238f,2,ch58st};
+
+/* char: 0x3b */
+
+static const Fl_Glut_StrokeVertex ch59st0[] =
+{
+ {12.9619f,66.6667f},
+ {8.2f,61.9048f},
+ {12.9619f,57.1429f},
+ {17.7238f,61.9048f},
+ {12.9619f,66.6667f}
+};
+
+static const Fl_Glut_StrokeVertex ch59st1[] =
+{
+ {17.7238f,4.7619f},
+ {12.9619f,0.0f},
+ {8.2f,4.7619f},
+ {12.9619f,9.5238f},
+ {17.7238f,4.7619f},
+ {17.7238f,-4.7619f},
+ {12.9619f,-14.2857f},
+ {8.2f,-19.0476f}
+};
+
+static const Fl_Glut_StrokeStrip ch59st[] =
+{
+ {5,ch59st0},
+ {8,ch59st1}
+};
+
+static const Fl_Glut_StrokeChar ch59 = {26.3038f,2,ch59st};
+
+/* char: 0x3c */
+
+static const Fl_Glut_StrokeVertex ch60st0[] =
+{
+ {79.2505f,85.7143f},
+ {3.06f,42.8571f},
+ {79.2505f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch60st[] =
+{
+ {3,ch60st0}
+};
+
+static const Fl_Glut_StrokeChar ch60 = {81.6105f,1,ch60st};
+
+/* char: 0x3d */
+
+static const Fl_Glut_StrokeVertex ch61st0[] =
+{
+ {5.7f,57.1429f},
+ {91.4143f,57.1429f}
+};
+
+static const Fl_Glut_StrokeVertex ch61st1[] =
+{
+ {5.7f,28.5714f},
+ {91.4143f,28.5714f}
+};
+
+static const Fl_Glut_StrokeStrip ch61st[] =
+{
+ {2,ch61st0},
+ {2,ch61st1}
+};
+
+static const Fl_Glut_StrokeChar ch61 = {97.2543f,2,ch61st};
+
+/* char: 0x3e */
+
+static const Fl_Glut_StrokeVertex ch62st0[] =
+{
+ {2.78f,85.7143f},
+ {78.9705f,42.8571f},
+ {2.78f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch62st[] =
+{
+ {3,ch62st0}
+};
+
+static const Fl_Glut_StrokeChar ch62 = {81.6105f,1,ch62st};
+
+/* char: 0x3f */
+
+static const Fl_Glut_StrokeVertex ch63st0[] =
+{
+ {8.42f,76.1905f},
+ {8.42f,80.9524f},
+ {13.1819f,90.4762f},
+ {17.9438f,95.2381f},
+ {27.4676f,100.0f},
+ {46.5152f,100.0f},
+ {56.039f,95.2381f},
+ {60.801f,90.4762f},
+ {65.5629f,80.9524f},
+ {65.5629f,71.4286f},
+ {60.801f,61.9048f},
+ {56.039f,57.1429f},
+ {36.9914f,47.619f},
+ {36.9914f,33.3333f}
+};
+
+static const Fl_Glut_StrokeVertex ch63st1[] =
+{
+ {36.9914f,9.5238f},
+ {32.2295f,4.7619f},
+ {36.9914f,0.0f},
+ {41.7533f,4.7619f},
+ {36.9914f,9.5238f}
+};
+
+static const Fl_Glut_StrokeStrip ch63st[] =
+{
+ {14,ch63st0},
+ {5,ch63st1}
+};
+
+static const Fl_Glut_StrokeChar ch63 = {73.9029f,2,ch63st};
+
+/* char: 0x40 */
+
+static const Fl_Glut_StrokeVertex ch64st0[] =
+{
+ {49.2171f,52.381f},
+ {39.6933f,57.1429f},
+ {30.1695f,57.1429f},
+ {25.4076f,47.619f},
+ {25.4076f,42.8571f},
+ {30.1695f,33.3333f},
+ {39.6933f,33.3333f},
+ {49.2171f,38.0952f}
+};
+
+static const Fl_Glut_StrokeVertex ch64st1[] =
+{
+ {49.2171f,57.1429f},
+ {49.2171f,38.0952f},
+ {53.979f,33.3333f},
+ {63.5029f,33.3333f},
+ {68.2648f,42.8571f},
+ {68.2648f,47.619f},
+ {63.5029f,61.9048f},
+ {53.979f,71.4286f},
+ {39.6933f,76.1905f},
+ {34.9314f,76.1905f},
+ {20.6457f,71.4286f},
+ {11.1219f,61.9048f},
+ {6.36f,47.619f},
+ {6.36f,42.8571f},
+ {11.1219f,28.5714f},
+ {20.6457f,19.0476f},
+ {34.9314f,14.2857f},
+ {39.6933f,14.2857f},
+ {53.979f,19.0476f}
+};
+
+static const Fl_Glut_StrokeStrip ch64st[] =
+{
+ {8,ch64st0},
+ {19,ch64st1}
+};
+
+static const Fl_Glut_StrokeChar ch64 = {74.3648f,2,ch64st};
+
+/* char: 0x41 */
+
+static const Fl_Glut_StrokeVertex ch65st0[] =
+{
+ {40.5952f,100.0f},
+ {2.5f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch65st1[] =
+{
+ {40.5952f,100.0f},
+ {78.6905f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch65st2[] =
+{
+ {16.7857f,33.3333f},
+ {64.4048f,33.3333f}
+};
+
+static const Fl_Glut_StrokeStrip ch65st[] =
+{
+ {2,ch65st0},
+ {2,ch65st1},
+ {2,ch65st2}
+};
+
+static const Fl_Glut_StrokeChar ch65 = {80.4905f,3,ch65st};
+
+/* char: 0x42 */
+
+static const Fl_Glut_StrokeVertex ch66st0[] =
+{
+ {11.42f,100.0f},
+ {11.42f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch66st1[] =
+{
+ {11.42f,100.0f},
+ {54.2771f,100.0f},
+ {68.5629f,95.2381f},
+ {73.3248f,90.4762f},
+ {78.0867f,80.9524f},
+ {78.0867f,71.4286f},
+ {73.3248f,61.9048f},
+ {68.5629f,57.1429f},
+ {54.2771f,52.381f}
+};
+
+static const Fl_Glut_StrokeVertex ch66st2[] =
+{
+ {11.42f,52.381f},
+ {54.2771f,52.381f},
+ {68.5629f,47.619f},
+ {73.3248f,42.8571f},
+ {78.0867f,33.3333f},
+ {78.0867f,19.0476f},
+ {73.3248f,9.5238f},
+ {68.5629f,4.7619f},
+ {54.2771f,0.0f},
+ {11.42f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch66st[] =
+{
+ {2,ch66st0},
+ {9,ch66st1},
+ {10,ch66st2}
+};
+
+static const Fl_Glut_StrokeChar ch66 = {83.6267f,3,ch66st};
+
+/* char: 0x43 */
+
+static const Fl_Glut_StrokeVertex ch67st0[] =
+{
+ {78.0886f,76.1905f},
+ {73.3267f,85.7143f},
+ {63.8029f,95.2381f},
+ {54.279f,100.0f},
+ {35.2314f,100.0f},
+ {25.7076f,95.2381f},
+ {16.1838f,85.7143f},
+ {11.4219f,76.1905f},
+ {6.66f,61.9048f},
+ {6.66f,38.0952f},
+ {11.4219f,23.8095f},
+ {16.1838f,14.2857f},
+ {25.7076f,4.7619f},
+ {35.2314f,0.0f},
+ {54.279f,0.0f},
+ {63.8029f,4.7619f},
+ {73.3267f,14.2857f},
+ {78.0886f,23.8095f}
+};
+
+static const Fl_Glut_StrokeStrip ch67st[] =
+{
+ {18,ch67st0}
+};
+
+static const Fl_Glut_StrokeChar ch67 = {84.4886f,1,ch67st};
+
+/* char: 0x44 */
+
+static const Fl_Glut_StrokeVertex ch68st0[] =
+{
+ {11.96f,100.0f},
+ {11.96f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch68st1[] =
+{
+ {11.96f,100.0f},
+ {45.2933f,100.0f},
+ {59.579f,95.2381f},
+ {69.1029f,85.7143f},
+ {73.8648f,76.1905f},
+ {78.6267f,61.9048f},
+ {78.6267f,38.0952f},
+ {73.8648f,23.8095f},
+ {69.1029f,14.2857f},
+ {59.579f,4.7619f},
+ {45.2933f,0.0f},
+ {11.96f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch68st[] =
+{
+ {2,ch68st0},
+ {12,ch68st1}
+};
+
+static const Fl_Glut_StrokeChar ch68 = {85.2867f,2,ch68st};
+
+/* char: 0x45 */
+
+static const Fl_Glut_StrokeVertex ch69st0[] =
+{
+ {11.42f,100.0f},
+ {11.42f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch69st1[] =
+{
+ {11.42f,100.0f},
+ {73.3248f,100.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch69st2[] =
+{
+ {11.42f,52.381f},
+ {49.5152f,52.381f}
+};
+
+static const Fl_Glut_StrokeVertex ch69st3[] =
+{
+ {11.42f,0.0f},
+ {73.3248f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch69st[] =
+{
+ {2,ch69st0},
+ {2,ch69st1},
+ {2,ch69st2},
+ {2,ch69st3}
+};
+
+static const Fl_Glut_StrokeChar ch69 = {78.1848f,4,ch69st};
+
+/* char: 0x46 */
+
+static const Fl_Glut_StrokeVertex ch70st0[] =
+{
+ {11.42f,100.0f},
+ {11.42f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch70st1[] =
+{
+ {11.42f,100.0f},
+ {73.3248f,100.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch70st2[] =
+{
+ {11.42f,52.381f},
+ {49.5152f,52.381f}
+};
+
+static const Fl_Glut_StrokeStrip ch70st[] =
+{
+ {2,ch70st0},
+ {2,ch70st1},
+ {2,ch70st2}
+};
+
+static const Fl_Glut_StrokeChar ch70 = {78.7448f,3,ch70st};
+
+/* char: 0x47 */
+
+static const Fl_Glut_StrokeVertex ch71st0[] =
+{
+ {78.4886f,76.1905f},
+ {73.7267f,85.7143f},
+ {64.2029f,95.2381f},
+ {54.679f,100.0f},
+ {35.6314f,100.0f},
+ {26.1076f,95.2381f},
+ {16.5838f,85.7143f},
+ {11.8219f,76.1905f},
+ {7.06f,61.9048f},
+ {7.06f,38.0952f},
+ {11.8219f,23.8095f},
+ {16.5838f,14.2857f},
+ {26.1076f,4.7619f},
+ {35.6314f,0.0f},
+ {54.679f,0.0f},
+ {64.2029f,4.7619f},
+ {73.7267f,14.2857f},
+ {78.4886f,23.8095f},
+ {78.4886f,38.0952f}
+};
+
+static const Fl_Glut_StrokeVertex ch71st1[] =
+{
+ {54.679f,38.0952f},
+ {78.4886f,38.0952f}
+};
+
+static const Fl_Glut_StrokeStrip ch71st[] =
+{
+ {19,ch71st0},
+ {2,ch71st1}
+};
+
+static const Fl_Glut_StrokeChar ch71 = {89.7686f,2,ch71st};
+
+/* char: 0x48 */
+
+static const Fl_Glut_StrokeVertex ch72st0[] =
+{
+ {11.42f,100.0f},
+ {11.42f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch72st1[] =
+{
+ {78.0867f,100.0f},
+ {78.0867f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch72st2[] =
+{
+ {11.42f,52.381f},
+ {78.0867f,52.381f}
+};
+
+static const Fl_Glut_StrokeStrip ch72st[] =
+{
+ {2,ch72st0},
+ {2,ch72st1},
+ {2,ch72st2}
+};
+
+static const Fl_Glut_StrokeChar ch72 = {89.0867f,3,ch72st};
+
+/* char: 0x49 */
+
+static const Fl_Glut_StrokeVertex ch73st0[] =
+{
+ {10.86f,100.0f},
+ {10.86f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch73st[] =
+{
+ {2,ch73st0}
+};
+
+static const Fl_Glut_StrokeChar ch73 = {21.3f,1,ch73st};
+
+/* char: 0x4a */
+
+static const Fl_Glut_StrokeVertex ch74st0[] =
+{
+ {50.119f,100.0f},
+ {50.119f,23.8095f},
+ {45.3571f,9.5238f},
+ {40.5952f,4.7619f},
+ {31.0714f,0.0f},
+ {21.5476f,0.0f},
+ {12.0238f,4.7619f},
+ {7.2619f,9.5238f},
+ {2.5f,23.8095f},
+ {2.5f,33.3333f}
+};
+
+static const Fl_Glut_StrokeStrip ch74st[] =
+{
+ {10,ch74st0}
+};
+
+static const Fl_Glut_StrokeChar ch74 = {59.999f,1,ch74st};
+
+/* char: 0x4b */
+
+static const Fl_Glut_StrokeVertex ch75st0[] =
+{
+ {11.28f,100.0f},
+ {11.28f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch75st1[] =
+{
+ {77.9467f,100.0f},
+ {11.28f,33.3333f}
+};
+
+static const Fl_Glut_StrokeVertex ch75st2[] =
+{
+ {35.0895f,57.1429f},
+ {77.9467f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch75st[] =
+{
+ {2,ch75st0},
+ {2,ch75st1},
+ {2,ch75st2}
+};
+
+static const Fl_Glut_StrokeChar ch75 = {79.3267f,3,ch75st};
+
+/* char: 0x4c */
+
+static const Fl_Glut_StrokeVertex ch76st0[] =
+{
+ {11.68f,100.0f},
+ {11.68f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch76st1[] =
+{
+ {11.68f,0.0f},
+ {68.8229f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch76st[] =
+{
+ {2,ch76st0},
+ {2,ch76st1}
+};
+
+static const Fl_Glut_StrokeChar ch76 = {71.3229f,2,ch76st};
+
+/* char: 0x4d */
+
+static const Fl_Glut_StrokeVertex ch77st0[] =
+{
+ {10.86f,100.0f},
+ {10.86f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch77st1[] =
+{
+ {10.86f,100.0f},
+ {48.9552f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch77st2[] =
+{
+ {87.0505f,100.0f},
+ {48.9552f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch77st3[] =
+{
+ {87.0505f,100.0f},
+ {87.0505f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch77st[] =
+{
+ {2,ch77st0},
+ {2,ch77st1},
+ {2,ch77st2},
+ {2,ch77st3}
+};
+
+static const Fl_Glut_StrokeChar ch77 = {97.2105f,4,ch77st};
+
+/* char: 0x4e */
+
+static const Fl_Glut_StrokeVertex ch78st0[] =
+{
+ {11.14f,100.0f},
+ {11.14f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch78st1[] =
+{
+ {11.14f,100.0f},
+ {77.8067f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch78st2[] =
+{
+ {77.8067f,100.0f},
+ {77.8067f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch78st[] =
+{
+ {2,ch78st0},
+ {2,ch78st1},
+ {2,ch78st2}
+};
+
+static const Fl_Glut_StrokeChar ch78 = {88.8067f,3,ch78st};
+
+/* char: 0x4f */
+
+static const Fl_Glut_StrokeVertex ch79st0[] =
+{
+ {34.8114f,100.0f},
+ {25.2876f,95.2381f},
+ {15.7638f,85.7143f},
+ {11.0019f,76.1905f},
+ {6.24f,61.9048f},
+ {6.24f,38.0952f},
+ {11.0019f,23.8095f},
+ {15.7638f,14.2857f},
+ {25.2876f,4.7619f},
+ {34.8114f,0.0f},
+ {53.859f,0.0f},
+ {63.3829f,4.7619f},
+ {72.9067f,14.2857f},
+ {77.6686f,23.8095f},
+ {82.4305f,38.0952f},
+ {82.4305f,61.9048f},
+ {77.6686f,76.1905f},
+ {72.9067f,85.7143f},
+ {63.3829f,95.2381f},
+ {53.859f,100.0f},
+ {34.8114f,100.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch79st[] =
+{
+ {21,ch79st0}
+};
+
+static const Fl_Glut_StrokeChar ch79 = {88.8305f,1,ch79st};
+
+/* char: 0x50 */
+
+static const Fl_Glut_StrokeVertex ch80st0[] =
+{
+ {12.1f,100.0f},
+ {12.1f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch80st1[] =
+{
+ {12.1f,100.0f},
+ {54.9571f,100.0f},
+ {69.2429f,95.2381f},
+ {74.0048f,90.4762f},
+ {78.7667f,80.9524f},
+ {78.7667f,66.6667f},
+ {74.0048f,57.1429f},
+ {69.2429f,52.381f},
+ {54.9571f,47.619f},
+ {12.1f,47.619f}
+};
+
+static const Fl_Glut_StrokeStrip ch80st[] =
+{
+ {2,ch80st0},
+ {10,ch80st1}
+};
+
+static const Fl_Glut_StrokeChar ch80 = {85.6667f,2,ch80st};
+
+/* char: 0x51 */
+
+static const Fl_Glut_StrokeVertex ch81st0[] =
+{
+ {33.8714f,100.0f},
+ {24.3476f,95.2381f},
+ {14.8238f,85.7143f},
+ {10.0619f,76.1905f},
+ {5.3f,61.9048f},
+ {5.3f,38.0952f},
+ {10.0619f,23.8095f},
+ {14.8238f,14.2857f},
+ {24.3476f,4.7619f},
+ {33.8714f,0.0f},
+ {52.919f,0.0f},
+ {62.4429f,4.7619f},
+ {71.9667f,14.2857f},
+ {76.7286f,23.8095f},
+ {81.4905f,38.0952f},
+ {81.4905f,61.9048f},
+ {76.7286f,76.1905f},
+ {71.9667f,85.7143f},
+ {62.4429f,95.2381f},
+ {52.919f,100.0f},
+ {33.8714f,100.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch81st1[] =
+{
+ {48.1571f,19.0476f},
+ {76.7286f,-9.5238f}
+};
+
+static const Fl_Glut_StrokeStrip ch81st[] =
+{
+ {21,ch81st0},
+ {2,ch81st1}
+};
+
+static const Fl_Glut_StrokeChar ch81 = {88.0905f,2,ch81st};
+
+/* char: 0x52 */
+
+static const Fl_Glut_StrokeVertex ch82st0[] =
+{
+ {11.68f,100.0f},
+ {11.68f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch82st1[] =
+{
+ {11.68f,100.0f},
+ {54.5371f,100.0f},
+ {68.8229f,95.2381f},
+ {73.5848f,90.4762f},
+ {78.3467f,80.9524f},
+ {78.3467f,71.4286f},
+ {73.5848f,61.9048f},
+ {68.8229f,57.1429f},
+ {54.5371f,52.381f},
+ {11.68f,52.381f}
+};
+
+static const Fl_Glut_StrokeVertex ch82st2[] =
+{
+ {45.0133f,52.381f},
+ {78.3467f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch82st[] =
+{
+ {2,ch82st0},
+ {10,ch82st1},
+ {2,ch82st2}
+};
+
+static const Fl_Glut_StrokeChar ch82 = {82.3667f,3,ch82st};
+
+/* char: 0x53 */
+
+static const Fl_Glut_StrokeVertex ch83st0[] =
+{
+ {74.6667f,85.7143f},
+ {65.1429f,95.2381f},
+ {50.8571f,100.0f},
+ {31.8095f,100.0f},
+ {17.5238f,95.2381f},
+ {8.0f,85.7143f},
+ {8.0f,76.1905f},
+ {12.7619f,66.6667f},
+ {17.5238f,61.9048f},
+ {27.0476f,57.1429f},
+ {55.619f,47.619f},
+ {65.1429f,42.8571f},
+ {69.9048f,38.0952f},
+ {74.6667f,28.5714f},
+ {74.6667f,14.2857f},
+ {65.1429f,4.7619f},
+ {50.8571f,0.0f},
+ {31.8095f,0.0f},
+ {17.5238f,4.7619f},
+ {8.0f,14.2857f}
+};
+
+static const Fl_Glut_StrokeStrip ch83st[] =
+{
+ {20,ch83st0}
+};
+
+static const Fl_Glut_StrokeChar ch83 = {80.8267f,1,ch83st};
+
+/* char: 0x54 */
+
+static const Fl_Glut_StrokeVertex ch84st0[] =
+{
+ {35.6933f,100.0f},
+ {35.6933f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch84st1[] =
+{
+ {2.36f,100.0f},
+ {69.0267f,100.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch84st[] =
+{
+ {2,ch84st0},
+ {2,ch84st1}
+};
+
+static const Fl_Glut_StrokeChar ch84 = {71.9467f,2,ch84st};
+
+/* char: 0x55 */
+
+static const Fl_Glut_StrokeVertex ch85st0[] =
+{
+ {11.54f,100.0f},
+ {11.54f,28.5714f},
+ {16.3019f,14.2857f},
+ {25.8257f,4.7619f},
+ {40.1114f,0.0f},
+ {49.6352f,0.0f},
+ {63.921f,4.7619f},
+ {73.4448f,14.2857f},
+ {78.2067f,28.5714f},
+ {78.2067f,100.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch85st[] =
+{
+ {10,ch85st0}
+};
+
+static const Fl_Glut_StrokeChar ch85 = {89.4867f,1,ch85st};
+
+/* char: 0x56 */
+
+static const Fl_Glut_StrokeVertex ch86st0[] =
+{
+ {2.36f,100.0f},
+ {40.4552f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch86st1[] =
+{
+ {78.5505f,100.0f},
+ {40.4552f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch86st[] =
+{
+ {2,ch86st0},
+ {2,ch86st1}
+};
+
+static const Fl_Glut_StrokeChar ch86 = {81.6105f,2,ch86st};
+
+/* char: 0x57 */
+
+static const Fl_Glut_StrokeVertex ch87st0[] =
+{
+ {2.22f,100.0f},
+ {26.0295f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch87st1[] =
+{
+ {49.839f,100.0f},
+ {26.0295f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch87st2[] =
+{
+ {49.839f,100.0f},
+ {73.6486f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch87st3[] =
+{
+ {97.4581f,100.0f},
+ {73.6486f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch87st[] =
+{
+ {2,ch87st0},
+ {2,ch87st1},
+ {2,ch87st2},
+ {2,ch87st3}
+};
+
+static const Fl_Glut_StrokeChar ch87 = {100.518f,4,ch87st};
+
+/* char: 0x58 */
+
+static const Fl_Glut_StrokeVertex ch88st0[] =
+{
+ {2.5f,100.0f},
+ {69.1667f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch88st1[] =
+{
+ {69.1667f,100.0f},
+ {2.5f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch88st[] =
+{
+ {2,ch88st0},
+ {2,ch88st1}
+};
+
+static const Fl_Glut_StrokeChar ch88 = {72.3667f,2,ch88st};
+
+/* char: 0x59 */
+
+static const Fl_Glut_StrokeVertex ch89st0[] =
+{
+ {1.52f,100.0f},
+ {39.6152f,52.381f},
+ {39.6152f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch89st1[] =
+{
+ {77.7105f,100.0f},
+ {39.6152f,52.381f}
+};
+
+static const Fl_Glut_StrokeStrip ch89st[] =
+{
+ {3,ch89st0},
+ {2,ch89st1}
+};
+
+static const Fl_Glut_StrokeChar ch89 = {79.6505f,2,ch89st};
+
+/* char: 0x5a */
+
+static const Fl_Glut_StrokeVertex ch90st0[] =
+{
+ {69.1667f,100.0f},
+ {2.5f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch90st1[] =
+{
+ {2.5f,100.0f},
+ {69.1667f,100.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch90st2[] =
+{
+ {2.5f,0.0f},
+ {69.1667f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch90st[] =
+{
+ {2,ch90st0},
+ {2,ch90st1},
+ {2,ch90st2}
+};
+
+static const Fl_Glut_StrokeChar ch90 = {73.7467f,3,ch90st};
+
+/* char: 0x5b */
+
+static const Fl_Glut_StrokeVertex ch91st0[] =
+{
+ {7.78f,119.048f},
+ {7.78f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeVertex ch91st1[] =
+{
+ {12.5419f,119.048f},
+ {12.5419f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeVertex ch91st2[] =
+{
+ {7.78f,119.048f},
+ {41.1133f,119.048f}
+};
+
+static const Fl_Glut_StrokeVertex ch91st3[] =
+{
+ {7.78f,-33.3333f},
+ {41.1133f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeStrip ch91st[] =
+{
+ {2,ch91st0},
+ {2,ch91st1},
+ {2,ch91st2},
+ {2,ch91st3}
+};
+
+static const Fl_Glut_StrokeChar ch91 = {46.1133f,4,ch91st};
+
+/* char: 0x5c */
+
+static const Fl_Glut_StrokeVertex ch92st0[] =
+{
+ {5.84f,100.0f},
+ {72.5067f,-14.2857f}
+};
+
+static const Fl_Glut_StrokeStrip ch92st[] =
+{
+ {2,ch92st0}
+};
+
+static const Fl_Glut_StrokeChar ch92 = {78.2067f,1,ch92st};
+
+/* char: 0x5d */
+
+static const Fl_Glut_StrokeVertex ch93st0[] =
+{
+ {33.0114f,119.048f},
+ {33.0114f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeVertex ch93st1[] =
+{
+ {37.7733f,119.048f},
+ {37.7733f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeVertex ch93st2[] =
+{
+ {4.44f,119.048f},
+ {37.7733f,119.048f}
+};
+
+static const Fl_Glut_StrokeVertex ch93st3[] =
+{
+ {4.44f,-33.3333f},
+ {37.7733f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeStrip ch93st[] =
+{
+ {2,ch93st0},
+ {2,ch93st1},
+ {2,ch93st2},
+ {2,ch93st3}
+};
+
+static const Fl_Glut_StrokeChar ch93 = {46.3933f,4,ch93st};
+
+/* char: 0x5e */
+
+static const Fl_Glut_StrokeVertex ch94st0[] =
+{
+ {44.0752f,109.524f},
+ {5.98f,42.8571f}
+};
+
+static const Fl_Glut_StrokeVertex ch94st1[] =
+{
+ {44.0752f,109.524f},
+ {82.1705f,42.8571f}
+};
+
+static const Fl_Glut_StrokeStrip ch94st[] =
+{
+ {2,ch94st0},
+ {2,ch94st1}
+};
+
+static const Fl_Glut_StrokeChar ch94 = {90.2305f,2,ch94st};
+
+/* char: 0x5f */
+
+static const Fl_Glut_StrokeVertex ch95st0[] =
+{
+ {-1.1f,-33.3333f},
+ {103.662f,-33.3333f},
+ {103.662f,-28.5714f},
+ {-1.1f,-28.5714f},
+ {-1.1f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeStrip ch95st[] =
+{
+ {5,ch95st0}
+};
+
+static const Fl_Glut_StrokeChar ch95 = {104.062f,1,ch95st};
+
+/* char: 0x60 */
+
+static const Fl_Glut_StrokeVertex ch96st0[] =
+{
+ {33.0219f,100.0f},
+ {56.8314f,71.4286f}
+};
+
+static const Fl_Glut_StrokeVertex ch96st1[] =
+{
+ {33.0219f,100.0f},
+ {28.26f,95.2381f},
+ {56.8314f,71.4286f}
+};
+
+static const Fl_Glut_StrokeStrip ch96st[] =
+{
+ {2,ch96st0},
+ {3,ch96st1}
+};
+
+static const Fl_Glut_StrokeChar ch96 = {83.5714f,2,ch96st};
+
+/* char: 0x61 */
+
+static const Fl_Glut_StrokeVertex ch97st0[] =
+{
+ {63.8229f,66.6667f},
+ {63.8229f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch97st1[] =
+{
+ {63.8229f,52.381f},
+ {54.299f,61.9048f},
+ {44.7752f,66.6667f},
+ {30.4895f,66.6667f},
+ {20.9657f,61.9048f},
+ {11.4419f,52.381f},
+ {6.68f,38.0952f},
+ {6.68f,28.5714f},
+ {11.4419f,14.2857f},
+ {20.9657f,4.7619f},
+ {30.4895f,0.0f},
+ {44.7752f,0.0f},
+ {54.299f,4.7619f},
+ {63.8229f,14.2857f}
+};
+
+static const Fl_Glut_StrokeStrip ch97st[] =
+{
+ {2,ch97st0},
+ {14,ch97st1}
+};
+
+static const Fl_Glut_StrokeChar ch97 = {66.6029f,2,ch97st};
+
+/* char: 0x62 */
+
+static const Fl_Glut_StrokeVertex ch98st0[] =
+{
+ {8.76f,100.0f},
+ {8.76f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch98st1[] =
+{
+ {8.76f,52.381f},
+ {18.2838f,61.9048f},
+ {27.8076f,66.6667f},
+ {42.0933f,66.6667f},
+ {51.6171f,61.9048f},
+ {61.141f,52.381f},
+ {65.9029f,38.0952f},
+ {65.9029f,28.5714f},
+ {61.141f,14.2857f},
+ {51.6171f,4.7619f},
+ {42.0933f,0.0f},
+ {27.8076f,0.0f},
+ {18.2838f,4.7619f},
+ {8.76f,14.2857f}
+};
+
+static const Fl_Glut_StrokeStrip ch98st[] =
+{
+ {2,ch98st0},
+ {14,ch98st1}
+};
+
+static const Fl_Glut_StrokeChar ch98 = {70.4629f,2,ch98st};
+
+/* char: 0x63 */
+
+static const Fl_Glut_StrokeVertex ch99st0[] =
+{
+ {62.6629f,52.381f},
+ {53.139f,61.9048f},
+ {43.6152f,66.6667f},
+ {29.3295f,66.6667f},
+ {19.8057f,61.9048f},
+ {10.2819f,52.381f},
+ {5.52f,38.0952f},
+ {5.52f,28.5714f},
+ {10.2819f,14.2857f},
+ {19.8057f,4.7619f},
+ {29.3295f,0.0f},
+ {43.6152f,0.0f},
+ {53.139f,4.7619f},
+ {62.6629f,14.2857f}
+};
+
+static const Fl_Glut_StrokeStrip ch99st[] =
+{
+ {14,ch99st0}
+};
+
+static const Fl_Glut_StrokeChar ch99 = {68.9229f,1,ch99st};
+
+/* char: 0x64 */
+
+static const Fl_Glut_StrokeVertex ch100st0[] =
+{
+ {61.7829f,100.0f},
+ {61.7829f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch100st1[] =
+{
+ {61.7829f,52.381f},
+ {52.259f,61.9048f},
+ {42.7352f,66.6667f},
+ {28.4495f,66.6667f},
+ {18.9257f,61.9048f},
+ {9.4019f,52.381f},
+ {4.64f,38.0952f},
+ {4.64f,28.5714f},
+ {9.4019f,14.2857f},
+ {18.9257f,4.7619f},
+ {28.4495f,0.0f},
+ {42.7352f,0.0f},
+ {52.259f,4.7619f},
+ {61.7829f,14.2857f}
+};
+
+static const Fl_Glut_StrokeStrip ch100st[] =
+{
+ {2,ch100st0},
+ {14,ch100st1}
+};
+
+static const Fl_Glut_StrokeChar ch100 = {70.2629f,2,ch100st};
+
+/* char: 0x65 */
+
+static const Fl_Glut_StrokeVertex ch101st0[] =
+{
+ {5.72f,38.0952f},
+ {62.8629f,38.0952f},
+ {62.8629f,47.619f},
+ {58.101f,57.1429f},
+ {53.339f,61.9048f},
+ {43.8152f,66.6667f},
+ {29.5295f,66.6667f},
+ {20.0057f,61.9048f},
+ {10.4819f,52.381f},
+ {5.72f,38.0952f},
+ {5.72f,28.5714f},
+ {10.4819f,14.2857f},
+ {20.0057f,4.7619f},
+ {29.5295f,0.0f},
+ {43.8152f,0.0f},
+ {53.339f,4.7619f},
+ {62.8629f,14.2857f}
+};
+
+static const Fl_Glut_StrokeStrip ch101st[] =
+{
+ {17,ch101st0}
+};
+
+static const Fl_Glut_StrokeChar ch101 = {68.5229f,1,ch101st};
+
+/* char: 0x66 */
+
+static const Fl_Glut_StrokeVertex ch102st0[] =
+{
+ {38.7752f,100.0f},
+ {29.2514f,100.0f},
+ {19.7276f,95.2381f},
+ {14.9657f,80.9524f},
+ {14.9657f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch102st1[] =
+{
+ {0.68f,66.6667f},
+ {34.0133f,66.6667f}
+};
+
+static const Fl_Glut_StrokeStrip ch102st[] =
+{
+ {5,ch102st0},
+ {2,ch102st1}
+};
+
+static const Fl_Glut_StrokeChar ch102 = {38.6552f,2,ch102st};
+
+/* char: 0x67 */
+
+static const Fl_Glut_StrokeVertex ch103st0[] =
+{
+ {62.5029f,66.6667f},
+ {62.5029f,-9.5238f},
+ {57.741f,-23.8095f},
+ {52.979f,-28.5714f},
+ {43.4552f,-33.3333f},
+ {29.1695f,-33.3333f},
+ {19.6457f,-28.5714f}
+};
+
+static const Fl_Glut_StrokeVertex ch103st1[] =
+{
+ {62.5029f,52.381f},
+ {52.979f,61.9048f},
+ {43.4552f,66.6667f},
+ {29.1695f,66.6667f},
+ {19.6457f,61.9048f},
+ {10.1219f,52.381f},
+ {5.36f,38.0952f},
+ {5.36f,28.5714f},
+ {10.1219f,14.2857f},
+ {19.6457f,4.7619f},
+ {29.1695f,0.0f},
+ {43.4552f,0.0f},
+ {52.979f,4.7619f},
+ {62.5029f,14.2857f}
+};
+
+static const Fl_Glut_StrokeStrip ch103st[] =
+{
+ {7,ch103st0},
+ {14,ch103st1}
+};
+
+static const Fl_Glut_StrokeChar ch103 = {70.9829f,2,ch103st};
+
+/* char: 0x68 */
+
+static const Fl_Glut_StrokeVertex ch104st0[] =
+{
+ {9.6f,100.0f},
+ {9.6f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch104st1[] =
+{
+ {9.6f,47.619f},
+ {23.8857f,61.9048f},
+ {33.4095f,66.6667f},
+ {47.6952f,66.6667f},
+ {57.219f,61.9048f},
+ {61.981f,47.619f},
+ {61.981f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch104st[] =
+{
+ {2,ch104st0},
+ {7,ch104st1}
+};
+
+static const Fl_Glut_StrokeChar ch104 = {71.021f,2,ch104st};
+
+/* char: 0x69 */
+
+static const Fl_Glut_StrokeVertex ch105st0[] =
+{
+ {10.02f,100.0f},
+ {14.7819f,95.2381f},
+ {19.5438f,100.0f},
+ {14.7819f,104.762f},
+ {10.02f,100.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch105st1[] =
+{
+ {14.7819f,66.6667f},
+ {14.7819f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch105st[] =
+{
+ {5,ch105st0},
+ {2,ch105st1}
+};
+
+static const Fl_Glut_StrokeChar ch105 = {28.8638f,2,ch105st};
+
+/* char: 0x6a */
+
+static const Fl_Glut_StrokeVertex ch106st0[] =
+{
+ {17.3876f,100.0f},
+ {22.1495f,95.2381f},
+ {26.9114f,100.0f},
+ {22.1495f,104.762f},
+ {17.3876f,100.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch106st1[] =
+{
+ {22.1495f,66.6667f},
+ {22.1495f,-14.2857f},
+ {17.3876f,-28.5714f},
+ {7.8638f,-33.3333f},
+ {-1.66f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeStrip ch106st[] =
+{
+ {5,ch106st0},
+ {5,ch106st1}
+};
+
+static const Fl_Glut_StrokeChar ch106 = {36.2314f,2,ch106st};
+
+/* char: 0x6b */
+
+static const Fl_Glut_StrokeVertex ch107st0[] =
+{
+ {9.6f,100.0f},
+ {9.6f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch107st1[] =
+{
+ {57.219f,66.6667f},
+ {9.6f,19.0476f}
+};
+
+static const Fl_Glut_StrokeVertex ch107st2[] =
+{
+ {28.6476f,38.0952f},
+ {61.981f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch107st[] =
+{
+ {2,ch107st0},
+ {2,ch107st1},
+ {2,ch107st2}
+};
+
+static const Fl_Glut_StrokeChar ch107 = {62.521f,3,ch107st};
+
+/* char: 0x6c */
+
+static const Fl_Glut_StrokeVertex ch108st0[] =
+{
+ {10.02f,100.0f},
+ {10.02f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch108st[] =
+{
+ {2,ch108st0}
+};
+
+static const Fl_Glut_StrokeChar ch108 = {19.34f,1,ch108st};
+
+/* char: 0x6d */
+
+static const Fl_Glut_StrokeVertex ch109st0[] =
+{
+ {9.6f,66.6667f},
+ {9.6f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch109st1[] =
+{
+ {9.6f,47.619f},
+ {23.8857f,61.9048f},
+ {33.4095f,66.6667f},
+ {47.6952f,66.6667f},
+ {57.219f,61.9048f},
+ {61.981f,47.619f},
+ {61.981f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch109st2[] =
+{
+ {61.981f,47.619f},
+ {76.2667f,61.9048f},
+ {85.7905f,66.6667f},
+ {100.076f,66.6667f},
+ {109.6f,61.9048f},
+ {114.362f,47.619f},
+ {114.362f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch109st[] =
+{
+ {2,ch109st0},
+ {7,ch109st1},
+ {7,ch109st2}
+};
+
+static const Fl_Glut_StrokeChar ch109 = {123.962f,3,ch109st};
+
+/* char: 0x6e */
+
+static const Fl_Glut_StrokeVertex ch110st0[] =
+{
+ {9.18f,66.6667f},
+ {9.18f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch110st1[] =
+{
+ {9.18f,47.619f},
+ {23.4657f,61.9048f},
+ {32.9895f,66.6667f},
+ {47.2752f,66.6667f},
+ {56.799f,61.9048f},
+ {61.561f,47.619f},
+ {61.561f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch110st[] =
+{
+ {2,ch110st0},
+ {7,ch110st1}
+};
+
+static const Fl_Glut_StrokeChar ch110 = {70.881f,2,ch110st};
+
+/* char: 0x6f */
+
+static const Fl_Glut_StrokeVertex ch111st0[] =
+{
+ {28.7895f,66.6667f},
+ {19.2657f,61.9048f},
+ {9.7419f,52.381f},
+ {4.98f,38.0952f},
+ {4.98f,28.5714f},
+ {9.7419f,14.2857f},
+ {19.2657f,4.7619f},
+ {28.7895f,0.0f},
+ {43.0752f,0.0f},
+ {52.599f,4.7619f},
+ {62.1229f,14.2857f},
+ {66.8848f,28.5714f},
+ {66.8848f,38.0952f},
+ {62.1229f,52.381f},
+ {52.599f,61.9048f},
+ {43.0752f,66.6667f},
+ {28.7895f,66.6667f}
+};
+
+static const Fl_Glut_StrokeStrip ch111st[] =
+{
+ {17,ch111st0}
+};
+
+static const Fl_Glut_StrokeChar ch111 = {71.7448f,1,ch111st};
+
+/* char: 0x70 */
+
+static const Fl_Glut_StrokeVertex ch112st0[] =
+{
+ {9.46f,66.6667f},
+ {9.46f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeVertex ch112st1[] =
+{
+ {9.46f,52.381f},
+ {18.9838f,61.9048f},
+ {28.5076f,66.6667f},
+ {42.7933f,66.6667f},
+ {52.3171f,61.9048f},
+ {61.841f,52.381f},
+ {66.6029f,38.0952f},
+ {66.6029f,28.5714f},
+ {61.841f,14.2857f},
+ {52.3171f,4.7619f},
+ {42.7933f,0.0f},
+ {28.5076f,0.0f},
+ {18.9838f,4.7619f},
+ {9.46f,14.2857f}
+};
+
+static const Fl_Glut_StrokeStrip ch112st[] =
+{
+ {2,ch112st0},
+ {14,ch112st1}
+};
+
+static const Fl_Glut_StrokeChar ch112 = {70.8029f,2,ch112st};
+
+/* char: 0x71 */
+
+static const Fl_Glut_StrokeVertex ch113st0[] =
+{
+ {61.9829f,66.6667f},
+ {61.9829f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeVertex ch113st1[] =
+{
+ {61.9829f,52.381f},
+ {52.459f,61.9048f},
+ {42.9352f,66.6667f},
+ {28.6495f,66.6667f},
+ {19.1257f,61.9048f},
+ {9.6019f,52.381f},
+ {4.84f,38.0952f},
+ {4.84f,28.5714f},
+ {9.6019f,14.2857f},
+ {19.1257f,4.7619f},
+ {28.6495f,0.0f},
+ {42.9352f,0.0f},
+ {52.459f,4.7619f},
+ {61.9829f,14.2857f}
+};
+
+static const Fl_Glut_StrokeStrip ch113st[] =
+{
+ {2,ch113st0},
+ {14,ch113st1}
+};
+
+static const Fl_Glut_StrokeChar ch113 = {70.7429f,2,ch113st};
+
+/* char: 0x72 */
+
+static const Fl_Glut_StrokeVertex ch114st0[] =
+{
+ {9.46f,66.6667f},
+ {9.46f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch114st1[] =
+{
+ {9.46f,38.0952f},
+ {14.2219f,52.381f},
+ {23.7457f,61.9048f},
+ {33.2695f,66.6667f},
+ {47.5552f,66.6667f}
+};
+
+static const Fl_Glut_StrokeStrip ch114st[] =
+{
+ {2,ch114st0},
+ {5,ch114st1}
+};
+
+static const Fl_Glut_StrokeChar ch114 = {49.4952f,2,ch114st};
+
+/* char: 0x73 */
+
+static const Fl_Glut_StrokeVertex ch115st0[] =
+{
+ {57.081f,52.381f},
+ {52.319f,61.9048f},
+ {38.0333f,66.6667f},
+ {23.7476f,66.6667f},
+ {9.4619f,61.9048f},
+ {4.7f,52.381f},
+ {9.4619f,42.8571f},
+ {18.9857f,38.0952f},
+ {42.7952f,33.3333f},
+ {52.319f,28.5714f},
+ {57.081f,19.0476f},
+ {57.081f,14.2857f},
+ {52.319f,4.7619f},
+ {38.0333f,0.0f},
+ {23.7476f,0.0f},
+ {9.4619f,4.7619f},
+ {4.7f,14.2857f}
+};
+
+static const Fl_Glut_StrokeStrip ch115st[] =
+{
+ {17,ch115st0}
+};
+
+static const Fl_Glut_StrokeChar ch115 = {62.321f,1,ch115st};
+
+/* char: 0x74 */
+
+static const Fl_Glut_StrokeVertex ch116st0[] =
+{
+ {14.8257f,100.0f},
+ {14.8257f,19.0476f},
+ {19.5876f,4.7619f},
+ {29.1114f,0.0f},
+ {38.6352f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch116st1[] =
+{
+ {0.54f,66.6667f},
+ {33.8733f,66.6667f}
+};
+
+static const Fl_Glut_StrokeStrip ch116st[] =
+{
+ {5,ch116st0},
+ {2,ch116st1}
+};
+
+static const Fl_Glut_StrokeChar ch116 = {39.3152f,2,ch116st};
+
+/* char: 0x75 */
+
+static const Fl_Glut_StrokeVertex ch117st0[] =
+{
+ {9.46f,66.6667f},
+ {9.46f,19.0476f},
+ {14.2219f,4.7619f},
+ {23.7457f,0.0f},
+ {38.0314f,0.0f},
+ {47.5552f,4.7619f},
+ {61.841f,19.0476f}
+};
+
+static const Fl_Glut_StrokeVertex ch117st1[] =
+{
+ {61.841f,66.6667f},
+ {61.841f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch117st[] =
+{
+ {7,ch117st0},
+ {2,ch117st1}
+};
+
+static const Fl_Glut_StrokeChar ch117 = {71.161f,2,ch117st};
+
+/* char: 0x76 */
+
+static const Fl_Glut_StrokeVertex ch118st0[] =
+{
+ {1.8f,66.6667f},
+ {30.3714f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch118st1[] =
+{
+ {58.9429f,66.6667f},
+ {30.3714f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch118st[] =
+{
+ {2,ch118st0},
+ {2,ch118st1}
+};
+
+static const Fl_Glut_StrokeChar ch118 = {60.6029f,2,ch118st};
+
+/* char: 0x77 */
+
+static const Fl_Glut_StrokeVertex ch119st0[] =
+{
+ {2.5f,66.6667f},
+ {21.5476f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch119st1[] =
+{
+ {40.5952f,66.6667f},
+ {21.5476f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch119st2[] =
+{
+ {40.5952f,66.6667f},
+ {59.6429f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch119st3[] =
+{
+ {78.6905f,66.6667f},
+ {59.6429f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch119st[] =
+{
+ {2,ch119st0},
+ {2,ch119st1},
+ {2,ch119st2},
+ {2,ch119st3}
+};
+
+static const Fl_Glut_StrokeChar ch119 = {80.4905f,4,ch119st};
+
+/* char: 0x78 */
+
+static const Fl_Glut_StrokeVertex ch120st0[] =
+{
+ {1.66f,66.6667f},
+ {54.041f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch120st1[] =
+{
+ {54.041f,66.6667f},
+ {1.66f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch120st[] =
+{
+ {2,ch120st0},
+ {2,ch120st1}
+};
+
+static const Fl_Glut_StrokeChar ch120 = {56.401f,2,ch120st};
+
+/* char: 0x79 */
+
+static const Fl_Glut_StrokeVertex ch121st0[] =
+{
+ {6.5619f,66.6667f},
+ {35.1333f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch121st1[] =
+{
+ {63.7048f,66.6667f},
+ {35.1333f,0.0f},
+ {25.6095f,-19.0476f},
+ {16.0857f,-28.5714f},
+ {6.5619f,-33.3333f},
+ {1.8f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeStrip ch121st[] =
+{
+ {2,ch121st0},
+ {6,ch121st1}
+};
+
+static const Fl_Glut_StrokeChar ch121 = {66.0648f,2,ch121st};
+
+/* char: 0x7a */
+
+static const Fl_Glut_StrokeVertex ch122st0[] =
+{
+ {56.821f,66.6667f},
+ {4.44f,0.0f}
+};
+
+static const Fl_Glut_StrokeVertex ch122st1[] =
+{
+ {4.44f,66.6667f},
+ {56.821f,66.6667f}
+};
+
+static const Fl_Glut_StrokeVertex ch122st2[] =
+{
+ {4.44f,0.0f},
+ {56.821f,0.0f}
+};
+
+static const Fl_Glut_StrokeStrip ch122st[] =
+{
+ {2,ch122st0},
+ {2,ch122st1},
+ {2,ch122st2}
+};
+
+static const Fl_Glut_StrokeChar ch122 = {61.821f,3,ch122st};
+
+/* char: 0x7b */
+
+static const Fl_Glut_StrokeVertex ch123st0[] =
+{
+ {31.1895f,119.048f},
+ {21.6657f,114.286f},
+ {16.9038f,109.524f},
+ {12.1419f,100.0f},
+ {12.1419f,90.4762f},
+ {16.9038f,80.9524f},
+ {21.6657f,76.1905f},
+ {26.4276f,66.6667f},
+ {26.4276f,57.1429f},
+ {16.9038f,47.619f}
+};
+
+static const Fl_Glut_StrokeVertex ch123st1[] =
+{
+ {21.6657f,114.286f},
+ {16.9038f,104.762f},
+ {16.9038f,95.2381f},
+ {21.6657f,85.7143f},
+ {26.4276f,80.9524f},
+ {31.1895f,71.4286f},
+ {31.1895f,61.9048f},
+ {26.4276f,52.381f},
+ {7.38f,42.8571f},
+ {26.4276f,33.3333f},
+ {31.1895f,23.8095f},
+ {31.1895f,14.2857f},
+ {26.4276f,4.7619f},
+ {21.6657f,0.0f},
+ {16.9038f,-9.5238f},
+ {16.9038f,-19.0476f},
+ {21.6657f,-28.5714f}
+};
+
+static const Fl_Glut_StrokeVertex ch123st2[] =
+{
+ {16.9038f,38.0952f},
+ {26.4276f,28.5714f},
+ {26.4276f,19.0476f},
+ {21.6657f,9.5238f},
+ {16.9038f,4.7619f},
+ {12.1419f,-4.7619f},
+ {12.1419f,-14.2857f},
+ {16.9038f,-23.8095f},
+ {21.6657f,-28.5714f},
+ {31.1895f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeStrip ch123st[] =
+{
+ {10,ch123st0},
+ {17,ch123st1},
+ {10,ch123st2}
+};
+
+static const Fl_Glut_StrokeChar ch123 = {41.6295f,3,ch123st};
+
+/* char: 0x7c */
+
+static const Fl_Glut_StrokeVertex ch124st0[] =
+{
+ {11.54f,119.048f},
+ {11.54f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeStrip ch124st[] =
+{
+ {2,ch124st0}
+};
+
+static const Fl_Glut_StrokeChar ch124 = {23.78f,1,ch124st};
+
+/* char: 0x7d */
+
+static const Fl_Glut_StrokeVertex ch125st0[] =
+{
+ {9.18f,119.048f},
+ {18.7038f,114.286f},
+ {23.4657f,109.524f},
+ {28.2276f,100.0f},
+ {28.2276f,90.4762f},
+ {23.4657f,80.9524f},
+ {18.7038f,76.1905f},
+ {13.9419f,66.6667f},
+ {13.9419f,57.1429f},
+ {23.4657f,47.619f}
+};
+
+static const Fl_Glut_StrokeVertex ch125st1[] =
+{
+ {18.7038f,114.286f},
+ {23.4657f,104.762f},
+ {23.4657f,95.2381f},
+ {18.7038f,85.7143f},
+ {13.9419f,80.9524f},
+ {9.18f,71.4286f},
+ {9.18f,61.9048f},
+ {13.9419f,52.381f},
+ {32.9895f,42.8571f},
+ {13.9419f,33.3333f},
+ {9.18f,23.8095f},
+ {9.18f,14.2857f},
+ {13.9419f,4.7619f},
+ {18.7038f,0.0f},
+ {23.4657f,-9.5238f},
+ {23.4657f,-19.0476f},
+ {18.7038f,-28.5714f}
+};
+
+static const Fl_Glut_StrokeVertex ch125st2[] =
+{
+ {23.4657f,38.0952f},
+ {13.9419f,28.5714f},
+ {13.9419f,19.0476f},
+ {18.7038f,9.5238f},
+ {23.4657f,4.7619f},
+ {28.2276f,-4.7619f},
+ {28.2276f,-14.2857f},
+ {23.4657f,-23.8095f},
+ {18.7038f,-28.5714f},
+ {9.18f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeStrip ch125st[] =
+{
+ {10,ch125st0},
+ {17,ch125st1},
+ {10,ch125st2}
+};
+
+static const Fl_Glut_StrokeChar ch125 = {41.4695f,3,ch125st};
+
+/* char: 0x7e */
+
+static const Fl_Glut_StrokeVertex ch126st0[] =
+{
+ {2.92f,28.5714f},
+ {2.92f,38.0952f},
+ {7.6819f,52.381f},
+ {17.2057f,57.1429f},
+ {26.7295f,57.1429f},
+ {36.2533f,52.381f},
+ {55.301f,38.0952f},
+ {64.8248f,33.3333f},
+ {74.3486f,33.3333f},
+ {83.8724f,38.0952f},
+ {88.6343f,47.619f}
+};
+
+static const Fl_Glut_StrokeVertex ch126st1[] =
+{
+ {2.92f,38.0952f},
+ {7.6819f,47.619f},
+ {17.2057f,52.381f},
+ {26.7295f,52.381f},
+ {36.2533f,47.619f},
+ {55.301f,33.3333f},
+ {64.8248f,28.5714f},
+ {74.3486f,28.5714f},
+ {83.8724f,33.3333f},
+ {88.6343f,47.619f},
+ {88.6343f,57.1429f}
+};
+
+static const Fl_Glut_StrokeStrip ch126st[] =
+{
+ {11,ch126st0},
+ {11,ch126st1}
+};
+
+static const Fl_Glut_StrokeChar ch126 = {91.2743f,2,ch126st};
+
+/* char: 0x7f */
+
+static const Fl_Glut_StrokeVertex ch127st0[] =
+{
+ {52.381f,100.0f},
+ {14.2857f,-33.3333f}
+};
+
+static const Fl_Glut_StrokeVertex ch127st1[] =
+{
+ {28.5714f,66.6667f},
+ {14.2857f,61.9048f},
+ {4.7619f,52.381f},
+ {0.0f,38.0952f},
+ {0.0f,23.8095f},
+ {4.7619f,14.2857f},
+ {14.2857f,4.7619f},
+ {28.5714f,0.0f},
+ {38.0952f,0.0f},
+ {52.381f,4.7619f},
+ {61.9048f,14.2857f},
+ {66.6667f,28.5714f},
+ {66.6667f,42.8571f},
+ {61.9048f,52.381f},
+ {52.381f,61.9048f},
+ {38.0952f,66.6667f},
+ {28.5714f,66.6667f}
+};
+
+static const Fl_Glut_StrokeStrip ch127st[] =
+{
+ {2,ch127st0},
+ {17,ch127st1}
+};
+
+static const Fl_Glut_StrokeChar ch127 = {66.6667f,2,ch127st};
+
+static const Fl_Glut_StrokeChar *chars[] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ &ch32, &ch33, &ch34, &ch35, &ch36, &ch37, &ch38, &ch39,
+ &ch40, &ch41, &ch42, &ch43, &ch44, &ch45, &ch46, &ch47,
+ &ch48, &ch49, &ch50, &ch51, &ch52, &ch53, &ch54, &ch55,
+ &ch56, &ch57, &ch58, &ch59, &ch60, &ch61, &ch62, &ch63,
+ &ch64, &ch65, &ch66, &ch67, &ch68, &ch69, &ch70, &ch71,
+ &ch72, &ch73, &ch74, &ch75, &ch76, &ch77, &ch78, &ch79,
+ &ch80, &ch81, &ch82, &ch83, &ch84, &ch85, &ch86, &ch87,
+ &ch88, &ch89, &ch90, &ch91, &ch92, &ch93, &ch94, &ch95,
+ &ch96, &ch97, &ch98, &ch99, &ch100, &ch101, &ch102, &ch103,
+ &ch104, &ch105, &ch106, &ch107, &ch108, &ch109, &ch110, &ch111,
+ &ch112, &ch113, &ch114, &ch115, &ch116, &ch117, &ch118, &ch119,
+ &ch120, &ch121, &ch122, &ch123, &ch124, &ch125, &ch126, &ch127
+};
+
+Fl_Glut_StrokeFont glutStrokeRoman = {(char *)"Roman",128,152.381f,chars};
diff --git a/third_party/windows/fltk-1.1.10/src/freeglut_teapot.cxx b/third_party/windows/fltk-1.1.10/src/freeglut_teapot.cxx new file mode 100644 index 0000000..bdb5f00 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/freeglut_teapot.cxx @@ -0,0 +1,164 @@ +/*
+ * freeglut_teapot.c
+ *
+ * Teapot(tm) rendering code.
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta@sourceforge.net>
+ * Creation date: Fri Dec 24 1999
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Original teapot code copyright follows:
+ */
+
+/*
+ * (c) Copyright 1993, Silicon Graphics, Inc.
+ *
+ * ALL RIGHTS RESERVED
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Silicon
+ * Graphics, Inc. not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission.
+ *
+ * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU
+ * "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR
+ * OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO
+ * EVENT SHALL SILICON GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE
+ * ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER,
+ * INCLUDING WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE,
+ * SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD PARTIES, WHETHER OR
+ * NOT SILICON GRAPHICS, INC. HAS BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * US Government Users Restricted Rights
+ *
+ * Use, duplication, or disclosure by the Government is subject to
+ * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
+ * (c)(1)(ii) of the Rights in Technical Data and Computer
+ * Software clause at DFARS 252.227-7013 and/or in similar or
+ * successor clauses in the FAR or the DOD or NASA FAR
+ * Supplement. Unpublished-- rights reserved under the copyright
+ * laws of the United States. Contractor/manufacturer is Silicon
+ * Graphics, Inc., 2011 N. Shoreline Blvd., Mountain View, CA
+ * 94039-7311.
+ *
+ * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
+ */
+
+#include <FL/glut.H>
+#include "freeglut_teapot_data.h"
+
+/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
+
+
+static void fghTeapot( GLint grid, GLdouble scale, GLenum type )
+{
+ double p[4][4][3], q[4][4][3], r[4][4][3], s[4][4][3];
+ long i, j, k, l;
+
+ glPushAttrib( GL_ENABLE_BIT | GL_EVAL_BIT );
+ glEnable( GL_AUTO_NORMAL );
+ glEnable( GL_NORMALIZE );
+ glEnable( GL_MAP2_VERTEX_3 );
+ glEnable( GL_MAP2_TEXTURE_COORD_2 );
+
+ glPushMatrix();
+ glRotated( 270.0, 1.0, 0.0, 0.0 );
+ glScaled( 0.5 * scale, 0.5 * scale, 0.5 * scale );
+ glTranslated( 0.0, 0.0, -1.5 );
+
+ for (i = 0; i < 10; i++) {
+ for (j = 0; j < 4; j++) {
+ for (k = 0; k < 4; k++) {
+ for (l = 0; l < 3; l++) {
+ p[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l];
+ q[j][k][l] = cpdata[patchdata[i][j * 4 + (3 - k)]][l];
+ if (l == 1)
+ q[j][k][l] *= -1.0;
+ if (i < 6) {
+ r[j][k][l] =
+ cpdata[patchdata[i][j * 4 + (3 - k)]][l];
+ if (l == 0)
+ r[j][k][l] *= -1.0;
+ s[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l];
+ if (l == 0)
+ s[j][k][l] *= -1.0;
+ if (l == 1)
+ s[j][k][l] *= -1.0;
+ }
+ }
+ }
+ }
+
+ glMap2d(GL_MAP2_TEXTURE_COORD_2, 0.0, 1.0, 2, 2, 0.0, 1.0, 4, 2,
+ &tex[0][0][0]);
+ glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4,
+ &p[0][0][0]);
+ glMapGrid2d(grid, 0.0, 1.0, grid, 0.0, 1.0);
+ glEvalMesh2(type, 0, grid, 0, grid);
+ glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4,
+ &q[0][0][0]);
+ glEvalMesh2(type, 0, grid, 0, grid);
+ if (i < 6) {
+ glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4,
+ &r[0][0][0]);
+ glEvalMesh2(type, 0, grid, 0, grid);
+ glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4,
+ &s[0][0][0]);
+ glEvalMesh2(type, 0, grid, 0, grid);
+ }
+ }
+
+ glPopMatrix();
+ glPopAttrib();
+}
+
+
+/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
+
+/*
+ * Renders a beautiful wired teapot...
+ */
+void glutWireTeapot( GLdouble size )
+{
+ /* We will use the general teapot rendering code */
+ fghTeapot( 10, size, GL_LINE );
+}
+
+/*
+ * Renders a beautiful filled teapot...
+ */
+void glutSolidTeapot( GLdouble size )
+{
+ /* We will use the general teapot rendering code */
+ fghTeapot( 7, size, GL_FILL );
+}
+
+/*** END OF FILE ***/
diff --git a/third_party/windows/fltk-1.1.10/src/freeglut_teapot_data.h b/third_party/windows/fltk-1.1.10/src/freeglut_teapot_data.h new file mode 100644 index 0000000..83b6c38 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/freeglut_teapot_data.h @@ -0,0 +1,145 @@ +/*
+ * freeglut_teapot_data.h
+ *
+ * The freeglut library teapot data include file.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef FREEGLUT_TEAPOT_DATA_H
+#define FREEGLUT_TEAPOT_DATA_H
+
+/*
+ * Original teapot code copyright follows:
+ */
+
+/*
+ * (c) Copyright 1993, Silicon Graphics, Inc.
+ *
+ * ALL RIGHTS RESERVED
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that
+ * both the copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Silicon
+ * Graphics, Inc. not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission.
+ *
+ * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU
+ * "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR
+ * OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO
+ * EVENT SHALL SILICON GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE
+ * ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER,
+ * INCLUDING WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE,
+ * SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD PARTIES, WHETHER OR
+ * NOT SILICON GRAPHICS, INC. HAS BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * US Government Users Restricted Rights
+ *
+ * Use, duplication, or disclosure by the Government is subject to
+ * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
+ * (c)(1)(ii) of the Rights in Technical Data and Computer
+ * Software clause at DFARS 252.227-7013 and/or in similar or
+ * successor clauses in the FAR or the DOD or NASA FAR
+ * Supplement. Unpublished-- rights reserved under the copyright
+ * laws of the United States. Contractor/manufacturer is Silicon
+ * Graphics, Inc., 2011 N. Shoreline Blvd., Mountain View, CA
+ * 94039-7311.
+ *
+ * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
+ */
+
+/*
+ * Rim, body, lid, and bottom data must be reflected in x and y;
+ * handle and spout data across the y axis only.
+ */
+static int patchdata[][16] =
+{
+ { 102, 103, 104, 105, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, /* rim */
+ { 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27 }, /* body */
+ { 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 },
+ { 96, 96, 96, 96, 97, 98, 99, 100, 101, 101, 101, 101, 0, 1, 2, 3 }, /* lid */
+ { 0, 1, 2, 3, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117 },
+ { 118, 118, 118, 118, 124, 122, 119, 121, 123, 126, 125, 120, 40, 39, 38, 37 }, /* bottom */
+ { 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56 }, /* handle */
+ { 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 28, 65, 66, 67 },
+ { 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83 }, /* spout */
+ { 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95 }
+};
+
+static double cpdata[][3] =
+{
+ {0.2, 0, 2.7}, {0.2, -0.112, 2.7}, {0.112, -0.2, 2.7}, {0,
+ -0.2, 2.7}, {1.3375, 0, 2.53125}, {1.3375, -0.749, 2.53125},
+ {0.749, -1.3375, 2.53125}, {0, -1.3375, 2.53125}, {1.4375,
+ 0, 2.53125}, {1.4375, -0.805, 2.53125}, {0.805, -1.4375,
+ 2.53125}, {0, -1.4375, 2.53125}, {1.5, 0, 2.4}, {1.5, -0.84,
+ 2.4}, {0.84, -1.5, 2.4}, {0, -1.5, 2.4}, {1.75, 0, 1.875},
+ {1.75, -0.98, 1.875}, {0.98, -1.75, 1.875}, {0, -1.75,
+ 1.875}, {2, 0, 1.35}, {2, -1.12, 1.35}, {1.12, -2, 1.35},
+ {0, -2, 1.35}, {2, 0, 0.9}, {2, -1.12, 0.9}, {1.12, -2,
+ 0.9}, {0, -2, 0.9}, {-2, 0, 0.9}, {2, 0, 0.45}, {2, -1.12,
+ 0.45}, {1.12, -2, 0.45}, {0, -2, 0.45}, {1.5, 0, 0.225},
+ {1.5, -0.84, 0.225}, {0.84, -1.5, 0.225}, {0, -1.5, 0.225},
+ {1.5, 0, 0.15}, {1.5, -0.84, 0.15}, {0.84, -1.5, 0.15}, {0,
+ -1.5, 0.15}, {-1.6, 0, 2.025}, {-1.6, -0.3, 2.025}, {-1.5,
+ -0.3, 2.25}, {-1.5, 0, 2.25}, {-2.3, 0, 2.025}, {-2.3, -0.3,
+ 2.025}, {-2.5, -0.3, 2.25}, {-2.5, 0, 2.25}, {-2.7, 0,
+ 2.025}, {-2.7, -0.3, 2.025}, {-3, -0.3, 2.25}, {-3, 0,
+ 2.25}, {-2.7, 0, 1.8}, {-2.7, -0.3, 1.8}, {-3, -0.3, 1.8},
+ {-3, 0, 1.8}, {-2.7, 0, 1.575}, {-2.7, -0.3, 1.575}, {-3,
+ -0.3, 1.35}, {-3, 0, 1.35}, {-2.5, 0, 1.125}, {-2.5, -0.3,
+ 1.125}, {-2.65, -0.3, 0.9375}, {-2.65, 0, 0.9375}, {-2,
+ -0.3, 0.9}, {-1.9, -0.3, 0.6}, {-1.9, 0, 0.6}, {1.7, 0,
+ 1.425}, {1.7, -0.66, 1.425}, {1.7, -0.66, 0.6}, {1.7, 0,
+ 0.6}, {2.6, 0, 1.425}, {2.6, -0.66, 1.425}, {3.1, -0.66,
+ 0.825}, {3.1, 0, 0.825}, {2.3, 0, 2.1}, {2.3, -0.25, 2.1},
+ {2.4, -0.25, 2.025}, {2.4, 0, 2.025}, {2.7, 0, 2.4}, {2.7,
+ -0.25, 2.4}, {3.3, -0.25, 2.4}, {3.3, 0, 2.4}, {2.8, 0,
+ 2.475}, {2.8, -0.25, 2.475}, {3.525, -0.25, 2.49375},
+ {3.525, 0, 2.49375}, {2.9, 0, 2.475}, {2.9, -0.15, 2.475},
+ {3.45, -0.15, 2.5125}, {3.45, 0, 2.5125}, {2.8, 0, 2.4},
+ {2.8, -0.15, 2.4}, {3.2, -0.15, 2.4}, {3.2, 0, 2.4}, {0, 0,
+ 3.15}, {0.8, 0, 3.15}, {0.8, -0.45, 3.15}, {0.45, -0.8,
+ 3.15}, {0, -0.8, 3.15}, {0, 0, 2.85}, {1.4, 0, 2.4}, {1.4,
+ -0.784, 2.4}, {0.784, -1.4, 2.4}, {0, -1.4, 2.4}, {0.4, 0,
+ 2.55}, {0.4, -0.224, 2.55}, {0.224, -0.4, 2.55}, {0, -0.4,
+ 2.55}, {1.3, 0, 2.55}, {1.3, -0.728, 2.55}, {0.728, -1.3,
+ 2.55}, {0, -1.3, 2.55}, {1.3, 0, 2.4}, {1.3, -0.728, 2.4},
+ {0.728, -1.3, 2.4}, {0, -1.3, 2.4}, {0, 0, 0}, {1.425,
+ -0.798, 0}, {1.5, 0, 0.075}, {1.425, 0, 0}, {0.798, -1.425,
+ 0}, {0, -1.5, 0.075}, {0, -1.425, 0}, {1.5, -0.84, 0.075},
+ {0.84, -1.5, 0.075}
+};
+
+static double tex[2][2][2] =
+{
+ { {0.0, 0.0}, {1.0, 0.0} },
+ { {0.0, 1.0}, {1.0, 1.0} }
+};
+
+
+#endif /* FREEGLUT_TEAPOT_DATA_H */
+
diff --git a/third_party/windows/fltk-1.1.10/src/gl_draw.cxx b/third_party/windows/fltk-1.1.10/src/gl_draw.cxx new file mode 100644 index 0000000..3e1ac8b --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/gl_draw.cxx @@ -0,0 +1,223 @@ +//
+// "$Id: gl_draw.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// OpenGL drawing support routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// Functions from <FL/gl.h>
+// See also Fl_Gl_Window and gl_start.cxx
+
+#include "flstring.h"
+#if HAVE_GL
+
+#include <FL/Fl.H>
+#include <FL/gl.h>
+#include <FL/x.H>
+#include <FL/fl_draw.H>
+#include "Fl_Gl_Choice.H"
+#include "Fl_Font.H"
+
+#if USE_XFT
+extern XFontStruct* fl_xxfont();
+#endif // USE_XFT
+
+int gl_height() {return fl_height();}
+int gl_descent() {return fl_descent();}
+double gl_width(const char* s) {return fl_width(s);}
+double gl_width(const char* s, int n) {return fl_width(s,n);}
+double gl_width(uchar c) {return fl_width(c);}
+
+void gl_font(int fontid, int size) {
+ fl_font(fontid, size);
+ if (!fl_fontsize->listbase) {
+#ifdef WIN32
+ int base = fl_fontsize->metr.tmFirstChar;
+ int count = fl_fontsize->metr.tmLastChar-base+1;
+ HFONT oldFid = (HFONT)SelectObject(fl_gc, fl_fontsize->fid);
+ fl_fontsize->listbase = glGenLists(256);
+ wglUseFontBitmaps(fl_gc, base, count, fl_fontsize->listbase+base);
+ SelectObject(fl_gc, oldFid);
+#elif defined(__APPLE_QD__)
+ // undefined characters automatically receive an empty GL list in aglUseFont
+ fl_fontsize->listbase = glGenLists(256);
+ aglUseFont(aglGetCurrentContext(), fl_fontsize->font, fl_fontsize->face,
+ fl_fontsize->size, 0, 256, fl_fontsize->listbase);
+#elif defined(__APPLE_QUARTZ__)
+ short font, face, size;
+ uchar fn[256];
+ fn[0]=strlen(fl_fontsize->q_name);
+ strcpy((char*)(fn+1), fl_fontsize->q_name);
+ GetFNum(fn, &font);
+ face = 0;
+ size = fl_fontsize->size;
+ fl_fontsize->listbase = glGenLists(256);
+ aglUseFont(aglGetCurrentContext(), font, face,
+ size, 0, 256, fl_fontsize->listbase);
+#else
+# if USE_XFT
+ fl_xfont = fl_xxfont();
+# endif // USE_XFT
+ int base = fl_xfont->min_char_or_byte2;
+ int count = fl_xfont->max_char_or_byte2-base+1;
+ fl_fontsize->listbase = glGenLists(256);
+ glXUseXFont(fl_xfont->fid, base, count, fl_fontsize->listbase+base);
+#endif
+ }
+ glListBase(fl_fontsize->listbase);
+}
+
+
+void gl_remove_displaylist_fonts()
+{
+# if HAVE_GL
+
+ // clear variables used mostly in fl_font
+ fl_font_ = 0;
+ fl_size_ = 0;
+
+ for (int j = 0 ; j < FL_FREE_FONT ; ++j)
+ {
+ Fl_FontSize* past = 0;
+ Fl_Fontdesc* s = fl_fonts + j ;
+ Fl_FontSize* f = s->first;
+ while (f != 0) {
+ if(f->listbase) {
+ if(f == s->first) {
+ s->first = f->next;
+ }
+ else {
+ past->next = f->next;
+ }
+
+ // It would be nice if this next line was in a descturctor somewhere
+ glDeleteLists(f->listbase, 256);
+
+ Fl_FontSize* tmp = f;
+ f = f->next;
+ delete tmp;
+ }
+ else {
+ past = f;
+ f = f->next;
+ }
+ }
+ }
+
+#endif
+}
+
+void gl_draw(const char* str, int n) {
+ glCallLists(n, GL_UNSIGNED_BYTE, str);
+}
+
+void gl_draw(const char* str, int n, int x, int y) {
+ glRasterPos2i(x, y);
+ gl_draw(str, n);
+}
+
+void gl_draw(const char* str, int n, float x, float y) {
+ glRasterPos2f(x, y);
+ gl_draw(str, n);
+}
+
+void gl_draw(const char* str) {
+ gl_draw(str, strlen(str));
+}
+
+void gl_draw(const char* str, int x, int y) {
+ gl_draw(str, strlen(str), x, y);
+}
+
+void gl_draw(const char* str, float x, float y) {
+ gl_draw(str, strlen(str), x, y);
+}
+
+static void gl_draw_invert(const char* str, int n, int x, int y) {
+ glRasterPos2i(x, -y);
+ gl_draw(str, n);
+}
+
+void gl_draw(
+ const char* str, // the (multi-line) string
+ int x, int y, int w, int h, // bounding box
+ Fl_Align align) {
+ fl_draw(str, x, -y-h, w, h, align, gl_draw_invert);
+}
+
+void gl_measure(const char* str, int& x, int& y) {fl_measure(str,x,y);}
+
+void gl_rect(int x, int y, int w, int h) {
+ if (w < 0) {w = -w; x = x-w;}
+ if (h < 0) {h = -h; y = y-h;}
+ glBegin(GL_LINE_STRIP);
+ glVertex2i(x+w-1, y+h-1);
+ glVertex2i(x+w-1, y);
+ glVertex2i(x, y);
+ glVertex2i(x, y+h-1);
+ glVertex2i(x+w, y+h-1);
+ glEnd();
+}
+
+#if HAVE_GL_OVERLAY
+extern uchar fl_overlay;
+extern int fl_overlay_depth;
+#endif
+
+void gl_color(Fl_Color i) {
+#if HAVE_GL_OVERLAY
+#ifdef WIN32
+ if (fl_overlay && fl_overlay_depth) {
+ if (fl_overlay_depth < 8) {
+ // only black & white produce the expected colors. This could
+ // be improved by fixing the colormap set in Fl_Gl_Overlay.cxx
+ int size = 1<<fl_overlay_depth;
+ if (!i) glIndexi(size-2);
+ else if (i >= size-2) glIndexi(size-1);
+ else glIndexi(i);
+ } else {
+ glIndexi(i ? i : FL_GRAY_RAMP);
+ }
+ return;
+ }
+#else
+ if (fl_overlay) {glIndexi(int(fl_xpixel(i))); return;}
+#endif
+#endif
+ uchar red, green, blue;
+ Fl::get_color(i, red, green, blue);
+ glColor3ub(red, green, blue);
+}
+
+void gl_draw_image(const uchar* b, int x, int y, int w, int h, int d, int ld) {
+ if (!ld) ld = w*d;
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, ld/d);
+ glRasterPos2i(x,y);
+ glDrawPixels(w,h,d<4?GL_RGB:GL_RGBA,GL_UNSIGNED_BYTE,(const ulong*)b);
+}
+
+#endif
+
+//
+// End of "$Id: gl_draw.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/gl_start.cxx b/third_party/windows/fltk-1.1.10/src/gl_start.cxx new file mode 100644 index 0000000..37d4b6c --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/gl_start.cxx @@ -0,0 +1,134 @@ +//
+// "$Id: gl_start.cxx 5190 2006-06-09 16:16:34Z mike $"
+//
+// OpenGL context routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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
+//
+
+// You MUST use gl_visual() to select the default visual before doing
+// show() of any windows. Mesa will crash if you try to use a visual
+// not returned by glxChooseVisual.
+
+// This does not work with Fl_Double_Window's! It will try to draw
+// into the front buffer. Depending on the system this will either
+// crash or do nothing (when pixmaps are being used as back buffer
+// and GL is being done by hardware), work correctly (when GL is done
+// with software, such as Mesa), or draw into the front buffer and
+// be erased when the buffers are swapped (when double buffer hardware
+// is being used)
+
+#include <config.h>
+#if HAVE_GL
+
+#include <FL/Fl.H>
+#include <FL/Fl_Window.H>
+#include <FL/x.H>
+#include <FL/fl_draw.H>
+#include "Fl_Gl_Choice.H"
+
+extern int fl_clip_state_number; // in fl_rect.cxx
+
+static GLContext context;
+static int clip_state_number=-1;
+static int pw, ph;
+
+#ifdef WIN32
+static Fl_Gl_Choice* gl_choice;
+#endif
+
+#ifdef __APPLE__
+static Fl_Gl_Choice* gl_choice;
+#endif
+
+Fl_Region XRectangleRegion(int x, int y, int w, int h); // in fl_rect.cxx
+
+void gl_start() {
+ if (!context) {
+#ifdef WIN32
+ if (!gl_choice) Fl::gl_visual(0);
+ context = fl_create_gl_context(Fl_Window::current(), gl_choice);
+#elif defined(__APPLE_QD__)
+ // \todo Mac : We need to check the code and verify it with Apple Sample code. The 'shiny'-test should at least work with the software OpenGL emulator
+ context = fl_create_gl_context(Fl_Window::current(), gl_choice);
+#elif defined(__APPLE_QUARTZ__)
+ // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
+ context = fl_create_gl_context(Fl_Window::current(), gl_choice);
+#else
+ context = fl_create_gl_context(fl_visual);
+#endif
+ }
+ fl_set_gl_context(Fl_Window::current(), context);
+#if !defined(WIN32) && !defined(__APPLE__)
+ glXWaitX();
+#endif
+ if (pw != Fl_Window::current()->w() || ph != Fl_Window::current()->h()) {
+ pw = Fl_Window::current()->w();
+ ph = Fl_Window::current()->h();
+ glLoadIdentity();
+ glViewport(0, 0, pw, ph);
+ glOrtho(0, pw, 0, ph, -1, 1);
+ glDrawBuffer(GL_FRONT);
+ }
+ if (clip_state_number != fl_clip_state_number) {
+ clip_state_number = fl_clip_state_number;
+ int x, y, w, h;
+ if (fl_clip_box(0, 0, Fl_Window::current()->w(), Fl_Window::current()->h(),
+ x, y, w, h)) {
+ fl_clip_region(XRectangleRegion(x,y,w,h));
+ glScissor(x, Fl_Window::current()->h()-(y+h), w, h);
+ glEnable(GL_SCISSOR_TEST);
+ } else {
+ glDisable(GL_SCISSOR_TEST);
+ }
+ }
+}
+
+void gl_finish() {
+ glFlush();
+#if !defined(WIN32) && !defined(__APPLE__)
+ glXWaitGL();
+#endif
+}
+
+int Fl::gl_visual(int mode, int *alist) {
+ Fl_Gl_Choice *c = Fl_Gl_Choice::find(mode,alist);
+ if (!c) return 0;
+#ifdef WIN32
+ gl_choice = c;
+#elif defined(__APPLE_QD__)
+ gl_choice = c;
+#elif defined(__APPLE_QUARTZ__)
+ // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
+ gl_choice = c;
+#else
+ fl_visual = c->vis;
+ fl_colormap = c->colormap;
+#endif
+ return 1;
+}
+
+#endif
+
+//
+// End of "$Id: gl_start.cxx 5190 2006-06-09 16:16:34Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/glut_compatability.cxx b/third_party/windows/fltk-1.1.10/src/glut_compatability.cxx new file mode 100644 index 0000000..0b52b14 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/glut_compatability.cxx @@ -0,0 +1,504 @@ +//
+// "$Id: glut_compatability.cxx 5845 2007-05-20 00:01:06Z mike $"
+//
+// GLUT emulation routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2007 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
+//
+
+// Emulation of Glut using fltk.
+
+// GLUT is Copyright (c) Mark J. Kilgard, 1994, 1995, 1996.
+// "This program is freely distributable without licensing fees and is
+// provided without guarantee or warrantee expressed or implied. This
+// program is -not- in the public domain."
+
+// Although I have copied the GLUT API, none of my code is based on
+// any Glut implementation details and is therefore covered by the LGPL.
+
+#include "flstring.h"
+#if HAVE_GL
+
+# include <FL/glut.H>
+# ifdef HAVE_GLXGETPROCADDRESSARB
+# define GLX_GLXEXT_LEGACY
+# include <GL/glx.h>
+# endif // HAVE_GLXGETPROCADDRESSARB
+# ifdef HAVE_DLFCN_H
+# include <dlfcn.h>
+# endif // HAVE_DLFCN_H
+# define MAXWINDOWS 32
+static Fl_Glut_Window *windows[MAXWINDOWS+1];
+
+Fl_Glut_Window *glut_window;
+int glut_menu;
+void (*glut_menustate_function)(int);
+void (*glut_menustatus_function)(int,int,int);
+
+static void default_reshape(int w, int h) {glViewport(0,0,w,h);}
+static void default_display() {}
+
+void Fl_Glut_Window::make_current() {
+ glut_window = this;
+ if (shown()) Fl_Gl_Window::make_current();
+}
+
+static int indraw;
+void Fl_Glut_Window::draw() {
+ glut_window = this;
+ indraw = 1;
+ if (!valid()) {reshape(w(),h()); valid(1);}
+ display();
+ indraw = 0;
+}
+
+void glutSwapBuffers() {
+ if (!indraw) glut_window->swap_buffers();
+}
+
+void Fl_Glut_Window::draw_overlay() {
+ glut_window = this;
+ if (!valid()) {reshape(w(),h()); valid(1);}
+ overlaydisplay();
+}
+
+static void domenu(int, int, int);
+
+int Fl_Glut_Window::handle(int event) {
+ make_current();
+ int ex = Fl::event_x();
+ int ey = Fl::event_y();
+ int button;
+ switch (event) {
+
+ case FL_PUSH:
+ if (keyboard || special) Fl::focus(this);
+ button = Fl::event_button()-1;
+ if (button<0) button = 0;
+ if (button>2) button = 2;
+ if (menu[button]) {domenu(menu[button],ex,ey); return 1;}
+ mouse_down |= 1<<button;
+ if (mouse) {mouse(button,GLUT_DOWN,ex,ey); return 1;}
+ if (motion) return 1;
+ break;
+
+ case FL_MOUSEWHEEL:
+ button = Fl::event_dy();
+ while (button < 0) {mouse(3,GLUT_DOWN,ex,ey); ++button;}
+ while (button > 0) {mouse(4,GLUT_DOWN,ex,ey); --button;}
+ return 1;
+
+ case FL_RELEASE:
+ for (button = 0; button < 3; button++) if (mouse_down & (1<<button)) {
+ if (mouse) mouse(button,GLUT_UP,ex,ey);
+ }
+ mouse_down = 0;
+ return 1;
+
+ case FL_ENTER:
+ if (entry) {entry(GLUT_ENTERED); return 1;}
+ if (passivemotion) return 1;
+ break;
+
+ case FL_LEAVE:
+ if (entry) {entry(GLUT_LEFT); return 1;}
+ if (passivemotion) return 1;
+ break;
+
+ case FL_DRAG:
+ if (motion) {motion(ex, ey); return 1;}
+ break;
+
+ case FL_MOVE:
+ if (passivemotion) {passivemotion(ex, ey); return 1;}
+ break;
+
+ case FL_FOCUS:
+ if (keyboard || special) return 1;
+ break;
+
+ case FL_SHORTCUT:
+ if (!keyboard && !special) break;
+
+ case FL_KEYBOARD:
+ if (Fl::event_text()[0]) {
+ if (keyboard) {keyboard(Fl::event_text()[0],ex,ey); return 1;}
+ break;
+ } else {
+ if (special) {
+ int k = Fl::event_key();
+ if (k > FL_F && k <= FL_F_Last) k -= FL_F;
+ special(k,ex,ey);
+ return 1;
+ }
+ break;
+ }
+
+ case FL_HIDE:
+ if (visibility) visibility(GLUT_NOT_VISIBLE);
+ break;
+
+ case FL_SHOW:
+ if (visibility) visibility(GLUT_VISIBLE);
+ break;
+ }
+
+ return Fl_Gl_Window::handle(event);
+}
+
+static int glut_mode = GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH;
+
+void Fl_Glut_Window::_init() {
+ for (number=1; number<MAXWINDOWS; number++) if (!windows[number]) break;
+ windows[number] = this;
+ menu[0] = menu[1] = menu[2] = 0;
+ reshape = default_reshape;
+ display = default_display;
+ overlaydisplay = default_display;
+ keyboard = 0;
+ mouse = 0;
+ motion = 0;
+ passivemotion = 0;
+ entry = 0;
+ visibility = 0;
+ special = 0;
+ mouse_down = 0;
+ mode(glut_mode);
+}
+
+Fl_Glut_Window::Fl_Glut_Window(int W, int H, const char *t) :
+ Fl_Gl_Window(W,H,t) {_init();}
+
+Fl_Glut_Window::Fl_Glut_Window(int X,int Y,int W,int H, const char *t) :
+ Fl_Gl_Window(X,Y,W,H,t) {_init();}
+
+static int initargc;
+static char **initargv;
+
+void glutInit(int *argc, char **argv) {
+ initargc = *argc;
+ initargv = new char*[*argc+1];
+ int i,j;
+ for (i=0; i<=*argc; i++) initargv[i] = argv[i];
+ for (i=j=1; i<*argc; ) {
+ if (Fl::arg(*argc,argv,i));
+ else argv[j++] = argv[i++];
+ }
+ argv[j] = 0;
+ *argc = j;
+}
+
+void glutInitDisplayMode(unsigned int mode) {
+ glut_mode = mode;
+}
+
+void glutMainLoop() {Fl::run();}
+
+////////////////////////////////////////////////////////////////
+
+static int initx, inity, initw=300, inith=300, initpos;
+
+void glutInitWindowPosition(int x, int y) {
+ initx = x; inity = y; initpos = 1;
+}
+
+void glutInitWindowSize(int w, int h) {
+ initw = w; inith = h;
+}
+
+int glutCreateWindow(char *title) {
+ return glutCreateWindow((const char*)title);
+}
+
+int glutCreateWindow(const char *title) {
+ Fl_Glut_Window *W;
+ if (initpos) {
+ W = new Fl_Glut_Window(initx,inity,initw,inith,title);
+ initpos = 0;
+ } else {
+ W = new Fl_Glut_Window(initw,inith,title);
+ }
+ W->resizable(W);
+ if (initargc) {
+ W->show(initargc,initargv);
+ initargc = 0;
+ } else {
+ W->show();
+ }
+ W->valid(0);
+ W->context_valid(0);
+ W->make_current();
+ return W->number;
+}
+
+int glutCreateSubWindow(int win, int x, int y, int w, int h) {
+ Fl_Glut_Window *W = new Fl_Glut_Window(x,y,w,h,0);
+ windows[win]->add(W);
+ if (windows[win]->shown()) W->show();
+ W->make_current();
+ return W->number;
+}
+
+Fl_Glut_Window::~Fl_Glut_Window() {
+ if (glut_window == this) glut_window = 0;
+ windows[number] = 0;
+}
+
+void glutDestroyWindow(int win) {
+ // should destroy children!!!
+ delete windows[win];
+}
+
+void glutPostWindowRedisplay(int win) {
+ windows[win]->redraw();
+}
+
+void glutSetWindow(int win) {
+ windows[win]->make_current();
+}
+
+////////////////////////////////////////////////////////////////
+#include <FL/Fl_Menu_Item.H>
+
+struct menu {
+ void (*cb)(int);
+ Fl_Menu_Item *m;
+ int size;
+ int alloc;
+};
+
+#define MAXMENUS 32
+static menu menus[MAXMENUS+1];
+
+static void domenu(int n, int ex, int ey) {
+ glut_menu = n;
+ menu *m = &menus[n];
+ if (glut_menustate_function) glut_menustate_function(1);
+ if (glut_menustatus_function) glut_menustatus_function(1,ex,ey);
+ const Fl_Menu_Item* g = m->m->popup(Fl::event_x(), Fl::event_y(), 0);
+ if (g && g->callback_) ((void (*)(int))(g->callback_))(int(g->argument()));
+ if (glut_menustatus_function) glut_menustatus_function(0,ex,ey);
+ if (glut_menustate_function) glut_menustate_function(0);
+}
+
+int glutCreateMenu(void (*cb)(int)) {
+ int i;
+ for (i=1; i<MAXMENUS; i++) if (!menus[i].cb) break;
+ menu *m = &menus[i];
+ m->cb = cb;
+ return glut_menu = i;
+}
+
+void glutDestroyMenu(int n) {
+ menu *m = &menus[n];
+ delete[] m->m;
+ m->m = 0;
+ m->cb = 0;
+ m->size = m->alloc = 0;
+}
+
+static Fl_Menu_Item* additem(menu *m) {
+ if (m->size+1 >= m->alloc) {
+ m->alloc = m->size*2+10;
+ Fl_Menu_Item* nm = new Fl_Menu_Item[m->alloc];
+ for (int i=0; i<m->size; i++) nm[i] = m->m[i];
+ delete[] m->m;
+ m->m = nm;
+ }
+ int n = m->size++;
+ m->m[n+1].text = 0;
+ Fl_Menu_Item* i = &(m->m[n]);
+ i->shortcut_ = 0;
+ i->flags = 0;
+ i->labeltype_ = i->labelfont_ = i->labelsize_ = i->labelcolor_ = 0;
+ return i;
+}
+
+void glutAddMenuEntry(char *label, int value) {
+ menu *m = &menus[glut_menu];
+ Fl_Menu_Item* i = additem(m);
+ i->text = label;
+ i->callback_ = (Fl_Callback*)(m->cb);
+ i->user_data_ = (void *)value;
+}
+
+void glutAddSubMenu(char *label, int submenu) {
+ menu *m = &menus[glut_menu];
+ Fl_Menu_Item* i = additem(m);
+ i->text = label;
+ i->callback_ = 0;
+ i->user_data_ = (void *)(menus[submenu].m);
+ i->flags = FL_PUP_SUBMENU;
+}
+
+void glutChangeToMenuEntry(int item, char *label, int value) {
+ menu *m = &menus[glut_menu];
+ Fl_Menu_Item* i = &m->m[item-1];
+ i->text = label;
+ i->callback_ = (Fl_Callback*)(m->cb);
+ i->user_data_ = (void *)value;
+ i->flags = 0;
+}
+
+void glutChangeToSubMenu(int item, char *label, int submenu) {
+ menu *m = &menus[glut_menu];
+ Fl_Menu_Item* i = &m->m[item-1];
+ i->text = label;
+ i->callback_ = 0;
+ i->user_data_ = (void *)(menus[submenu].m);
+ i->flags = FL_PUP_SUBMENU;
+}
+
+void glutRemoveMenuItem(int item) {
+ menu *m = &menus[glut_menu];
+ if (item > m->size || item < 1) return;
+ for (int i = item-1; i <= m->size; i++) m->m[i] = m->m[i+1];
+ m->size--;
+}
+
+////////////////////////////////////////////////////////////////
+
+int glutGet(GLenum type) {
+ switch (type) {
+ case GLUT_RETURN_ZERO: return 0;
+ case GLUT_WINDOW_X: return glut_window->x();
+ case GLUT_WINDOW_Y: return glut_window->y();
+ case GLUT_WINDOW_WIDTH: return glut_window->w();
+ case GLUT_WINDOW_HEIGHT: return glut_window->h();
+ case GLUT_WINDOW_PARENT:
+ if (glut_window->parent())
+ return ((Fl_Glut_Window *)(glut_window->parent()))->number;
+ else
+ return 0;
+//case GLUT_WINDOW_NUM_CHILDREN:
+//case GLUT_WINDOW_CURSOR: return
+ case GLUT_SCREEN_WIDTH: return Fl::w();
+ case GLUT_SCREEN_HEIGHT: return Fl::h();
+//case GLUT_SCREEN_WIDTH_MM:
+//case GLUT_SCREEN_HEIGHT_MM:
+ case GLUT_MENU_NUM_ITEMS: return menus[glut_menu].size;
+ case GLUT_DISPLAY_MODE_POSSIBLE: return Fl_Gl_Window::can_do(glut_mode);
+ case GLUT_INIT_WINDOW_X: return initx;
+ case GLUT_INIT_WINDOW_Y: return inity;
+ case GLUT_INIT_WINDOW_WIDTH: return initw;
+ case GLUT_INIT_WINDOW_HEIGHT: return inith;
+ case GLUT_INIT_DISPLAY_MODE: return glut_mode;
+//case GLUT_ELAPSED_TIME:
+ case GLUT_WINDOW_BUFFER_SIZE:
+ if (glutGet(GLUT_WINDOW_RGBA))
+ return glutGet(GLUT_WINDOW_RED_SIZE)+
+ glutGet(GLUT_WINDOW_GREEN_SIZE)+
+ glutGet(GLUT_WINDOW_BLUE_SIZE)+
+ glutGet(GLUT_WINDOW_ALPHA_SIZE);
+ else
+ return glutGet(GLUT_WINDOW_COLORMAP_SIZE);
+ case GLUT_VERSION: return 20400;
+ default: {GLint p; glGetIntegerv(type, &p); return p;}
+ }
+}
+
+int glutLayerGet(GLenum type) {
+ switch (type) {
+ case GLUT_OVERLAY_POSSIBLE: return glut_window->can_do_overlay();
+//case GLUT_LAYER_IN_USE:
+//case GLUT_HAS_OVERLAY:
+ case GLUT_TRANSPARENT_INDEX: return 0; // true for SGI
+ case GLUT_NORMAL_DAMAGED: return glut_window->damage();
+ case GLUT_OVERLAY_DAMAGED: return 1; // kind of works...
+ default: return 0;
+ }
+}
+
+int glutDeviceGet(GLenum type) {
+ switch (type) {
+ case GLUT_HAS_KEYBOARD : return 1;
+ case GLUT_HAS_MOUSE : return 1;
+ case GLUT_NUM_MOUSE_BUTTONS : return 3;
+ default : return 0;
+ }
+}
+
+// Get extension function address...
+GLUTproc glutGetProcAddress(const char *procName) {
+# ifdef WIN32
+ return (GLUTproc)wglGetProcAddress((LPCSTR)procName);
+
+# elif defined(HAVE_DLSYM) && defined(HAVE_DLFCN_H)
+ char symbol[1024];
+
+ snprintf(symbol, sizeof(symbol), "_%s", procName);
+
+# ifdef RTLD_DEFAULT
+ return (GLUTproc)dlsym(RTLD_DEFAULT, symbol);
+
+# else // No RTLD_DEFAULT support, so open the current a.out symbols...
+ static void *rtld_default = 0;
+
+ if (!rtld_default) rtld_default = dlopen(0, RTLD_LAZY);
+
+ if (rtld_default) return (GLUTproc)dlsym(rtld_default, symbol);
+ else return 0;
+
+# endif // RTLD_DEFAULT
+
+# elif defined(HAVE_GLXGETPROCADDRESSARB)
+ return (GLUTproc)glXGetProcAddressARB((const GLubyte *)procName);
+
+# else
+ return (GLUTproc)0;
+# endif // WIN32
+}
+
+// Parse the GL_EXTENSIONS string to see if the named extension is
+// supported.
+//
+// This code was copied from FreeGLUT 2.4.0 which carries the
+// following notice:
+//
+// Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+int glutExtensionSupported( const char* extension )
+{
+ if (!extension || strchr(extension, ' ')) return 0;
+
+ const char *extensions, *start;
+ const int len = strlen( extension );
+
+ start = extensions = (const char *) glGetString(GL_EXTENSIONS);
+
+ if (!extensions) return 0;
+
+ for (;;) {
+ const char *p = strstr(extensions, extension);
+ if (!p) return 0; /* not found */
+ /* check that the match isn't a super string */
+ if ((p == start || p[-1] == ' ') &&
+ (p[len] == ' ' || p[len] == 0)) return 1;
+ /* skip the false match and continue */
+ extensions = p + len;
+ }
+}
+
+#endif // HAVE_GL
+
+//
+// End of "$Id: glut_compatability.cxx 5845 2007-05-20 00:01:06Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/glut_font.cxx b/third_party/windows/fltk-1.1.10/src/glut_font.cxx new file mode 100644 index 0000000..64991db --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/glut_font.cxx @@ -0,0 +1,199 @@ +//
+// "$Id: glut_font.cxx 5650 2007-02-01 18:10:07Z mike $"
+//
+// GLUT font routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2007 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
+//
+// The stroked text code was copied from FreeGLUT 2.4.0 which carries
+// the following notice:
+//
+// Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+//
+
+// (sort of) emulation of Glut's bitmap drawing functions, using FL's
+// font stuff. Not all the fonts match!
+
+#include <config.h>
+#if HAVE_GL
+# include <FL/glut.H>
+
+Fl_Glut_Bitmap_Font glutBitmap9By15 = {FL_SCREEN, 15};
+Fl_Glut_Bitmap_Font glutBitmap8By13 = {FL_SCREEN, 13};
+Fl_Glut_Bitmap_Font glutBitmapTimesRoman10 = {FL_TIMES, 10};
+Fl_Glut_Bitmap_Font glutBitmapTimesRoman24 = {FL_TIMES, 24};
+Fl_Glut_Bitmap_Font glutBitmapHelvetica10 = {FL_HELVETICA, 10};
+Fl_Glut_Bitmap_Font glutBitmapHelvetica12 = {FL_HELVETICA, 12};
+Fl_Glut_Bitmap_Font glutBitmapHelvetica18 = {FL_HELVETICA, 18};
+
+void glutBitmapCharacter(void* font, int character) {
+ gl_font(((Fl_Glut_Bitmap_Font *)font)->font,((Fl_Glut_Bitmap_Font *)font)->size);
+ char a[1]; a[0] = character;
+ gl_draw(a,1);
+}
+
+int glutBitmapHeight(void* font) {
+ gl_font(((Fl_Glut_Bitmap_Font *)font)->font,((Fl_Glut_Bitmap_Font *)font)->size);
+ return gl_height();
+}
+
+int glutBitmapLength(void *font, const unsigned char *string) {
+ gl_font(((Fl_Glut_Bitmap_Font *)font)->font,((Fl_Glut_Bitmap_Font *)font)->size);
+ const char *s = (const char*)string;
+ return int(gl_width(s)+.5);
+}
+
+void glutBitmapString(void *font, const unsigned char *string) {
+ gl_font(((Fl_Glut_Bitmap_Font *)font)->font,((Fl_Glut_Bitmap_Font *)font)->size);
+ const char *s = (const char*)string;
+ gl_draw(s);
+}
+
+int glutBitmapWidth(void* font, int character) {
+ gl_font(((Fl_Glut_Bitmap_Font *)font)->font,((Fl_Glut_Bitmap_Font *)font)->size);
+ return int(gl_width(character)+.5);
+}
+
+
+/*
+ * Draw a stroke character
+ */
+void glutStrokeCharacter(void* fontID, int character) {
+ const Fl_Glut_StrokeChar *schar;
+ const Fl_Glut_StrokeStrip *strip;
+ int i, j;
+ Fl_Glut_StrokeFont* font = (Fl_Glut_StrokeFont *)fontID;
+
+ if (character < 0 || character >= font->Quantity) return;
+
+ schar = font->Characters[character];
+ if (!schar) return;
+
+ strip = schar->Strips;
+
+ for (i = 0; i < schar->Number; i++, strip++)
+ {
+ glBegin(GL_LINE_STRIP);
+ for (j = 0; j < strip->Number; j++)
+ glVertex2f(strip->Vertices[j].X, strip->Vertices[j].Y);
+ glEnd();
+ }
+
+ glTranslatef(schar->Right, 0.0, 0.0);
+}
+
+void glutStrokeString(void* fontID, const unsigned char *string) {
+ unsigned char c;
+ int i, j;
+ float length = 0.0;
+ Fl_Glut_StrokeFont* font = (Fl_Glut_StrokeFont *)fontID;
+
+ if (!string || ! *string) return;
+
+ /*
+ * Step through the string, drawing each character.
+ * A newline will simply translate the next character's insertion
+ * point back to the start of the line and down one line.
+ */
+
+ while ((c = *string++) != 0) {
+ if (c < font->Quantity) {
+ if (c == '\n') {
+ glTranslatef(-length, -(float)(font->Height), 0.0);
+ length = 0.0;
+ } else {
+ /* Not an EOL, draw the bitmap character */
+ const Fl_Glut_StrokeChar *schar = font->Characters[c];
+ if (schar) {
+ const Fl_Glut_StrokeStrip *strip = schar->Strips;
+
+ for (i = 0; i < schar->Number; i++, strip++) {
+ glBegin(GL_LINE_STRIP);
+ for (j = 0; j < strip->Number; j++)
+ glVertex2f(strip->Vertices[j].X, strip->Vertices[j].Y);
+ glEnd();
+ }
+
+ length += schar->Right;
+ glTranslatef(schar->Right, 0.0, 0.0);
+ }
+ }
+ }
+ }
+}
+
+/*
+ * Return the width in pixels of a stroke character
+ */
+int glutStrokeWidth( void* fontID, int character )
+{
+ const Fl_Glut_StrokeChar *schar;
+ Fl_Glut_StrokeFont* font = (Fl_Glut_StrokeFont *)fontID;
+ if (character < 0 || character >= font->Quantity) return 0;
+ schar = font->Characters[ character ];
+
+ return schar ? (int)(schar->Right + 0.5) : 0;
+}
+
+/*
+ * Return the width of a string drawn using a stroke font
+ */
+int glutStrokeLength(void* fontID, const unsigned char* string) {
+ unsigned char c;
+ float length = 0.0;
+ float this_line_length = 0.0;
+ Fl_Glut_StrokeFont* font = (Fl_Glut_StrokeFont *)fontID;
+
+ if (!string || ! *string) return 0;
+
+ while ((c = *string++) != 0) {
+ if (c < font->Quantity) {
+ if (c == '\n') {
+ /* EOL; reset the length of this line */
+ if (length < this_line_length) length = this_line_length;
+ this_line_length = 0.0;
+ } else {
+ /* Not an EOL, increment the length of this line */
+ const Fl_Glut_StrokeChar *schar = font->Characters[c];
+ if (schar) this_line_length += schar->Right;
+ }
+ }
+ }
+
+ if (length < this_line_length) length = this_line_length;
+
+ return (int)(length + 0.5);
+}
+
+/*
+ * Returns the height of a stroke font
+ */
+GLfloat glutStrokeHeight(void* fontID) {
+ Fl_Glut_StrokeFont* font = (Fl_Glut_StrokeFont *)fontID;
+ return font->Height;
+}
+
+#endif // HAVE_GL
+
+//
+// End of "$Id: glut_font.cxx 5650 2007-02-01 18:10:07Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/makedepend b/third_party/windows/fltk-1.1.10/src/makedepend new file mode 100644 index 0000000..ded3d3f --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/makedepend @@ -0,0 +1,601 @@ +# DO NOT DELETE THIS LINE -- make depend depends on it.
+Fl.o: Fl.cxx ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H \
+ ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/x.H \
+ ../FL/Fl_Window.H ../FL/Fl_Tooltip.H ../FL/Fl_Widget.H flstring.h \
+ ../FL/Fl_Export.H ../config.h ../FL/fl_draw.H
+Fl_Adjuster.o: Fl_Adjuster.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Adjuster.H ../FL/Fl_Valuator.H \
+ ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/fl_draw.H \
+ fastarrow.h mediumarrow.h slowarrow.h
+Fl_Bitmap.o: Fl_Bitmap.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/x.H ../FL/Fl_Window.H ../FL/Fl_Group.H \
+ ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/Fl_Widget.H \
+ ../FL/Fl_Menu_Item.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H flstring.h \
+ ../FL/Fl_Export.H ../config.h
+Fl_Browser.o: Fl_Browser.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Browser.H ../FL/Fl_Browser_.H \
+ ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Scrollbar.H \
+ ../FL/Fl_Slider.H ../FL/Fl_Valuator.H ../FL/fl_draw.H flstring.h \
+ ../FL/Fl_Export.H ../config.h
+Fl_Browser_.o: Fl_Browser_.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Widget.H ../FL/Fl_Browser_.H \
+ ../FL/Fl_Group.H ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H \
+ ../FL/Fl_Valuator.H ../FL/fl_draw.H
+Fl_Browser_load.o: Fl_Browser_load.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Browser.H ../FL/Fl_Browser_.H \
+ ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Scrollbar.H \
+ ../FL/Fl_Slider.H ../FL/Fl_Valuator.H
+Fl_Box.o: Fl_Box.cxx ../FL/Fl_Widget.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Box.H
+Fl_Button.o: Fl_Button.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Button.H ../FL/Fl_Widget.H ../FL/Fl_Group.H \
+ ../FL/Fl_Window.H ../FL/Fl_Group.H
+Fl_Chart.o: Fl_Chart.cxx ../FL/math.h ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Chart.H ../FL/Fl_Widget.H ../FL/fl_draw.H \
+ flstring.h ../FL/Fl_Export.H ../config.h
+Fl_Check_Browser.o: Fl_Check_Browser.cxx flstring.h ../FL/Fl_Export.H \
+ ../config.h ../FL/fl_draw.H ../FL/Enumerations.H ../FL/Fl_Export.H \
+ ../FL/Fl_Check_Browser.H ../FL/Fl.H ../FL/Fl_Browser_.H \
+ ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Scrollbar.H \
+ ../FL/Fl_Slider.H ../FL/Fl_Valuator.H
+Fl_Check_Button.o: Fl_Check_Button.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Check_Button.H ../FL/Fl_Light_Button.H \
+ ../FL/Fl_Button.H ../FL/Fl_Widget.H
+Fl_Choice.o: Fl_Choice.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Choice.H ../FL/Fl_Menu_.H ../FL/Fl_Widget.H \
+ ../FL/Fl_Menu_Item.H ../FL/Fl_Image.H ../FL/fl_draw.H flstring.h \
+ ../FL/Fl_Export.H ../config.h
+Fl_Clock.o: Fl_Clock.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Clock.H ../FL/Fl_Widget.H ../FL/fl_draw.H
+Fl_Color_Chooser.o: Fl_Color_Chooser.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Color_Chooser.H ../FL/Fl_Group.H \
+ ../FL/Fl_Widget.H ../FL/Fl_Box.H ../FL/Fl_Return_Button.H \
+ ../FL/Fl_Button.H ../FL/Fl_Choice.H ../FL/Fl_Menu_.H \
+ ../FL/Fl_Menu_Item.H ../FL/Fl_Image.H ../FL/Fl_Value_Input.H \
+ ../FL/Fl_Valuator.H ../FL/Fl_Input.H ../FL/Fl_Input_.H ../FL/fl_draw.H \
+ ../FL/math.h ../FL/Fl_Window.H ../FL/Fl_Group.H
+Fl_Counter.o: Fl_Counter.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Counter.H ../FL/Fl_Valuator.H \
+ ../FL/Fl_Widget.H ../FL/fl_draw.H
+Fl_Dial.o: Fl_Dial.cxx ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H \
+ ../FL/Fl_Dial.H ../FL/Fl_Valuator.H ../FL/Fl_Widget.H ../FL/fl_draw.H \
+ ../FL/math.h
+Fl_Double_Window.o: Fl_Double_Window.cxx ../config.h ../FL/Fl.H \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/Fl_Double_Window.H \
+ ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/x.H \
+ ../FL/fl_draw.H
+Fl_File_Browser.o: Fl_File_Browser.cxx ../FL/Fl_File_Browser.H \
+ ../FL/Fl_Browser.H ../FL/Fl_Browser_.H ../FL/Fl_Group.H \
+ ../FL/Fl_Widget.H ../FL/Enumerations.H ../FL/Fl_Export.H \
+ ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H ../FL/Fl_Valuator.H \
+ ../FL/Fl_File_Icon.H ../FL/Fl.H ../FL/filename.H ../FL/fl_draw.H \
+ ../FL/filename.H flstring.h ../FL/Fl_Export.H ../config.h
+Fl_File_Chooser.o: Fl_File_Chooser.cxx ../FL/Fl_File_Chooser.H ../FL/Fl.H \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/Fl_Double_Window.H \
+ ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Group.H \
+ ../FL/Fl_Choice.H ../FL/Fl_Menu_.H ../FL/Fl_Menu_Item.H \
+ ../FL/Fl_Image.H ../FL/Fl_Menu_Button.H ../FL/Fl_Button.H \
+ ../FL/Fl_Preferences.H ../FL/Fl_Tile.H ../FL/Fl_File_Browser.H \
+ ../FL/Fl_Browser.H ../FL/Fl_Browser_.H ../FL/Fl_Scrollbar.H \
+ ../FL/Fl_Slider.H ../FL/Fl_Valuator.H ../FL/Fl_File_Icon.H ../FL/Fl.H \
+ ../FL/filename.H ../FL/Fl_Box.H ../FL/Fl_Check_Button.H \
+ ../FL/Fl_Light_Button.H ../FL/Fl_Button.H ../FL/Fl_File_Input.H \
+ ../FL/Fl_Input.H ../FL/Fl_Input_.H ../FL/Fl_Return_Button.H \
+ ../FL/fl_ask.H ../FL/fl_draw.H ../FL/Fl_Bitmap.H
+Fl_File_Chooser2.o: Fl_File_Chooser2.cxx ../FL/Fl_File_Chooser.H \
+ ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H \
+ ../FL/Fl_Double_Window.H ../FL/Fl_Window.H ../FL/Fl_Group.H \
+ ../FL/Fl_Widget.H ../FL/Fl_Group.H ../FL/Fl_Choice.H ../FL/Fl_Menu_.H \
+ ../FL/Fl_Menu_Item.H ../FL/Fl_Image.H ../FL/Fl_Menu_Button.H \
+ ../FL/Fl_Button.H ../FL/Fl_Preferences.H ../FL/Fl_Tile.H \
+ ../FL/Fl_File_Browser.H ../FL/Fl_Browser.H ../FL/Fl_Browser_.H \
+ ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H ../FL/Fl_Valuator.H \
+ ../FL/Fl_File_Icon.H ../FL/Fl.H ../FL/filename.H ../FL/Fl_Box.H \
+ ../FL/Fl_Check_Button.H ../FL/Fl_Light_Button.H ../FL/Fl_Button.H \
+ ../FL/Fl_File_Input.H ../FL/Fl_Input.H ../FL/Fl_Input_.H \
+ ../FL/Fl_Return_Button.H ../FL/fl_ask.H ../FL/filename.H ../FL/x.H \
+ ../FL/Fl_Shared_Image.H flstring.h ../FL/Fl_Export.H ../config.h
+Fl_File_Icon.o: Fl_File_Icon.cxx flstring.h ../FL/Fl_Export.H ../config.h \
+ ../FL/Fl_File_Icon.H ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H \
+ ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/filename.H
+Fl_File_Input.o: Fl_File_Input.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_File_Input.H ../FL/Fl_Input.H \
+ ../FL/Fl_Input_.H ../FL/Fl_Widget.H ../FL/Fl_Window.H ../FL/Fl_Group.H \
+ ../FL/fl_draw.H flstring.h ../FL/Fl_Export.H ../config.h
+Fl_Group.o: Fl_Group.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Window.H \
+ ../FL/Fl_Group.H ../FL/fl_draw.H
+Fl_Help_View.o: Fl_Help_View.cxx ../FL/Fl_Help_View.H ../FL/Fl.H \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/Fl_Group.H \
+ ../FL/Fl_Widget.H ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H \
+ ../FL/Fl_Valuator.H ../FL/fl_draw.H ../FL/Fl_Shared_Image.H \
+ ../FL/Fl_Image.H ../FL/Fl_Window.H ../FL/Fl_Pixmap.H ../FL/x.H \
+ ../FL/Fl_Window.H flstring.h ../FL/Fl_Export.H ../config.h
+Fl_Image.o: Fl_Image.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H \
+ ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Widget.H \
+ ../FL/Fl_Menu_Item.H ../FL/Fl_Image.H ../FL/Fl_Image.H flstring.h \
+ ../FL/Fl_Export.H ../config.h
+Fl_Input.o: Fl_Input.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H \
+ ../FL/Fl_Input.H ../FL/Fl_Input_.H ../FL/fl_draw.H ../FL/fl_ask.H \
+ flstring.h ../FL/Fl_Export.H ../config.h
+Fl_Input_.o: Fl_Input_.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Input_.H ../FL/Fl_Widget.H ../FL/Fl_Window.H \
+ ../FL/Fl_Group.H ../FL/fl_draw.H ../FL/fl_ask.H flstring.h \
+ ../FL/Fl_Export.H ../config.h
+Fl_Light_Button.o: Fl_Light_Button.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Light_Button.H ../FL/Fl_Button.H \
+ ../FL/Fl_Widget.H ../FL/fl_draw.H flstring.h ../FL/Fl_Export.H \
+ ../config.h
+Fl_Menu.o: Fl_Menu.cxx ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H \
+ ../FL/Fl_Menu_Window.H ../FL/Fl_Single_Window.H ../FL/Fl_Window.H \
+ ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Menu_.H \
+ ../FL/Fl_Menu_Item.H ../FL/Fl_Image.H ../FL/fl_draw.H flstring.h \
+ ../FL/Fl_Export.H ../config.h
+Fl_Menu_.o: Fl_Menu_.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Menu_.H ../FL/Fl_Widget.H \
+ ../FL/Fl_Menu_Item.H ../FL/Fl_Image.H flstring.h ../FL/Fl_Export.H \
+ ../config.h
+Fl_Menu_Bar.o: Fl_Menu_Bar.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Menu_Bar.H ../FL/Fl_Menu_.H \
+ ../FL/Fl_Widget.H ../FL/Fl_Menu_Item.H ../FL/Fl_Image.H ../FL/fl_draw.H
+Fl_Sys_Menu_Bar.o: Fl_Sys_Menu_Bar.cxx
+Fl_Menu_Button.o: Fl_Menu_Button.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Menu_Button.H ../FL/Fl_Menu_.H \
+ ../FL/Fl_Widget.H ../FL/Fl_Menu_Item.H ../FL/Fl_Image.H ../FL/fl_draw.H
+Fl_Menu_Window.o: Fl_Menu_Window.cxx ../config.h ../FL/Fl.H \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/x.H ../FL/Fl_Window.H \
+ ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/fl_draw.H \
+ ../FL/Fl_Menu_Window.H ../FL/Fl_Single_Window.H
+Fl_Menu_add.o: Fl_Menu_add.cxx ../FL/Fl_Menu_.H ../FL/Fl_Widget.H \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/Fl_Menu_Item.H \
+ ../FL/Fl_Image.H flstring.h ../FL/Fl_Export.H ../config.h
+Fl_Menu_global.o: Fl_Menu_global.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Menu_.H ../FL/Fl_Widget.H \
+ ../FL/Fl_Menu_Item.H ../FL/Fl_Image.H
+Fl_Multi_Label.o: Fl_Multi_Label.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Widget.H ../FL/Fl_Menu_Item.H \
+ ../FL/Fl_Widget.H ../FL/Fl_Image.H ../FL/Fl_Multi_Label.H
+Fl_Overlay_Window.o: Fl_Overlay_Window.cxx ../config.h ../FL/Fl.H \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/Fl_Overlay_Window.H \
+ ../FL/Fl_Double_Window.H ../FL/Fl_Window.H ../FL/Fl_Group.H \
+ ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/x.H
+Fl_Pack.o: Fl_Pack.cxx ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H \
+ ../FL/Fl_Pack.H ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/fl_draw.H
+Fl_Pixmap.o: Fl_Pixmap.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H \
+ ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Widget.H \
+ ../FL/Fl_Menu_Item.H ../FL/Fl_Image.H ../FL/Fl_Pixmap.H flstring.h \
+ ../FL/Fl_Export.H ../config.h
+Fl_Positioner.o: Fl_Positioner.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Positioner.H ../FL/Fl_Widget.H \
+ ../FL/fl_draw.H
+Fl_Preferences.o: Fl_Preferences.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Preferences.H ../FL/filename.H flstring.h \
+ ../FL/Fl_Export.H ../config.h
+Fl_Progress.o: Fl_Progress.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Progress.H ../FL/Fl_Widget.H ../FL/fl_draw.H
+Fl_Repeat_Button.o: Fl_Repeat_Button.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Repeat_Button.H ../FL/Fl.H ../FL/Fl_Button.H \
+ ../FL/Fl_Widget.H
+Fl_Return_Button.o: Fl_Return_Button.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Return_Button.H ../FL/Fl_Button.H \
+ ../FL/Fl_Widget.H ../FL/fl_draw.H
+Fl_Roller.o: Fl_Roller.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Roller.H ../FL/Fl_Valuator.H \
+ ../FL/Fl_Widget.H ../FL/fl_draw.H
+Fl_Round_Button.o: Fl_Round_Button.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Round_Button.H ../FL/Fl_Light_Button.H \
+ ../FL/Fl_Button.H ../FL/Fl_Widget.H
+Fl_Scroll.o: Fl_Scroll.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Tiled_Image.H ../FL/Fl_Image.H \
+ ../FL/Fl_Scroll.H ../FL/Fl_Group.H ../FL/Fl_Widget.H \
+ ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H ../FL/Fl_Valuator.H \
+ ../FL/fl_draw.H
+Fl_Scrollbar.o: Fl_Scrollbar.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H \
+ ../FL/Fl_Valuator.H ../FL/Fl_Widget.H ../FL/fl_draw.H flstring.h \
+ ../FL/Fl_Export.H ../config.h
+Fl_Shared_Image.o: Fl_Shared_Image.cxx flstring.h ../FL/Fl_Export.H \
+ ../config.h ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H \
+ ../FL/Fl_Shared_Image.H ../FL/Fl_Image.H ../FL/Fl_XBM_Image.H \
+ ../FL/Fl_Bitmap.H ../FL/Fl_XPM_Image.H ../FL/Fl_Pixmap.H
+Fl_Single_Window.o: Fl_Single_Window.cxx ../FL/Fl_Single_Window.H \
+ ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H \
+ ../FL/Enumerations.H ../FL/Fl_Export.H
+Fl_Slider.o: Fl_Slider.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Slider.H ../FL/Fl_Valuator.H \
+ ../FL/Fl_Widget.H ../FL/fl_draw.H flstring.h ../FL/Fl_Export.H \
+ ../config.h
+Fl_Tabs.o: Fl_Tabs.cxx ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H \
+ ../FL/Fl_Tabs.H ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/fl_draw.H \
+ ../FL/Fl_Tooltip.H ../FL/Fl_Widget.H
+Fl_Text_Buffer.o: Fl_Text_Buffer.cxx flstring.h ../FL/Fl_Export.H \
+ ../config.h ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H \
+ ../FL/Fl_Text_Buffer.H
+Fl_Text_Display.o: Fl_Text_Display.cxx flstring.h ../FL/Fl_Export.H \
+ ../config.h ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H \
+ ../FL/Fl_Text_Buffer.H ../FL/Fl_Text_Display.H ../FL/fl_draw.H \
+ ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Scrollbar.H \
+ ../FL/Fl_Slider.H ../FL/Fl_Valuator.H ../FL/Fl_Text_Buffer.H \
+ ../FL/Fl_Window.H
+Fl_Text_Editor.o: Fl_Text_Editor.cxx flstring.h ../FL/Fl_Export.H \
+ ../config.h ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H \
+ ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H \
+ ../FL/Fl_Text_Editor.H ../FL/Fl_Text_Display.H ../FL/fl_draw.H \
+ ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H ../FL/Fl_Valuator.H \
+ ../FL/Fl_Text_Buffer.H ../FL/fl_ask.H
+Fl_Tile.o: Fl_Tile.cxx ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H \
+ ../FL/Fl_Tile.H ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Window.H
+Fl_Tiled_Image.o: Fl_Tiled_Image.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Tiled_Image.H ../FL/Fl_Image.H \
+ ../FL/fl_draw.H
+Fl_Tooltip.o: Fl_Tooltip.cxx ../FL/Fl_Tooltip.H ../FL/Fl.H \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/Fl_Widget.H \
+ ../FL/fl_draw.H ../FL/Fl_Menu_Window.H ../FL/Fl_Single_Window.H \
+ ../FL/Fl_Window.H ../FL/Fl_Group.H
+Fl_Valuator.o: Fl_Valuator.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Valuator.H ../FL/Fl_Widget.H ../FL/math.h \
+ flstring.h ../FL/Fl_Export.H ../config.h
+Fl_Value_Input.o: Fl_Value_Input.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Value_Input.H ../FL/Fl_Valuator.H \
+ ../FL/Fl_Widget.H ../FL/Fl_Input.H ../FL/Fl_Input_.H ../FL/Fl_Group.H \
+ ../FL/math.h
+Fl_Value_Output.o: Fl_Value_Output.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Value_Output.H ../FL/Fl_Valuator.H \
+ ../FL/Fl_Widget.H ../FL/fl_draw.H
+Fl_Value_Slider.o: Fl_Value_Slider.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Value_Slider.H ../FL/Fl_Slider.H \
+ ../FL/Fl_Valuator.H ../FL/Fl_Widget.H ../FL/fl_draw.H
+Fl_Widget.o: Fl_Widget.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Widget.H ../FL/Fl_Group.H ../FL/Fl_Tooltip.H \
+ ../FL/fl_draw.H flstring.h ../FL/Fl_Export.H ../config.h
+Fl_Window.o: Fl_Window.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H \
+ flstring.h ../FL/Fl_Export.H ../config.h
+Fl_Window_fullscreen.o: Fl_Window_fullscreen.cxx ../FL/Fl.H \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/x.H ../FL/Fl_Window.H \
+ ../FL/Fl_Group.H ../FL/Fl_Widget.H
+Fl_Window_hotspot.o: Fl_Window_hotspot.cxx ../FL/Fl.H \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/Fl_Window.H \
+ ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/x.H ../FL/Fl_Window.H
+Fl_Window_iconize.o: Fl_Window_iconize.cxx ../FL/x.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H
+Fl_Wizard.o: Fl_Wizard.cxx ../FL/Fl_Wizard.H ../FL/Fl_Group.H \
+ ../FL/Fl_Widget.H ../FL/Enumerations.H ../FL/Fl_Export.H \
+ ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/fl_draw.H
+Fl_XBM_Image.o: Fl_XBM_Image.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_XBM_Image.H ../FL/Fl_Bitmap.H \
+ ../FL/Fl_Image.H flstring.h ../FL/Fl_Export.H ../config.h
+Fl_XPM_Image.o: Fl_XPM_Image.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_XPM_Image.H ../FL/Fl_Pixmap.H \
+ ../FL/Fl_Image.H flstring.h ../FL/Fl_Export.H ../config.h
+Fl_abort.o: Fl_abort.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H flstring.h ../FL/Fl_Export.H ../config.h
+Fl_add_idle.o: Fl_add_idle.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H
+Fl_arg.o: Fl_arg.cxx ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H \
+ ../FL/x.H ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H \
+ ../FL/Fl_Window.H ../FL/Fl_Tooltip.H ../FL/Fl_Widget.H ../FL/filename.H \
+ ../FL/fl_draw.H flstring.h ../FL/Fl_Export.H ../config.h
+Fl_compose.o: Fl_compose.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H
+Fl_display.o: Fl_display.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H flstring.h ../FL/Fl_Export.H ../config.h
+Fl_get_key.o: Fl_get_key.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/x.H ../FL/Fl_Window.H ../FL/Fl_Group.H \
+ ../FL/Fl_Widget.H
+Fl_get_system_colors.o: Fl_get_system_colors.cxx ../FL/Fl.H \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/fl_draw.H ../FL/x.H \
+ ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/math.h \
+ flstring.h ../FL/Fl_Export.H ../config.h ../FL/Fl_Pixmap.H \
+ ../FL/Fl_Image.H ../FL/Fl_Tiled_Image.H tile.xpm
+Fl_grab.o: Fl_grab.cxx ../config.h ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/x.H ../FL/Fl_Window.H ../FL/Fl_Group.H \
+ ../FL/Fl_Widget.H
+Fl_lock.o: Fl_lock.cxx ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H \
+ ../config.h
+Fl_own_colormap.o: Fl_own_colormap.cxx ../config.h ../FL/Fl.H \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/x.H ../FL/Fl_Window.H \
+ ../FL/Fl_Group.H ../FL/Fl_Widget.H
+Fl_visual.o: Fl_visual.cxx ../config.h ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/x.H ../FL/Fl_Window.H ../FL/Fl_Group.H \
+ ../FL/Fl_Widget.H
+Fl_x.o: Fl_x.cxx ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H \
+ ../FL/x.H ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H \
+ ../FL/Fl_Window.H ../FL/Fl_Tooltip.H ../FL/Fl_Widget.H flstring.h \
+ ../FL/Fl_Export.H ../config.h
+filename_absolute.o: filename_absolute.cxx ../FL/filename.H \
+ ../FL/Fl_Export.H flstring.h ../FL/Fl_Export.H ../config.h
+filename_expand.o: filename_expand.cxx ../FL/filename.H ../FL/Fl_Export.H \
+ flstring.h ../FL/Fl_Export.H ../config.h
+filename_ext.o: filename_ext.cxx ../FL/filename.H ../FL/Fl_Export.H
+filename_isdir.o: filename_isdir.cxx flstring.h ../FL/Fl_Export.H \
+ ../config.h ../FL/filename.H ../FL/Fl_Export.H
+filename_list.o: filename_list.cxx ../FL/filename.H ../FL/Fl_Export.H \
+ flstring.h ../FL/Fl_Export.H ../config.h
+filename_match.o: filename_match.cxx ../FL/filename.H ../FL/Fl_Export.H
+filename_setext.o: filename_setext.cxx ../FL/filename.H ../FL/Fl_Export.H \
+ flstring.h ../FL/Fl_Export.H ../config.h
+fl_arc.o: fl_arc.cxx ../FL/fl_draw.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/math.h
+fl_arci.o: fl_arci.cxx ../FL/fl_draw.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/x.H ../FL/Fl_Window.H ../FL/Fl_Group.H \
+ ../FL/Fl_Widget.H
+fl_ask.o: fl_ask.cxx flstring.h ../FL/Fl_Export.H ../config.h ../FL/Fl.H \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/fl_ask.H ../FL/Fl_Box.H \
+ ../FL/Fl_Widget.H ../FL/Fl_Button.H ../FL/Fl_Return_Button.H \
+ ../FL/Fl_Button.H ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Input.H \
+ ../FL/Fl_Input_.H ../FL/Fl_Secret_Input.H ../FL/Fl_Input.H ../FL/x.H \
+ ../FL/Fl_Window.H ../FL/fl_draw.H
+fl_boxtype.o: fl_boxtype.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Widget.H ../FL/fl_draw.H ../config.h
+fl_color.o: fl_color.cxx Fl_XColor.H ../config.h ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl.H ../FL/Enumerations.H ../FL/x.H \
+ ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/fl_draw.H \
+ fl_cmap.h
+fl_cursor.o: fl_cursor.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H \
+ ../FL/x.H ../FL/Fl_Window.H ../FL/fl_draw.H
+fl_curve.o: fl_curve.cxx ../FL/fl_draw.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H
+fl_diamond_box.o: fl_diamond_box.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/fl_draw.H
+fl_dnd.o: fl_dnd.cxx fl_dnd_x.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H \
+ ../FL/x.H ../FL/Fl_Window.H flstring.h ../FL/Fl_Export.H ../config.h
+fl_draw.o: fl_draw.cxx ../FL/fl_draw.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Image.H flstring.h ../FL/Fl_Export.H \
+ ../config.h
+fl_draw_image.o: fl_draw_image.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H \
+ ../FL/Fl_Group.H ../FL/Fl_Widget.H Fl_XColor.H ../config.h \
+ ../FL/Enumerations.H flstring.h ../FL/Fl_Export.H
+fl_draw_pixmap.o: fl_draw_pixmap.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H \
+ ../FL/Fl_Group.H ../FL/Fl_Widget.H flstring.h ../FL/Fl_Export.H \
+ ../config.h
+fl_encoding_latin1.o: fl_encoding_latin1.cxx ../FL/fl_draw.H \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/Enumerations.H flstring.h \
+ ../FL/Fl_Export.H ../config.h
+fl_encoding_mac_roman.o: fl_encoding_mac_roman.cxx ../FL/fl_draw.H \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/Enumerations.H flstring.h \
+ ../FL/Fl_Export.H ../config.h
+fl_engraved_label.o: fl_engraved_label.cxx ../FL/Fl.H \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/Fl_Widget.H \
+ ../FL/fl_draw.H
+fl_file_dir.o: fl_file_dir.cxx flstring.h ../FL/Fl_Export.H ../config.h \
+ ../FL/filename.H ../FL/Fl_Export.H ../FL/Fl_File_Chooser.H ../FL/Fl.H \
+ ../FL/Enumerations.H ../FL/Fl_Double_Window.H ../FL/Fl_Window.H \
+ ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Group.H ../FL/Fl_Choice.H \
+ ../FL/Fl_Menu_.H ../FL/Fl_Menu_Item.H ../FL/Fl_Image.H \
+ ../FL/Fl_Menu_Button.H ../FL/Fl_Button.H ../FL/Fl_Preferences.H \
+ ../FL/Fl_Tile.H ../FL/Fl_File_Browser.H ../FL/Fl_Browser.H \
+ ../FL/Fl_Browser_.H ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H \
+ ../FL/Fl_Valuator.H ../FL/Fl_File_Icon.H ../FL/Fl.H ../FL/filename.H \
+ ../FL/Fl_Box.H ../FL/Fl_Check_Button.H ../FL/Fl_Light_Button.H \
+ ../FL/Fl_Button.H ../FL/Fl_File_Input.H ../FL/Fl_Input.H \
+ ../FL/Fl_Input_.H ../FL/Fl_Return_Button.H ../FL/fl_ask.H
+fl_font.o: fl_font.cxx flstring.h ../FL/Fl_Export.H ../config.h \
+ ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/fl_draw.H \
+ ../FL/x.H ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H \
+ Fl_Font.H fl_font_xft.cxx
+fl_gtk.o: fl_gtk.cxx ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H \
+ ../FL/fl_draw.H
+fl_labeltype.o: fl_labeltype.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Widget.H ../FL/Fl_Group.H ../FL/fl_draw.H \
+ ../FL/Fl_Image.H ../FL/Fl_Input_.H
+fl_line_style.o: fl_line_style.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H \
+ ../FL/Fl_Group.H ../FL/Fl_Widget.H flstring.h ../FL/Fl_Export.H \
+ ../config.h
+fl_open_uri.o: fl_open_uri.cxx ../FL/filename.H ../FL/Fl_Export.H \
+ flstring.h ../FL/Fl_Export.H ../config.h
+fl_oval_box.o: fl_oval_box.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/fl_draw.H
+fl_overlay.o: fl_overlay.cxx ../FL/x.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H \
+ ../FL/fl_draw.H
+fl_overlay_visual.o: fl_overlay_visual.cxx ../config.h
+fl_plastic.o: fl_plastic.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/fl_draw.H flstring.h ../FL/Fl_Export.H \
+ ../config.h
+fl_read_image.o: fl_read_image.cxx ../FL/x.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H \
+ ../FL/fl_draw.H flstring.h ../FL/Fl_Export.H ../config.h
+fl_rect.o: fl_rect.cxx ../config.h ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/x.H \
+ ../FL/Fl_Window.H ../FL/Fl_Group.H
+fl_round_box.o: fl_round_box.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/fl_draw.H
+fl_rounded_box.o: fl_rounded_box.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/fl_draw.H
+fl_set_font.o: fl_set_font.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/x.H ../FL/Fl_Window.H ../FL/Fl_Group.H \
+ ../FL/Fl_Widget.H ../FL/fl_draw.H flstring.h ../FL/Fl_Export.H \
+ ../config.h Fl_Font.H
+fl_set_fonts.o: fl_set_fonts.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/x.H ../FL/Fl_Window.H ../FL/Fl_Group.H \
+ ../FL/Fl_Widget.H Fl_Font.H ../config.h flstring.h ../FL/Fl_Export.H \
+ fl_set_fonts_xft.cxx
+fl_scroll_area.o: fl_scroll_area.cxx ../config.h ../FL/Fl.H \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/x.H ../FL/Fl_Window.H \
+ ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/fl_draw.H
+fl_shadow_box.o: fl_shadow_box.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/fl_draw.H
+fl_shortcut.o: fl_shortcut.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Widget.H ../FL/Fl_Button.H ../FL/fl_draw.H \
+ flstring.h ../FL/Fl_Export.H ../config.h ../FL/x.H ../FL/Fl_Window.H \
+ ../FL/Fl_Group.H
+fl_show_colormap.o: fl_show_colormap.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Single_Window.H ../FL/Fl_Window.H \
+ ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/fl_draw.H \
+ ../FL/fl_show_colormap.H ../config.h
+fl_symbols.o: fl_symbols.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/fl_draw.H ../FL/math.h flstring.h \
+ ../FL/Fl_Export.H ../config.h
+fl_vertex.o: fl_vertex.cxx ../config.h ../FL/fl_draw.H \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/x.H ../FL/Fl_Window.H \
+ ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl.H ../FL/math.h
+screen_xywh.o: screen_xywh.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/x.H ../FL/Fl_Window.H ../FL/Fl_Group.H \
+ ../FL/Fl_Widget.H ../config.h
+forms_compatability.o: forms_compatability.cxx ../FL/forms.H ../FL/Fl.H \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/Fl_Group.H \
+ ../FL/Fl_Widget.H ../FL/Fl_Window.H ../FL/fl_draw.H \
+ ../FL/Fl_FormsBitmap.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H \
+ ../FL/Fl_FormsPixmap.H ../FL/Fl_Pixmap.H ../FL/Fl_Box.H \
+ ../FL/Fl_Browser.H ../FL/Fl_Browser_.H ../FL/Fl_Scrollbar.H \
+ ../FL/Fl_Slider.H ../FL/Fl_Valuator.H ../FL/Fl_Button.H \
+ ../FL/Fl_Light_Button.H ../FL/Fl_Round_Button.H ../FL/Fl_Check_Button.H \
+ ../FL/Fl_Chart.H ../FL/Fl_Choice.H ../FL/Fl_Menu_.H \
+ ../FL/Fl_Menu_Item.H ../FL/Fl_Clock.H ../FL/Fl_Counter.H \
+ ../FL/Fl_Dial.H ../FL/Fl_Free.H ../FL/fl_ask.H ../FL/fl_show_colormap.H \
+ ../FL/filename.H ../FL/Fl_File_Chooser.H ../FL/Fl.H \
+ ../FL/Fl_Double_Window.H ../FL/Fl_Group.H ../FL/Fl_Choice.H \
+ ../FL/Fl_Menu_Button.H ../FL/Fl_Button.H ../FL/Fl_Preferences.H \
+ ../FL/Fl_Tile.H ../FL/Fl_File_Browser.H ../FL/Fl_File_Icon.H \
+ ../FL/Fl_Box.H ../FL/Fl_Check_Button.H ../FL/Fl_File_Input.H \
+ ../FL/Fl_Input.H ../FL/Fl_Input_.H ../FL/Fl_Return_Button.H \
+ ../FL/fl_ask.H ../FL/Fl_Input.H ../FL/Fl_Menu_Button.H \
+ ../FL/Fl_Positioner.H ../FL/Fl_Value_Slider.H ../FL/Fl_Timer.H \
+ ../FL/Fl_Repeat_Button.H
+forms_bitmap.o: forms_bitmap.cxx ../FL/forms.H ../FL/Fl.H \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/Fl_Group.H \
+ ../FL/Fl_Widget.H ../FL/Fl_Window.H ../FL/fl_draw.H \
+ ../FL/Fl_FormsBitmap.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H \
+ ../FL/Fl_FormsPixmap.H ../FL/Fl_Pixmap.H ../FL/Fl_Box.H \
+ ../FL/Fl_Browser.H ../FL/Fl_Browser_.H ../FL/Fl_Scrollbar.H \
+ ../FL/Fl_Slider.H ../FL/Fl_Valuator.H ../FL/Fl_Button.H \
+ ../FL/Fl_Light_Button.H ../FL/Fl_Round_Button.H ../FL/Fl_Check_Button.H \
+ ../FL/Fl_Chart.H ../FL/Fl_Choice.H ../FL/Fl_Menu_.H \
+ ../FL/Fl_Menu_Item.H ../FL/Fl_Clock.H ../FL/Fl_Counter.H \
+ ../FL/Fl_Dial.H ../FL/Fl_Free.H ../FL/fl_ask.H ../FL/fl_show_colormap.H \
+ ../FL/filename.H ../FL/Fl_File_Chooser.H ../FL/Fl.H \
+ ../FL/Fl_Double_Window.H ../FL/Fl_Group.H ../FL/Fl_Choice.H \
+ ../FL/Fl_Menu_Button.H ../FL/Fl_Button.H ../FL/Fl_Preferences.H \
+ ../FL/Fl_Tile.H ../FL/Fl_File_Browser.H ../FL/Fl_File_Icon.H \
+ ../FL/Fl_Box.H ../FL/Fl_Check_Button.H ../FL/Fl_File_Input.H \
+ ../FL/Fl_Input.H ../FL/Fl_Input_.H ../FL/Fl_Return_Button.H \
+ ../FL/fl_ask.H ../FL/Fl_Input.H ../FL/Fl_Menu_Button.H \
+ ../FL/Fl_Positioner.H ../FL/Fl_Value_Slider.H ../FL/Fl_Timer.H
+forms_free.o: forms_free.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Free.H ../FL/Fl_Widget.H
+forms_fselect.o: forms_fselect.cxx ../FL/forms.H ../FL/Fl.H \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/Fl_Group.H \
+ ../FL/Fl_Widget.H ../FL/Fl_Window.H ../FL/fl_draw.H \
+ ../FL/Fl_FormsBitmap.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H \
+ ../FL/Fl_FormsPixmap.H ../FL/Fl_Pixmap.H ../FL/Fl_Box.H \
+ ../FL/Fl_Browser.H ../FL/Fl_Browser_.H ../FL/Fl_Scrollbar.H \
+ ../FL/Fl_Slider.H ../FL/Fl_Valuator.H ../FL/Fl_Button.H \
+ ../FL/Fl_Light_Button.H ../FL/Fl_Round_Button.H ../FL/Fl_Check_Button.H \
+ ../FL/Fl_Chart.H ../FL/Fl_Choice.H ../FL/Fl_Menu_.H \
+ ../FL/Fl_Menu_Item.H ../FL/Fl_Clock.H ../FL/Fl_Counter.H \
+ ../FL/Fl_Dial.H ../FL/Fl_Free.H ../FL/fl_ask.H ../FL/fl_show_colormap.H \
+ ../FL/filename.H ../FL/Fl_File_Chooser.H ../FL/Fl.H \
+ ../FL/Fl_Double_Window.H ../FL/Fl_Group.H ../FL/Fl_Choice.H \
+ ../FL/Fl_Menu_Button.H ../FL/Fl_Button.H ../FL/Fl_Preferences.H \
+ ../FL/Fl_Tile.H ../FL/Fl_File_Browser.H ../FL/Fl_File_Icon.H \
+ ../FL/Fl_Box.H ../FL/Fl_Check_Button.H ../FL/Fl_File_Input.H \
+ ../FL/Fl_Input.H ../FL/Fl_Input_.H ../FL/Fl_Return_Button.H \
+ ../FL/fl_ask.H ../FL/Fl_Input.H ../FL/Fl_Menu_Button.H \
+ ../FL/Fl_Positioner.H ../FL/Fl_Value_Slider.H ../FL/Fl_Timer.H \
+ flstring.h ../FL/Fl_Export.H ../config.h
+forms_pixmap.o: forms_pixmap.cxx ../FL/forms.H ../FL/Fl.H \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/Fl_Group.H \
+ ../FL/Fl_Widget.H ../FL/Fl_Window.H ../FL/fl_draw.H \
+ ../FL/Fl_FormsBitmap.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H \
+ ../FL/Fl_FormsPixmap.H ../FL/Fl_Pixmap.H ../FL/Fl_Box.H \
+ ../FL/Fl_Browser.H ../FL/Fl_Browser_.H ../FL/Fl_Scrollbar.H \
+ ../FL/Fl_Slider.H ../FL/Fl_Valuator.H ../FL/Fl_Button.H \
+ ../FL/Fl_Light_Button.H ../FL/Fl_Round_Button.H ../FL/Fl_Check_Button.H \
+ ../FL/Fl_Chart.H ../FL/Fl_Choice.H ../FL/Fl_Menu_.H \
+ ../FL/Fl_Menu_Item.H ../FL/Fl_Clock.H ../FL/Fl_Counter.H \
+ ../FL/Fl_Dial.H ../FL/Fl_Free.H ../FL/fl_ask.H ../FL/fl_show_colormap.H \
+ ../FL/filename.H ../FL/Fl_File_Chooser.H ../FL/Fl.H \
+ ../FL/Fl_Double_Window.H ../FL/Fl_Group.H ../FL/Fl_Choice.H \
+ ../FL/Fl_Menu_Button.H ../FL/Fl_Button.H ../FL/Fl_Preferences.H \
+ ../FL/Fl_Tile.H ../FL/Fl_File_Browser.H ../FL/Fl_File_Icon.H \
+ ../FL/Fl_Box.H ../FL/Fl_Check_Button.H ../FL/Fl_File_Input.H \
+ ../FL/Fl_Input.H ../FL/Fl_Input_.H ../FL/Fl_Return_Button.H \
+ ../FL/fl_ask.H ../FL/Fl_Input.H ../FL/Fl_Menu_Button.H \
+ ../FL/Fl_Positioner.H ../FL/Fl_Value_Slider.H ../FL/Fl_Timer.H
+forms_timer.o: forms_timer.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Timer.H ../FL/Fl_Widget.H ../FL/fl_draw.H
+Fl_Gl_Choice.o: Fl_Gl_Choice.cxx ../config.h ../FL/Fl.H \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/x.H ../FL/Fl_Window.H \
+ ../FL/Fl_Group.H ../FL/Fl_Widget.H Fl_Gl_Choice.H ../FL/gl_draw.H \
+ ../FL/gl.h flstring.h ../FL/Fl_Export.H
+Fl_Gl_Overlay.o: Fl_Gl_Overlay.cxx ../config.h ../FL/Fl.H \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/x.H ../FL/Fl_Window.H \
+ ../FL/Fl_Group.H ../FL/Fl_Widget.H Fl_Gl_Choice.H ../FL/Fl_Gl_Window.H
+Fl_Gl_Window.o: Fl_Gl_Window.cxx flstring.h ../FL/Fl_Export.H ../config.h \
+ ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/x.H \
+ ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H Fl_Gl_Choice.H \
+ ../FL/Fl_Gl_Window.H
+freeglut_geometry.o: freeglut_geometry.cxx ../FL/glut.H ../FL/gl.h \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/Fl.H ../FL/Fl_Gl_Window.H \
+ ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/math.h
+freeglut_stroke_mono_roman.o: freeglut_stroke_mono_roman.cxx ../FL/glut.H \
+ ../FL/gl.h ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/Fl.H \
+ ../FL/Fl_Gl_Window.H ../FL/Fl_Window.H ../FL/Fl_Group.H \
+ ../FL/Fl_Widget.H
+freeglut_stroke_roman.o: freeglut_stroke_roman.cxx ../FL/glut.H \
+ ../FL/gl.h ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/Fl.H \
+ ../FL/Fl_Gl_Window.H ../FL/Fl_Window.H ../FL/Fl_Group.H \
+ ../FL/Fl_Widget.H
+freeglut_teapot.o: freeglut_teapot.cxx ../FL/glut.H ../FL/gl.h \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/Fl.H ../FL/Fl_Gl_Window.H \
+ ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H \
+ freeglut_teapot_data.h
+gl_draw.o: gl_draw.cxx flstring.h ../FL/Fl_Export.H ../config.h \
+ ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/gl.h ../FL/x.H \
+ ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/fl_draw.H \
+ Fl_Gl_Choice.H Fl_Font.H
+gl_start.o: gl_start.cxx ../config.h ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H \
+ ../FL/x.H ../FL/Fl_Window.H ../FL/fl_draw.H Fl_Gl_Choice.H
+glut_compatability.o: glut_compatability.cxx flstring.h ../FL/Fl_Export.H \
+ ../config.h ../FL/glut.H ../FL/gl.h ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl.H ../FL/Fl_Gl_Window.H ../FL/Fl_Window.H \
+ ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Menu_Item.H \
+ ../FL/Fl_Image.H
+glut_font.o: glut_font.cxx ../config.h ../FL/glut.H ../FL/gl.h \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/Fl.H ../FL/Fl_Gl_Window.H \
+ ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H
+fl_images_core.o: fl_images_core.cxx ../FL/Fl_Shared_Image.H \
+ ../FL/Fl_Image.H ../FL/Enumerations.H ../FL/Fl_Export.H \
+ ../FL/Fl_BMP_Image.H ../FL/Fl_GIF_Image.H ../FL/Fl_Pixmap.H \
+ ../FL/Fl_JPEG_Image.H ../FL/Fl_PNG_Image.H ../FL/Fl_PNM_Image.H \
+ flstring.h ../FL/Fl_Export.H ../config.h
+Fl_BMP_Image.o: Fl_BMP_Image.cxx ../FL/Fl_BMP_Image.H ../FL/Fl_Image.H \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../config.h
+Fl_File_Icon2.o: Fl_File_Icon2.cxx flstring.h ../FL/Fl_Export.H \
+ ../config.h ../FL/math.h ../FL/Fl_File_Icon.H ../FL/Fl.H \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/Fl_Shared_Image.H \
+ ../FL/Fl_Image.H ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/filename.H
+Fl_GIF_Image.o: Fl_GIF_Image.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_GIF_Image.H ../FL/Fl_Pixmap.H \
+ ../FL/Fl_Image.H flstring.h ../FL/Fl_Export.H ../config.h
+Fl_Help_Dialog.o: Fl_Help_Dialog.cxx ../FL/Fl_Help_Dialog.H ../FL/Fl.H \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/Fl_Double_Window.H \
+ ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Group.H \
+ ../FL/Fl_Button.H ../FL/Fl_Input.H ../FL/Fl_Input_.H ../FL/Fl_Box.H \
+ ../FL/Fl_Help_View.H ../FL/Fl.H ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H \
+ ../FL/Fl_Valuator.H ../FL/fl_draw.H ../FL/Fl_Shared_Image.H \
+ ../FL/Fl_Image.H flstring.h ../FL/Fl_Export.H ../config.h \
+ ../FL/fl_ask.H
+Fl_JPEG_Image.o: Fl_JPEG_Image.cxx ../FL/Fl_JPEG_Image.H ../FL/Fl_Image.H \
+ ../FL/Enumerations.H ../FL/Fl_Export.H ../config.h
+Fl_PNG_Image.o: Fl_PNG_Image.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_PNG_Image.H ../FL/Fl_Image.H ../config.h
+Fl_PNM_Image.o: Fl_PNM_Image.cxx ../FL/Fl.H ../FL/Enumerations.H \
+ ../FL/Fl_Export.H ../FL/Fl_PNM_Image.H ../FL/Fl_Image.H flstring.h \
+ ../FL/Fl_Export.H ../config.h
+fl_call_main.o: fl_call_main.c
+flstring.o: flstring.c flstring.h ../FL/Fl_Export.H ../config.h
+scandir.o: scandir.c flstring.h ../FL/Fl_Export.H ../config.h
+numericsort.o: numericsort.c ../config.h ../FL/filename.H \
+ ../FL/Fl_Export.H
+vsnprintf.o: vsnprintf.c flstring.h ../FL/Fl_Export.H ../config.h
diff --git a/third_party/windows/fltk-1.1.10/src/makefile.wat b/third_party/windows/fltk-1.1.10/src/makefile.wat new file mode 100644 index 0000000..4f347dc --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/makefile.wat @@ -0,0 +1,235 @@ +#
+# "$Id: makefile.wat 5699 2007-02-20 17:02:41Z matt $"
+#
+# Library makefile for the Fast Light Tool Kit (FLTK).
+#
+# Copyright 1998-2004 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 to "fltk-bugs@fltk.org".
+#
+
+CPPFILES = &
+ Fl.obj &
+ Fl_Adjuster.obj &
+ Fl_Bitmap.obj &
+ Fl_Browser.obj &
+ Fl_Browser_.obj &
+ Fl_Browser_load.obj &
+ Fl_Box.obj &
+ Fl_Button.obj &
+ Fl_Chart.obj &
+ Fl_Check_Browser.obj &
+ Fl_Check_Button.obj &
+ Fl_Choice.obj &
+ Fl_Clock.obj &
+ Fl_Color_Chooser.obj &
+ Fl_Counter.obj &
+ Fl_Dial.obj &
+ Fl_Double_Window.obj &
+ Fl_File_Browser.obj &
+ Fl_File_Chooser.obj &
+ Fl_File_Chooser2.obj &
+ Fl_File_Icon.obj &
+ Fl_File_Input.obj &
+ Fl_Group.obj &
+ Fl_Help_View.obj &
+ Fl_Image.obj &
+ Fl_Input.obj &
+ Fl_Input_.obj &
+ Fl_Light_Button.obj &
+ Fl_Menu.obj &
+ Fl_Menu_.obj &
+ Fl_Menu_Bar.obj &
+ Fl_Sys_Menu_Bar.obj &
+ Fl_Menu_Button.obj &
+ Fl_Menu_Window.obj &
+ Fl_Menu_add.obj &
+ Fl_Menu_global.obj &
+ Fl_Multi_Label.obj &
+ Fl_Overlay_Window.obj &
+ Fl_Pack.obj &
+ Fl_Pixmap.obj &
+ Fl_Positioner.obj &
+ Fl_Preferences.obj &
+ Fl_Progress.obj &
+ Fl_Repeat_Button.obj &
+ Fl_Return_Button.obj &
+ Fl_Roller.obj &
+ Fl_Round_Button.obj &
+ Fl_Scroll.obj &
+ Fl_Scrollbar.obj &
+ Fl_Shared_Image.obj &
+ Fl_Single_Window.obj &
+ Fl_Slider.obj &
+ Fl_Tabs.obj &
+ Fl_Text_Buffer.obj &
+ Fl_Text_Display.obj &
+ Fl_Text_Editor.obj &
+ Fl_Tile.obj &
+ Fl_Tiled_Image.obj &
+ Fl_Tooltip.obj &
+ Fl_Valuator.obj &
+ Fl_Value_Input.obj &
+ Fl_Value_Output.obj &
+ Fl_Value_Slider.obj &
+ Fl_Widget.obj &
+ Fl_Window.obj &
+ Fl_Window_fullscreen.obj &
+ Fl_Window_hotspot.obj &
+ Fl_Window_iconize.obj &
+ Fl_Wizard.obj &
+ Fl_XBM_Image.obj &
+ Fl_XPM_Image.obj &
+ Fl_abort.obj &
+ Fl_add_idle.obj &
+ Fl_arg.obj &
+ Fl_compose.obj &
+ Fl_display.obj &
+ Fl_get_key.obj &
+ Fl_get_system_colors.obj &
+ Fl_grab.obj &
+ Fl_lock.obj &
+ Fl_own_colormap.obj &
+ Fl_visual.obj &
+ Fl_x.obj &
+ filename_absolute.obj &
+ filename_expand.obj &
+ filename_ext.obj &
+ filename_isdir.obj &
+ filename_list.obj &
+ filename_match.obj &
+ filename_setext.obj &
+ fl_arc.obj &
+ fl_arci.obj &
+ fl_ask.obj &
+ fl_boxtype.obj &
+ fl_color.obj &
+ fl_cursor.obj &
+ fl_curve.obj &
+ fl_diamond_box.obj &
+ fl_dnd.obj &
+ fl_draw.obj &
+ fl_draw_image.obj &
+ fl_draw_pixmap.obj &
+ fl_encoding_latin1.obj &
+ fl_encoding_mac_roman.obj &
+ fl_engraved_label.obj &
+ fl_file_dir.obj &
+ fl_font.obj &
+ fl_gtk.obj &
+ fl_labeltype.obj &
+ fl_line_style.obj &
+ fl_open_uri.obj &
+ fl_oval_box.obj &
+ fl_overlay.obj &
+ fl_overlay_visual.obj &
+ fl_plastic.obj &
+ fl_read_image.obj &
+ fl_rect.obj &
+ fl_round_box.obj &
+ fl_rounded_box.obj &
+ fl_set_font.obj &
+ fl_set_fonts.obj &
+ fl_scroll_area.obj &
+ fl_shadow_box.obj &
+ fl_shortcut.obj &
+ fl_show_colormap.obj &
+ fl_symbols.obj &
+ fl_vertex.obj &
+ screen_xywh.obj
+
+FLCPPFILES = &
+ forms_compatability.obj &
+ forms_bitmap.obj &
+ forms_free.obj &
+ forms_fselect.obj &
+ forms_pixmap.obj &
+ forms_timer.obj
+
+GLCPPFILES = &
+ Fl_Gl_Choice.obj &
+ Fl_Gl_Overlay.obj &
+ Fl_Gl_Window.obj &
+ freeglut_geometry.obj &
+ freeglut_stroke_mono_roman.obj &
+ freeglut_stroke_roman.obj &
+ freeglut_teapot.obj &
+ gl_draw.obj &
+ gl_start.obj &
+ glut_compatability.obj &
+ glut_font.obj
+
+IMGCPPFILES = &
+ fl_images_core.obj &
+ Fl_BMP_Image.obj &
+ Fl_File_Icon2.obj &
+ Fl_GIF_Image.obj &
+ Fl_Help_Dialog.obj &
+ Fl_JPEG_Image.obj &
+ Fl_PNG_Image.obj &
+ Fl_PNM_Image.obj
+
+CFILES = fl_call_main.obj flstring.obj scandir.obj numericsort.obj vsnprintf.obj
+
+################################################################
+
+!include ../watcom.mif
+
+OBJECTS = $(CPPFILES) $(CFILES)
+FLOBJECTS = $(FLCPPFILES)
+GLOBJECTS = $(GLCPPFILES)
+IMGOBJECTS = $(IMGCPPFILES)
+
+# The four basic fltk libraries are defined in ../watcom.mif, so that appliactions
+# can also use them.
+all: $(LIBNAME) &
+ $(LIBNAMEFL) &
+ $(LIBNAMEGL) &
+ $(LIBNAMEIMG)
+
+# $(DSONAME) &
+# $(FLDSONAME) &
+# $(GLDSONAME) &
+# $(IMGDSONAME)
+
+
+$(LIBNAME): $(OBJECTS)
+ $(LIB) $(LIBOPTS) $@ $<
+
+$(LIBNAMEFL): $(FLOBJECTS)
+ $(LIB) $(LIBOPTS) $@ $<
+
+$(LIBNAMEGL): $(GLOBJECTS)
+ $(LIB) $(LIBOPTS) $@ $<
+
+$(LIBNAMEIMG): $(IMGOBJECTS)
+ $(LIB) $(LIBOPTS) $@ $<
+
+#
+# Clean all directories
+#
+clean : .SYMBOLIC
+ @echo Cleaning up.
+CLEANEXTS = exe map sym obj lk1
+ @for %a in ($(CLEANEXTS)) do -rm -f $(ODIR)\*.%a
+ -rm -f *.err
+ -rm -f $(LIBNAME)
+ -rm -f $(LIBNAMEFL)
+ -rm -f $(LIBNAMEGL)
+ -rm -f $(LIBNAMEIMG)
+
diff --git a/third_party/windows/fltk-1.1.10/src/mediumarrow.h b/third_party/windows/fltk-1.1.10/src/mediumarrow.h new file mode 100644 index 0000000..9952e20 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/mediumarrow.h @@ -0,0 +1,6 @@ +#define mediumarrow_width 16
+#define mediumarrow_height 16
+static unsigned char mediumarrow_bits[] = {
+ 0x40, 0x00, 0x60, 0x00, 0x70, 0x00, 0x78, 0x00, 0xfc, 0x3f, 0x78, 0x00,
+ 0x70, 0x00, 0x60, 0x02, 0x40, 0x06, 0x00, 0x0e, 0x00, 0x1e, 0xfc, 0x3f,
+ 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x06, 0x00, 0x02};
diff --git a/third_party/windows/fltk-1.1.10/src/new.xbm b/third_party/windows/fltk-1.1.10/src/new.xbm new file mode 100644 index 0000000..4f8665b --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/new.xbm @@ -0,0 +1,6 @@ +#define new_width 16
+#define new_height 16
+static unsigned char new_bits[] = {
+ 0x00, 0x00, 0x78, 0x00, 0x84, 0x00, 0x02, 0x01, 0x01, 0xfe, 0x01, 0x80,
+ 0x31, 0x80, 0x31, 0x80, 0xfd, 0x80, 0xfd, 0x80, 0x31, 0x80, 0x31, 0x80,
+ 0x01, 0x80, 0x01, 0x80, 0xff, 0xff, 0x00, 0x00};
diff --git a/third_party/windows/fltk-1.1.10/src/ns.xbm b/third_party/windows/fltk-1.1.10/src/ns.xbm new file mode 100644 index 0000000..208f952 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/ns.xbm @@ -0,0 +1,8 @@ +#define ns_width 16
+#define ns_height 16
+#define ns_x_hot 8
+#define ns_y_hot 8
+static unsigned char ns_bits[] = {
+ 0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0x80, 0x01, 0x80, 0x01,
+ 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
+ 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00};
diff --git a/third_party/windows/fltk-1.1.10/src/ns_mask.xbm b/third_party/windows/fltk-1.1.10/src/ns_mask.xbm new file mode 100644 index 0000000..6607ac2 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/ns_mask.xbm @@ -0,0 +1,8 @@ +#define ns_mask_width 16
+#define ns_mask_height 16
+#define ns_mask_x_hot 8
+#define ns_mask_y_hot 8
+static unsigned char ns_mask_bits[] = {
+ 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f, 0xf0, 0x0f, 0xc0, 0x03,
+ 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xf0, 0x0f,
+ 0xf0, 0x0f, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01};
diff --git a/third_party/windows/fltk-1.1.10/src/numericsort.c b/third_party/windows/fltk-1.1.10/src/numericsort.c new file mode 100644 index 0000000..cbc8971 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/numericsort.c @@ -0,0 +1,111 @@ +/*
+ * "$Id: numericsort.c 4288 2005-04-16 00:13:17Z mike $"
+ *
+ * Numeric sorting routine for the Fast Light Tool Kit (FLTK).
+ *
+ * Copyright 1998-2005 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
+ */
+
+/* My own scandir sorting function, useful for the film industry where
+ we have many files with numbers in their names: */
+
+#include <config.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include <FL/filename.H>
+
+#if !defined(WIN32) || defined(__CYGWIN__)
+# ifdef HAVE_DIRENT_H
+# include <dirent.h>
+# else
+# define dirent direct
+# if HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif /* HAVE_SYS_NDIR_H */
+# if HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif /* HAVE_SYS_DIR_H */
+# if HAVE_NDIR_H
+# include <ndir.h>
+# endif /* HAVE_NDIR_H */
+# endif /* HAVE_DIRENT_H */
+#endif /* !WIN32 || __CYGWIN__ */
+
+/*
+ * 'numericsort()' - Compare two directory entries, possibly with
+ * a case-insensitive comparison...
+ */
+
+static int numericsort(struct dirent **A, struct dirent **B, int cs) {
+ const char* a = (*A)->d_name;
+ const char* b = (*B)->d_name;
+ int ret = 0;
+ for (;;) {
+ if (isdigit(*a & 255) && isdigit(*b & 255)) {
+ int diff,magdiff;
+ while (*a == '0') a++;
+ while (*b == '0') b++;
+ while (isdigit(*a & 255) && *a == *b) {a++; b++;}
+ diff = (isdigit(*a & 255) && isdigit(*b & 255)) ? *a - *b : 0;
+ magdiff = 0;
+ while (isdigit(*a & 255)) {magdiff++; a++;}
+ while (isdigit(*b & 255)) {magdiff--; b++;}
+ if (magdiff) {ret = magdiff; break;} /* compare # of significant digits*/
+ if (diff) {ret = diff; break;} /* compare first non-zero digit */
+ } else {
+ if (cs) {
+ /* compare case-sensitive */
+ if ((ret = *a-*b)) break;
+ } else {
+ /* compare case-insensitve */
+ if ((ret = tolower(*a & 255)-tolower(*b & 255))) break;
+ }
+
+ if (!*a) break;
+ a++; b++;
+ }
+ }
+ if (!ret) return 0;
+ else return (ret < 0) ? -1 : 1;
+}
+
+/*
+ * 'fl_casenumericsort()' - Compare directory entries with case-sensitivity.
+ */
+
+int fl_casenumericsort(struct dirent **A, struct dirent **B) {
+ return numericsort(A, B, 0);
+}
+
+/*
+ * 'fl_numericsort()' - Compare directory entries with case-sensitivity.
+ */
+
+int fl_numericsort(struct dirent **A, struct dirent **B) {
+ return numericsort(A, B, 1);
+}
+
+/*
+ * End of "$Id: numericsort.c 4288 2005-04-16 00:13:17Z mike $".
+ */
diff --git a/third_party/windows/fltk-1.1.10/src/scandir.c b/third_party/windows/fltk-1.1.10/src/scandir.c new file mode 100644 index 0000000..5e01215 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/scandir.c @@ -0,0 +1,124 @@ +/* Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C 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.
+
+The GNU C 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. */
+
+#if defined(WIN32) && !defined(__CYGWIN__)
+# include "scandir_win32.c"
+#else
+
+# include "flstring.h"
+
+# if !HAVE_SCANDIR
+# include <stdlib.h>
+# include <sys/types.h>
+# include <errno.h>
+
+# if HAVE_DIRENT_H
+# include <dirent.h>
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+# else
+# define dirent direct
+# define NAMLEN(dirent) (dirent)->d_namlen
+# if HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif
+# if HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif
+# if HAVE_NDIR_H
+# include <ndir.h>
+# endif
+# endif
+
+int
+fl_scandir(const char *dir, struct dirent ***namelist,
+ int (*select)(struct dirent *),
+ int (*compar)(struct dirent **, struct dirent **))
+{
+ DIR *dp = opendir (dir);
+ struct dirent **v = NULL;
+ size_t vsize = 0, i;
+ struct dirent *d;
+ int save;
+
+ if (dp == NULL)
+ return -1;
+
+ save = errno;
+ errno = 0;
+
+ i = 0;
+ while ((d = readdir (dp)) != NULL)
+ if (select == NULL || (*select) (d))
+ {
+ size_t dsize;
+
+ if (i == vsize)
+ {
+ struct dirent **newv;
+ if (vsize == 0)
+ vsize = 10;
+ else
+ vsize *= 2;
+ newv = (struct dirent **) realloc (v, vsize * sizeof (*v));
+ if (newv == NULL)
+ {
+ lose:
+ errno = ENOMEM;
+ break;
+ }
+ v = newv;
+ }
+
+# define _D_EXACT_NAMLEN(d) (strlen ((d)->d_name))
+# define _D_ALLOC_NAMLEN(d) (sizeof (d)->d_name > 1 ? sizeof (d)->d_name : \
+ _D_EXACT_NAMLEN (d) + 1)
+
+ dsize = &d->d_name[_D_ALLOC_NAMLEN (d)] - (char *) d;
+ v[i] = (struct dirent *) malloc (dsize);
+ if (v[i] == NULL)
+ goto lose;
+
+ memcpy (v[i++], d, dsize);
+ }
+
+ if (errno != 0)
+ {
+ save = errno;
+ (void) closedir (dp);
+ while (i > 0)
+ free (v[--i]);
+ free (v);
+ errno = save;
+ return -1;
+ }
+
+ (void) closedir (dp);
+ errno = save;
+
+ /* Sort the list if we have a comparison function to sort with. */
+ if (compar) qsort (v, i, sizeof (*v), (int (*)(const void *, const void *))compar);
+ *namelist = v;
+ return i;
+}
+
+# endif
+#endif
+
+/*
+ * End of "$Id: scandir.c 4052 2005-02-24 21:55:12Z mike $".
+ */
diff --git a/third_party/windows/fltk-1.1.10/src/scandir_win32.c b/third_party/windows/fltk-1.1.10/src/scandir_win32.c new file mode 100644 index 0000000..128060b --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/scandir_win32.c @@ -0,0 +1,115 @@ +/*
+ * "$Id: scandir_win32.c 4548 2005-08-29 20:16:36Z matt $"
+ *
+ * WIN32 scandir function for the Fast Light Tool Kit (FLTK).
+ *
+ * Copyright 1998-2005 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
+ */
+
+#ifndef __CYGWIN__
+/* Emulation of posix scandir() call */
+
+#include <FL/filename.H>
+#include "flstring.h"
+#include <windows.h>
+#include <stdlib.h>
+
+int fl_scandir(const char *dirname, struct dirent ***namelist,
+ int (*select)(struct dirent *),
+ int (*compar)(struct dirent **, struct dirent **)) {
+ int len;
+ char *findIn, *d, is_dir = 0;
+ WIN32_FIND_DATA find;
+ HANDLE h;
+ int nDir = 0, NDir = 0;
+ struct dirent **dir = 0, *selectDir;
+ unsigned long ret;
+
+ len = strlen(dirname);
+ findIn = (char *)malloc((size_t)(len+5));
+
+ if (!findIn) return -1;
+
+ strcpy(findIn, dirname);
+ for (d = findIn; *d; d++) if (*d=='/') *d='\\';
+ if ((len==0)) { strcpy(findIn, ".\\*"); }
+ if ((len==2)&&findIn[1]==':'&&isalpha(findIn[0])) { *d++ = '\\'; *d = 0; }
+ if ((len==1)&& (d[-1]=='.')) { strcpy(findIn, ".\\*"); is_dir = 1; }
+ if ((len>0) && (d[-1]=='\\')) { *d++ = '*'; *d = 0; is_dir = 1; }
+ if ((len>1) && (d[-1]=='.') && (d[-2]=='\\')) { d[-1] = '*'; is_dir = 1; }
+ if (!is_dir) { /* this file may still be a directory that we need to list */
+ DWORD attr = GetFileAttributes(findIn);
+ if (attr&FILE_ATTRIBUTE_DIRECTORY)
+ strcpy(d, "\\*");
+ }
+ if ((h=FindFirstFile(findIn, &find))==INVALID_HANDLE_VALUE) {
+ free(findIn);
+ ret = GetLastError();
+ if (ret != ERROR_NO_MORE_FILES) {
+ nDir = -1;
+ }
+ *namelist = dir;
+ return nDir;
+ }
+ do {
+ selectDir=(struct dirent*)malloc(sizeof(struct dirent)+strlen(find.cFileName)+2);
+ strcpy(selectDir->d_name, find.cFileName);
+ if (find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ /* Append a trailing slash to directory names... */
+ strcat(selectDir->d_name, "/");
+ }
+ if (!select || (*select)(selectDir)) {
+ if (nDir==NDir) {
+ struct dirent **tempDir = (struct dirent **)calloc(sizeof(struct dirent*), (size_t)(NDir+33));
+ if (NDir) memcpy(tempDir, dir, sizeof(struct dirent*)*NDir);
+ if (dir) free(dir);
+ dir = tempDir;
+ NDir += 32;
+ }
+ dir[nDir] = selectDir;
+ nDir++;
+ dir[nDir] = 0;
+ } else {
+ free(selectDir);
+ }
+ } while (FindNextFile(h, &find));
+ ret = GetLastError();
+ if (ret != ERROR_NO_MORE_FILES) {
+ /* don't return an error code, because the dir list may still be valid
+ up to this point */
+ }
+ FindClose(h);
+
+ free (findIn);
+
+ if (compar) qsort(dir, (size_t)nDir, sizeof(*dir),
+ (int(*)(const void*, const void*))compar);
+
+ *namelist = dir;
+ return nDir;
+}
+
+#endif
+
+/*
+ * End of "$Id: scandir_win32.c 4548 2005-08-29 20:16:36Z matt $".
+ */
diff --git a/third_party/windows/fltk-1.1.10/src/screen_xywh.cxx b/third_party/windows/fltk-1.1.10/src/screen_xywh.cxx new file mode 100644 index 0000000..a393666 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/screen_xywh.cxx @@ -0,0 +1,256 @@ +//
+// "$Id: screen_xywh.cxx 5848 2007-05-20 16:18:31Z mike $"
+//
+// Screen/monitor bounding box API for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2005 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/x.H>
+#include <config.h>
+
+
+// Number of screens...
+static int num_screens = 0;
+
+#ifdef WIN32
+# if !defined(HMONITOR_DECLARED) && (_WIN32_WINNT < 0x0500)
+# define COMPILE_MULTIMON_STUBS
+# include <multimon.h>
+# endif // !HMONITOR_DECLARED && _WIN32_WINNT < 0x0500
+
+// We go the much more difficult route of individually picking some multi-screen
+// functions from the USER32.DLL . If these functions are not available, we
+// will gracefully fall back to single monitor support.
+//
+// If we were to insist on the existence of "EnumDisplayMonitors" and
+// "GetMonitorInfoA", it would be impossible to use FLTK on Windows 2000
+// before SP2 or earlier.
+
+// BOOL EnumDisplayMonitors(HDC, LPCRECT, MONITORENUMPROC, LPARAM)
+typedef BOOL (WINAPI* fl_edm_func)(HDC, LPCRECT, MONITORENUMPROC, LPARAM);
+// BOOL GetMonitorInfo(HMONITOR, LPMONITORINFO)
+typedef BOOL (WINAPI* fl_gmi_func)(HMONITOR, LPMONITORINFO);
+
+static fl_gmi_func fl_gmi = NULL; // used to get a proc pointer for GetMonitorInfoA
+
+static RECT screens[16];
+
+static BOOL CALLBACK screen_cb(HMONITOR mon, HDC, LPRECT r, LPARAM) {
+ if (num_screens >= 16) return TRUE;
+
+ MONITORINFO mi;
+ mi.cbSize = sizeof(mi);
+
+// GetMonitorInfo(mon, &mi);
+// (but we use our self-aquired function pointer instead)
+ if (fl_gmi(mon, &mi)) {
+ screens[num_screens] = mi.rcWork;
+ num_screens ++;
+ }
+ return TRUE;
+}
+
+static void screen_init() {
+ // Since not all versions of Windows include multiple monitor support,
+ // we do a run-time check for the required functions...
+ HMODULE hMod = GetModuleHandle("USER32.DLL");
+
+ if (hMod) {
+ // check that EnumDisplayMonitors is available
+ fl_edm_func fl_edm = (fl_edm_func)GetProcAddress(hMod, "EnumDisplayMonitors");
+
+ if (fl_edm) {
+ // We do have EnumDisplayMonitors, so lets find out how many monitors...
+ num_screens = GetSystemMetrics(SM_CMONITORS);
+
+ if (num_screens > 1) {
+ // If there is more than 1 monitor, enumerate them...
+ fl_gmi = (fl_gmi_func)GetProcAddress(hMod, "GetMonitorInfoA");
+
+ if (fl_gmi) {
+ // We have GetMonitorInfoA, enumerate all the screens...
+ num_screens = 0;
+// EnumDisplayMonitors(0,0,screen_cb,0);
+// (but we use our self-aquired function pointer instead)
+ fl_edm(0, 0, screen_cb, 0);
+ return;
+ }
+ }
+ }
+ }
+
+ // If we get here, assume we have 1 monitor...
+ num_screens = 1;
+}
+#elif defined(__APPLE__)
+XRectangle screens[16];
+
+static void screen_init() {
+ GDHandle gd;
+
+ for (gd = GetDeviceList(), num_screens = 0; gd; gd = GetNextDevice(gd)) {
+ GDPtr gp = *gd;
+ screens[num_screens].x = gp->gdRect.left;
+ screens[num_screens].y = gp->gdRect.top;
+ screens[num_screens].width = gp->gdRect.right - gp->gdRect.left;
+ screens[num_screens].height = gp->gdRect.bottom - gp->gdRect.top;
+
+ num_screens ++;
+ if (num_screens >= 16) break;
+ }
+}
+#elif HAVE_XINERAMA
+# include <X11/extensions/Xinerama.h>
+
+// Screen data...
+static XineramaScreenInfo *screens;
+
+static void screen_init() {
+ if (!fl_display) fl_open_display();
+
+ if (XineramaIsActive(fl_display)) {
+ screens = XineramaQueryScreens(fl_display, &num_screens);
+ } else num_screens = 1;
+}
+#else
+static void screen_init() {
+ num_screens = 1;
+}
+#endif // WIN32
+
+
+// Return the number of screens...
+int Fl::screen_count() {
+ if (!num_screens) screen_init();
+
+ return num_screens;
+}
+
+// Return the screen bounding rect for the given mouse position...
+void Fl::screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my) {
+ if (!num_screens) screen_init();
+
+#ifdef WIN32
+ if (num_screens > 1) {
+ int i;
+
+ for (i = 0; i < num_screens; i ++) {
+ if (mx >= screens[i].left && mx < screens[i].right &&
+ my >= screens[i].top && my < screens[i].bottom) {
+ X = screens[i].left;
+ Y = screens[i].top;
+ W = screens[i].right - screens[i].left;
+ H = screens[i].bottom - screens[i].top;
+ return;
+ }
+ }
+ }
+#elif defined(__APPLE__)
+ if (num_screens > 1) {
+ int i;
+
+ for (i = 0; i < num_screens; i ++) {
+ if (mx >= screens[i].x &&
+ mx < (screens[i].x + screens[i].width) &&
+ my >= screens[i].y &&
+ my < (screens[i].y + screens[i].height)) {
+ X = screens[i].x;
+ Y = screens[i].y;
+ W = screens[i].width;
+ H = screens[i].height;
+ return;
+ }
+ }
+ }
+#elif HAVE_XINERAMA
+ if (num_screens > 1) {
+ int i;
+
+ for (i = 0; i < num_screens; i ++) {
+ if (mx >= screens[i].x_org &&
+ mx < (screens[i].x_org + screens[i].width) &&
+ my >= screens[i].y_org &&
+ my < (screens[i].y_org + screens[i].height)) {
+ X = screens[i].x_org;
+ Y = screens[i].y_org;
+ W = screens[i].width;
+ H = screens[i].height;
+ return;
+ }
+ }
+ }
+#else
+ (void)mx;
+ (void)my;
+#endif // WIN32
+
+ X = Fl::x();
+ Y = Fl::y();
+ W = Fl::w();
+ H = Fl::h();
+}
+
+// Return the screen bounding rect for the given screen...
+void Fl::screen_xywh(int &X, int &Y, int &W, int &H, int n) {
+ if (!num_screens) screen_init();
+
+#ifdef WIN32
+ if (num_screens > 1 && n >= 0 && n < num_screens) {
+ X = screens[n].left;
+ Y = screens[n].top;
+ W = screens[n].right - screens[n].left;
+ H = screens[n].bottom - screens[n].top;
+ return;
+ }
+#elif defined(__APPLE__)
+ if (num_screens > 1 && n >= 0 && n < num_screens) {
+ X = screens[n].x;
+ Y = screens[n].y;
+ W = screens[n].width;
+ H = screens[n].height;
+ return;
+ }
+#elif HAVE_XINERAMA
+ if (num_screens > 1 && n >= 0 && n < num_screens) {
+ X = screens[n].x_org;
+ Y = screens[n].y_org;
+ W = screens[n].width;
+ H = screens[n].height;
+ return;
+ }
+#else
+ (void)n;
+#endif // WIN32
+
+ X = Fl::x();
+ Y = Fl::y();
+ W = Fl::w();
+ H = Fl::h();
+}
+
+
+//
+// End of "$Id: screen_xywh.cxx 5848 2007-05-20 16:18:31Z mike $".
+//
diff --git a/third_party/windows/fltk-1.1.10/src/slowarrow.h b/third_party/windows/fltk-1.1.10/src/slowarrow.h new file mode 100644 index 0000000..0958377 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/slowarrow.h @@ -0,0 +1,6 @@ +#define slowarrow_width 16
+#define slowarrow_height 16
+static unsigned char slowarrow_bits[] = {
+ 0x40, 0x00, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0xf0, 0x0f, 0x60, 0x00,
+ 0x60, 0x00, 0x40, 0x02, 0x40, 0x02, 0x00, 0x06, 0x00, 0x06, 0xf0, 0x0f,
+ 0x00, 0x06, 0x00, 0x06, 0x00, 0x02, 0x00, 0x02};
diff --git a/third_party/windows/fltk-1.1.10/src/tile.xpm b/third_party/windows/fltk-1.1.10/src/tile.xpm new file mode 100644 index 0000000..9d4087a --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/tile.xpm @@ -0,0 +1,91 @@ +/* XPM */
+static char tile_cmap[3][32] = {
+"O c #FFFFFF",
+"o c #EFEFEF",
+". c #E8E8E8"
+};
+static const char * tile_xpm[] = {
+"64 64 3 1",
+tile_cmap[0],
+tile_cmap[1],
+tile_cmap[2],
+
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"................................................................",
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
+
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"................................................................",
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
+
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"................................................................",
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
+
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"................................................................",
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
+
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"................................................................",
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
+
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"................................................................",
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
+
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"................................................................",
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
+
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"................................................................",
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
+
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"................................................................",
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
+
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"................................................................",
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
+
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"................................................................",
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
+
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"................................................................",
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
+
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"................................................................",
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
+
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"................................................................",
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
+
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"................................................................",
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
+
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"................................................................",
+"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
+"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO"};
diff --git a/third_party/windows/fltk-1.1.10/src/up.xbm b/third_party/windows/fltk-1.1.10/src/up.xbm new file mode 100644 index 0000000..af566b0 --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/up.xbm @@ -0,0 +1,6 @@ +#define up_width 16
+#define up_height 16
+static unsigned char up_bits[] = {
+ 0x00, 0x00, 0x78, 0x00, 0x84, 0x00, 0x02, 0x01, 0x31, 0xfe, 0x79, 0x80,
+ 0xfd, 0x80, 0x31, 0x80, 0x31, 0x80, 0x31, 0x80, 0x31, 0x80, 0x31, 0x80,
+ 0x01, 0x80, 0x01, 0x80, 0xff, 0xff, 0x00, 0x00};
diff --git a/third_party/windows/fltk-1.1.10/src/vsnprintf.c b/third_party/windows/fltk-1.1.10/src/vsnprintf.c new file mode 100644 index 0000000..77961be --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/vsnprintf.c @@ -0,0 +1,281 @@ +/*
+ * "$Id: vsnprintf.c 5850 2007-05-21 15:56:17Z matt $"
+ *
+ * snprintf() and vsnprintf() functions for the Fast Light Tool Kit (FLTK).
+ *
+ * Copyright 1998-2007 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 <stdio.h>
+#include "flstring.h"
+
+#ifdef HAVE_SYS_STDTYPES_H
+# include <sys/stdtypes.h>
+#endif /* HAVE_SYS_STDTYPES_H */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int fl_vsnprintf(char* buffer, size_t bufsize, const char* format, va_list ap) {
+ char *bufptr, /* Pointer to position in buffer */
+ *bufend, /* Pointer to end of buffer */
+ sign, /* Sign of format width */
+ size, /* Size character (h, l, L) */
+ type; /* Format type character */
+ int width, /* Width of field */
+ prec; /* Number of characters of precision */
+ char tformat[100], /* Temporary format string for sprintf() */
+ *tptr, /* Pointer into temporary format */
+ temp[1024]; /* Buffer for formatted numbers */
+ char *s; /* Pointer to string */
+ int slen; /* Length of string */
+ int bytes; /* Total number of bytes needed */
+
+
+ /*
+ * Loop through the format string, formatting as needed...
+ */
+
+ bufptr = buffer;
+ bufend = buffer + bufsize - 1;
+ bytes = 0;
+
+ while (*format) {
+ if (*format == '%') {
+ tptr = tformat;
+ *tptr++ = *format++;
+
+ if (*format == '%') {
+ if (bufptr && bufptr < bufend) *bufptr++ = *format;
+ bytes ++;
+ format ++;
+ continue;
+ } else if (strchr(" -+#\'", *format)) {
+ *tptr++ = *format;
+ sign = *format++;
+ } else sign = 0;
+
+ if (*format == '*') {
+ /* Get width from argument... */
+ format ++;
+ width = va_arg(ap, int);
+ snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", width);
+ tptr += strlen(tptr);
+ } else {
+ width = 0;
+ while (isdigit(*format & 255)) {
+ if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format;
+ width = width * 10 + *format++ - '0';
+ }
+ }
+
+ if (*format == '.') {
+ if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format;
+ format ++;
+
+ if (*format == '*') {
+ /* Get precision from argument... */
+ format ++;
+ prec = va_arg(ap, int);
+ snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", prec);
+ tptr += strlen(tptr);
+ } else {
+ prec = 0;
+ while (isdigit(*format & 255)) {
+ if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format;
+ prec = prec * 10 + *format++ - '0';
+ }
+ }
+ } else prec = -1;
+
+ size = '\0';
+
+ if (*format == 'l' && format[1] == 'l') {
+ size = 'L';
+ if (tptr < (tformat + sizeof(tformat) - 2)) {
+ *tptr++ = 'l';
+ *tptr++ = 'l';
+ }
+ format += 2;
+ } else if (*format == 'h' || *format == 'l' || *format == 'L') {
+ if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format;
+ size = *format++;
+ }
+
+ if (!*format) break;
+
+ if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format;
+ type = *format++;
+ *tptr = '\0';
+
+ switch (type) {
+ case 'E' : /* Floating point formats */
+ case 'G' :
+ case 'e' :
+ case 'f' :
+ case 'g' :
+ if ((width + 2) > sizeof(temp)) break;
+
+ sprintf(temp, tformat, va_arg(ap, double));
+
+ bytes += strlen(temp);
+
+ if (bufptr) {
+ if ((bufptr + strlen(temp)) > bufend) {
+ strncpy(bufptr, temp, (size_t)(bufend - bufptr));
+ bufptr = bufend;
+ } else {
+ strcpy(bufptr, temp);
+ bufptr += strlen(temp);
+ }
+ }
+ break;
+
+ case 'B' : /* Integer formats */
+ case 'X' :
+ case 'b' :
+ case 'd' :
+ case 'i' :
+ case 'o' :
+ case 'u' :
+ case 'x' :
+ if ((width + 2) > sizeof(temp)) break;
+
+#ifdef HAVE_LONG_LONG
+ if (size == 'L')
+ sprintf(temp, tformat, va_arg(ap, long long));
+ else
+#endif /* HAVE_LONG_LONG */
+ if (size == 'l')
+ sprintf(temp, tformat, va_arg(ap, long));
+ else
+ sprintf(temp, tformat, va_arg(ap, int));
+
+ bytes += strlen(temp);
+
+ if (bufptr) {
+ if ((bufptr + strlen(temp)) > bufend) {
+ strncpy(bufptr, temp, (size_t)(bufend - bufptr));
+ bufptr = bufend;
+ } else {
+ strcpy(bufptr, temp);
+ bufptr += strlen(temp);
+ }
+ }
+ break;
+
+ case 'p' : /* Pointer value */
+ if ((width + 2) > sizeof(temp)) break;
+
+ sprintf(temp, tformat, va_arg(ap, void *));
+
+ bytes += strlen(temp);
+
+ if (bufptr) {
+ if ((bufptr + strlen(temp)) > bufend) {
+ strncpy(bufptr, temp, (size_t)(bufend - bufptr));
+ bufptr = bufend;
+ } else {
+ strcpy(bufptr, temp);
+ bufptr += strlen(temp);
+ }
+ }
+ break;
+
+ case 'c' : /* Character or character array */
+ bytes += width;
+
+ if (bufptr) {
+ if (width <= 1) *bufptr++ = va_arg(ap, int);
+ else {
+ if ((bufptr + width) > bufend) width = bufend - bufptr;
+
+ memcpy(bufptr, va_arg(ap, char *), (size_t)width);
+ bufptr += width;
+ }
+ }
+ break;
+
+ case 's' : /* String */
+ if ((s = va_arg(ap, char *)) == NULL) s = "(null)";
+
+ slen = strlen(s);
+ if (slen > width && prec != width) width = slen;
+
+ bytes += width;
+
+ if (bufptr) {
+ if ((bufptr + width) > bufend) width = bufend - bufptr;
+
+ if (slen > width) slen = width;
+
+ if (sign == '-') {
+ strncpy(bufptr, s, (size_t)slen);
+ memset(bufptr + slen, ' ', (size_t)(width - slen));
+ } else {
+ memset(bufptr, ' ', (size_t)(width - slen));
+ strncpy(bufptr + width - slen, s, (size_t)slen);
+ }
+
+ bufptr += width;
+ }
+ break;
+
+ case 'n' : /* Output number of chars so far */
+ *(va_arg(ap, int *)) = bytes;
+ break;
+ }
+ } else {
+ bytes ++;
+
+ if (bufptr && bufptr < bufend) *bufptr++ = *format;
+ format ++;
+ }
+ }
+
+ /*
+ * Nul-terminate the string and return the number of characters needed.
+ */
+
+ if (bufptr) *bufptr = '\0';
+
+ return (bytes);
+}
+
+int fl_snprintf(char* str, size_t size, const char* fmt, ...) {
+ int ret;
+ va_list ap;
+ va_start(ap, fmt);
+ ret = vsnprintf(str, size, fmt, ap);
+ va_end(ap);
+ return ret;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+ * End of "$Id: vsnprintf.c 5850 2007-05-21 15:56:17Z matt $".
+ */
+
|
