aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lisp/ChangeLog5
-rw-r--r--lwlib/ChangeLog8
-rw-r--r--src/ChangeLog49
-rw-r--r--src/atimer.c336
-rw-r--r--src/atimer.h75
5 files changed, 473 insertions, 0 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 73972d8f26..3bee200456 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,8 @@
+2000-01-25 Gerd Moellmann <[email protected]>
+
+ * scroll-bar.el (scroll-bar-timer): Variable removed.
+ (scroll-bar-toolkit-scroll): Don't use a timer.
+
2000-01-25 Kenichi Handa <[email protected]>
* language/thai-util.el (thai-composition-function): Delete
diff --git a/lwlib/ChangeLog b/lwlib/ChangeLog
index 9563a8f5b9..25dda71e44 100644
--- a/lwlib/ChangeLog
+++ b/lwlib/ChangeLog
@@ -1,3 +1,11 @@
+2000-01-25 Gerd Moellmann <[email protected]>
+
+ * 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 <[email protected]>
* lwlib-Xm.c (xm_arm_callback): New function.
diff --git a/src/ChangeLog b/src/ChangeLog
index 1195c6f20b..adcfb0089f 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,52 @@
+2000-01-25 Gerd Moellmann <[email protected]>
+
+ * sysdep.c (sys_select): Turn atimers off and on instead of
+ recording and restoring old alarm handler
+
+ * process.c (toplevel): Include atimer.h.
+ (create_process_1): Rewritten.
+ (create_process): Use atimers instead of alarm.
+ (wait_reading_process_input) [hpux]: Turn atimers off instead
+ of turning off SIGALRM.
+ (wait_reading_process_input): Turn off atimers instead off
+ calling stop_polling.
+
+ * emacs.c (main): Call init_atimer.
+
+ * keyboard.c (toplevel): Include systime.h and atimer.h.
+ (polling_for_input): Removed because unused.
+ (input_poll_signal) [POLL_FOR_INPUT]: Removed.
+ (poll_timer): New variable.
+ (poll_for_input, poll_for_input_1): New functions.
+ (start_polling, stop_polling): Rewritten.
+
+ * keyboard.h (polling_for_input): Removed.
+
+ * atimer.h, atimer.c: New files.
+
+ * Makefile.in (obj): Add atimer.o.
+ (atimer.o): New target.
+
+ * blockinput.h (pending_atimers): Add extern declaration.
+ (UNBLOCK_INPUT): Rewritten. Handle pending atimers.
+
+ * lisp.h (popup_activated_flag): Add extern declaration.
+
+ * xmenu.c (popup_activated_flag): Make externally visible.
+ (popup_activate_callback) [USE_MOTIF]: Increment
+ popup_activated_flag.
+ (popup_deactivate_callback) [USE_MOTIF]: Decrement it.
+
+ * xterm.c (toplevel): Include atimer.h.
+ (toolkit_scroll_bar_interaction): New variable.
+ (Fxt_process_timeouts): Removed.
+ (x_process_timeouts): New function.
+ (xt_action_hook): Clear toolkit_scroll_bar_interaction.
+ (x_send_scroll_bar_event): Set toolkit_scroll_bar_interaction.
+ (x_make_frame_visible): Call poll_for_input_1 instead of
+ input_poll_signal. Don't call alarm.
+ (x_initialize): Install timer calling x_process_timeouts.
+
2000-01-24 Dave Love <[email protected]>
* irix5-0.h: Don't set LD_SWITCH_SYSTEM -- we use unexelf now.
diff --git a/src/atimer.c b/src/atimer.c
new file mode 100644
index 0000000000..92f5076fcc
--- /dev/null
+++ b/src/atimer.c
@@ -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);
+}
diff --git a/src/atimer.h b/src/atimer.h
new file mode 100644
index 0000000000..9a5b7ef310
--- /dev/null
+++ b/src/atimer.h
@@ -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));
+