changeset 27433:87dcc6a2c31b

*** empty log message ***
author Gerd Moellmann <gerd@gnu.org>
date Tue, 25 Jan 2000 15:59:42 +0000
parents b904070c3d8b
children 8c80483f84c7
files lisp/ChangeLog lwlib/ChangeLog src/ChangeLog src/atimer.c src/atimer.h
diffstat 5 files changed, 424 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/ChangeLog	Tue Jan 25 15:58:45 2000 +0000
+++ b/lisp/ChangeLog	Tue Jan 25 15:59:42 2000 +0000
@@ -1,3 +1,8 @@
+2000-01-25  Gerd Moellmann  <gerd@gnu.org>
+
+	* scroll-bar.el (scroll-bar-timer): Variable removed.
+	(scroll-bar-toolkit-scroll): Don't use a timer.
+
 2000-01-25  Kenichi Handa  <handa@etl.go.jp>
 
 	* language/thai-util.el (thai-composition-function): Delete
--- a/lwlib/ChangeLog	Tue Jan 25 15:58:45 2000 +0000
+++ b/lwlib/ChangeLog	Tue Jan 25 15:59:42 2000 +0000
@@ -1,3 +1,11 @@
+2000-01-25  Gerd Moellmann  <gerd@gnu.org>
+
+	* lwlib-Xm.c (make_menu_in_widget): Don't add XmNpopdownCallback,
+	add XmNunmapCallback.
+	(xm_unmap_callback): New function.
+	(xm_pull_down_callback): Call pre-activate callback only if
+	parent is the menu bar.
+
 2000-01-17  Gerd Moellmann  <gerd@gnu.org>
 
 	* lwlib-Xm.c (xm_arm_callback): New function.
