# HG changeset patch # User Gerd Moellmann # Date 948815982 0 # Node ID 87dcc6a2c31b3d4d79895257d64ec132cb0dded2 # Parent b904070c3d8b93a255c3fb06da6c3a9b37decce6 *** empty log message *** diff -r b904070c3d8b -r 87dcc6a2c31b lisp/ChangeLog --- 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 + + * scroll-bar.el (scroll-bar-timer): Variable removed. + (scroll-bar-toolkit-scroll): Don't use a timer. + 2000-01-25 Kenichi Handa * language/thai-util.el (thai-composition-function): Delete diff -r b904070c3d8b -r 87dcc6a2c31b lwlib/ChangeLog --- 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 + + * 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 * lwlib-Xm.c (xm_arm_callback): New function. diff -r b904070c3d8b -r 87dcc6a2c31b src/ChangeLog Binary file src/ChangeLog has changed diff -r b904070c3d8b -r 87dcc6a2c31b src/atimer.c --- /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 +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_SYS_TIME_H +#include +#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 -r b904070c3d8b -r 87dcc6a2c31b src/atimer.h --- /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)); +