summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Fl.cxx1135
-rw-r--r--src/Fl_Double_Window.cxx326
-rw-r--r--src/Fl_Gl_Window.cxx586
-rw-r--r--src/Fl_visual.cxx158
-rw-r--r--src/Fl_win32.cxx1534
-rw-r--r--src/Fl_x.cxx2
-rw-r--r--src/fl_font_win32.cxx318
-rw-r--r--src/fl_rect.cxx702
-rw-r--r--src/gl_start.cxx196
-rw-r--r--src/numericsort.c112
-rw-r--r--src/scandir_win32.c164
11 files changed, 2619 insertions, 2614 deletions
diff --git a/src/Fl.cxx b/src/Fl.cxx
index 17973ded6..d16c27973 100644
--- a/src/Fl.cxx
+++ b/src/Fl.cxx
@@ -1,565 +1,570 @@
-// Fl.C
-
-// fltk (Fast Light Tool Kit) version 0.99
-// Copyright (C) 1998 Bill Spitzak
-
-// 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.
-
-// Written by Bill Spitzak spitzak@d2.com
-
-#include <FL/Fl.H>
-#include <FL/Fl_Window.H>
-#include <FL/x.H>
-#include <ctype.h>
-
-int Fl::damage_;
-Fl_Widget *Fl::belowmouse_;
-Fl_Widget *Fl::pushed_;
-Fl_Widget *Fl::focus_;
-Fl_Widget *Fl::selection_owner_;
-int Fl::e_x, Fl::e_y, Fl::e_x_root, Fl::e_y_root;
-int Fl::e_state;
-int Fl::e_clicks;
-int Fl::e_is_click;
-int Fl::e_keysym;
-char *Fl::e_text;
-int Fl::e_length;
-
-int Fl::event_inside(int x,int y,int w,int h) /*const*/ {
- int mx = event_x();
- int my = event_y();
- return (mx >= x && mx < x+w && my >= y && my < y+h);
-}
-
-int Fl::event_inside(const Fl_Widget *o) /*const*/ {
- return event_inside(o->x(),o->y(),o->w(),o->h());
-}
-
-// Timeouts are insert-sorted into order. This works good if there
-// are only a small number:
-
-#define MAXTIMEOUT 8
-
-static struct {
- double time;
- void (*cb)(void*);
- void* arg;
-} timeout[MAXTIMEOUT+1];
-static int numtimeouts;
-
-void Fl::add_timeout(double t, void (*cb)(void *), void *v) {
- int i;
- if (numtimeouts<MAXTIMEOUT) numtimeouts++;
- for (i=0; i<numtimeouts-1; i++) {
- if (timeout[i].time > t) {
- for (int j=numtimeouts-1; j>i; j--) timeout[j] = timeout[j-1];
- break;
- }
- }
- timeout[i].time = t;
- timeout[i].cb = cb;
- timeout[i].arg = v;
-}
-
-void Fl::remove_timeout(void (*cb)(void *), void *v) {
- int i,j;
- for (i=j=0; i<numtimeouts; i++) {
- if (timeout[i].cb == cb && timeout[i].arg==v) ;
- else {if (j<i) timeout[j]=timeout[i]; j++;}
- }
- numtimeouts = j;
-}
-
-static void call_timeouts() {
- if (timeout[0].time > 0) return;
- struct {
- void (*cb)(void *);
- void *arg;
- } temp[MAXTIMEOUT];
- int i,j,k;
- // copy all expired timeouts to temp array:
- for (i=j=0; j<numtimeouts && timeout[j].time <= 0; i++,j++) {
- temp[i].cb = timeout[j].cb;
- temp[i].arg= timeout[j].arg;
- }
- // remove them from source array:
- for (k=0; j<numtimeouts;) timeout[k++] = timeout[j++];
- numtimeouts = k;
- // and then call them:
- for (k=0; k<i; k++) temp[k].cb(temp[k].arg);
-}
-
-void Fl::flush() {
- if (damage()) {
- damage_ = 0;
- for (Fl_X* x = Fl_X::first; x; x = x->next) {
- if (x->w->damage() && x->w->visible()) {
- x->flush();
- x->w->clear_damage();
- }
- }
- }
-#ifndef WIN32
- if (fl_display) XFlush(fl_display);
-#endif
-}
-
-extern double fl_wait(int timeout_flag, double timeout);
-extern int fl_ready();
-
-static int initclock; // if false we didn't call fl_elapsed() last time
-
-#ifndef WIN32
-#include <sys/time.h>
-#endif
-
-// fl_elapsed must return the amount of time since the last time it was
-// called. To reduce the number of system calls the to get the
-// current time, the "initclock" symbol is turned on by an indefinate
-// wait. This should then reset the measured-from time and return zero
-static double fl_elapsed() {
-
-#ifdef WIN32
-
- unsigned long newclock = fl_msg.time; // NOT YET IMPLEMENTED!
- const int TICKS_PER_SECOND = 1000; // divisor of the value to get seconds
- static unsigned long prevclock;
- if (!initclock) {prevclock = newclock; initclock = 1; return 0.0;}
- double t = double(newclock-prevclock)/TICKS_PER_SECOND;
- prevclock = newclock;
-
-#else
-
- static struct timeval prevclock;
- struct timeval newclock;
- gettimeofday(&newclock, 0);
- if (!initclock) {
- prevclock.tv_sec = newclock.tv_sec;
- prevclock.tv_usec = newclock.tv_usec;
- initclock = 1;
- return 0.0;
- }
- double t = 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;
-
-#endif
-
- // expire any timeouts:
- if (t > 0.0) for (int i=0; i<numtimeouts; i++) timeout[i].time -= t;
- return t;
-}
-
-void (*Fl::idle)();
-static char in_idle;
-static void callidle() {
- if (!Fl::idle || in_idle) return;
- in_idle = 1;
- Fl::idle();
- in_idle = 0;
-}
-
-int Fl::wait() {
- callidle();
- if (numtimeouts) {fl_elapsed(); call_timeouts();}
- flush();
- if (!Fl_X::first) return 0; // no windows
- if (idle && !in_idle)
- fl_wait(1,0.0);
- else if (numtimeouts)
- fl_wait(1, timeout[0].time);
- else {
- initclock = 0;
- fl_wait(0,0);
- }
- return 1;
-}
-
-double Fl::wait(double time) {
- callidle();
- if (numtimeouts) {time -= fl_elapsed(); call_timeouts();}
- flush();
- double wait_time = idle && !in_idle ? 0.0 : time;
- if (numtimeouts && timeout[0].time < wait_time) wait_time = timeout[0].time;
- fl_wait(1, wait_time);
- return time - fl_elapsed();
-}
-
-int Fl::check() {
- callidle();
- if (numtimeouts) {fl_elapsed(); call_timeouts();}
- flush();
- if (!Fl_X::first) return 0; // no windows
- fl_wait(1, 0.0);
- return 1;
-}
-
-int Fl::ready() {
- // if (idle && !in_idle) return 1; // should it do this?
- if (numtimeouts) {fl_elapsed(); if (timeout[0].time <= 0) return 1;}
- return fl_ready();
-}
-
-int Fl::run() {
- while (wait());
- return 0;
-}
-
-////////////////////////////////////////////////////////////////
-// 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)
- if (window->xid == xid) {
- 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;
-}
-
-void Fl::redraw() {
- for (Fl_X* x = Fl_X::first; x; x = x->next) x->w->redraw();
-}
-
-Fl_Window* Fl::first_window() {Fl_X* x = Fl_X::first; return x ? x->w : 0;}
-
-Fl_Window* Fl::next_window(const Fl_Window* w) {
- Fl_X* x = Fl_X::i(w)->next; return x ? x->w : 0;}
-
-////////////////////////////////////////////////////////////////
-// Event handlers:
-
-struct handler_link {
- int (*handle)(int);
- const handler_link *next;
-};
-
-static const handler_link *handlers = 0;
-
-void Fl::add_handler(int (*h)(int)) {
- handler_link *l = new handler_link;
- l->handle = h;
- l->next = handlers;
- handlers = l;
-}
-
-static int send_handlers(int event) {
- for (const handler_link *h = handlers; h; h = h->next)
- if (h->handle(event)) return 1;
- return 0;
-}
-
-////////////////////////////////////////////////////////////////
-
-Fl_Widget* fl_oldfocus; // kludge for Fl_Group...
-
-void Fl::focus(Fl_Widget *o) {
- Fl_Widget *p = focus_;
- if (o != p) {
- focus_ = o;
- fl_oldfocus = 0;
- for (; p && !p->contains(o); p = p->parent()) {
- p->handle(FL_UNFOCUS);
- fl_oldfocus = p;
- }
- }
-}
-
-void Fl::belowmouse(Fl_Widget *o) {
- Fl_Widget *p = belowmouse_;
- if (o != p) {
- event_is_click(0);
- belowmouse_ = o;
- for (; p && !p->contains(o); p = p->parent()) p->handle(FL_LEAVE);
- }
-}
-
-// Because mouse events are posted to the outermost window we need to
-// adjust them for child windows if they are pushed(). This should also
-// be done for the focus() but that is nyi.
-static int mouse_dx;
-static int mouse_dy;
-
-void Fl::pushed(Fl_Widget *o) {
- pushed_ = o;
- mouse_dx = 0;
- mouse_dy = 0;
- if (o) for (Fl_Widget* w = o; w->parent(); w = w->parent()) {
- if (w->type()>=FL_WINDOW) {mouse_dx -= w->x(); mouse_dy -= w->y();}
- }
-}
-
-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_;
-
-// Update modal(), focus() and other state according to system state.
-// This is called whenever a window is added or hidden, and whenever
-// X says the focus or mouse window have changed, and when grab_ is
-// changed.
-void fl_fix_focus() {
-
- // set Fl::modal() based on grab or any modal windows displayed:
- if (Fl::grab_)
- Fl::modal_ = Fl::grab_;
- else {
- Fl_Window* w = Fl::first_window();
- while (w && w->parent()) w = Fl::next_window(w);
- Fl::modal_ = w && w->modal() ? w : 0;
- }
-
- // set focus based on Fl::modal() and fl_xfocus
- Fl_Window *w = fl_xfocus;
- while (w && w->parent()) w = w->window();
- if (w) {
- if (Fl::modal()) w = Fl::modal();
- if (!w->contains(Fl::focus()))
- if (!w->take_focus()) Fl::focus(w);
- } else
- Fl::focus(0);
-
- if (Fl::pushed()) {
-
- // move pushed() to modal window (necessary for menus):
- if (Fl::modal() && !Fl::modal()->contains(Fl::pushed()))
- Fl::pushed_ = Fl::modal();
-
- } else { // set belowmouse only when pushed() is false
-
- // 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())) {
- Fl::belowmouse(w); w->handle(FL_ENTER);}
- } else
- Fl::belowmouse(0);
- }
-}
-
-////////////////////////////////////////////////////////////////
-
-int Fl::handle(int event, Fl_Window* window)
-{
- Fl_Widget* w = window;
-
- switch (event) {
-
- case FL_CLOSE:
- if (modal() && window != modal()) return 0;
- w->do_callback();
- return 1;
-
- case FL_SHOW:
- ((Fl_Widget*)w)->show();
- return 1;
-
- case FL_HIDE:
- ((Fl_Widget*)w)->hide();
- return 1;
-
- case FL_PUSH:
- if (Fl::grab()) w = Fl::grab();
- else if (Fl::modal() && w != Fl::modal()) return 0;
- Fl::pushed_ = w; mouse_dx = mouse_dy = 0;
- if (w->handle(event)) return 1;
- // raise windows that are clicked on:
- window->show();
- return 1;
-
- case FL_MOVE:
- case FL_DRAG:
- if (window != fl_xmousewin) {
- // this should not happen if enter/leave events were reported
- // correctly by the system, but just in case...
- fl_xmousewin = window; fl_fix_focus();
- }
- if (Fl::pushed()) {
- Fl::e_x += mouse_dx;
- Fl::e_y += mouse_dy;
- event = FL_DRAG;
- w = Fl::pushed();
- } else if (Fl::grab())
- w = Fl::grab();
- else if (Fl::modal() && w != Fl::modal())
- w = 0;
- break;
-
- case FL_RELEASE: {
- if (Fl::pushed_) w = Fl::pushed_; Fl::pushed_ = 0;
- int r = w->handle(event);
- fl_fix_focus();
- if (fl_xmousewin) fl_xmousewin->handle(FL_MOVE);
- return r;}
-
- case FL_UNFOCUS:
- window = 0;
- case FL_FOCUS:
- fl_xfocus = window;
- Fl::e_keysym = 0; // make sure it is not confused with navigation key
- fl_fix_focus();
- return 1;
-
- case FL_KEYBOARD:
- if (window != fl_xfocus) {
- // this should not happen if enter/leave events were reported
- // correctly by the system, but just in case...
- fl_xfocus = window; fl_fix_focus();
- }
- // Try it as keystroke, sending it to focus and all parents:
- for (w = Fl::focus(); w; w = w->parent())
- if (w->handle(FL_KEYBOARD)) return 1;
-
- // Try it as shortcut, sending to mouse widget and all parents:
- w = Fl::belowmouse(); if (!w) {w = Fl::modal(); if (!w) w = window;}
- for (; w; w = w->parent()) if (w->handle(FL_SHORTCUT)) return 1;
-
- // try using add_handle() functions:
- if (send_handlers(FL_SHORTCUT)) return 1;
-
- // Try swapping the case of the text in the shortcut:
- if (isalpha(Fl::event_text()[0])) {
- *(char*)(Fl::event_text()) ^= ('A'^'a');
- w = Fl::belowmouse(); if (!w) {w = Fl::modal(); if (!w) w = window;}
- for (; w; w = w->parent()) if (w->handle(FL_SHORTCUT)) return 1;
- if (send_handlers(FL_SHORTCUT)) return 1;
- }
-
- // make Escape key close windows:
- if (Fl::event_key()==FL_Escape) {
- window->do_callback();
- return 1;
- }
-
- return 0;
-
- case FL_ENTER:
- fl_xmousewin = window; fl_fix_focus();
- return 1;
-
- case FL_LEAVE:
- if (window == fl_xmousewin) {fl_xmousewin = 0; fl_fix_focus();}
- return 1;
-
- default:
- break;
- }
- if (w && w->handle(event)) return 1;
- return send_handlers(event);
-}
-
-////////////////////////////////////////////////////////////////
-// hide() destroys the X window, it does not do unmap!
-
-void fl_throw_focus(Fl_Widget*); // in Fl_x.C
-
-void Fl_Window::hide() {
- if (!shown()) return;
-
- // remove from the list of windows:
- Fl_X* x = i;
- Fl_X** pp = &Fl_X::first;
- for (; *pp != x; pp = &(*pp)->next) if (!*pp) return;
- *pp = x->next;
- i = 0;
-
- // recursively remove any subwindows:
- for (Fl_X *w = Fl_X::first; w;) {
- Fl_Window* W = w->w;
- if (W->window() == this) {
- W->hide();
- W->set_visible();
- w = Fl_X::first;
- } else w = w->next;
- }
-
- // Make sure no events are sent to this window:
- if (this == fl_xmousewin) fl_xmousewin = 0;
- if (this == fl_xfocus) fl_xfocus = 0;
- fl_throw_focus(this);
- handle(FL_HIDE);
-
-#ifdef WIN32
- if (x->private_dc) ReleaseDC(x->xid,x->private_dc);
- if (x->xid == fl_window) fl_GetDC(0); // releases dc belonging to window
-#endif
- if (x->region) XDestroyRegion(x->region);
- XDestroyWindow(fl_display, x->xid);
-
- delete x;
-}
-
-Fl_Window::~Fl_Window() {
- hide();
-}
-
-// Child windows must respond to FL_SHOW and FL_HIDE by actually
-// doing unmap operations. Outer windows assumme FL_SHOW & FL_HIDE
-// are messages from X:
-
-int Fl_Window::handle(int event) {
- if (parent()) switch (event) {
- case FL_SHOW:
- if (!shown()) show();
- else XMapWindow(fl_display, fl_xid(this));
- break;
- case FL_HIDE:
- if (shown()) XUnmapWindow(fl_display, fl_xid(this));
- break;
- }
- return Fl_Group::handle(event);
-}
-
-////////////////////////////////////////////////////////////////
-// ~Fl_Widget() calls this: this function must get rid of any
-// global pointers to the widget. This is also called by hide()
-// and deactivate().
-
-// call this to free a selection (or change the owner):
-void Fl::selection_owner(Fl_Widget *owner) {
- if (selection_owner_ && owner != selection_owner_)
- selection_owner_->handle(FL_SELECTIONCLEAR);
- selection_owner_ = owner;
-}
-
-#ifndef WIN32
-Fl_Widget *fl_selection_requestor; // from Fl_cutpaste.C
-#endif
-
-void fl_throw_focus(Fl_Widget *o) {
- if (o->contains(Fl::pushed())) Fl::pushed(0);
- if (o->contains(Fl::selection_owner())) Fl::selection_owner(0);
-#ifndef WIN32
- if (o->contains(fl_selection_requestor)) fl_selection_requestor = 0;
-#endif
- int fix = 0;
- if (o->contains(Fl::belowmouse())) {Fl::belowmouse(0); fix = 1;}
- if (o->contains(Fl::focus())) {Fl::focus(0); fix = 1;}
- if (fix) fl_fix_focus();
-}
-
-// End of Fl.C //
+// Fl.C
+
+// fltk (Fast Light Tool Kit) version 0.99
+// Copyright (C) 1998 Bill Spitzak
+
+// 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.
+
+// Written by Bill Spitzak spitzak@d2.com
+
+#include <FL/Fl.H>
+#include <FL/Fl_Window.H>
+#include <FL/x.H>
+#include <ctype.h>
+
+int Fl::damage_;
+Fl_Widget *Fl::belowmouse_;
+Fl_Widget *Fl::pushed_;
+Fl_Widget *Fl::focus_;
+Fl_Widget *Fl::selection_owner_;
+int Fl::e_x, Fl::e_y, Fl::e_x_root, Fl::e_y_root;
+int Fl::e_state;
+int Fl::e_clicks;
+int Fl::e_is_click;
+int Fl::e_keysym;
+char *Fl::e_text;
+int Fl::e_length;
+
+int Fl::event_inside(int x,int y,int w,int h) /*const*/ {
+ int mx = event_x();
+ int my = event_y();
+ return (mx >= x && mx < x+w && my >= y && my < y+h);
+}
+
+int Fl::event_inside(const Fl_Widget *o) /*const*/ {
+ return event_inside(o->x(),o->y(),o->w(),o->h());
+}
+
+// Timeouts are insert-sorted into order. This works good if there
+// are only a small number:
+
+#define MAXTIMEOUT 8
+
+static struct {
+ double time;
+ void (*cb)(void*);
+ void* arg;
+} timeout[MAXTIMEOUT+1];
+static int numtimeouts;
+
+void Fl::add_timeout(double t, void (*cb)(void *), void *v) {
+ int i;
+ if (numtimeouts<MAXTIMEOUT) numtimeouts++;
+ for (i=0; i<numtimeouts-1; i++) {
+ if (timeout[i].time > t) {
+ for (int j=numtimeouts-1; j>i; j--) timeout[j] = timeout[j-1];
+ break;
+ }
+ }
+ timeout[i].time = t;
+ timeout[i].cb = cb;
+ timeout[i].arg = v;
+}
+
+void Fl::remove_timeout(void (*cb)(void *), void *v) {
+ int i,j;
+ for (i=j=0; i<numtimeouts; i++) {
+ if (timeout[i].cb == cb && timeout[i].arg==v) ;
+ else {if (j<i) timeout[j]=timeout[i]; j++;}
+ }
+ numtimeouts = j;
+}
+
+static void call_timeouts() {
+ if (timeout[0].time > 0) return;
+ struct {
+ void (*cb)(void *);
+ void *arg;
+ } temp[MAXTIMEOUT];
+ int i,j,k;
+ // copy all expired timeouts to temp array:
+ for (i=j=0; j<numtimeouts && timeout[j].time <= 0; i++,j++) {
+ temp[i].cb = timeout[j].cb;
+ temp[i].arg= timeout[j].arg;
+ }
+ // remove them from source array:
+ for (k=0; j<numtimeouts;) timeout[k++] = timeout[j++];
+ numtimeouts = k;
+ // and then call them:
+ for (k=0; k<i; k++) temp[k].cb(temp[k].arg);
+}
+
+void Fl::flush() {
+ if (damage()) {
+ damage_ = 0;
+ for (Fl_X* x = Fl_X::first; x; x = x->next) {
+ if (x->w->damage() && x->w->visible()) {
+ x->flush();
+ x->w->clear_damage();
+ }
+ }
+ }
+#ifndef WIN32
+ if (fl_display) XFlush(fl_display);
+#endif
+}
+
+extern double fl_wait(int timeout_flag, double timeout);
+extern int fl_ready();
+
+static int initclock; // if false we didn't call fl_elapsed() last time
+
+#ifndef WIN32
+#include <sys/time.h>
+#endif
+
+// fl_elapsed must return the amount of time since the last time it was
+// called. To reduce the number of system calls the to get the
+// current time, the "initclock" symbol is turned on by an indefinate
+// wait. This should then reset the measured-from time and return zero
+static double fl_elapsed() {
+
+#ifdef WIN32
+
+ unsigned long newclock = fl_msg.time; // NOT YET IMPLEMENTED!
+ const int TICKS_PER_SECOND = 1000; // divisor of the value to get seconds
+ static unsigned long prevclock;
+ if (!initclock) {prevclock = newclock; initclock = 1; return 0.0;}
+ double t = double(newclock-prevclock)/TICKS_PER_SECOND;
+ prevclock = newclock;
+
+#else
+
+ static struct timeval prevclock;
+ struct timeval newclock;
+ gettimeofday(&newclock, 0);
+ if (!initclock) {
+ prevclock.tv_sec = newclock.tv_sec;
+ prevclock.tv_usec = newclock.tv_usec;
+ initclock = 1;
+ return 0.0;
+ }
+ double t = 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;
+
+#endif
+
+ // expire any timeouts:
+ if (t > 0.0) for (int i=0; i<numtimeouts; i++) timeout[i].time -= t;
+ return t;
+}
+
+void (*Fl::idle)();
+static char in_idle;
+static void callidle() {
+ if (!Fl::idle || in_idle) return;
+ in_idle = 1;
+ Fl::idle();
+ in_idle = 0;
+}
+
+int Fl::wait() {
+ callidle();
+ if (numtimeouts) {fl_elapsed(); call_timeouts();}
+ flush();
+ if (!Fl_X::first) return 0; // no windows
+ if (idle && !in_idle)
+ fl_wait(1,0.0);
+ else if (numtimeouts)
+ fl_wait(1, timeout[0].time);
+ else {
+ initclock = 0;
+ fl_wait(0,0);
+ }
+ return 1;
+}
+
+double Fl::wait(double time) {
+ callidle();
+ if (numtimeouts) {time -= fl_elapsed(); call_timeouts();}
+ flush();
+ double wait_time = idle && !in_idle ? 0.0 : time;
+ if (numtimeouts && timeout[0].time < wait_time) wait_time = timeout[0].time;
+ fl_wait(1, wait_time);
+ return time - fl_elapsed();
+}
+
+int Fl::check() {
+ callidle();
+ if (numtimeouts) {fl_elapsed(); call_timeouts();}
+ flush();
+ if (!Fl_X::first) return 0; // no windows
+ fl_wait(1, 0.0);
+ return 1;
+}
+
+int Fl::ready() {
+ // if (idle && !in_idle) return 1; // should it do this?
+ if (numtimeouts) {fl_elapsed(); if (timeout[0].time <= 0) return 1;}
+ return fl_ready();
+}
+
+int Fl::run() {
+ while (wait());
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////
+// 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)
+ if (window->xid == xid) {
+ 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;
+}
+
+void Fl::redraw() {
+ for (Fl_X* x = Fl_X::first; x; x = x->next) x->w->redraw();
+}
+
+Fl_Window* Fl::first_window() {Fl_X* x = Fl_X::first; return x ? x->w : 0;}
+
+Fl_Window* Fl::next_window(const Fl_Window* w) {
+ Fl_X* x = Fl_X::i(w)->next; return x ? x->w : 0;}
+
+////////////////////////////////////////////////////////////////
+// Event handlers:
+
+struct handler_link {
+ int (*handle)(int);
+ const handler_link *next;
+};
+
+static const handler_link *handlers = 0;
+
+void Fl::add_handler(int (*h)(int)) {
+ handler_link *l = new handler_link;
+ l->handle = h;
+ l->next = handlers;
+ handlers = l;
+}
+
+static int send_handlers(int event) {
+ for (const handler_link *h = handlers; h; h = h->next)
+ if (h->handle(event)) return 1;
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////
+
+Fl_Widget* fl_oldfocus; // kludge for Fl_Group...
+
+void Fl::focus(Fl_Widget *o) {
+ Fl_Widget *p = focus_;
+ if (o != p) {
+ focus_ = o;
+ fl_oldfocus = 0;
+ for (; p && !p->contains(o); p = p->parent()) {
+ p->handle(FL_UNFOCUS);
+ fl_oldfocus = p;
+ }
+ }
+}
+
+void Fl::belowmouse(Fl_Widget *o) {
+ Fl_Widget *p = belowmouse_;
+ if (o != p) {
+ event_is_click(0);
+ belowmouse_ = o;
+ for (; p && !p->contains(o); p = p->parent()) p->handle(FL_LEAVE);
+ }
+}
+
+// Because mouse events are posted to the outermost window we need to
+// adjust them for child windows if they are pushed(). This should also
+// be done for the focus() but that is nyi.
+static int mouse_dx;
+static int mouse_dy;
+
+void Fl::pushed(Fl_Widget *o) {
+ pushed_ = o;
+ mouse_dx = 0;
+ mouse_dy = 0;
+ if (o) for (Fl_Widget* w = o; w->parent(); w = w->parent()) {
+ if (w->type()>=FL_WINDOW) {mouse_dx -= w->x(); mouse_dy -= w->y();}
+ }
+}
+
+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_;
+
+// Update modal(), focus() and other state according to system state.
+// This is called whenever a window is added or hidden, and whenever
+// X says the focus or mouse window have changed, and when grab_ is
+// changed.
+void fl_fix_focus() {
+
+ // set Fl::modal() based on grab or any modal windows displayed:
+ if (Fl::grab_)
+ Fl::modal_ = Fl::grab_;
+ else {
+ Fl_Window* w = Fl::first_window();
+ while (w && w->parent()) w = Fl::next_window(w);
+ Fl::modal_ = w && w->modal() ? w : 0;
+ }
+
+ // set focus based on Fl::modal() and fl_xfocus
+ Fl_Window *w = fl_xfocus;
+ while (w && w->parent()) w = w->window();
+ if (w) {
+ if (Fl::modal()) w = Fl::modal();
+ if (!w->contains(Fl::focus()))
+ if (!w->take_focus()) Fl::focus(w);
+ } else
+ Fl::focus(0);
+
+ if (Fl::pushed()) {
+
+ // move pushed() to modal window (necessary for menus):
+ if (Fl::modal() && !Fl::modal()->contains(Fl::pushed()))
+ Fl::pushed_ = Fl::modal();
+
+ } else { // set belowmouse only when pushed() is false
+
+ // 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())) {
+ Fl::belowmouse(w); w->handle(FL_ENTER);}
+ } else
+ Fl::belowmouse(0);
+ }
+}
+
+////////////////////////////////////////////////////////////////
+
+int Fl::handle(int event, Fl_Window* window)
+{
+ Fl_Widget* w = window;
+
+ switch (event) {
+
+ case FL_CLOSE:
+ if (modal() && window != modal()) return 0;
+ w->do_callback();
+ return 1;
+
+ case FL_SHOW:
+ ((Fl_Widget*)w)->show();
+ return 1;
+
+ case FL_HIDE:
+ ((Fl_Widget*)w)->hide();
+ return 1;
+
+ case FL_PUSH:
+ if (Fl::grab()) w = Fl::grab();
+ else if (Fl::modal() && w != Fl::modal()) return 0;
+ Fl::pushed_ = w; mouse_dx = mouse_dy = 0;
+ if (w->handle(event)) return 1;
+ // raise windows that are clicked on:
+ window->show();
+ return 1;
+
+ case FL_MOVE:
+ case FL_DRAG:
+ if (window != fl_xmousewin) {
+ // this should not happen if enter/leave events were reported
+ // correctly by the system, but just in case...
+ fl_xmousewin = window; fl_fix_focus();
+ }
+ if (Fl::pushed()) {
+ Fl::e_x += mouse_dx;
+ Fl::e_y += mouse_dy;
+ event = FL_DRAG;
+ w = Fl::pushed();
+ } else if (Fl::grab())
+ w = Fl::grab();
+ else if (Fl::modal() && w != Fl::modal())
+ w = 0;
+ break;
+
+ case FL_RELEASE: {
+ if (Fl::pushed_) {
+ Fl::e_x += mouse_dx;
+ Fl::e_y += mouse_dy;
+ w = Fl::pushed_;
+ Fl::pushed_ = 0; // must be zero before callback is done!
+ }
+ int r = w->handle(event);
+ fl_fix_focus();
+ if (fl_xmousewin) fl_xmousewin->handle(FL_MOVE);
+ return r;}
+
+ case FL_UNFOCUS:
+ window = 0;
+ case FL_FOCUS:
+ fl_xfocus = window;
+ Fl::e_keysym = 0; // make sure it is not confused with navigation key
+ fl_fix_focus();
+ return 1;
+
+ case FL_KEYBOARD:
+ if (window != fl_xfocus) {
+ // this should not happen if enter/leave events were reported
+ // correctly by the system, but just in case...
+ fl_xfocus = window; fl_fix_focus();
+ }
+ // Try it as keystroke, sending it to focus and all parents:
+ for (w = Fl::focus(); w; w = w->parent())
+ if (w->handle(FL_KEYBOARD)) return 1;
+
+ // Try it as shortcut, sending to mouse widget and all parents:
+ w = Fl::belowmouse(); if (!w) {w = Fl::modal(); if (!w) w = window;}
+ for (; w; w = w->parent()) if (w->handle(FL_SHORTCUT)) return 1;
+
+ // try using add_handle() functions:
+ if (send_handlers(FL_SHORTCUT)) return 1;
+
+ // Try swapping the case of the text in the shortcut:
+ if (isalpha(Fl::event_text()[0])) {
+ *(char*)(Fl::event_text()) ^= ('A'^'a');
+ w = Fl::belowmouse(); if (!w) {w = Fl::modal(); if (!w) w = window;}
+ for (; w; w = w->parent()) if (w->handle(FL_SHORTCUT)) return 1;
+ if (send_handlers(FL_SHORTCUT)) return 1;
+ }
+
+ // make Escape key close windows:
+ if (Fl::event_key()==FL_Escape) {
+ window->do_callback();
+ return 1;
+ }
+
+ return 0;
+
+ case FL_ENTER:
+ fl_xmousewin = window; fl_fix_focus();
+ return 1;
+
+ case FL_LEAVE:
+ if (window == fl_xmousewin) {fl_xmousewin = 0; fl_fix_focus();}
+ return 1;
+
+ default:
+ break;
+ }
+ if (w && w->handle(event)) return 1;
+ return send_handlers(event);
+}
+
+////////////////////////////////////////////////////////////////
+// hide() destroys the X window, it does not do unmap!
+
+void fl_throw_focus(Fl_Widget*); // in Fl_x.C
+
+void Fl_Window::hide() {
+ if (!shown()) return;
+
+ // remove from the list of windows:
+ Fl_X* x = i;
+ Fl_X** pp = &Fl_X::first;
+ for (; *pp != x; pp = &(*pp)->next) if (!*pp) return;
+ *pp = x->next;
+ i = 0;
+
+ // recursively remove any subwindows:
+ for (Fl_X *w = Fl_X::first; w;) {
+ Fl_Window* W = w->w;
+ if (W->window() == this) {
+ W->hide();
+ W->set_visible();
+ w = Fl_X::first;
+ } else w = w->next;
+ }
+
+ // Make sure no events are sent to this window:
+ if (this == fl_xmousewin) fl_xmousewin = 0;
+ if (this == fl_xfocus) fl_xfocus = 0;
+ fl_throw_focus(this);
+ handle(FL_HIDE);
+
+#ifdef WIN32
+ if (x->private_dc) ReleaseDC(x->xid,x->private_dc);
+ if (x->xid == fl_window) fl_GetDC(0); // releases dc belonging to window
+#endif
+ if (x->region) XDestroyRegion(x->region);
+ XDestroyWindow(fl_display, x->xid);
+
+ delete x;
+}
+
+Fl_Window::~Fl_Window() {
+ hide();
+}
+
+// Child windows must respond to FL_SHOW and FL_HIDE by actually
+// doing unmap operations. Outer windows assumme FL_SHOW & FL_HIDE
+// are messages from X:
+
+int Fl_Window::handle(int event) {
+ if (parent()) switch (event) {
+ case FL_SHOW:
+ if (!shown()) show();
+ else XMapWindow(fl_display, fl_xid(this));
+ break;
+ case FL_HIDE:
+ if (shown()) XUnmapWindow(fl_display, fl_xid(this));
+ break;
+ }
+ return Fl_Group::handle(event);
+}
+
+////////////////////////////////////////////////////////////////
+// ~Fl_Widget() calls this: this function must get rid of any
+// global pointers to the widget. This is also called by hide()
+// and deactivate().
+
+// call this to free a selection (or change the owner):
+void Fl::selection_owner(Fl_Widget *owner) {
+ if (selection_owner_ && owner != selection_owner_)
+ selection_owner_->handle(FL_SELECTIONCLEAR);
+ selection_owner_ = owner;
+}
+
+#ifndef WIN32
+Fl_Widget *fl_selection_requestor; // from Fl_cutpaste.C
+#endif
+
+void fl_throw_focus(Fl_Widget *o) {
+ if (o->contains(Fl::pushed())) Fl::pushed(0);
+ if (o->contains(Fl::selection_owner())) Fl::selection_owner(0);
+#ifndef WIN32
+ if (o->contains(fl_selection_requestor)) fl_selection_requestor = 0;
+#endif
+ int fix = 0;
+ if (o->contains(Fl::belowmouse())) {Fl::belowmouse(0); fix = 1;}
+ if (o->contains(Fl::focus())) {Fl::focus(0); fix = 1;}
+ if (fix) fl_fix_focus();
+}
+
+// End of Fl.C //
diff --git a/src/Fl_Double_Window.cxx b/src/Fl_Double_Window.cxx
index 864ba1019..036c7ab10 100644
--- a/src/Fl_Double_Window.cxx
+++ b/src/Fl_Double_Window.cxx
@@ -1,163 +1,163 @@
-// Fl_Double_Window.C
-
-// A double-buffered window. This is achieved by using the Xdbe extension,
-// or a pixmap if that is not available.
-
-// On systems that support double buffering "naturally" the base
-// Fl_Window class will probably do double-buffer and this subclass
-// does nothing.
-
-#include <config.h>
-#include <FL/Fl.H>
-#include <FL/Fl_Double_Window.H>
-#include <FL/x.H>
-#include <FL/fl_draw.H>
-
-#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() {
-#ifndef WIN32
- if (!shown()) { // don't set the background pixel
- fl_open_display();
- Fl_X::make_xid(this);
- return;
- }
-#endif
- Fl_Window::show();
-}
-
-#ifdef WIN32
-
-// I've removed the second one (never understool why
-// it was there to begin with).
-
-static HDC blt_gc;
-
-void fl_switch_offscreen(HBITMAP bitmap) {
- if (!blt_gc) {
- blt_gc = CreateCompatibleDC(fl_gc);
- SetTextAlign(blt_gc, TA_BASELINE|TA_LEFT);
- SetBkMode(blt_gc, TRANSPARENT);
-#if USE_COLORMAP
- if (fl_palette) SelectPalette(blt_gc, fl_palette, FALSE);
-#endif
- }
- SelectObject(blt_gc, bitmap);
- fl_gc = blt_gc;
-}
-
-void fl_copy_offscreen(int x,int y,int w,int h,HBITMAP bitmap,int srcx,int srcy) {
- SelectObject(blt_gc, bitmap);
- BitBlt(window_dc, x, y, w, h, blt_gc, srcx, srcy, SRCCOPY);
-}
-
-#endif
-
-// protected method used by Fl_Overlay_Window to fake overlay:
-void Fl_Double_Window::_flush(int eraseoverlay) {
- make_current(); // make sure fl_gc is non-zero
- Fl_X *i = Fl_X::i(this);
- if (!i->other_xid) {
-#if USE_XDBE
- if (can_xdbe()) i->other_xid =
- XdbeAllocateBackBufferName(fl_display, fl_xid(this), XdbeCopied);
- else
-#endif
- i->other_xid = fl_create_offscreen(w(), h());
- clear_damage(~0);
- }
- XRectangle rect = {0,0,w(),h()};
- if (damage()) {
- if ( // don't draw if back buffer is ok
-#if USE_XDBE
- use_xdbe ||
-#endif
- damage() != 2) {
-/*
-#ifdef WIN32
- fl_begin_offscreen(i->other_xid);
- fl_clip_region(i->region); i->region = 0;
- draw();
- fl_end_offscreen();
-#else
-*/
-#ifdef WIN32
- fl_begin_offscreen(i->other_xid);
-#endif
- fl_window = i->other_xid;
- fl_clip_region(i->region); i->region = 0;
- draw();
- fl_window = i->xid;
-#ifdef WIN32
- fl_end_offscreen();
-#endif
-//#endif
- }
- }
- fl_clip_region(0);
-#if USE_XDBE
- if (i->region && !eraseoverlay) XClipBox(i->region, &rect);
- if (use_xdbe) {
- XdbeSwapInfo s;
- s.swap_window = fl_xid(this);
- s.swap_action = XdbeCopied;
- XdbeSwapBuffers(fl_display,&s,1);
- } else
-#endif
- fl_copy_offscreen(rect.x, rect.y, rect.width, rect.height,
- i->other_xid, rect.x, rect.y);
-}
-
-void Fl_Double_Window::flush() {_flush(0);}
-
-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* i = Fl_X::i(this);
- if (i && i->other_xid && (ow != w() || oh != h())) {
- fl_delete_offscreen(i->other_xid);
- i->other_xid = 0;
- }
-}
-
-void Fl_Double_Window::hide() {
- Fl_X* i = Fl_X::i(this);
- if (i && i->other_xid) {
-#if USE_XDBE
- if (!use_xdbe)
-#endif
- fl_delete_offscreen(i->other_xid);
- }
- Fl_Window::hide();
-}
-
-Fl_Double_Window::~Fl_Double_Window() {
- hide();
-}
+// Fl_Double_Window.C
+
+// A double-buffered window. This is achieved by using the Xdbe extension,
+// or a pixmap if that is not available.
+
+// On systems that support double buffering "naturally" the base
+// Fl_Window class will probably do double-buffer and this subclass
+// does nothing.
+
+#include <config.h>
+#include <FL/Fl.H>
+#include <FL/Fl_Double_Window.H>
+#include <FL/x.H>
+#include <FL/fl_draw.H>
+
+#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() {
+#ifndef WIN32
+ if (!shown()) { // don't set the background pixel
+ fl_open_display();
+ Fl_X::make_xid(this);
+ return;
+ }
+#endif
+ Fl_Window::show();
+}
+
+#ifdef WIN32
+
+// I've removed the second one (never understool why
+// it was there to begin with).
+
+static HDC blt_gc;
+
+void fl_switch_offscreen(HBITMAP bitmap) {
+ if (!blt_gc) {
+ blt_gc = CreateCompatibleDC(fl_gc);
+ SetTextAlign(blt_gc, TA_BASELINE|TA_LEFT);
+ SetBkMode(blt_gc, TRANSPARENT);
+#if USE_COLORMAP
+ if (fl_palette) SelectPalette(blt_gc, fl_palette, FALSE);
+#endif
+ }
+ SelectObject(blt_gc, bitmap);
+ fl_gc = blt_gc;
+}
+
+void fl_copy_offscreen(int x,int y,int w,int h,HBITMAP bitmap,int srcx,int srcy) {
+ SelectObject(blt_gc, bitmap);
+ BitBlt(window_dc, x, y, w, h, blt_gc, srcx, srcy, SRCCOPY);
+}
+
+#endif
+
+// protected method used by Fl_Overlay_Window to fake overlay:
+void Fl_Double_Window::_flush(int eraseoverlay) {
+ make_current(); // make sure fl_gc is non-zero
+ Fl_X *i = Fl_X::i(this);
+ if (!i->other_xid) {
+#if USE_XDBE
+ if (can_xdbe()) i->other_xid =
+ XdbeAllocateBackBufferName(fl_display, fl_xid(this), XdbeCopied);
+ else
+#endif
+ i->other_xid = fl_create_offscreen(w(), h());
+ clear_damage(~0);
+ }
+ XRectangle rect = {0,0,w(),h()};
+ if (damage()) {
+ if ( // don't draw if back buffer is ok
+#if USE_XDBE
+ use_xdbe ||
+#endif
+ damage() != 2) {
+/*
+#ifdef WIN32
+ fl_begin_offscreen(i->other_xid);
+ fl_clip_region(i->region); i->region = 0;
+ draw();
+ fl_end_offscreen();
+#else
+*/
+#ifdef WIN32
+ fl_begin_offscreen(i->other_xid);
+#endif
+ fl_window = i->other_xid;
+ fl_clip_region(i->region); i->region = 0;
+ draw();
+ fl_window = i->xid;
+#ifdef WIN32
+ fl_end_offscreen();
+#endif
+//#endif
+ }
+ }
+ fl_clip_region(0);
+#if USE_XDBE
+ if (i->region && !eraseoverlay) XClipBox(i->region, &rect);
+ if (use_xdbe) {
+ XdbeSwapInfo s;
+ s.swap_window = fl_xid(this);
+ s.swap_action = XdbeCopied;
+ XdbeSwapBuffers(fl_display,&s,1);
+ } else
+#endif
+ fl_copy_offscreen(rect.x, rect.y, rect.width, rect.height,
+ i->other_xid, rect.x, rect.y);
+}
+
+void Fl_Double_Window::flush() {_flush(0);}
+
+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* i = Fl_X::i(this);
+ if (i && i->other_xid && (ow != w() || oh != h())) {
+ fl_delete_offscreen(i->other_xid);
+ i->other_xid = 0;
+ }
+}
+
+void Fl_Double_Window::hide() {
+ Fl_X* i = Fl_X::i(this);
+ if (i && i->other_xid) {
+#if USE_XDBE
+ if (!use_xdbe)
+#endif
+ fl_delete_offscreen(i->other_xid);
+ }
+ Fl_Window::hide();
+}
+
+Fl_Double_Window::~Fl_Double_Window() {
+ hide();
+}
diff --git a/src/Fl_Gl_Window.cxx b/src/Fl_Gl_Window.cxx
index 0879e734e..8778d0b4f 100644
--- a/src/Fl_Gl_Window.cxx
+++ b/src/Fl_Gl_Window.cxx
@@ -1,293 +1,293 @@
-// Fl_Gl_Window.C
-
-#include <config.h>
-#if HAVE_GL
-
-#include <FL/Fl.H>
-#include <FL/x.H>
-#include <FL/Fl_Gl_Window.H>
-#include "Fl_Gl_Choice.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.
-
-// The default of SWAP_SWAP works on an SGI, and will also work (but
-// is sub-optimal) on machines that should be SWAP_COPY or SWAP_NODAMAGE.
-// The win32 emulation of OpenGL can use COPY, but some (all?) OpenGL
-// cards use SWAP.
-
-// contents of back buffer after glXSwapBuffers():
-#define UNDEFINED 0 // unknown
-#define SWAP 1 // former front buffer
-#define COPY 2 // unchanged
-#define NODAMAGE 3 // unchanged even by X expose() events
-
-#ifdef MESA
-#define SWAP_TYPE NODAMAGE
-#else
-#define SWAP_TYPE SWAP
-#endif
-
-////////////////////////////////////////////////////////////////
-
-HDC fl_GetDC(HWND);
-
-int Fl_Gl_Window::can_do(int a, const int *b) {
-#ifdef WIN32
- Fl_Gl_Choice *g = Fl_Gl_Choice::find(a,b);
-/*
- Is this necessary? Don't all windows have the same
- support for pixel formats?
- HWND w = GetDesktopWindow();
- HDC dc = GetDC(w);
-*/
- if (!fl_gc) fl_GetDC(0);
- int r = ChoosePixelFormat(fl_gc, &g->pfd);
- return r != 0;
-#else
- return Fl_Gl_Choice::find(a,b) != 0;
-#endif
-}
-
-void Fl_Gl_Window::show() {
-#ifndef WIN32
- if (!shown()) {
- if (!g) {
- g = Fl_Gl_Choice::find(mode_,alist);
- if (!g) {Fl::error("Insufficient GL support"); return;}
- }
- Fl_X::make_xid(this, g->vis, g->colormap);
- if (overlay && overlay != this) ((Fl_Gl_Window*)overlay)->show();
- }
-#endif
- Fl_Window::show();
-}
-
-void Fl_Gl_Window::invalidate() {
- valid(0);
-#ifndef WIN32
- if (overlay) ((Fl_Gl_Window*)overlay)->valid(0);
-#endif
-}
-
-extern GLXContext fl_first_context; // in Fl_Gl_Choice.C
-
-int Fl_Gl_Window::mode(int m, const int *a) {
- if (m == mode_ && a == alist) return 0;
- mode_ = m; alist = a;
-#ifdef WIN32
- // destroy context and g:
- if (shown()) {hide(); show();}
-#else
- // under X, if the visual changes we must make a new X window (!):
- if (shown()) {
- Fl_Gl_Choice *g1 = g;
- g = Fl_Gl_Choice::find(mode_,alist);
- if (!g || g->vis->visualid != g1->vis->visualid || g->d != g1->d) {
- hide(); show();
- }
- }
-#endif
- return 1;
-}
-
-#ifdef WIN32
-extern char fl_direct_paint; // true when responding to WM_PAINT
-#endif
-
-void Fl_Gl_Window::make_current() {
-#ifdef WIN32
- HDC hdc = fl_private_dc(this, mode_,&g);
- if (!context) {
- context = wglCreateContext(hdc);
- if (fl_first_context) wglShareLists(fl_first_context, (GLXContext)context);
- else fl_first_context = (GLXContext)context;
- valid(0);
- }
- wglMakeCurrent(hdc, (GLXContext)context);
-#else
- if (!context) {
- context = glXCreateContext(fl_display, g->vis, fl_first_context, 1);
- if (!fl_first_context) fl_first_context = (GLXContext)context;
- valid(0);
- }
- glXMakeCurrent(fl_display, fl_xid(this), (GLXContext)context);
-#endif
- glDrawBuffer(GL_BACK);
-}
-
-void Fl_Gl_Window::ortho() {
- glLoadIdentity();
- glViewport(0, 0, w(), h());
- glOrtho(0, w(), 0, h(), -1, 1);
-}
-
-void Fl_Gl_Window::swap_buffers() {
-#ifdef WIN32
- SwapBuffers(Fl_X::i(this)->private_dc);
-#else
- glXSwapBuffers(fl_display, fl_xid(this));
-#endif
-}
-
-#if HAVE_GL_OVERLAY
-#if WIN32
-uchar fl_overlay; // changes how fl_color() works
-#endif
-#endif
-
-void Fl_Gl_Window::flush() {
- make_current();
-
-#if HAVE_GL_OVERLAY
-#ifdef WIN32
- uchar save_valid = valid_;
- if (overlay && overlay!= this && damage() == 8) goto DRAW_OVERLAY_ONLY;
-#endif
-#endif
-
- if (g->d) {
-
-#if SWAP_TYPE == NODAMAGE
-
- // don't draw if only overlay damage or expose events:
- if ((damage()&~0xA0) || !valid()) draw();
- swap_buffers();
-
-#elif SWAP_TYPE == COPY
-
- // don't draw if only the overlay is damaged:
- if (damage() != 8 || !valid()) draw();
- swap_buffers();
-
-#else // SWAP_TYPE == SWAP || SWAP_TYPE == UNDEFINED
-
- if (overlay == this) { // Use CopyPixels to act like SWAP_TYPE == COPY
-
- // don't draw if only the overlay is damaged:
- if (damage1_ || damage() != 8 || !valid()) draw();
- // we use a seperate context for the copy because rasterpos must be 0
- // and depth test needs to be off:
- static GLXContext ortho_context;
- int init = !ortho_context;
-#ifdef WIN32
- if (init) ortho_context = wglCreateContext(Fl_X::i(this)->private_dc);
- wglMakeCurrent(Fl_X::i(this)->private_dc, ortho_context);
-#else
- if (init)
- ortho_context = glXCreateContext(fl_display,g->vis,fl_first_context,1);
- glXMakeCurrent(fl_display, fl_xid(this), ortho_context);
-#endif
- if (init) {
- glDisable(GL_DEPTH_TEST);
- glReadBuffer(GL_BACK);
- glDrawBuffer(GL_FRONT);
- }
- glCopyPixels(0,0,w(),h(),GL_COLOR);
- make_current(); // set current context back to draw overlay
- damage1_ = 0;
-
- } else {
-
-#if SWAP_TYPE == SWAP
- uchar old_damage = damage();
- clear_damage(damage1_|old_damage); draw();
- swap_buffers();
- damage1_ = old_damage;
-#else // SWAP_TYPE == UNDEFINED
- clear_damage(~0); draw();
- swap_buffers();
- damage1_ = ~0;
-#endif
-
- }
-#endif
-
- if (overlay==this) { // fake overlay in front buffer
- glDrawBuffer(GL_FRONT);
- draw_overlay();
- glDrawBuffer(GL_BACK);
- glFlush();
- }
-
- } else { // single-buffered context is simpler:
-
- // this faking of the overlay is incorrect but worked good for
- // one in-house program:
- if (overlay != this || damage()!=8 || !Fl::pushed()) draw();
- if (overlay == this) draw_overlay();
- glFlush();
-
- }
-
-#if HAVE_GL_OVERLAY
-#ifdef WIN32
- if (overlay && overlay != this) {
- DRAW_OVERLAY_ONLY:
- valid_ = save_valid;
- wglMakeCurrent(Fl_X::i(this)->private_dc, (GLXContext)overlay);
- glDisable(GL_SCISSOR_TEST);
- fl_overlay = 1;
- glClear(GL_COLOR_BUFFER_BIT);
- draw_overlay();
- wglSwapLayerBuffers(Fl_X::i(this)->private_dc,WGL_SWAP_OVERLAY1);
- fl_overlay = 0;
- }
-#endif
-#endif
-
- valid(1);
-}
-
-void Fl_Gl_Window::resize(int X,int Y,int W,int H) {
- if (W != w() || H != h()) valid(0);
- Fl_Window::resize(X,Y,W,H);
-}
-
-void Fl_Gl_Window::hide() {
- if (context) {
-#ifdef WIN32
- wglMakeCurrent(0, 0);
- if (context && context != fl_first_context)
- wglDeleteContext((GLXContext)context);
- g = 0;
-#else
- glXMakeCurrent(fl_display, 0, 0);
- if (context != fl_first_context)
- glXDestroyContext(fl_display, (GLXContext)context);
-#ifdef GLX_MESA_release_buffers
- glXReleaseBuffersMESA(fl_display, fl_xid(this));
-#endif
-#endif
- context = 0;
- }
- 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;
- damage1_ = 0;
-}
-
-void Fl_Gl_Window::draw_overlay() {}
-
-#endif
+// Fl_Gl_Window.C
+
+#include <config.h>
+#if HAVE_GL
+
+#include <FL/Fl.H>
+#include <FL/x.H>
+#include <FL/Fl_Gl_Window.H>
+#include "Fl_Gl_Choice.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.
+
+// The default of SWAP_SWAP works on an SGI, and will also work (but
+// is sub-optimal) on machines that should be SWAP_COPY or SWAP_NODAMAGE.
+// The win32 emulation of OpenGL can use COPY, but some (all?) OpenGL
+// cards use SWAP.
+
+// contents of back buffer after glXSwapBuffers():
+#define UNDEFINED 0 // unknown
+#define SWAP 1 // former front buffer
+#define COPY 2 // unchanged
+#define NODAMAGE 3 // unchanged even by X expose() events
+
+#ifdef MESA
+#define SWAP_TYPE NODAMAGE
+#else
+#define SWAP_TYPE SWAP
+#endif
+
+////////////////////////////////////////////////////////////////
+
+HDC fl_GetDC(HWND);
+
+int Fl_Gl_Window::can_do(int a, const int *b) {
+#ifdef WIN32
+ Fl_Gl_Choice *g = Fl_Gl_Choice::find(a,b);
+/*
+ Is this necessary? Don't all windows have the same
+ support for pixel formats?
+ HWND w = GetDesktopWindow();
+ HDC dc = GetDC(w);
+*/
+ if (!fl_gc) fl_GetDC(0);
+ int r = ChoosePixelFormat(fl_gc, &g->pfd);
+ return r != 0;
+#else
+ return Fl_Gl_Choice::find(a,b) != 0;
+#endif
+}
+
+void Fl_Gl_Window::show() {
+#ifndef WIN32
+ if (!shown()) {
+ if (!g) {
+ g = Fl_Gl_Choice::find(mode_,alist);
+ if (!g) {Fl::error("Insufficient GL support"); return;}
+ }
+ Fl_X::make_xid(this, g->vis, g->colormap);
+ if (overlay && overlay != this) ((Fl_Gl_Window*)overlay)->show();
+ }
+#endif
+ Fl_Window::show();
+}
+
+void Fl_Gl_Window::invalidate() {
+ valid(0);
+#ifndef WIN32
+ if (overlay) ((Fl_Gl_Window*)overlay)->valid(0);
+#endif
+}
+
+extern GLXContext fl_first_context; // in Fl_Gl_Choice.C
+
+int Fl_Gl_Window::mode(int m, const int *a) {
+ if (m == mode_ && a == alist) return 0;
+ mode_ = m; alist = a;
+#ifdef WIN32
+ // destroy context and g:
+ if (shown()) {hide(); show();}
+#else
+ // under X, if the visual changes we must make a new X window (!):
+ if (shown()) {
+ Fl_Gl_Choice *g1 = g;
+ g = Fl_Gl_Choice::find(mode_,alist);
+ if (!g || g->vis->visualid != g1->vis->visualid || g->d != g1->d) {
+ hide(); show();
+ }
+ }
+#endif
+ return 1;
+}
+
+#ifdef WIN32
+extern char fl_direct_paint; // true when responding to WM_PAINT
+#endif
+
+void Fl_Gl_Window::make_current() {
+#ifdef WIN32
+ HDC hdc = fl_private_dc(this, mode_,&g);
+ if (!context) {
+ context = wglCreateContext(hdc);
+ if (fl_first_context) wglShareLists(fl_first_context, (GLXContext)context);
+ else fl_first_context = (GLXContext)context;
+ valid(0);
+ }
+ wglMakeCurrent(hdc, (GLXContext)context);
+#else
+ if (!context) {
+ context = glXCreateContext(fl_display, g->vis, fl_first_context, 1);
+ if (!fl_first_context) fl_first_context = (GLXContext)context;
+ valid(0);
+ }
+ glXMakeCurrent(fl_display, fl_xid(this), (GLXContext)context);
+#endif
+ glDrawBuffer(GL_BACK);
+}
+
+void Fl_Gl_Window::ortho() {
+ glLoadIdentity();
+ glViewport(0, 0, w(), h());
+ glOrtho(0, w(), 0, h(), -1, 1);
+}
+
+void Fl_Gl_Window::swap_buffers() {
+#ifdef WIN32
+ SwapBuffers(Fl_X::i(this)->private_dc);
+#else
+ glXSwapBuffers(fl_display, fl_xid(this));
+#endif
+}
+
+#if HAVE_GL_OVERLAY
+#if WIN32
+uchar fl_overlay; // changes how fl_color() works
+#endif
+#endif
+
+void Fl_Gl_Window::flush() {
+ make_current();
+
+#if HAVE_GL_OVERLAY
+#ifdef WIN32
+ uchar save_valid = valid_;
+ if (overlay && overlay!= this && damage() == 8) goto DRAW_OVERLAY_ONLY;
+#endif
+#endif
+
+ if (g->d) {
+
+#if SWAP_TYPE == NODAMAGE
+
+ // don't draw if only overlay damage or expose events:
+ if ((damage()&~0xA0) || !valid()) draw();
+ swap_buffers();
+
+#elif SWAP_TYPE == COPY
+
+ // don't draw if only the overlay is damaged:
+ if (damage() != 8 || !valid()) draw();
+ swap_buffers();
+
+#else // SWAP_TYPE == SWAP || SWAP_TYPE == UNDEFINED
+
+ if (overlay == this) { // Use CopyPixels to act like SWAP_TYPE == COPY
+
+ // don't draw if only the overlay is damaged:
+ if (damage1_ || damage() != 8 || !valid()) draw();
+ // we use a seperate context for the copy because rasterpos must be 0
+ // and depth test needs to be off:
+ static GLXContext ortho_context;
+ int init = !ortho_context;
+#ifdef WIN32
+ if (init) ortho_context = wglCreateContext(Fl_X::i(this)->private_dc);
+ wglMakeCurrent(Fl_X::i(this)->private_dc, ortho_context);
+#else
+ if (init)
+ ortho_context = glXCreateContext(fl_display,g->vis,fl_first_context,1);
+ glXMakeCurrent(fl_display, fl_xid(this), ortho_context);
+#endif
+ if (init) {
+ glDisable(GL_DEPTH_TEST);
+ glReadBuffer(GL_BACK);
+ glDrawBuffer(GL_FRONT);
+ }
+ glCopyPixels(0,0,w(),h(),GL_COLOR);
+ make_current(); // set current context back to draw overlay
+ damage1_ = 0;
+
+ } else {
+
+#if SWAP_TYPE == SWAP
+ uchar old_damage = damage();
+ clear_damage(damage1_|old_damage); draw();
+ swap_buffers();
+ damage1_ = old_damage;
+#else // SWAP_TYPE == UNDEFINED
+ clear_damage(~0); draw();
+ swap_buffers();
+ damage1_ = ~0;
+#endif
+
+ }
+#endif
+
+ if (overlay==this) { // fake overlay in front buffer
+ glDrawBuffer(GL_FRONT);
+ draw_overlay();
+ glDrawBuffer(GL_BACK);
+ glFlush();
+ }
+
+ } else { // single-buffered context is simpler:
+
+ // this faking of the overlay is incorrect but worked good for
+ // one in-house program:
+ if (overlay != this || damage()!=8 || !Fl::pushed()) draw();
+ if (overlay == this) draw_overlay();
+ glFlush();
+
+ }
+
+#if HAVE_GL_OVERLAY
+#ifdef WIN32
+ if (overlay && overlay != this) {
+ DRAW_OVERLAY_ONLY:
+ valid_ = save_valid;
+ wglMakeCurrent(Fl_X::i(this)->private_dc, (GLXContext)overlay);
+ glDisable(GL_SCISSOR_TEST);
+ fl_overlay = 1;
+ glClear(GL_COLOR_BUFFER_BIT);
+ draw_overlay();
+ wglSwapLayerBuffers(Fl_X::i(this)->private_dc,WGL_SWAP_OVERLAY1);
+ fl_overlay = 0;
+ }
+#endif
+#endif
+
+ valid(1);
+}
+
+void Fl_Gl_Window::resize(int X,int Y,int W,int H) {
+ if (W != w() || H != h()) valid(0);
+ Fl_Window::resize(X,Y,W,H);
+}
+
+void Fl_Gl_Window::hide() {
+ if (context) {
+#ifdef WIN32
+ wglMakeCurrent(0, 0);
+ if (context && context != fl_first_context)
+ wglDeleteContext((GLXContext)context);
+ g = 0;
+#else
+ glXMakeCurrent(fl_display, 0, 0);
+ if (context != fl_first_context)
+ glXDestroyContext(fl_display, (GLXContext)context);
+#ifdef GLX_MESA_release_buffers
+ glXReleaseBuffersMESA(fl_display, fl_xid(this));
+#endif
+#endif
+ context = 0;
+ }
+ 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;
+ damage1_ = 0;
+}
+
+void Fl_Gl_Window::draw_overlay() {}
+
+#endif
diff --git a/src/Fl_visual.cxx b/src/Fl_visual.cxx
index 05d90edd1..76df209b4 100644
--- a/src/Fl_visual.cxx
+++ b/src/Fl_visual.cxx
@@ -1,79 +1,79 @@
-// Fl_visual.C
-//
-// 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;
-}
-#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 (!(flags & FL_INDEX)) {
- if (!v.red_mask) return 0; // detects static, true, and direct color
- 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.red_mask && v.depth > 8) return 0;
-#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
+// Fl_visual.C
+//
+// 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;
+}
+#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 (!(flags & FL_INDEX)) {
+ if (!v.red_mask) return 0; // detects static, true, and direct color
+ 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.red_mask && v.depth > 8) return 0;
+#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
diff --git a/src/Fl_win32.cxx b/src/Fl_win32.cxx
index 0a7ecd3b1..d27c2c2cc 100644
--- a/src/Fl_win32.cxx
+++ b/src/Fl_win32.cxx
@@ -1,767 +1,767 @@
-// Fl_win32.C
-
-// fltk (Fast Light Tool Kit) version 0.99
-// Copyright (C) 1998 Bill Spitzak
-
-// 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.
-
-// Written by Bill Spitzak spitzak@d2.com
-
-// This file contains win32-specific code for fltk which is always linked
-// in. Search other files for "WIN32" or filenames ending in _win32.C
-// for other system-specific code.
-
-#include <config.h>
-#include <FL/Fl.H>
-#include <FL/win32.H>
-#include <FL/Fl_Window.H>
-#include <string.h>
-
-////////////////////////////////////////////////////////////////
-// interface to poll/select call:
-
-// fd's are not yet implemented.
-// On NT these are probably only used for network stuff, so this may
-// talk to a package that Wonko has proposed writing to make the network
-// interface system independent.
-
-#define POLLIN 1
-#define POLLOUT 4
-#define POLLERR 8
-
-void Fl::add_fd(int n, int events, void (*cb)(int, void*), void *v) {}
-
-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) {}
-
-MSG fl_msg;
-
-int fl_ready() {
- return PeekMessage(&fl_msg, NULL, 0, 0, PM_NOREMOVE);
-}
-
-double fl_wait(int timeout_flag, double time) {
- int have_message;
- // get the first message by waiting the correct amount of time:
- if (!timeout_flag) {
- GetMessage(&fl_msg, NULL, 0, 0);
- have_message = 1;
- } else {
- if (time >= 0.001) {
- int timerid = SetTimer(NULL, 0, int(time*1000), NULL);
- GetMessage(&fl_msg, NULL, 0, 0);
- KillTimer(NULL, timerid);
- have_message = 1;
- } else {
- have_message = PeekMessage(&fl_msg, NULL, 0, 0, PM_REMOVE);
- }
- }
- // execute it, them execute any other messages that become ready during it:
- while (have_message) {
- DispatchMessage(&fl_msg);
- have_message = PeekMessage(&fl_msg, NULL, 0, 0, PM_REMOVE);
- }
- return time;
-}
-
-////////////////////////////////////////////////////////////////
-
-int Fl::h() {return GetSystemMetrics(SM_CYSCREEN);}
-
-int Fl::w() {return GetSystemMetrics(SM_CXSCREEN);}
-
-void Fl::get_mouse(int &x, int &y) {
- POINT p;
- GetCursorPos(&p);
- x = p.x;
- y = p.y;
-}
-
-////////////////////////////////////////////////////////////////
-
-extern Fl_Window *fl_xfocus; // in Fl.C
-extern Fl_Window *fl_xmousewin; // in Fl.C
-void fl_fix_focus(); // in Fl.C
-
-////////////////////////////////////////////////////////////////
-
-extern 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;
- 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:
- if (!fl_capture) SetCapture(fl_xid(window));
- 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.C
-// This table is in numeric order by VK:
-static const struct {unsigned short vk, fltk;} vktab[] = {
- {VK_BACK, FL_BackSpace},
- {VK_TAB, FL_Tab},
- {VK_CLEAR, FL_KP+'5'},
- {VK_RETURN, FL_Enter},
- {VK_SHIFT, FL_Shift_L},
- {VK_CONTROL, FL_Control_L},
- {VK_MENU, FL_Alt_L},
- {VK_PAUSE, FL_Pause},
- {VK_CAPITAL, FL_Caps_Lock},
- {VK_ESCAPE, FL_Escape},
- {VK_SPACE, ' '},
- {VK_PRIOR, FL_Page_Up},
- {VK_NEXT, FL_Page_Down},
- {VK_END, FL_End},
- {VK_HOME, FL_Home},
- {VK_LEFT, FL_Left},
- {VK_UP, FL_Up},
- {VK_RIGHT, FL_Right},
- {VK_DOWN, FL_Down},
- {VK_SNAPSHOT, FL_Print}, // does not work on NT
- {VK_INSERT, FL_Insert},
- {VK_DELETE, 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];
- 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;
- }
- if (extended) switch (vk) {
- case VK_CONTROL : return FL_Control_R;
- case VK_MENU: return FL_Alt_R;
- case VK_RETURN: return FL_KP_Enter;
- }
- return vklut[vk];
-}
-
-#if USE_COLORMAP
-extern HPALETTE fl_select_palette(); // in fl_color_win32.C
-#endif
-
-static Fl_Window* resize_bug_fix;
-
-static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- static char buffer[2];
-
- fl_msg.message = uMsg;
-
- Fl_Window *window = fl_find(hWnd);
-
- STUPID_MICROSOFT:
- 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);
- return 0;
-
- case WM_PAINT: {
- // MSWindows has already set the clip region! Fltk does not like this,
- // since it wants to draw it's own damage at the same time, and
- // this damage may be outside the clip region. I kludge around
- // this, grep for fl_direct_paint to find the kludges...
- // if (!(window->damage())) fl_direct_paint = 1;
- PAINTSTRUCT ps;
-
- // I think MSWindows refuses to allocate two DCs for the same hWnd,
- // so it may kludge the way the DCs are being handled. Works for now,
- // the "final" solution can wait... Whatever the behaviour of the win32
- // API, there is bound to be some small memory leak here.
- // If anyone knows EXACTLY how DCs are allocated, please fix.
- fl_window = hWnd;
- fl_gc = BeginPaint(hWnd, &ps);
- // A bug popped up because of the two following lines, which according to
- // the original code's comments GetDC always resets. I just don't get
- // why the problem hadn't manifested itself here earlier (well, probably
- // because MSWindows was not allocating a new DC, but using the old one)
- // Anyway, these followed the original GetDC calls, but for some reason
- // were not here with the BeginPaint
- SetTextAlign(fl_gc, TA_BASELINE|TA_LEFT);
- SetBkMode(fl_gc, TRANSPARENT);
-
- window->expose(2, ps.rcPaint.left, ps.rcPaint.top,
- ps.rcPaint.right-ps.rcPaint.left,
- ps.rcPaint.bottom-ps.rcPaint.top);
-
- Fl_X::i(window)->flush();
- window->clear_damage();
- //Since damage has been reset, we can dispose of the clip region
- Region &r=Fl_X::i(window)->region;
- if (r) {
- DeleteObject(r);
- r = 0;
- }
- EndPaint(hWnd, &ps);
-
- fl_gc = 0;
- fl_window = (HWND)-1;
- } break;
-
- 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: mouse_event(window, 3, 0, wParam, lParam); return 0;
-
- // kludges so the pop-up menus work. Title bar still blinks, sigh...
- case WM_CAPTURECHANGED:
- if (fl_capture && lParam != (LPARAM)fl_capture) {
- SetCapture(fl_capture);
- return 0;
- }
- break;
- case WM_ACTIVATE:
- if (fl_capture && wParam && hWnd!=fl_capture) {
- SetActiveWindow(fl_capture);
- return 0;
- }
- 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_KEYDOWN:
- case WM_SYSKEYDOWN:
- // save the keysym until we figure out the characters:
- Fl::e_keysym = ms2fltk(wParam,lParam&(1<<24));
- case WM_KEYUP:
- case WM_SYSKEYUP:
- TranslateMessage(&fl_msg); // always returns 1!!!
- // TranslateMessage is supposed to return true only if it turns
- // into another message, but it seems to always return 1 on my
- // NT machine. So I will instead peek to see if there is a
- // character message in the queue, I hope this can only happen
- // if the translation worked:
- if (PeekMessage(&fl_msg, hWnd, WM_CHAR, WM_SYSDEADCHAR, 1)) {
- uMsg = fl_msg.message;
- wParam = fl_msg.wParam;
- lParam = fl_msg.lParam;
- goto STUPID_MICROSOFT;
- }
- // otherwise use it as a 0-character key...
- case WM_DEADCHAR:
- case WM_SYSDEADCHAR:
- buffer[0] = 0;
- Fl::e_text = buffer;
- Fl::e_length = 0;
- goto GETSTATE;
- case WM_CHAR:
- case WM_SYSCHAR:
- buffer[0] = char(wParam);
- Fl::e_text = buffer;
- Fl::e_length = 1;
- GETSTATE:
- {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)&~1 || GetKeyState(VK_RWIN)&~1) state |= FL_META;
- if (GetKeyState(VK_SCROLL)) state |= FL_SCROLL_LOCK;
- Fl::e_state = state;}
- if (lParam & (1<<31)) goto DEFAULT; // ignore up events after fixing shift
- // for (int i = lParam&0xff; i--;)
- while (window->parent()) window = window->window();
- if (Fl::handle(FL_KEYBOARD,window)) return 0;
- break;
-
- 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;
- window->position(LOWORD(lParam), HIWORD(lParam));
- 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
-
- default:
- DEFAULT:
- if (Fl::handle(0,0)) return 0;
- break;
- }
-
- return DefWindowProc(hWnd, uMsg, wParam, lParam);
-}
-
-////////////////////////////////////////////////////////////////
-
-void Fl_Window::resize(int X,int Y,int W,int H) {
- int resize_from_program = 1;
- if (this == resize_bug_fix) {
- resize_from_program = 0;
- resize_bug_fix = 0;
- }
- if (X==x() && Y==y() && W==w() && H==h()) return;
- if (X != x() || Y != y()) set_flag(FL_FORCE_POSITION);
- if (W != w() || H != h()) Fl_Group::resize(X,Y,W,H); else {x(X); y(Y);}
- if (resize_from_program && shown()) {
- if (border() && !parent()) {
- X -= GetSystemMetrics(SM_CXFRAME);
- Y -= GetSystemMetrics(SM_CYFRAME)+GetSystemMetrics(SM_CYCAPTION);
- W += 2*GetSystemMetrics(SM_CXFRAME);
- H += 2*GetSystemMetrics(SM_CYFRAME)+GetSystemMetrics(SM_CYCAPTION);
- }
- MoveWindow(i->xid, X, Y, W, H, TRUE);
- //if (!parent()) redraw();
- }
-}
-
-////////////////////////////////////////////////////////////////
-
-char fl_show_iconic; // hack for Fl_Window::iconic()
-// int fl_background_pixel = -1; // color to use for background
-HCURSOR fl_default_cursor;
-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()
- w->clear_damage(); // wait for expose events
-
- static char* class_name;
- if (!class_name) { // create a single WNDCLASS used for everything:
- class_name = "FLTK";
- WNDCLASSEX wc;
- wc.style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC | CS_DBLCLKS;
- wc.lpfnWndProc = (WNDPROC)WndProc;
- wc.cbClsExtra = wc.cbWndExtra = 0;
- wc.hInstance = fl_display;
- wc.hIcon = wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
- 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.hbrBackground = NULL;
- wc.lpszMenuName = NULL;
- wc.lpszClassName = class_name;
- wc.cbSize = sizeof(WNDCLASSEX);
- RegisterClassEx(&wc);
- }
-
- HWND parent;
- DWORD style;
- DWORD styleEx;
- int xp = w->x();
- int yp = w->y();
- int wp = w->w();
- int hp = w->h();
-
- if (w->parent()) {
- style = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
- styleEx = WS_EX_LEFT | 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());
- }
- }
- if (w->border()) {
- style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU
- | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
- styleEx = WS_EX_LEFT | WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT;
- if (w->maxw != w->minw || w->maxh != w->minh)
- style |= WS_THICKFRAME | WS_MAXIMIZEBOX;
- if (!w->modal()) style |= WS_MINIMIZEBOX;
- xp -= GetSystemMetrics(SM_CXFRAME);
- yp -= GetSystemMetrics(SM_CYFRAME)+GetSystemMetrics(SM_CYCAPTION);
- wp += 2*GetSystemMetrics(SM_CXFRAME);
- hp += 2*GetSystemMetrics(SM_CYFRAME)+GetSystemMetrics(SM_CYCAPTION);
- } else {
- style = WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_OVERLAPPED;
- styleEx = WS_EX_LEFT | WS_EX_TOPMOST | WS_EX_TOOLWINDOW;
- }
- if (!(w->flags() & Fl_Window::FL_FORCE_POSITION)) {
- xp = yp = CW_USEDEFAULT;
- }
- parent = 0;
- if (w->non_modal() && !fl_disable_transient_for) {
- // find some other window to be "transient for":
- for (Fl_X* y = Fl_X::first; y; y = y->next) {
- Fl_Window* w = y->w;
- while (w->parent()) w = w->window();
- if (!w->non_modal()) {
- parent = fl_xid(w);
- break;
- }
- }
- }
- }
-
- 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;
-
- // use w->xclass() to set the icon...
-
- w->set_visible();
- w->handle(FL_SHOW); // get child windows to appear
- ShowWindow(x->xid, fl_show_iconic ? SW_MINIMIZE : SW_SHOW);
- fl_show_iconic = 0;
- fl_fix_focus();
- return x;
-}
-
-////////////////////////////////////////////////////////////////
-
-HINSTANCE fl_display;
-
-int Fl_WinMain(HINSTANCE hInstance, LPSTR lpCmdLine, int nCmdShow,
- int (*mainp)(int, char**)) {
- fl_display = hInstance;
-
- int argc;
- char **argv;
- // test version for now:
- argc = 1; char* testargv[] = {"test", 0}; argv = testargv;
-
- return mainp(argc, argv);
-}
-
-////////////////////////////////////////////////////////////////
-
-void Fl_Window::size_range_() {
- size_range_set = 1;
-}
-
-void Fl_X::set_minmax(LPMINMAXINFO minmax)
-{
- int wd, hd;
- if (w->border()) {
- wd = 2*GetSystemMetrics(SM_CXFRAME);
- hd = 2*GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
- } else {
- wd = hd = 0;
- }
- 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;
- }
-}
-
-////////////////////////////////////////////////////////////////
-
-// returns pointer to the filename, or null if name ends with '/'
-const char *filename_name(const char *name) {
- const char *p,*q;
- 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 = 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.C:
-// 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() {
- if (!shown()) {
- // if (can_boxcheat(box())) fl_background_pixel = fl_xpixel(color());
- Fl_X::make(this);
- } else {
- ShowWindow(i->xid, SW_RESTORE);
- SetActiveWindow(i->xid);
- }
-}
-
-Fl_Window *Fl_Window::current_;
-HDC window_dc;
-// 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 = (HWND)-1;
-
-// Here we ensure only one GetDC is ever in place. There is a little
-// workaround for the case of direct_paint.
-HDC fl_GetDC(HWND w) {
- /*
- if (fl_direct_paint) {
- if (w == direct_paint_window) return direct_paint_dc;
- }
-*/
- if (fl_gc) {
- if (w == fl_window) return fl_gc;
- ReleaseDC(fl_window, fl_gc);
- }
- fl_gc = GetDC(w);
- 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));
- current_ = this;
-}
-
-// WM_PAINT events and cropped damage call this:
-void Fl_Window::expose(uchar flags,int X,int Y,int W,int H) {
- if (i) {
- Region temp= XRectangleRegion(X,Y,W,H);
- if (i->region) {
- CombineRgn(temp,temp,i->region,RGN_AND);
- DeleteObject((HGDIOBJ)i->region);
- }
- i->region=temp;
- }
- damage(flags);
-}
-
-#include <FL/fl_draw.H>
-
-void Fl_Widget::damage(uchar flags) {
- if (type() < FL_WINDOW) {
- damage(flags, x(), y(), w(), h());
- } else {
- Fl_X* i = Fl_X::i((Fl_Window*)this);
- if (i) {
- if (i->region) {DeleteObject((HGDIOBJ)i->region); i->region = 0;}
- damage_ |= flags;
- Fl::damage(1);
- }
- }
-}
-
-void Fl_Widget::redraw() {damage(~0);}
-
-Region XRectangleRegion(int x, int y, int w, int h); // in fl_rect.C
-
-void Fl_Widget::damage(uchar flags, int X, int Y, int W, int H) {
- if (type() < FL_WINDOW) {
- damage_ |= flags;
- if (parent()) parent()->damage(1,X,Y,W,H);
- } else {
- // see if damage covers entire window:
- if (X<=0 && Y<=0 && W>=w() && H>=h()) {damage(flags); return;}
- Fl_X* i = Fl_X::i((Fl_Window*)this);
- if (i) {
- if (damage()) {
- // if we already have damage we must merge with existing region:
- if (i->region) {
- Region r = XRectangleRegion(X,Y,W,H);
- CombineRgn(i->region,i->region,r,RGN_OR);
- DeleteObject(r);
- }
- damage_ |= flags;
- } else {
- // create a new region:
- if (i->region) DeleteObject(i->region);
- i->region = XRectangleRegion(X,Y,W,H);
- damage_ = flags;
- }
- Fl::damage(1);
- }
- }
-}
-
-void Fl_Window::flush() {
- make_current();
- if (damage() & ~6) {
- draw();
- } else {
- fl_clip_region(i->region);
- draw();
- fl_pop_clip();
- }
-}
-
-// End of Fl_win32.C //
+// Fl_win32.C
+
+// fltk (Fast Light Tool Kit) version 0.99
+// Copyright (C) 1998 Bill Spitzak
+
+// 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.
+
+// Written by Bill Spitzak spitzak@d2.com
+
+// This file contains win32-specific code for fltk which is always linked
+// in. Search other files for "WIN32" or filenames ending in _win32.C
+// for other system-specific code.
+
+#include <config.h>
+#include <FL/Fl.H>
+#include <FL/win32.H>
+#include <FL/Fl_Window.H>
+#include <string.h>
+
+////////////////////////////////////////////////////////////////
+// interface to poll/select call:
+
+// fd's are not yet implemented.
+// On NT these are probably only used for network stuff, so this may
+// talk to a package that Wonko has proposed writing to make the network
+// interface system independent.
+
+#define POLLIN 1
+#define POLLOUT 4
+#define POLLERR 8
+
+void Fl::add_fd(int n, int events, void (*cb)(int, void*), void *v) {}
+
+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) {}
+
+MSG fl_msg;
+
+int fl_ready() {
+ return PeekMessage(&fl_msg, NULL, 0, 0, PM_NOREMOVE);
+}
+
+double fl_wait(int timeout_flag, double time) {
+ int have_message;
+ // get the first message by waiting the correct amount of time:
+ if (!timeout_flag) {
+ GetMessage(&fl_msg, NULL, 0, 0);
+ have_message = 1;
+ } else {
+ if (time >= 0.001) {
+ int timerid = SetTimer(NULL, 0, int(time*1000), NULL);
+ GetMessage(&fl_msg, NULL, 0, 0);
+ KillTimer(NULL, timerid);
+ have_message = 1;
+ } else {
+ have_message = PeekMessage(&fl_msg, NULL, 0, 0, PM_REMOVE);
+ }
+ }
+ // execute it, them execute any other messages that become ready during it:
+ while (have_message) {
+ DispatchMessage(&fl_msg);
+ have_message = PeekMessage(&fl_msg, NULL, 0, 0, PM_REMOVE);
+ }
+ return time;
+}
+
+////////////////////////////////////////////////////////////////
+
+int Fl::h() {return GetSystemMetrics(SM_CYSCREEN);}
+
+int Fl::w() {return GetSystemMetrics(SM_CXSCREEN);}
+
+void Fl::get_mouse(int &x, int &y) {
+ POINT p;
+ GetCursorPos(&p);
+ x = p.x;
+ y = p.y;
+}
+
+////////////////////////////////////////////////////////////////
+
+extern Fl_Window *fl_xfocus; // in Fl.C
+extern Fl_Window *fl_xmousewin; // in Fl.C
+void fl_fix_focus(); // in Fl.C
+
+////////////////////////////////////////////////////////////////
+
+extern 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;
+ 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:
+ if (!fl_capture) SetCapture(fl_xid(window));
+ 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.C
+// This table is in numeric order by VK:
+static const struct {unsigned short vk, fltk;} vktab[] = {
+ {VK_BACK, FL_BackSpace},
+ {VK_TAB, FL_Tab},
+ {VK_CLEAR, FL_KP+'5'},
+ {VK_RETURN, FL_Enter},
+ {VK_SHIFT, FL_Shift_L},
+ {VK_CONTROL, FL_Control_L},
+ {VK_MENU, FL_Alt_L},
+ {VK_PAUSE, FL_Pause},
+ {VK_CAPITAL, FL_Caps_Lock},
+ {VK_ESCAPE, FL_Escape},
+ {VK_SPACE, ' '},
+ {VK_PRIOR, FL_Page_Up},
+ {VK_NEXT, FL_Page_Down},
+ {VK_END, FL_End},
+ {VK_HOME, FL_Home},
+ {VK_LEFT, FL_Left},
+ {VK_UP, FL_Up},
+ {VK_RIGHT, FL_Right},
+ {VK_DOWN, FL_Down},
+ {VK_SNAPSHOT, FL_Print}, // does not work on NT
+ {VK_INSERT, FL_Insert},
+ {VK_DELETE, 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];
+ 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;
+ }
+ if (extended) switch (vk) {
+ case VK_CONTROL : return FL_Control_R;
+ case VK_MENU: return FL_Alt_R;
+ case VK_RETURN: return FL_KP_Enter;
+ }
+ return vklut[vk];
+}
+
+#if USE_COLORMAP
+extern HPALETTE fl_select_palette(); // in fl_color_win32.C
+#endif
+
+static Fl_Window* resize_bug_fix;
+
+static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ static char buffer[2];
+
+ fl_msg.message = uMsg;
+
+ Fl_Window *window = fl_find(hWnd);
+
+ STUPID_MICROSOFT:
+ 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);
+ return 0;
+
+ case WM_PAINT: {
+ // MSWindows has already set the clip region! Fltk does not like this,
+ // since it wants to draw it's own damage at the same time, and
+ // this damage may be outside the clip region. I kludge around
+ // this, grep for fl_direct_paint to find the kludges...
+ // if (!(window->damage())) fl_direct_paint = 1;
+ PAINTSTRUCT ps;
+
+ // I think MSWindows refuses to allocate two DCs for the same hWnd,
+ // so it may kludge the way the DCs are being handled. Works for now,
+ // the "final" solution can wait... Whatever the behaviour of the win32
+ // API, there is bound to be some small memory leak here.
+ // If anyone knows EXACTLY how DCs are allocated, please fix.
+ fl_window = hWnd;
+ fl_gc = BeginPaint(hWnd, &ps);
+ // A bug popped up because of the two following lines, which according to
+ // the original code's comments GetDC always resets. I just don't get
+ // why the problem hadn't manifested itself here earlier (well, probably
+ // because MSWindows was not allocating a new DC, but using the old one)
+ // Anyway, these followed the original GetDC calls, but for some reason
+ // were not here with the BeginPaint
+ SetTextAlign(fl_gc, TA_BASELINE|TA_LEFT);
+ SetBkMode(fl_gc, TRANSPARENT);
+
+ window->expose(2, ps.rcPaint.left, ps.rcPaint.top,
+ ps.rcPaint.right-ps.rcPaint.left,
+ ps.rcPaint.bottom-ps.rcPaint.top);
+
+ Fl_X::i(window)->flush();
+ window->clear_damage();
+ //Since damage has been reset, we can dispose of the clip region
+ Region &r=Fl_X::i(window)->region;
+ if (r) {
+ DeleteObject(r);
+ r = 0;
+ }
+ EndPaint(hWnd, &ps);
+
+ fl_gc = 0;
+ fl_window = (HWND)-1;
+ } break;
+
+ 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: mouse_event(window, 3, 0, wParam, lParam); return 0;
+
+ // kludges so the pop-up menus work. Title bar still blinks, sigh...
+ case WM_CAPTURECHANGED:
+ if (fl_capture && lParam != (LPARAM)fl_capture) {
+ SetCapture(fl_capture);
+ return 0;
+ }
+ break;
+ case WM_ACTIVATE:
+ if (fl_capture && wParam && hWnd!=fl_capture) {
+ SetActiveWindow(fl_capture);
+ return 0;
+ }
+ 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_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ // save the keysym until we figure out the characters:
+ Fl::e_keysym = ms2fltk(wParam,lParam&(1<<24));
+ case WM_KEYUP:
+ case WM_SYSKEYUP:
+ TranslateMessage(&fl_msg); // always returns 1!!!
+ // TranslateMessage is supposed to return true only if it turns
+ // into another message, but it seems to always return 1 on my
+ // NT machine. So I will instead peek to see if there is a
+ // character message in the queue, I hope this can only happen
+ // if the translation worked:
+ if (PeekMessage(&fl_msg, hWnd, WM_CHAR, WM_SYSDEADCHAR, 1)) {
+ uMsg = fl_msg.message;
+ wParam = fl_msg.wParam;
+ lParam = fl_msg.lParam;
+ goto STUPID_MICROSOFT;
+ }
+ // otherwise use it as a 0-character key...
+ case WM_DEADCHAR:
+ case WM_SYSDEADCHAR:
+ buffer[0] = 0;
+ Fl::e_text = buffer;
+ Fl::e_length = 0;
+ goto GETSTATE;
+ case WM_CHAR:
+ case WM_SYSCHAR:
+ buffer[0] = char(wParam);
+ Fl::e_text = buffer;
+ Fl::e_length = 1;
+ GETSTATE:
+ {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)&~1 || GetKeyState(VK_RWIN)&~1) state |= FL_META;
+ if (GetKeyState(VK_SCROLL)) state |= FL_SCROLL_LOCK;
+ Fl::e_state = state;}
+ if (lParam & (1<<31)) goto DEFAULT; // ignore up events after fixing shift
+ // for (int i = lParam&0xff; i--;)
+ while (window->parent()) window = window->window();
+ if (Fl::handle(FL_KEYBOARD,window)) return 0;
+ break;
+
+ 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;
+ window->position(LOWORD(lParam), HIWORD(lParam));
+ 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
+
+ default:
+ DEFAULT:
+ if (Fl::handle(0,0)) return 0;
+ break;
+ }
+
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+////////////////////////////////////////////////////////////////
+
+void Fl_Window::resize(int X,int Y,int W,int H) {
+ int resize_from_program = 1;
+ if (this == resize_bug_fix) {
+ resize_from_program = 0;
+ resize_bug_fix = 0;
+ }
+ if (X==x() && Y==y() && W==w() && H==h()) return;
+ if (X != x() || Y != y()) set_flag(FL_FORCE_POSITION);
+ if (W != w() || H != h()) Fl_Group::resize(X,Y,W,H); else {x(X); y(Y);}
+ if (resize_from_program && shown()) {
+ if (border() && !parent()) {
+ X -= GetSystemMetrics(SM_CXFRAME);
+ Y -= GetSystemMetrics(SM_CYFRAME)+GetSystemMetrics(SM_CYCAPTION);
+ W += 2*GetSystemMetrics(SM_CXFRAME);
+ H += 2*GetSystemMetrics(SM_CYFRAME)+GetSystemMetrics(SM_CYCAPTION);
+ }
+ MoveWindow(i->xid, X, Y, W, H, TRUE);
+ //if (!parent()) redraw();
+ }
+}
+
+////////////////////////////////////////////////////////////////
+
+char fl_show_iconic; // hack for Fl_Window::iconic()
+// int fl_background_pixel = -1; // color to use for background
+HCURSOR fl_default_cursor;
+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()
+ w->clear_damage(); // wait for expose events
+
+ static char* class_name;
+ if (!class_name) { // create a single WNDCLASS used for everything:
+ class_name = "FLTK";
+ WNDCLASSEX wc;
+ wc.style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC | CS_DBLCLKS;
+ wc.lpfnWndProc = (WNDPROC)WndProc;
+ wc.cbClsExtra = wc.cbWndExtra = 0;
+ wc.hInstance = fl_display;
+ wc.hIcon = wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
+ 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.hbrBackground = NULL;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = class_name;
+ wc.cbSize = sizeof(WNDCLASSEX);
+ RegisterClassEx(&wc);
+ }
+
+ HWND parent;
+ DWORD style;
+ DWORD styleEx;
+ int xp = w->x();
+ int yp = w->y();
+ int wp = w->w();
+ int hp = w->h();
+
+ if (w->parent()) {
+ style = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
+ styleEx = WS_EX_LEFT | 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());
+ }
+ }
+ if (w->border()) {
+ style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU
+ | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
+ styleEx = WS_EX_LEFT | WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT;
+ if (w->maxw != w->minw || w->maxh != w->minh)
+ style |= WS_THICKFRAME | WS_MAXIMIZEBOX;
+ if (!w->modal()) style |= WS_MINIMIZEBOX;
+ xp -= GetSystemMetrics(SM_CXFRAME);
+ yp -= GetSystemMetrics(SM_CYFRAME)+GetSystemMetrics(SM_CYCAPTION);
+ wp += 2*GetSystemMetrics(SM_CXFRAME);
+ hp += 2*GetSystemMetrics(SM_CYFRAME)+GetSystemMetrics(SM_CYCAPTION);
+ } else {
+ style = WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_OVERLAPPED;
+ styleEx = WS_EX_LEFT | WS_EX_TOPMOST | WS_EX_TOOLWINDOW;
+ }
+ if (!(w->flags() & Fl_Window::FL_FORCE_POSITION)) {
+ xp = yp = CW_USEDEFAULT;
+ }
+ parent = 0;
+ if (w->non_modal() && !fl_disable_transient_for) {
+ // find some other window to be "transient for":
+ for (Fl_X* y = Fl_X::first; y; y = y->next) {
+ Fl_Window* w = y->w;
+ while (w->parent()) w = w->window();
+ if (!w->non_modal()) {
+ parent = fl_xid(w);
+ break;
+ }
+ }
+ }
+ }
+
+ 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;
+
+ // use w->xclass() to set the icon...
+
+ w->set_visible();
+ w->handle(FL_SHOW); // get child windows to appear
+ ShowWindow(x->xid, fl_show_iconic ? SW_MINIMIZE : SW_SHOW);
+ fl_show_iconic = 0;
+ fl_fix_focus();
+ return x;
+}
+
+////////////////////////////////////////////////////////////////
+
+HINSTANCE fl_display;
+
+int Fl_WinMain(HINSTANCE hInstance, LPSTR lpCmdLine, int nCmdShow,
+ int (*mainp)(int, char**)) {
+ fl_display = hInstance;
+
+ int argc;
+ char **argv;
+ // test version for now:
+ argc = 1; char* testargv[] = {"test", 0}; argv = testargv;
+
+ return mainp(argc, argv);
+}
+
+////////////////////////////////////////////////////////////////
+
+void Fl_Window::size_range_() {
+ size_range_set = 1;
+}
+
+void Fl_X::set_minmax(LPMINMAXINFO minmax)
+{
+ int wd, hd;
+ if (w->border()) {
+ wd = 2*GetSystemMetrics(SM_CXFRAME);
+ hd = 2*GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
+ } else {
+ wd = hd = 0;
+ }
+ 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;
+ }
+}
+
+////////////////////////////////////////////////////////////////
+
+// returns pointer to the filename, or null if name ends with '/'
+const char *filename_name(const char *name) {
+ const char *p,*q;
+ 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 = 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.C:
+// 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() {
+ if (!shown()) {
+ // if (can_boxcheat(box())) fl_background_pixel = fl_xpixel(color());
+ Fl_X::make(this);
+ } else {
+ ShowWindow(i->xid, SW_RESTORE);
+ SetActiveWindow(i->xid);
+ }
+}
+
+Fl_Window *Fl_Window::current_;
+HDC window_dc;
+// 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 = (HWND)-1;
+
+// Here we ensure only one GetDC is ever in place. There is a little
+// workaround for the case of direct_paint.
+HDC fl_GetDC(HWND w) {
+ /*
+ if (fl_direct_paint) {
+ if (w == direct_paint_window) return direct_paint_dc;
+ }
+*/
+ if (fl_gc) {
+ if (w == fl_window) return fl_gc;
+ ReleaseDC(fl_window, fl_gc);
+ }
+ fl_gc = GetDC(w);
+ 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));
+ current_ = this;
+}
+
+// WM_PAINT events and cropped damage call this:
+void Fl_Window::expose(uchar flags,int X,int Y,int W,int H) {
+ if (i) {
+ Region temp= XRectangleRegion(X,Y,W,H);
+ if (i->region) {
+ CombineRgn(temp,temp,i->region,RGN_AND);
+ DeleteObject((HGDIOBJ)i->region);
+ }
+ i->region=temp;
+ }
+ damage(flags);
+}
+
+#include <FL/fl_draw.H>
+
+void Fl_Widget::damage(uchar flags) {
+ if (type() < FL_WINDOW) {
+ damage(flags, x(), y(), w(), h());
+ } else {
+ Fl_X* i = Fl_X::i((Fl_Window*)this);
+ if (i) {
+ if (i->region) {DeleteObject((HGDIOBJ)i->region); i->region = 0;}
+ damage_ |= flags;
+ Fl::damage(1);
+ }
+ }
+}
+
+void Fl_Widget::redraw() {damage(~0);}
+
+Region XRectangleRegion(int x, int y, int w, int h); // in fl_rect.C
+
+void Fl_Widget::damage(uchar flags, int X, int Y, int W, int H) {
+ if (type() < FL_WINDOW) {
+ damage_ |= flags;
+ if (parent()) parent()->damage(1,X,Y,W,H);
+ } else {
+ // see if damage covers entire window:
+ if (X<=0 && Y<=0 && W>=w() && H>=h()) {damage(flags); return;}
+ Fl_X* i = Fl_X::i((Fl_Window*)this);
+ if (i) {
+ if (damage()) {
+ // if we already have damage we must merge with existing region:
+ if (i->region) {
+ Region r = XRectangleRegion(X,Y,W,H);
+ CombineRgn(i->region,i->region,r,RGN_OR);
+ DeleteObject(r);
+ }
+ damage_ |= flags;
+ } else {
+ // create a new region:
+ if (i->region) DeleteObject(i->region);
+ i->region = XRectangleRegion(X,Y,W,H);
+ damage_ = flags;
+ }
+ Fl::damage(1);
+ }
+ }
+}
+
+void Fl_Window::flush() {
+ make_current();
+ if (damage() & ~6) {
+ draw();
+ } else {
+ fl_clip_region(i->region);
+ draw();
+ fl_pop_clip();
+ }
+}
+
+// End of Fl_win32.C //
diff --git a/src/Fl_x.cxx b/src/Fl_x.cxx
index 2d5a5ab46..ef0bb386d 100644
--- a/src/Fl_x.cxx
+++ b/src/Fl_x.cxx
@@ -389,7 +389,7 @@ int fl_handle(const XEvent& xevent)
}
// ignore all effects of shift on the keysyms (makes it a lot
// easier to program shortcuts!)
- keysym = XKeycodeToKeysym(fl_display, i, 0);
+ if (keysym < 0x400) keysym = XKeycodeToKeysym(fl_display, i, 0);
#ifdef __sgi
// get some missing PC keyboard keys:
if (!keysym) switch(i) {
diff --git a/src/fl_font_win32.cxx b/src/fl_font_win32.cxx
index 99283a433..f82f710fe 100644
--- a/src/fl_font_win32.cxx
+++ b/src/fl_font_win32.cxx
@@ -1,159 +1,159 @@
-// fl_font_win32.C
-
-#include <config.h>
-#include <FL/Fl.H>
-#include <FL/fl_draw.H>
-#include <FL/win32.H>
-#include "Fl_Font.H"
-
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-
-Fl_XFont::Fl_XFont(const char *name, int size, int num) {
- 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
- number = num;
- minsize = maxsize = size;
-}
-
-Fl_XFont *fl_current_xfont;
-
-Fl_XFont::~Fl_XFont() {
-#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_current_xfont) fl_current_xfont = 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_XFont *find(int fnum, int size) {
- Fl_Fontdesc *s = fl_fonts+fnum;
- if (!s->name) s = fl_fonts; // use 0 if fnum undefined
- Fl_XFont *f;
- for (f = s->first; f; f = f->next)
- if (f->minsize <= size && f->maxsize >= size) return f;
- f = new Fl_XFont(s->name, size, fnum);
- f->next = s->first;
- s->first = f;
- return f;
-}
-
-////////////////////////////////////////////////////////////////
-// Public interface:
-
-int fl_font_;
-int fl_size_;
-//static HDC font_gc;
-
-void fl_font(int fnum, int size) {
- if (fnum == fl_font_ && size == fl_size_) return;
- fl_font_ = fnum; fl_size_ = size;
- fl_current_xfont = find(fnum, size);
-}
-
-void fl_font(int fnum, int size, Fl_Font default_font, int default_size) {
- if (fnum<4) fnum |= default_font;
- fl_font(fnum, size + default_size);
-}
-
-int fl_height() {
- return (fl_current_xfont->metr.tmAscent + fl_current_xfont->metr.tmDescent);
-}
-
-int fl_descent() {
- return fl_current_xfont->metr.tmDescent;
-}
-
-double fl_width(const char *c) {
- double w = 0.0;
- while (*c) w += fl_current_xfont->width[uchar(*c++)];
- return w;
-}
-
-double fl_width(const char *c, int n) {
- double w = 0.0;
- while (n--) w += fl_current_xfont->width[uchar(*c++)];
- return w;
-}
-
-double fl_width(uchar c) {
- return fl_current_xfont->width[c];
-}
-
-void fl_draw(const char *str, int n, int x, int y) {
- SetTextColor(fl_gc, fl_RGB());
- SelectObject(fl_gc, fl_current_xfont->fid);
- TextOut(fl_gc, x, y, str, n);
-}
-
-void fl_draw(const char *str, int x, int y) {
- fl_draw(str, strlen(str), x, y);
-}
-
-// end of fl_font_win32.C
+// fl_font_win32.C
+
+#include <config.h>
+#include <FL/Fl.H>
+#include <FL/fl_draw.H>
+#include <FL/win32.H>
+#include "Fl_Font.H"
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+Fl_XFont::Fl_XFont(const char *name, int size, int num) {
+ 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
+ number = num;
+ minsize = maxsize = size;
+}
+
+Fl_XFont *fl_current_xfont;
+
+Fl_XFont::~Fl_XFont() {
+#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_current_xfont) fl_current_xfont = 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_XFont *find(int fnum, int size) {
+ Fl_Fontdesc *s = fl_fonts+fnum;
+ if (!s->name) s = fl_fonts; // use 0 if fnum undefined
+ Fl_XFont *f;
+ for (f = s->first; f; f = f->next)
+ if (f->minsize <= size && f->maxsize >= size) return f;
+ f = new Fl_XFont(s->name, size, fnum);
+ f->next = s->first;
+ s->first = f;
+ return f;
+}
+
+////////////////////////////////////////////////////////////////
+// Public interface:
+
+int fl_font_;
+int fl_size_;
+//static HDC font_gc;
+
+void fl_font(int fnum, int size) {
+ if (fnum == fl_font_ && size == fl_size_) return;
+ fl_font_ = fnum; fl_size_ = size;
+ fl_current_xfont = find(fnum, size);
+}
+
+void fl_font(int fnum, int size, Fl_Font default_font, int default_size) {
+ if (fnum<4) fnum |= default_font;
+ fl_font(fnum, size + default_size);
+}
+
+int fl_height() {
+ return (fl_current_xfont->metr.tmAscent + fl_current_xfont->metr.tmDescent);
+}
+
+int fl_descent() {
+ return fl_current_xfont->metr.tmDescent;
+}
+
+double fl_width(const char *c) {
+ double w = 0.0;
+ while (*c) w += fl_current_xfont->width[uchar(*c++)];
+ return w;
+}
+
+double fl_width(const char *c, int n) {
+ double w = 0.0;
+ while (n--) w += fl_current_xfont->width[uchar(*c++)];
+ return w;
+}
+
+double fl_width(uchar c) {
+ return fl_current_xfont->width[c];
+}
+
+void fl_draw(const char *str, int n, int x, int y) {
+ SetTextColor(fl_gc, fl_RGB());
+ SelectObject(fl_gc, fl_current_xfont->fid);
+ TextOut(fl_gc, x, y, str, n);
+}
+
+void fl_draw(const char *str, int x, int y) {
+ fl_draw(str, strlen(str), x, y);
+}
+
+// end of fl_font_win32.C
diff --git a/src/fl_rect.cxx b/src/fl_rect.cxx
index 1ea826c6f..f047bb824 100644
--- a/src/fl_rect.cxx
+++ b/src/fl_rect.cxx
@@ -1,351 +1,351 @@
-// fl_rect.C
-
-// 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 <FL/Fl_Widget.H>
-#include <FL/fl_draw.H>
-#include <FL/x.H>
-
-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);
-#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());
-#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);
-#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--;
- MoveToEx(fl_gc, x, y, 0L);
- LineTo(fl_gc, x1, y);
- LineTo(fl_gc, x1, y2);
-#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
- MoveToEx(fl_gc, x, y, 0L);
- LineTo(fl_gc, x1, y);
- LineTo(fl_gc, x1, y2);
- LineTo(fl_gc, x3, y2);
-#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--;
- MoveToEx(fl_gc, x, y, 0L); LineTo(fl_gc, x, y1);
-#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++;
- MoveToEx(fl_gc, x, y, 0L);
- LineTo(fl_gc, x, y1);
- LineTo(fl_gc, x2, y1);
-#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
- MoveToEx(fl_gc, x, y, 0L);
- LineTo(fl_gc, x, y1);
- LineTo(fl_gc, x2, y1);
- LineTo(fl_gc, x2, y3);
-#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);
-#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);
-#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);
-#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);
-#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);
-#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);
-#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());
-#else
- XDrawPoint(fl_display, fl_window, fl_gc, x, y);
-#endif
-}
-
-////////////////////////////////////////////////////////////////
-
-static Region rstack[10];
-static int rstackptr;
-int fl_clip_state_number=0; // used by gl_begin.C to update GL clip
-
-#ifndef WIN32
-// Missing X call: (is this the fastest way to init a 1-rectangle region?)
-// MSWindows equivalent exists, implemented inline in win32.H
-Region XRectangleRegion(int x, int y, int w, int h) {
- XRectangle R;
- R.x = x; R.y = y; R.width = w; R.height = h;
- Region r = XCreateRegion();
- XUnionRectWithRegion(&R, r, r);
- return r;
-}
-#endif
-
-// undo any clobbering of clip done by your program:
-void fl_restore_clip() {
- fl_clip_state_number++;
- Region r = rstack[rstackptr];
-#ifdef WIN32
- SelectClipRgn(fl_gc, r); //if r is NULL, clip is automatically cleared
-#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(Region r) {
- Region oldr = rstack[rstackptr];
- if (oldr) XDestroyRegion(oldr);
- rstack[rstackptr] = r;
- fl_restore_clip();
-}
-
-// Intersect & push a new clip rectangle:
-void fl_clip(int x, int y, int w, int h) {
- Region r;
- if (w > 0 && h > 0) {
- r = XRectangleRegion(x,y,w,h);
- Region current = rstack[rstackptr];
- if (current) {
-#ifndef WIN32
- Region temp = XCreateRegion();
- XIntersectRegion(current, r, temp);
- XDestroyRegion(r);
- r = temp;
-#else
- CombineRgn(r,r,current,RGN_AND);
-#endif
- }
- } else { // make empty clip region:
-#ifndef WIN32
- r = XCreateRegion();
-#else
- r = 0; //whatever, for win32 this is the same as having 0 for HRGN
-#endif
- }
- rstack[++rstackptr] = r;
- fl_restore_clip();
-}
-
-// make there be no clip (used by fl_begin_offscreen() only!)
-void fl_push_no_clip() {
- rstack[++rstackptr] = 0;
- fl_restore_clip();
-}
-
-// pop back to previous clip:
-void fl_pop_clip() {
- Region oldr = rstack[rstackptr--];
- if (oldr) XDestroyRegion(oldr);
- fl_restore_clip();
-}
-
-// does this rectangle intersect current clip?
-int fl_not_clipped(int x, int y, int w, int h) {
- Region r = rstack[rstackptr];
-#ifndef WIN32
- return r ? XRectInRegion(r, x, y, w, h) : 1;
-#else
- if (!r) return 1;
- RECT rect;
- rect.left = x; rect.top = y; rect.right = x+w; rect.bottom = y+h;
- return RectInRegion(r,&rect);
-#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;
- Region r = rstack[rstackptr];
- if (!r) return 0;
-#ifndef WIN32
- 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;
- }
-#else
-// The win32 API makes no distinction between partial and complete
-// intersection, so we have to check for partial intersection ourselves.
- RECT rect;
- rect.left = x; rect.top = y; rect.right = x+w; rect.bottom = y+h;
- if (!RectInRegion(r,&rect)) {
- W = H = 0;
- return 2;
- } else {
- if (PtInRegion(r, rect.left, rect.top) &&
- PtInRegion(r, rect.left, rect.top) &&
- PtInRegion(r, rect.right, rect.bottom) &&
- PtInRegion(r, rect.right, rect.bottom))
- return 0;
- }
-#endif
-
-#ifndef WIN32
- Region rr = XRectangleRegion(x,y,w,h);
- 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);
-#else
- Region rr = XRectangleRegion(x,y,w,h);
- CombineRgn(rr, rr, r,RGN_AND);
- GetRgnBox(rr, &rect);
- X = rect.left; Y = rect.top; W = rect.right - X; H = rect.bottom - Y;
- DeleteObject(rr);
-#endif
- return 1;
-}
-
-// end of fl_rect.C
+// fl_rect.C
+
+// 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 <FL/Fl_Widget.H>
+#include <FL/fl_draw.H>
+#include <FL/x.H>
+
+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);
+#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());
+#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);
+#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--;
+ MoveToEx(fl_gc, x, y, 0L);
+ LineTo(fl_gc, x1, y);
+ LineTo(fl_gc, x1, y2);
+#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
+ MoveToEx(fl_gc, x, y, 0L);
+ LineTo(fl_gc, x1, y);
+ LineTo(fl_gc, x1, y2);
+ LineTo(fl_gc, x3, y2);
+#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--;
+ MoveToEx(fl_gc, x, y, 0L); LineTo(fl_gc, x, y1);
+#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++;
+ MoveToEx(fl_gc, x, y, 0L);
+ LineTo(fl_gc, x, y1);
+ LineTo(fl_gc, x2, y1);
+#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
+ MoveToEx(fl_gc, x, y, 0L);
+ LineTo(fl_gc, x, y1);
+ LineTo(fl_gc, x2, y1);
+ LineTo(fl_gc, x2, y3);
+#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);
+#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);
+#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);
+#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);
+#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);
+#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);
+#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());
+#else
+ XDrawPoint(fl_display, fl_window, fl_gc, x, y);
+#endif
+}
+
+////////////////////////////////////////////////////////////////
+
+static Region rstack[10];
+static int rstackptr;
+int fl_clip_state_number=0; // used by gl_begin.C to update GL clip
+
+#ifndef WIN32
+// Missing X call: (is this the fastest way to init a 1-rectangle region?)
+// MSWindows equivalent exists, implemented inline in win32.H
+Region XRectangleRegion(int x, int y, int w, int h) {
+ XRectangle R;
+ R.x = x; R.y = y; R.width = w; R.height = h;
+ Region r = XCreateRegion();
+ XUnionRectWithRegion(&R, r, r);
+ return r;
+}
+#endif
+
+// undo any clobbering of clip done by your program:
+void fl_restore_clip() {
+ fl_clip_state_number++;
+ Region r = rstack[rstackptr];
+#ifdef WIN32
+ SelectClipRgn(fl_gc, r); //if r is NULL, clip is automatically cleared
+#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(Region r) {
+ Region oldr = rstack[rstackptr];
+ if (oldr) XDestroyRegion(oldr);
+ rstack[rstackptr] = r;
+ fl_restore_clip();
+}
+
+// Intersect & push a new clip rectangle:
+void fl_clip(int x, int y, int w, int h) {
+ Region r;
+ if (w > 0 && h > 0) {
+ r = XRectangleRegion(x,y,w,h);
+ Region current = rstack[rstackptr];
+ if (current) {
+#ifndef WIN32
+ Region temp = XCreateRegion();
+ XIntersectRegion(current, r, temp);
+ XDestroyRegion(r);
+ r = temp;
+#else
+ CombineRgn(r,r,current,RGN_AND);
+#endif
+ }
+ } else { // make empty clip region:
+#ifndef WIN32
+ r = XCreateRegion();
+#else
+ r = 0; //whatever, for win32 this is the same as having 0 for HRGN
+#endif
+ }
+ rstack[++rstackptr] = r;
+ fl_restore_clip();
+}
+
+// make there be no clip (used by fl_begin_offscreen() only!)
+void fl_push_no_clip() {
+ rstack[++rstackptr] = 0;
+ fl_restore_clip();
+}
+
+// pop back to previous clip:
+void fl_pop_clip() {
+ Region oldr = rstack[rstackptr--];
+ if (oldr) XDestroyRegion(oldr);
+ fl_restore_clip();
+}
+
+// does this rectangle intersect current clip?
+int fl_not_clipped(int x, int y, int w, int h) {
+ Region r = rstack[rstackptr];
+#ifndef WIN32
+ return r ? XRectInRegion(r, x, y, w, h) : 1;
+#else
+ if (!r) return 1;
+ RECT rect;
+ rect.left = x; rect.top = y; rect.right = x+w; rect.bottom = y+h;
+ return RectInRegion(r,&rect);
+#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;
+ Region r = rstack[rstackptr];
+ if (!r) return 0;
+#ifndef WIN32
+ 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;
+ }
+#else
+// The win32 API makes no distinction between partial and complete
+// intersection, so we have to check for partial intersection ourselves.
+ RECT rect;
+ rect.left = x; rect.top = y; rect.right = x+w; rect.bottom = y+h;
+ if (!RectInRegion(r,&rect)) {
+ W = H = 0;
+ return 2;
+ } else {
+ if (PtInRegion(r, rect.left, rect.top) &&
+ PtInRegion(r, rect.left, rect.top) &&
+ PtInRegion(r, rect.right, rect.bottom) &&
+ PtInRegion(r, rect.right, rect.bottom))
+ return 0;
+ }
+#endif
+
+#ifndef WIN32
+ Region rr = XRectangleRegion(x,y,w,h);
+ 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);
+#else
+ Region rr = XRectangleRegion(x,y,w,h);
+ CombineRgn(rr, rr, r,RGN_AND);
+ GetRgnBox(rr, &rect);
+ X = rect.left; Y = rect.top; W = rect.right - X; H = rect.bottom - Y;
+ DeleteObject(rr);
+#endif
+ return 1;
+}
+
+// end of fl_rect.C
diff --git a/src/gl_start.cxx b/src/gl_start.cxx
index 7fa20dbbb..152c2310c 100644
--- a/src/gl_start.cxx
+++ b/src/gl_start.cxx
@@ -1,98 +1,98 @@
-// Code to switch current fltk drawing context in/out of GL "mode":
-
-// 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 GLXContext fl_first_context; // in Fl_Gl_Choice.C
-extern int fl_clip_state_number; // in fl_rect.C
-
-static GLXContext context;
-static int clip_state_number=-1;
-static int pw, ph;
-
-#ifdef WIN32
-static int default_mode;
-#endif
-
-Region XRectangleRegion(int x, int y, int w, int h); // in fl_rect.C
-
-void gl_start() {
-#ifdef WIN32
- HDC hdc = fl_private_dc(Fl_Window::current(), default_mode,0);
- if (!context) {
- context = wglCreateContext(hdc);
- if (!fl_first_context) fl_first_context = context;
- else wglShareLists(fl_first_context, context);
- }
- wglMakeCurrent(hdc, context);
-#else
- if (!context) {
- context = glXCreateContext(fl_display, fl_visual, fl_first_context, 1);
- if (!context) Fl::fatal("OpenGL does not support this visual");
- if (!fl_first_context) fl_first_context = context;
- }
- glXMakeCurrent(fl_display, fl_window, context);
- 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() {
-#ifdef WIN32
- glFlush();
-#else
- glXWaitGL();
-#endif
-}
-
-int Fl::gl_visual(int mode, int *alist) {
-#ifdef WIN32
- default_mode = mode;
-#else
- Fl_Gl_Choice *c = Fl_Gl_Choice::find(mode,alist);
- if (!c) return 0;
- fl_visual = c->vis;
- fl_colormap = c->colormap;
-#endif
- return 1;
-}
-
-#endif
+// Code to switch current fltk drawing context in/out of GL "mode":
+
+// 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 GLXContext fl_first_context; // in Fl_Gl_Choice.C
+extern int fl_clip_state_number; // in fl_rect.C
+
+static GLXContext context;
+static int clip_state_number=-1;
+static int pw, ph;
+
+#ifdef WIN32
+static int default_mode;
+#endif
+
+Region XRectangleRegion(int x, int y, int w, int h); // in fl_rect.C
+
+void gl_start() {
+#ifdef WIN32
+ HDC hdc = fl_private_dc(Fl_Window::current(), default_mode,0);
+ if (!context) {
+ context = wglCreateContext(hdc);
+ if (!fl_first_context) fl_first_context = context;
+ else wglShareLists(fl_first_context, context);
+ }
+ wglMakeCurrent(hdc, context);
+#else
+ if (!context) {
+ context = glXCreateContext(fl_display, fl_visual, fl_first_context, 1);
+ if (!context) Fl::fatal("OpenGL does not support this visual");
+ if (!fl_first_context) fl_first_context = context;
+ }
+ glXMakeCurrent(fl_display, fl_window, context);
+ 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() {
+#ifdef WIN32
+ glFlush();
+#else
+ glXWaitGL();
+#endif
+}
+
+int Fl::gl_visual(int mode, int *alist) {
+#ifdef WIN32
+ default_mode = mode;
+#else
+ Fl_Gl_Choice *c = Fl_Gl_Choice::find(mode,alist);
+ if (!c) return 0;
+ fl_visual = c->vis;
+ fl_colormap = c->colormap;
+#endif
+ return 1;
+}
+
+#endif
diff --git a/src/numericsort.c b/src/numericsort.c
index b0729c326..0df0815d6 100644
--- a/src/numericsort.c
+++ b/src/numericsort.c
@@ -1,56 +1,56 @@
-/* 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>
-
-#ifdef WIN32
-#include <FL/filename.H>
-#else
-#if HAVE_DIRENT_H
-# include <dirent.h>
-#else
-# define dirent direct
-# 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
-#endif
-
-#ifdef __cplusplus
-extern "C"
-#endif
-int numericsort(const struct dirent **A, const struct dirent **B) {
- const char* a = (*A)->d_name;
- const char* b = (*B)->d_name;
- int ret = 0;
- for (;;) {
- if (isdigit(*a) && isdigit(*b)) {
- int zdiff,diff,magdiff;
- zdiff = 0;
- while (*a == '0') {a++; zdiff++;}
- while (*b == '0') {b++; zdiff--;}
- while (isdigit(*a) && *a == *b) {a++; b++;}
- diff = (isdigit(*a) && isdigit(*b)) ? *a - *b : 0;
- magdiff = 0;
- while (isdigit(*a)) {magdiff++; a++;}
- while (isdigit(*b)) {magdiff--; b++;}
- if (ret);
- else if (magdiff) ret = magdiff;
- else if (diff) ret = diff;
- else if (zdiff) ret = zdiff;
- } else if (*a == *b) {
- if (!*a) return ret;
- a++; b++;
- } else
- return (*a-*b);
- }
-}
+/* 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>
+
+#ifdef WIN32
+#include <FL/filename.H>
+#else
+#if HAVE_DIRENT_H
+# include <dirent.h>
+#else
+# define dirent direct
+# 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
+#endif
+
+#ifdef __cplusplus
+extern "C"
+#endif
+int numericsort(const struct dirent **A, const struct dirent **B) {
+ const char* a = (*A)->d_name;
+ const char* b = (*B)->d_name;
+ int ret = 0;
+ for (;;) {
+ if (isdigit(*a) && isdigit(*b)) {
+ int zdiff,diff,magdiff;
+ zdiff = 0;
+ while (*a == '0') {a++; zdiff++;}
+ while (*b == '0') {b++; zdiff--;}
+ while (isdigit(*a) && *a == *b) {a++; b++;}
+ diff = (isdigit(*a) && isdigit(*b)) ? *a - *b : 0;
+ magdiff = 0;
+ while (isdigit(*a)) {magdiff++; a++;}
+ while (isdigit(*b)) {magdiff--; b++;}
+ if (ret);
+ else if (magdiff) ret = magdiff;
+ else if (diff) ret = diff;
+ else if (zdiff) ret = zdiff;
+ } else if (*a == *b) {
+ if (!*a) return ret;
+ a++; b++;
+ } else
+ return (*a-*b);
+ }
+}
diff --git a/src/scandir_win32.c b/src/scandir_win32.c
index 525b289d4..cbb4b536b 100644
--- a/src/scandir_win32.c
+++ b/src/scandir_win32.c
@@ -1,82 +1,82 @@
-// scandir_win32.C
-
-// Emulation of posix scandir() call
-
-#include <config.h>
-#include <FL/filename.H>
-#include <string.h>
-#include <windows.h>
-
-#ifdef __cplusplus
-extern "C"
-#endif
-int scandir(const char *dirname, struct dirent ***namelist,
- int (*select)(const struct dirent *),
- int (*compar)(const struct dirent **, const struct dirent **)) {
-
- int len = strlen(dirname);
- char *findIn = new char[len+5]; strcpy(findIn, dirname);
- for (char *d = findIn; *d; d++) if (*d=='/') *d='\\';
- if ((len==0)) { strcpy(findIn, ".\\*"); }
- if ((len==1)&& (d[-1]=='.')) { strcpy(findIn, ".\\*"); }
- if ((len>0) && (d[-1]=='\\')) { *d++ = '*'; *d = 0; }
- if ((len>1) && (d[-1]=='.') && (d[-2]=='\\')) { d[-1] = '*'; }
-
- WIN32_FIND_DATA find;
- HANDLE h;
- int nDir = 0, NDir = 0;
- struct dirent **dir = 0, *selectDir;
- /*
- selectDir = (struct dirent*)new char[sizeof(dirent)+1];
- strcpy(selectDir->d_name, ".");
- dir[0] = selectDir;
- selectDir = (struct dirent*)new char[sizeof(dirent)+2];
- strcpy(selectDir->d_name, "..");
- dir[1] = selectDir;
- */
- unsigned long ret;
-
- if ((h=FindFirstFile(findIn, &find))==INVALID_HANDLE_VALUE) {
- ret = GetLastError();
- if (ret != ERROR_NO_MORE_FILES) {
- // TODO: return some error code
- }
- *namelist = dir;
- return nDir;
- }
- do {
- selectDir=(struct dirent*)new char[sizeof(dirent)+strlen(find.cFileName)];
- strcpy(selectDir->d_name, find.cFileName);
- if (!select || (*select)(selectDir)) {
- if (nDir==NDir) {
- struct dirent **tempDir = new struct dirent*[NDir+33];
- if (NDir) memcpy(tempDir, dir, sizeof(struct dirent*)*NDir);
- if (dir) delete dir;
- dir = tempDir;
- NDir += 32;
- }
- dir[nDir] = selectDir;
- nDir++;
- dir[nDir] = 0;
- } else {
- delete selectDir;
- }
- } while (FindNextFile(h, &find));
- ret = GetLastError();
- if (ret != ERROR_NO_MORE_FILES) {
- // TODO: return some error code
- }
- FindClose(h);
-
- delete findIn;
-
- if (compar) qsort (dir, nDir, sizeof(*dir),
- (int(*)(const void*, const void*))compar);
-
- *namelist = dir;
- return nDir;
-}
-
-int alphasort (const struct dirent **a, const struct dirent **b) {
- return strcmp ((*a)->d_name, (*b)->d_name);
-}
+// scandir_win32.C
+
+// Emulation of posix scandir() call
+
+#include <config.h>
+#include <FL/filename.H>
+#include <string.h>
+#include <windows.h>
+
+#ifdef __cplusplus
+extern "C"
+#endif
+int scandir(const char *dirname, struct dirent ***namelist,
+ int (*select)(const struct dirent *),
+ int (*compar)(const struct dirent **, const struct dirent **)) {
+
+ int len = strlen(dirname);
+ char *findIn = new char[len+5]; strcpy(findIn, dirname);
+ for (char *d = findIn; *d; d++) if (*d=='/') *d='\\';
+ if ((len==0)) { strcpy(findIn, ".\\*"); }
+ if ((len==1)&& (d[-1]=='.')) { strcpy(findIn, ".\\*"); }
+ if ((len>0) && (d[-1]=='\\')) { *d++ = '*'; *d = 0; }
+ if ((len>1) && (d[-1]=='.') && (d[-2]=='\\')) { d[-1] = '*'; }
+
+ WIN32_FIND_DATA find;
+ HANDLE h;
+ int nDir = 0, NDir = 0;
+ struct dirent **dir = 0, *selectDir;
+ /*
+ selectDir = (struct dirent*)new char[sizeof(dirent)+1];
+ strcpy(selectDir->d_name, ".");
+ dir[0] = selectDir;
+ selectDir = (struct dirent*)new char[sizeof(dirent)+2];
+ strcpy(selectDir->d_name, "..");
+ dir[1] = selectDir;
+ */
+ unsigned long ret;
+
+ if ((h=FindFirstFile(findIn, &find))==INVALID_HANDLE_VALUE) {
+ ret = GetLastError();
+ if (ret != ERROR_NO_MORE_FILES) {
+ // TODO: return some error code
+ }
+ *namelist = dir;
+ return nDir;
+ }
+ do {
+ selectDir=(struct dirent*)new char[sizeof(dirent)+strlen(find.cFileName)];
+ strcpy(selectDir->d_name, find.cFileName);
+ if (!select || (*select)(selectDir)) {
+ if (nDir==NDir) {
+ struct dirent **tempDir = new struct dirent*[NDir+33];
+ if (NDir) memcpy(tempDir, dir, sizeof(struct dirent*)*NDir);
+ if (dir) delete dir;
+ dir = tempDir;
+ NDir += 32;
+ }
+ dir[nDir] = selectDir;
+ nDir++;
+ dir[nDir] = 0;
+ } else {
+ delete selectDir;
+ }
+ } while (FindNextFile(h, &find));
+ ret = GetLastError();
+ if (ret != ERROR_NO_MORE_FILES) {
+ // TODO: return some error code
+ }
+ FindClose(h);
+
+ delete findIn;
+
+ if (compar) qsort (dir, nDir, sizeof(*dir),
+ (int(*)(const void*, const void*))compar);
+
+ *namelist = dir;
+ return nDir;
+}
+
+int alphasort (const struct dirent **a, const struct dirent **b) {
+ return strcmp ((*a)->d_name, (*b)->d_name);
+}