Binary file src/ChangeLog has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/atimer.c	Tue Jan 25 15:59:42 2000 +0000
@@ -0,0 +1,336 @@
+/* Asynchronous timers.
+   Copyright (C) 2000 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Emacs 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#include <config.h>
+#include <lisp.h>
+#include <signal.h>
+#include <syssignal.h>
+#include <systime.h>
+#include <blockinput.h>
+#include <atimer.h>
+#include <stdio.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+/* The ubiquitous min/max macros.  */
+
+#define max(X, Y) ((X) > (Y) ? (X) : (Y))
+#define min(X, Y) ((X) < (Y) ? (X) : (Y))
+
+/* Free-list of atimer structures.  */
+
+static struct atimer *free_atimers;
+
+/* List of active atimers, sorted by expiration time.  The timer that
+   will become ripe next is always at the front of this list.  */
+
+static struct atimer *atimers;
+
+/* Non-zero means alarm_signal_handler has found ripe timers but
+   interrupt_input_blocked was non-zero.  In this case, timer
+   functions are not called until the next UNBLOCK_INPUT because timer
+   functions are expected to call X, and X cannot be assumed to be
+   reentrant.  */
+
+int pending_atimers;
+
+/* Block/unblock SIGALRM.. */
+
+#define BLOCK_ATIMERS   sigblock (sigmask (SIGALRM))
+#define UNBLOCK_ATIMERS sigunblock (sigmask (SIGALRM))
+
+/* Function prototypes.  */
+
+static void set_alarm P_ ((void));
+static void schedule_atimer P_ ((struct atimer *));
+
+
+/* Start a new atimer of type TYPE.  TIME specifies when the timer is
+   ripe.  FN is the function to call when the timer fires.
+   CLIENT_DATA is stored in the client_data member of the atimer
+   structure returned and so made available to FN when it is called.
+
+   If TYPE is ATIMER_ABSOLUTE, TIME is the absolute time at which the
+   timer fires.
+
+   If TYPE is ATIMER_RELATIVE, the timer is ripe TIME s/us in the
+   future.
+
+   In both cases, the timer is automatically freed after it has fired.
+
+   If TYPE is ATIMER_CONTINUOUS, the timer fires every TIME s/us.
+
+   Value is a pointer to the atimer started.  It can be used in calls
+   to cancel_atimer; don't free it yourself.  */
+
+struct atimer *
+start_atimer (type, time, fn, client_data)
+     enum atimer_type type;
+     EMACS_TIME time;
+     atimer_callback fn;
+     void *client_data;
+{
+  struct atimer *t;
+
+  /* Round TIME up to the next full second if we don't have
+     itimers.  */
+#ifndef HAVE_SETITIMER
+  if (EMACS_USECS (time) != 0)
+    {
+      EMACS_USECS (time) = 0;
+      ++EMACS_SECS (time);
+    }
+#endif /* not HAVE_SETITIMER */
+
+  /* Get an atimer structure from the free-list, or allocate
+     a new one.  */
+  if (free_atimers)
+    {
+      t = free_atimers;
+      free_atimers = t->next;
+    }
+  else
+    t = (struct atimer *) xmalloc (sizeof *t);
+
+  /* Fill the atimer structure.  */
+  bzero (t, sizeof *t);
+  t->type = type;
+  t->fn = fn;
+  t->client_data = client_data;
+
+  BLOCK_ATIMERS;
+
+  /* Compute the timer's expiration time.  */
+  switch (type)
+    {
+    case ATIMER_ABSOLUTE:
+      t->expiration = time;
+      break;
+      
+    case ATIMER_RELATIVE:
+      EMACS_GET_TIME (t->expiration);
+      EMACS_ADD_TIME (t->expiration, t->expiration, time);
+      break;
+      
+    case ATIMER_CONTINUOUS:
+      EMACS_GET_TIME (t->expiration);
+      EMACS_ADD_TIME (t->expiration, t->expiration, time);
+      t->interval = time;
+      break;
+    }
+
+  /* Insert the timer in the list of active atimers.  */
+  schedule_atimer (t);
+  UNBLOCK_ATIMERS;
+
+  /* Arrange for a SIGALRM at the time the next atimer is ripe.  */
+  set_alarm ();
+  
+  return t;
+}
+
+
+/* Cancel and free atimer TIMER.  */
+
+void
+cancel_atimer (timer)
+     struct atimer *timer;
+{
+  struct atimer *t, *prev;
+
+  BLOCK_ATIMERS;
+
+  /* See if TIMER is active.  */
+  for (t = atimers, prev = 0; t && t != timer; t = t->next)
+    ;
+
+  /* If it is, take it off the list of active timers, put in on the
+     free-list.  We don't bother to arrange for setting a different
+     alarm time, since a too early one doesn't hurt.  */
+  if (t)
+    {
+      if (prev)
+	prev->next = t->next;
+      else
+	atimers = t->next;
+
+      t->next = free_atimers;
+      free_atimers = t;
+    }
+
+  UNBLOCK_ATIMERS;
+}
+
+
+/* Arrange for a SIGALRM to arrive when the next timer is ripe.  */
+
+static void
+set_alarm ()
+{
+  
+#if defined (USG) && !defined (POSIX_SIGNALS)
+  /* USG systems forget handlers when they are used;
+     must reestablish each time.  */
+  signal (SIGALRM, alarm_signal_handler);
+#endif /* USG */
+  
+  if (atimers)
+    {
+      EMACS_TIME now, time;
+#ifdef HAVE_SETITIMER
+      struct itimerval it;
+#endif
+
+      /* Determine s/us till the next timer is ripe.  */
+      EMACS_GET_TIME (now);
+      EMACS_SUB_TIME (time, atimers->expiration, now);
+
+#ifdef HAVE_SETITIMER
+      /* Don't set the interval to 0; this disables the timer.  */
+      if (EMACS_TIME_LE (atimers->expiration, now))
+	{
+	  EMACS_SET_SECS (time, 0);
+	  EMACS_SET_USECS (time, 1000);
+	}
+      
+      bzero (&it, sizeof it);
+      it.it_value = time;
+      setitimer (ITIMER_REAL, &it, 0);
+#else /* not HAVE_SETITIMER */
+      alarm (max (EMACS_SECS (time), 1));
+#endif /* not HAVE_SETITIMER */
+    }
+}
+
+
+/* Insert timer T into the list of active atimers `atimers', keeping
+   the list sorted by expiration time.  T must not be in this list
+   already.  */
+
+static void
+schedule_atimer (t)
+     struct atimer *t;
+{
+  struct atimer *a = atimers, *prev = NULL;
+
+  /* Look for the first atimer that is ripe after T.  */
+  while (a && EMACS_TIME_GT (t->expiration, a->expiration))
+    prev = a, a = a->next;
+
+  /* Insert T in front of the atimer found, if any.  */
+  if (prev)
+    prev->next = t;
+  else
+    atimers = t;
+  
+  t->next = a;
+}
+
+
+/* Signal handler for SIGALRM.  SIGNO is the signal number, i.e.
+   SIGALRM.  */
+
+SIGTYPE
+alarm_signal_handler (signo)
+     int signo;
+{
+  EMACS_TIME now;
+  
+  EMACS_GET_TIME (now);
+  pending_atimers = 0;
+  
+  while (atimers
+	 && (pending_atimers = interrupt_input_blocked) == 0
+	 && EMACS_TIME_LE (atimers->expiration, now))
+    {
+      struct atimer *t;
+      
+      t = atimers;
+      atimers = atimers->next;
+      t->fn (t);
+      
+      if (t->type == ATIMER_CONTINUOUS)
+	{
+	  EMACS_ADD_TIME (t->expiration, now, t->interval);
+	  schedule_atimer (t);
+	}
+      else
+	{
+	  t->next = free_atimers;
+	  free_atimers = t;
+	}
+      
+      EMACS_GET_TIME (now);
+    }
+  
+#if defined (USG) && !defined (POSIX_SIGNALS)
+  /* USG systems forget handlers when they are used;
+     must reestablish each time.  */
+  signal (SIGALRM, alarm_signal_handler);
+#endif /* USG */
+  
+  set_alarm ();
+}
+
+
+/* Call alarm_signal_handler for pending timers.  */
+
+void
+do_pending_atimers ()
+{
+  if (pending_atimers)
+    {
+      BLOCK_ATIMERS;
+      alarm_signal_handler (SIGALRM);
+      UNBLOCK_ATIMERS;
+    }
+}
+
+
+/* Turn alarms on/off.  This seems to be temporarily necessary on
+   some systems like HPUX (see process.c).  */
+
+void
+turn_on_atimers (on)
+     int on;
+{
+  if (on)
+    {
+      signal (SIGALRM, alarm_signal_handler);
+      set_alarm ();
+    }
+  else
+    alarm (0);
+}
+
+
+void
+init_atimer ()
+{
+  free_atimers = atimers = NULL;
+  pending_atimers = 0;
+  signal (SIGALRM, alarm_signal_handler);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/atimer.h	Tue Jan 25 15:59:42 2000 +0000
@@ -0,0 +1,75 @@
+/* Asynchronous timers.
+   Copyright (C) 2000 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Emacs 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* Forward declaration.  */
+
+struct atimer;
+
+/* Types of timers.  */
+
+enum atimer_type
+{
+  /* Timer is ripe at some absolute time.  */
+  ATIMER_ABSOLUTE,
+
+  /* Timer is ripe at now plus an offset.  */
+  ATIMER_RELATIVE,
+
+  /* Timer runs continously.  */
+  ATIMER_CONTINUOUS
+};
+
+/* Type of timer callback functions.  */
+
+typedef void (* atimer_callback) P_ ((struct atimer *timer));
+
+/* Structure describing an asynchronous timer.  */
+
+struct atimer
+{
+  /* The type of this timer.  */
+  enum atimer_type type;
+  
+  /* Time when this timer is ripe.  */
+  EMACS_TIME expiration;
+
+  /* Interval of this timer.  */
+  EMACS_TIME interval;
+
+  /* Function to call when timer is ripe.  Interupt input is
+     garanteed to not be blocked when this function is called.  */
+  atimer_callback fn;
+
+  /* Additional user-specified data to pass to FN.  */
+  void *client_data;
+
+  /* Next in list of active or free atimers.  */
+  struct atimer *next;
+};
+
+/* Function prototypes.  */
+
+struct atimer *start_atimer P_ ((enum atimer_type, EMACS_TIME,
+				 atimer_callback, void *));
+void cancel_atimer P_ ((struct atimer *));
+void do_pending_atimers P_ ((void));
+void init_atimer P_ ((void));
+void turn_on_atimers P_ ((int));
+