diff --git a/FL/Fl.H b/FL/Fl.H
index 74f1a9df577eb88d31bf0d7ad0afe7eb990f3f5f..a674d61f12cc03ccb1532a2e2b89816324021626 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 3ab680519b9bfbf30ff9c7f134a62e6cfe3ac745..d719937dc57dd34bfb7839f606f780f31a22fad8 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 d2a06357acc209151f6f65d7afe4925ebf09dc72..591f4edba50b28a682e46e6688110164e799cc73 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 7a2ad174707e3c148190637cdf4e2cf0dfa5d38e..1fc52303a1787363ee2abd4f3dff25f4b7a17f8e 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 f04cb7e7c3d7788146d3ab23cc56dcf737aa9be6..d8a64fd8c08e1c4c76dfdfe341915cd718b6c680 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 ba932cf7ecc4e70d0c3c195dd10c07a0fdd2a240..7f4d40f13188666f43a75e0067b5652221b80169 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 $".
 //