summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--FL/Fl.H7
-rw-r--r--FL/glut.H10
-rw-r--r--documentation/functions.html41
-rw-r--r--src/Fl.cxx213
-rw-r--r--src/Fl_Gl_Window.cxx6
-rw-r--r--src/Fl_Input_.cxx15
6 files changed, 188 insertions, 104 deletions
diff --git a/FL/Fl.H b/FL/Fl.H
index 74f1a9df5..a674d61f1 100644
--- a/FL/Fl.H
+++ b/FL/Fl.H
@@ -1,5 +1,5 @@
//
-// "$Id: Fl.H,v 1.8.2.9 2000/06/21 17:36:33 bill Exp $"
+// "$Id: Fl.H,v 1.8.2.10 2000/12/12 08:57:29 spitzak Exp $"
//
// Main header file for the Fast Light Tool Kit (FLTK).
//
@@ -94,6 +94,9 @@ public:
static FL_EXPORT void repeat_timeout(double t, Fl_Timeout_Handler,void* = 0);
static FL_EXPORT int has_timeout(Fl_Timeout_Handler, void* = 0);
static FL_EXPORT void remove_timeout(Fl_Timeout_Handler, void* = 0);
+ static FL_EXPORT void add_check(Fl_Timeout_Handler, void* = 0);
+ static FL_EXPORT int has_check(Fl_Timeout_Handler, void* = 0);
+ static FL_EXPORT void remove_check(Fl_Timeout_Handler, void* = 0);
static FL_EXPORT void add_fd(int fd, int when, void (*cb)(int,void*),void* =0);
static FL_EXPORT void add_fd(int fd, void (*cb)(int, void*), void* = 0);
static FL_EXPORT void remove_fd(int, int when);
@@ -214,5 +217,5 @@ public:
#endif
//
-// End of "$Id: Fl.H,v 1.8.2.9 2000/06/21 17:36:33 bill Exp $".
+// End of "$Id: Fl.H,v 1.8.2.10 2000/12/12 08:57:29 spitzak Exp $".
//
diff --git a/FL/glut.H b/FL/glut.H
index 3ab680519..d719937dc 100644
--- a/FL/glut.H
+++ b/FL/glut.H
@@ -1,5 +1,5 @@
//
-// "$Id: glut.H,v 1.6.2.7 2000/12/06 15:45:12 easysw Exp $"
+// "$Id: glut.H,v 1.6.2.8 2000/12/12 08:57:30 spitzak Exp $"
//
// GLUT emulation header file for the Fast Light Tool Kit (FLTK).
//
@@ -430,16 +430,14 @@ extern "C" {
extern int APIENTRY glutExtensionSupported(char *name);
-/* Stroke font opaque addresses (use constants instead in source code). */
-extern void *glutStrokeRoman;
-extern void *glutStrokeMonoRoman;
-
/* Stroke font constants (use these in GLUT program). */
#if defined(_WIN32) || defined(WIN32)
# define GLUT_STROKE_ROMAN ((void*)0)
# define GLUT_STROKE_MONO_ROMAN ((void*)1)
#else
+extern void *glutStrokeRoman;
# define GLUT_STROKE_ROMAN (&glutStrokeRoman)
+extern void *glutStrokeMonoRoman;
# define GLUT_STROKE_MONO_ROMAN (&glutStrokeMonoRoman)
#endif
@@ -472,5 +470,5 @@ extern void APIENTRY glutSolidIcosahedron();
#endif /* __glut_h__ */
//
-// End of "$Id: glut.H,v 1.6.2.7 2000/12/06 15:45:12 easysw Exp $".
+// End of "$Id: glut.H,v 1.6.2.8 2000/12/12 08:57:30 spitzak Exp $".
//
diff --git a/documentation/functions.html b/documentation/functions.html
index d2a06357a..591f4edba 100644
--- a/documentation/functions.html
+++ b/documentation/functions.html
@@ -326,9 +326,39 @@ fair degree of accuracy:
main() {
Fl::add_timeout(1.0,callback);
- for (;;) Fl::wait();
+ return Fl::run();
}</PRE></UL>
+<h3><A name=add_timeout>static void Fl::add_check(void (*cb)(void*),void*v=0)</A></h3>
+
+Fltk will call this callback just before it flushes the display and
+waits for events. This is different than an idle callback because it
+is only called once, then fltk calls the system and tells it not to
+return until an event happens.
+
+<p>This can be used by code that wants to monitor the
+application's state, such as to keep a display up to date. The
+advantage of using a check callback is that it is called only when no
+events are pending. If events are coming in quickly, whole blocks of
+them will be processed before this is called once. This can save
+significant time and avoid the application falling behind the events.
+
+<p>Sample code:
+
+<ul><pre>bool state_changed; // anything that changes the display turns this on
+
+void callback(void*) {
+ if (!state_changed) return;
+ state_changed = false;
+ do_expensive_calculation();
+ widget->redraw();
+}
+
+main() {
+ Fl::add_check(1.0,callback);
+ return Fl::run();
+}</pre></ul>
+
<h3><A name=arg>static int Fl::arg(int argc, char **argv, int &amp;i)</A></h3>
Consume a single switch from <tt>argv</tt>, starting at word i.
@@ -867,6 +897,15 @@ Returns true if the timeout exists and has not been called yet.
Removes a timeout callback. It is harmless to remove a timeout
callback that no longer exists.
+<h3><A name=has_check>static int Fl::has_check(void (*cb)(void*), void* = 0)</A></h3>
+
+Returns true if the check exists and has not been called yet.
+
+<h3><A name=remove_check>static void Fl::remove_check(void (*cb)(void*), void* = 0)</A></h3>
+
+Removes a check callback. It is harmless to remove a check
+callback that no longer exists.
+
<h3><A name=run>static Fl::run()</A></h3>
As long as any windows are displayed this calls <tt>Fl::wait()</tt>
diff --git a/src/Fl.cxx b/src/Fl.cxx
index 7a2ad1747..1fc52303a 100644
--- a/src/Fl.cxx
+++ b/src/Fl.cxx
@@ -1,5 +1,5 @@
//
-// "$Id: Fl.cxx,v 1.24.2.34 2000/11/20 19:02:20 easysw Exp $"
+// "$Id: Fl.cxx,v 1.24.2.35 2000/12/12 08:57:30 spitzak Exp $"
//
// Main event handling code for the Fast Light Tool Kit (FLTK).
//
@@ -67,23 +67,16 @@ int Fl::event_inside(const Fl_Widget *o) /*const*/ {
}
////////////////////////////////////////////////////////////////
-// Timeouts and Fl::wait()
-
-void (*Fl::idle)();
-
-// Timeouts are insert-sorted into order. This works good if there
-// are only a small number:
-
-static struct Timeout {
+// Timeouts are stored in a sorted list, so only the first one needs
+// to be checked to see if any should be called.
+
+struct Timeout {
double time;
void (*cb)(void*);
void* arg;
-} * timeout;
-static int numtimeouts;
-static int timeout_array_size;
-
-extern int fl_wait(double time); // warning: assummes time >= 0.0
-extern int fl_ready();
+ Timeout* next;
+};
+static Timeout* first_timeout, *free_timeout;
#ifndef WIN32
#include <sys/time.h>
@@ -96,68 +89,152 @@ extern int fl_ready();
static char reset_clock = 1;
static void elapse_timeouts() {
-
#ifdef WIN32
-
unsigned long newclock = GetTickCount();
static unsigned long prevclock;
- if (reset_clock) {
- prevclock = newclock;
- reset_clock = 0;
- return;
- }
- if (newclock <= prevclock) return;
double elapsed = (newclock-prevclock)/1000.0;
prevclock = newclock;
-
#else
-
static struct timeval prevclock;
struct timeval newclock;
gettimeofday(&newclock, NULL);
- if (reset_clock) {
- prevclock.tv_sec = newclock.tv_sec;
- prevclock.tv_usec = newclock.tv_usec;
- reset_clock = 0;
- return;
- }
double elapsed = newclock.tv_sec - prevclock.tv_sec +
(newclock.tv_usec - prevclock.tv_usec)/1000000.0;
prevclock.tv_sec = newclock.tv_sec;
prevclock.tv_usec = newclock.tv_usec;
- if (elapsed <= 0) return;
-
#endif
+ if (reset_clock) {
+ reset_clock = 0;
+ } else if (elapsed > 0) {
+ for (Timeout* t = first_timeout; t; t = t->next) t->time -= elapsed;
+ }
+}
+
+void Fl::add_timeout(double time, Fl_Timeout_Handler cb, void *arg) {
+ elapse_timeouts();
+ repeat_timeout(time, cb, arg);
+}
+
+void Fl::repeat_timeout(double time, Fl_Timeout_Handler cb, void *arg) {
+ elapse_timeouts();
+ Timeout* t = free_timeout;
+ if (t) free_timeout = t->next;
+ else t = new Timeout;
+ t->time = time;
+ t->cb = cb;
+ t->arg = arg;
+ // insert-sort the new timeout:
+ Timeout** p = &first_timeout;
+ while (*p && (*p)->time <= time) p = &((*p)->next);
+ t->next = *p;
+ *p = t;
+}
+
+int Fl::has_timeout(Fl_Timeout_Handler cb, void *arg) {
+ for (Timeout* t = first_timeout; t; t = t->next)
+ if (t->cb == cb && t->arg == arg) return 1;
+ return 0;
+}
+
+void Fl::remove_timeout(Fl_Timeout_Handler cb, void *arg) {
+ // This version removes all matching timeouts, not just the first one.
+ // This may change in the future.
+ for (Timeout** p = &first_timeout; *p;) {
+ Timeout* t = *p;
+ if (t->cb == cb && t->arg == arg) {
+ *p = t->next;
+ t->next = free_timeout;
+ free_timeout = t;
+ } else {
+ p = &(t->next);
+ }
+ }
+}
- for (int i=0; i<numtimeouts; i++) timeout[i].time -= elapsed;
+////////////////////////////////////////////////////////////////
+// Checks are just stored in a list. They are called in the reverse
+// order that they were added (this may change in the future).
+// This is a bit messy because I want to allow checks to be added,
+// removed, and have wait() called from inside them, to do this
+// next_check points at the next unprocessed one for the outermost
+// call to Fl::wait().
+
+struct Check {
+ void (*cb)(void*);
+ void* arg;
+ Check* next;
+};
+static Check* first_check, *next_check, *free_check;
+
+void Fl::add_check(Fl_Timeout_Handler cb, void *arg) {
+ Check* t = free_check;
+ if (t) free_check = t->next;
+ else t = new Check;
+ t->cb = cb;
+ t->arg = arg;
+ t->next = first_check;
+ if (next_check == first_check) next_check = t;
+ first_check = t;
+}
+
+void Fl::remove_check(Fl_Timeout_Handler cb, void *arg) {
+ for (Check** p = &first_check; *p;) {
+ Check* t = *p;
+ if (t->cb == cb && t->arg == arg) {
+ if (next_check == t) next_check = t->next;
+ *p = t->next;
+ t->next = free_check;
+ free_check = t;
+ } else {
+ p = &(t->next);
+ }
+ }
}
+
+////////////////////////////////////////////////////////////////
+// wait/run/check/ready:
+
+void (*Fl::idle)(); // see Fl_add_idle.cxx for the add/remove functions
+
+extern int fl_wait(double time); // in Fl_x.cxx or Fl_win32.cxx
static char in_idle;
double Fl::wait(double time_to_wait) {
- if (numtimeouts) {
+ if (first_timeout) {
elapse_timeouts();
- if (timeout[0].time <= time_to_wait) time_to_wait = timeout[0].time;
- while (numtimeouts) {
- if (timeout[0].time > 0) break;
+ while (Timeout* t = first_timeout) {
+ if (t->time > 0) break;
// The first timeout in the array has expired.
// We must remove timeout from array before doing the callback:
- void (*cb)(void*) = timeout[0].cb;
- void *arg = timeout[0].arg;
- numtimeouts--;
- if (numtimeouts)
- memmove(timeout, timeout+1, numtimeouts*sizeof(Timeout));
+ void (*cb)(void*) = t->cb;
+ void *arg = t->arg;
+ first_timeout = t->next;
+ t->next = free_timeout;
+ free_timeout = t;
// Now it is safe for the callback to do add_timeout:
cb(arg);
}
} else {
reset_clock = 1; // we are not going to check the clock
}
+ // checks are a bit messy so that add/remove and wait may be called
+ // from inside them without causing an infinite loop:
+ if (next_check == first_check) {
+ while (next_check) {
+ Check* check = next_check;
+ next_check = check->next;
+ (check->cb)(check->arg);
+ }
+ next_check = first_check;
+ }
if (idle) {
if (!in_idle) {in_idle = 1; idle(); in_idle = 0;}
// the idle function may turn off idle, we can then wait:
if (idle) time_to_wait = 0.0;
}
+ if (first_timeout && first_timeout->time < time_to_wait)
+ time_to_wait = first_timeout->time;
if (time_to_wait <= 0.0) {
// do flush second so that the results of events are visible:
int ret = fl_wait(0.0);
@@ -187,58 +264,18 @@ int Fl::check() {
return Fl_X::first != 0; // return true if there is a window
}
+extern int fl_ready();
+
int Fl::ready() {
- if (numtimeouts) {
+ if (first_timeout) {
elapse_timeouts();
- if (timeout[0].time <= 0) return 1;
+ if (first_timeout->time <= 0) return 1;
} else {
reset_clock = 1;
}
return fl_ready();
}
-void Fl::add_timeout(double t, Fl_Timeout_Handler cb, void *v) {
- elapse_timeouts();
- repeat_timeout(t, cb, v);
-}
-
-void Fl::repeat_timeout(double t, Fl_Timeout_Handler cb, void *v) {
-
- if (numtimeouts >= timeout_array_size) {
- timeout_array_size = 2*timeout_array_size+1;
- timeout = (Timeout*)realloc(timeout, timeout_array_size*sizeof(Timeout));
- }
-
- // insert-sort the new timeout:
- int i;
- for (i=0; i<numtimeouts; i++) {
- if (timeout[i].time > t) {
- for (int j=numtimeouts; j>i; j--) timeout[j] = timeout[j-1];
- break;
- }
- }
- timeout[i].time = t;
- timeout[i].cb = cb;
- timeout[i].arg = v;
-
- numtimeouts++;
-}
-
-int Fl::has_timeout(Fl_Timeout_Handler cb, void *v) {
- for (int i=0; i<numtimeouts; i++)
- if (timeout[i].cb == cb && timeout[i].arg==v) return 1;
- return 0;
-}
-
-void Fl::remove_timeout(Fl_Timeout_Handler cb, 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;
-}
-
////////////////////////////////////////////////////////////////
// Window list management:
@@ -734,5 +771,5 @@ void Fl_Window::flush() {
}
//
-// End of "$Id: Fl.cxx,v 1.24.2.34 2000/11/20 19:02:20 easysw Exp $".
+// End of "$Id: Fl.cxx,v 1.24.2.35 2000/12/12 08:57:30 spitzak Exp $".
//
diff --git a/src/Fl_Gl_Window.cxx b/src/Fl_Gl_Window.cxx
index f04cb7e7c..d8a64fd8c 100644
--- a/src/Fl_Gl_Window.cxx
+++ b/src/Fl_Gl_Window.cxx
@@ -1,5 +1,5 @@
//
-// "$Id: Fl_Gl_Window.cxx,v 1.12.2.18 2000/12/06 15:45:13 easysw Exp $"
+// "$Id: Fl_Gl_Window.cxx,v 1.12.2.19 2000/12/12 08:57:30 spitzak Exp $"
//
// OpenGL window code for the Fast Light Tool Kit (FLTK).
//
@@ -122,7 +122,7 @@ void Fl_Gl_Window::make_current() {
RealizePalette(fl_gc);
}
#endif // USE_COLORMAP
- glDrawBuffer(GL_BACK);
+ if (g->d) glDrawBuffer(GL_BACK);
current_ = this;
}
@@ -337,5 +337,5 @@ void Fl_Gl_Window::draw_overlay() {}
#endif
//
-// End of "$Id: Fl_Gl_Window.cxx,v 1.12.2.18 2000/12/06 15:45:13 easysw Exp $".
+// End of "$Id: Fl_Gl_Window.cxx,v 1.12.2.19 2000/12/12 08:57:30 spitzak Exp $".
//
diff --git a/src/Fl_Input_.cxx b/src/Fl_Input_.cxx
index ba932cf7e..7f4d40f13 100644
--- a/src/Fl_Input_.cxx
+++ b/src/Fl_Input_.cxx
@@ -1,5 +1,5 @@
//
-// "$Id: Fl_Input_.cxx,v 1.21.2.9 2000/09/19 07:21:19 spitzak Exp $"
+// "$Id: Fl_Input_.cxx,v 1.21.2.10 2000/12/12 08:57:30 spitzak Exp $"
//
// Common input widget routines for the Fast Light Tool Kit (FLTK).
//
@@ -586,7 +586,7 @@ int Fl_Input_::replace(int b, int e, const char* text, int ilen) {
size_ += ilen;
}
undowidget = this;
- mark_ = position_ = undoat = b+ilen;
+ undoat = b+ilen;
#ifdef WORDWRAP
// Insertions into the word at the end of the line will cause it to
@@ -597,8 +597,15 @@ int Fl_Input_::replace(int b, int e, const char* text, int ilen) {
if (type() == FL_MULTILINE_INPUT)
while (b > 0 && !isspace(index(b))) b--;
#endif
-
+
+ // make sure we redraw the old selection or cursor:
+ if (mark_ < b) b = mark_;
+ if (position_ < b) b = position_;
+
minimal_update(b);
+
+ mark_ = position_ = undoat;
+
if (when()&FL_WHEN_CHANGED) do_callback(); else set_changed();
return 1;
}
@@ -810,5 +817,5 @@ Fl_Input_::~Fl_Input_() {
}
//
-// End of "$Id: Fl_Input_.cxx,v 1.21.2.9 2000/09/19 07:21:19 spitzak Exp $".
+// End of "$Id: Fl_Input_.cxx,v 1.21.2.10 2000/12/12 08:57:30 spitzak Exp $".
//