~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Tina4/src/X11/tw_interrupt.c

Version: ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /**@(#)Interval timer handling & interupt processing.
  2   @(#)Interrupt on 'escape' key, interrupt button or '^C' press.
  3 **/
  4 #include <tina/sys.h>
  5 #include <tina/sysfuncs.h>
  6 #include <sys/time.h>
  7 #include <stdio.h>
  8 #include <signal.h>
  9 #include <setjmp.h>
 10 #include <sys/time.h>
 11 #include <X11/X.h>
 12 #include <X11/Xlib.h>
 13 #include <X11/keysym.h>
 14 
 15 /* Handle X #define's of  Bool & Complex */
 16 /* Save X's definition of Bool */
 17 #define XBool int
 18 /* Save X's definition of Complex */
 19 #define XComplex Complex
 20 /* X11 #define's Bool. #undef because Tina typedef's Bool! */
 21 #undef Bool
 22 /* X11 #define's Complex. #undef because Tina typedef's Complex! */
 23 #undef Complex
 24 
 25 typedef void *(*voidStarFn) ();
 26 
 27 #ifdef __STRICT_ANSI__
 28 #ifdef SOLARIS
 29 typedef void Alarm_handler_fn(int sig);
 30 
 31 #elif defined IBM
 32 typedef void Alarm_handler_fn(int);
 33 
 34 #else                           /* not (IBM or SOLARIS) */
 35 /* typedef void Alarm_handler_fn(int sig, int code, struct sigcontext *
 36  * scp, char *addr); */
 37 typedef void Alarm_handler_fn(int sig, int code);
 38 
 39 #endif                          /* SOLARIS */
 40 #else                           /* __STRICT_ANSI__ */
 41 typedef void Alarm_handler_fn();
 42 
 43 #endif                          /* __STRICT_ANSI__ */
 44 
 45 /* FORWARD REFS */
 46 Bool    interrupt_check(void);
 47 static Bool interrupt_button_check(Display * display);
 48 static XBool button_release_check(Display * display, XEvent * xevent, char *window);
 49 static Bool control_c_check(Display * display);
 50 static Bool escape_check(Display * display);
 51 static XBool key_pressed_check(Display * display, XEvent * xevent, char *keycode_val);
 52 static void itimer_start(void);
 53 static void itimer_stop(void);
 54 
 55 
 56 /* STATIC GLOBALS */
 57 Bool    interruptible = false;
 58 
 59 static voidStarFn cleanup_fn = NULL;    /* to cleanup fn */
 60 static Display *interrupt_button_display = NULL;
 61 static Window interrupt_button_window = None;
 62 
 63 
 64 /* EXTERNS */
 65 extern jmp_buf interrupt_reentry_point;
 66 
 67 /* Interrupt lengthy processing and return to event read/dispatch loop */
 68 void    abandon(void)
 69 {
 70     extern void tw_active_tool_data_get();
 71     extern void tw_set_tina_cursor();
 72 
 73     Display *active_display;
 74     Window  active_window;
 75 
 76     interruptible = false;
 77 #ifdef __STDC__
 78     if (cleanup_fn)
 79 #else
 80     if (*cleanup_fn)
 81 #endif /* __STDC__ */
 82     {
 83         (*cleanup_fn) ();
 84         cleanup_fn = NULL;
 85     }
 86     format("Interrupted!\n");
 87     tw_active_tool_data_get(&active_display, &active_window);
 88     tw_set_tina_cursor(active_display, active_window);
 89     longjmp(interrupt_reentry_point, 7);
 90 }
 91 
 92 /* Handle alarm signals. Ie SIGALRM (from timer). */
 93 /* ARGSUSED Quieten lint */
 94 /* void    alarm_handler(int sig, int code, void *scp, char *addr) */
 95 void    alarm_handler(int sig, int code)
 96 {
 97     /* HP warns: 'alarm_handler wrong type' (return type is ok, args
 98      * are not) */
 99     (void) signal(SIGALRM, (Alarm_handler_fn *) alarm_handler);
100     if (interrupt_check())
101     {
102         abandon();
103     }
104 }
105 
106 /* Return true iff event was button release in given window. Else False */
107 /* ARGSUSED Quieten lint */
108 static XBool button_release_check(Display * display, XEvent * xevent, char *window)
109 {
110     return (window &&
111             (xevent->type == ButtonRelease) &&
112             (xevent->xbutton.window == (Window) window));
113 }
114 
115 /* Return true if control_c key has been pressed (in any window in this
116  * application).  Else False. NB Removes event from queue. Does not
117  * block if event not found. */
118 static Bool control_c_check(Display * display)
119 {
120     KeyCode control_c_code = XKeysymToKeycode(display, XK_C);
121     XEvent  xevent;
122 
123     return (Bool) (XCheckIfEvent(display, &xevent, key_pressed_check,
124       (char *) &control_c_code) && (xevent.xkey.state & ControlMask));
125 }
126 
127 /* Return true if escape key has been pressed (in any window in this
128  * application).  Else False. NB Removes event from queue. Does not
129  * block if event not found. */
130 static Bool escape_check(Display * display)
131 {
132     KeyCode esc_code = XKeysymToKeycode(display, XK_Escape);
133     XEvent  xevent;
134 
135     return (Bool) XCheckIfEvent(display, &xevent, key_pressed_check, (char *) &esc_code);
136 }
137 
138 
139 /* Check for interrupts (escape key, interrupt button, ^C). Return true
140  * iff interruptible is true AND interrupt found. NB only detects ^C &
141  * escape button presses IF interrupt_button has been created. */
142 Bool    interrupt_check(void)
143 {
144     return (Bool) (interruptible &&
145                    interrupt_button_window &&
146                    interrupt_button_display &&
147                    (control_c_check(interrupt_button_display) ||
148                     escape_check(interrupt_button_display) ||
149                     interrupt_button_check(interrupt_button_display)));
150 }
151 
152 /* Enable interrupts and set cleanup function. (NULL function not
153  * called.) */
154 void    interrupt_enable(voidStarFn cleanup_fn_val)
155 {
156     void    interrupt_button_data_get();
157 
158     interrupt_button_data_get(&interrupt_button_display, &interrupt_button_window);
159 
160     if (interrupt_button_display && interrupt_button_window)
161     {
162         cleanup_fn = cleanup_fn_val;
163         itimer_start();
164         interruptible = true;
165     }
166 }
167 
168 
169 /* Disable interrupts.  Return previous interruptible status. Ie true
170  * iff was interruptible.  Sets arg to point to cleanup function, which
171  * may be NULL. */
172 Bool    interrupt_disable(voidStarFn * cleanup_fn_val)
173 {
174     Bool    interruptible_old = interruptible;
175 
176     itimer_stop();
177 
178     interruptible = false;
179     *cleanup_fn_val = cleanup_fn;
180 
181     return interruptible_old;
182 }
183 
184 
185 /* Handle interrupt signals.  Ie SIGINT (^C) */
186 /* ARGSUSED Quieten lint */
187 void    interrupt_handler(int sig, int code, void *scp, char *addr)
188 {
189     extern void exit(int);
190     char    buf[20];
191 
192     /* HP warns: 'alarm_handler wrong type' (return type is ok, args
193      * are not) */
194     (void) signal(SIGINT, (Alarm_handler_fn *) interrupt_handler);
195 
196 #ifndef IBM
197     if (((void) printf("\nExit Tina? (y/n): "),
198          (*gets(buf) == 'y')))
199 #endif
200 
201     {
202         (void) printf("Tina: Bye.\n");
203         exit(0);
204     }
205 }
206 
207 /* Return true if interrupt button pressed.  Else False. NB Removes
208  * event from queue. Does not block if event not found. */
209 static Bool interrupt_button_check(Display * display)
210 {
211     XEvent  xevent;
212 
213     return (Bool) XCheckIfEvent(display, &xevent, button_release_check,
214                                 (char *) interrupt_button_window);
215 }
216 
217 
218 /* Start timer to interrupt program every second.  The alarm_handler
219  * catches alarm signals and ^C (SIGINT).  */
220 static void itimer_start(void)
221 {
222 
223     static struct itimerval it_value = {{1L, 1L}, {1L, 1L}};    /* timeout every sec */
224 
225     (void) setitimer(ITIMER_REAL, &it_value, (struct itimerval *) 0);
226 }
227 
228 /* Stop timer.  */
229 static void itimer_stop(void)
230 {
231 
232     static struct itimerval it_value = {{0L, 0L}, {0L, 0L}};    /* timer off */
233 
234     (void) setitimer(ITIMER_REAL, &it_value, (struct itimerval *) 0);
235 }
236 
237 /* Return true iff event was keypress of key with code 'keycode'. Else
238  * False */
239 /* ARGSUSED Quieten lint */
240 static XBool key_pressed_check(Display * display, XEvent * xevent, char *keycode_val)
241 {
242     KeyCode *keycode = (KeyCode *) keycode_val;
243 
244     return ((xevent->type == KeyPress) && (xevent->xkey.keycode == *keycode));
245 }
246 
247 /* Toggle X synchronisation.  When on, X is unbuffered, errors are
248  * reported immediately but runs much slower. */
249 void    toggle_sync(void)
250 {
251     extern Display *tw_get_display();
252     static int sync = 1;
253 
254     format("X %sbuffered.\n", sync ? "UN" : "");
255     XSynchronize(tw_get_display(), sync);
256     sync = !sync;
257 }
258 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.