source: owl.c @ 1a0874f

release-1.6release-1.7release-1.8release-1.9
Last change on this file since 1a0874f was 2a17b63, checked in by Nelson Elhage <nelhage@mit.edu>, 12 years ago
Push and pop contexts whenever we change context. This allows us to get rid of the awful hack in owl_process_input_char, and opens the path to being able to invoke popup windows from the editwin and vice versa (In fact, you can now do so without segfaulting, although the display layer does not yet quite do the right thing).
  • Property mode set to 100644
File size: 20.0 KB
Line 
1/*  Copyright (c) 2006-2009 The BarnOwl Developers. All rights reserved.
2 *  Copyright (c) 2004 James Kretchmar. All rights reserved.
3 *
4 *  This program is free software. You can redistribute it and/or
5 *  modify under the terms of the Sleepycat License. See the COPYING
6 *  file included with the distribution for more information.
7 */
8
9#include <stdio.h>
10#include <unistd.h>
11#include <getopt.h>
12#include <stdlib.h>
13#include <string.h>
14#include <signal.h>
15#include <time.h>
16#include <sys/param.h>
17#include <sys/types.h>
18#include <sys/time.h>
19#include <termios.h>
20#include <sys/stat.h>
21#include <locale.h>
22#include "owl.h"
23
24
25#if OWL_STDERR_REDIR
26#ifdef HAVE_SYS_IOCTL_H
27#include <sys/ioctl.h>
28#endif
29#ifdef HAVE_SYS_FILIO_H
30#include <sys/filio.h>
31#endif
32int stderr_replace(void);
33#endif
34
35#define STDIN 0
36
37owl_global g;
38
39typedef struct _owl_options {
40  bool load_initial_subs;
41  char *configfile;
42  char *tty;
43  char *confdir;
44  bool debug;
45  bool rm_debug;
46} owl_options;
47
48void usage(void)
49{
50  fprintf(stderr, "Barnowl version %s\n", OWL_VERSION_STRING);
51  fprintf(stderr, "Usage: barnowl [-n] [-d] [-D] [-v] [-h] [-c <configfile>] [-s <confdir>] [-t <ttyname>]\n");
52  fprintf(stderr, "  -n,--no-subs        don't load zephyr subscriptions\n");
53  fprintf(stderr, "  -d,--debug          enable debugging\n");
54  fprintf(stderr, "  -D,--remove-debug   enable debugging and delete previous debug file\n");
55  fprintf(stderr, "  -v,--version        print the Barnowl version number and exit\n");
56  fprintf(stderr, "  -h,--help           print this help message\n");
57  fprintf(stderr, "  -c,--config-file    specify an alternate config file\n");
58  fprintf(stderr, "  -s,--config-dir     specify an alternate config dir (default ~/.owl)\n");
59  fprintf(stderr, "  -t,--tty            set the tty name\n");
60}
61
62/* TODO: free owl_options after init is done? */
63void owl_parse_options(int argc, char *argv[], owl_options *opts) {
64  static const struct option long_options[] = {
65    { "no-subs",         0, 0, 'n' },
66    { "config-file",     1, 0, 'c' },
67    { "config-dir",      1, 0, 's' },
68    { "tty",             1, 0, 't' },
69    { "debug",           0, 0, 'd' },
70    { "remove-debug",    0, 0, 'D' },
71    { "version",         0, 0, 'v' },
72    { "help",            0, 0, 'h' },
73    { NULL, 0, NULL, 0}
74  };
75  char c;
76
77  while((c = getopt_long(argc, argv, "nc:t:s:dDvh",
78                         long_options, NULL)) != -1) {
79    switch(c) {
80    case 'n':
81      opts->load_initial_subs = 0;
82      break;
83    case 'c':
84      opts->configfile = owl_strdup(optarg);
85      break;
86    case 's':
87      opts->confdir = owl_strdup(optarg);
88      break;
89    case 't':
90      opts->tty = owl_strdup(optarg);
91      break;
92    case 'D':
93      opts->rm_debug = 1;
94      /* fallthrough */
95    case 'd':
96      opts->debug = 1;
97      break;
98    case 'v':
99      printf("This is barnowl version %s\n", OWL_VERSION_STRING);
100      exit(0);
101    case 'h':
102    default:
103      usage();
104      exit(1);
105    }
106  }
107}
108
109void owl_start_color(void) {
110  start_color();
111#ifdef HAVE_USE_DEFAULT_COLORS
112  use_default_colors();
113#endif
114
115  /* define simple color pairs */
116  if (has_colors() && COLOR_PAIRS>=8) {
117    int bg = COLOR_BLACK;
118#ifdef HAVE_USE_DEFAULT_COLORS
119    bg = -1;
120#endif
121    init_pair(OWL_COLOR_BLACK,   COLOR_BLACK,   bg);
122    init_pair(OWL_COLOR_RED,     COLOR_RED,     bg);
123    init_pair(OWL_COLOR_GREEN,   COLOR_GREEN,   bg);
124    init_pair(OWL_COLOR_YELLOW,  COLOR_YELLOW,  bg);
125    init_pair(OWL_COLOR_BLUE,    COLOR_BLUE,    bg);
126    init_pair(OWL_COLOR_MAGENTA, COLOR_MAGENTA, bg);
127    init_pair(OWL_COLOR_CYAN,    COLOR_CYAN,    bg);
128    init_pair(OWL_COLOR_WHITE,   COLOR_WHITE,   bg);
129  }
130}
131
132void owl_start_curses(void) {
133  struct termios tio;
134  /* save initial terminal settings */
135  tcgetattr(0, owl_global_get_startup_tio(&g));
136
137  tcgetattr(0, &tio);
138  tio.c_iflag &= ~(ISTRIP|IEXTEN);
139  tio.c_cc[VQUIT] = 0;
140  tio.c_cc[VSUSP] = 0;
141  tcsetattr(0, TCSAFLUSH, &tio);
142
143  /* screen init */
144  initscr();
145  cbreak();
146  noecho();
147
148  owl_start_color();
149}
150
151static void owl_setup_default_filters(void)
152{
153  int i;
154  static const struct {
155    const char *name;
156    const char *desc;
157  } filters[] = {
158    { "personal",
159      "isprivate ^true$ and ( not type ^zephyr$ or ( class ^message  ) )" },
160    { "trash",
161      "class ^mail$ or opcode ^ping$ or type ^admin$ or ( not login ^none$ )" },
162    { "wordwrap", "not ( type ^admin$ or type ^zephyr$ )" },
163    { "ping", "opcode ^ping$" },
164    { "auto", "opcode ^auto$" },
165    { "login", "not login ^none$" },
166    { "reply-lockout", "class ^noc or class ^mail$" },
167    { "out", "direction ^out$" },
168    { "aim", "type ^aim$" },
169    { "zephyr", "type ^zephyr$" },
170    { "none", "false" },
171    { "all", "true" },
172    { NULL, NULL }
173  };
174
175  owl_function_debugmsg("startup: creating default filters");
176
177  for (i = 0; filters[i].name != NULL; i++)
178    owl_global_add_filter(&g, owl_filter_new_fromstring(filters[i].name,
179                                                        filters[i].desc));
180}
181
182/*
183 * Process a new message passed to us on the message queue from some
184 * protocol. This includes adding it to the message list, updating the
185 * view and scrolling if appropriate, logging it, and so on.
186 *
187 * Either a pointer is kept to the message internally, or it is freed
188 * if unneeded. The caller no longer ``owns'' the message's memory.
189 *
190 * Returns 1 if the message was added to the message list, and 0 if it
191 * was ignored due to user settings or otherwise.
192 */
193int owl_process_message(owl_message *m) {
194  const owl_filter *f;
195  /* if this message it on the puntlist, nuke it and continue */
196  if (owl_global_message_is_puntable(&g, m)) {
197    owl_message_free(m);
198    return 0;
199  }
200
201  /*  login or logout that should be ignored? */
202  if (owl_global_is_ignorelogins(&g)
203      && owl_message_is_loginout(m)) {
204    owl_message_free(m);
205    return 0;
206  }
207
208  if (!owl_global_is_displayoutgoing(&g)
209      && owl_message_is_direction_out(m)) {
210    owl_message_free(m);
211    return 0;
212  }
213
214  /* add it to the global list */
215  owl_messagelist_append_element(owl_global_get_msglist(&g), m);
216  /* add it to any necessary views; right now there's only the current view */
217  owl_view_consider_message(owl_global_get_current_view(&g), m);
218
219  if(owl_message_is_direction_in(m)) {
220    /* let perl know about it*/
221    owl_perlconfig_getmsg(m, NULL);
222
223    /* do we need to autoreply? */
224    if (owl_global_is_zaway(&g) && !owl_message_get_attribute_value(m, "isauto")) {
225      if (owl_message_is_type_zephyr(m)) {
226        owl_zephyr_zaway(m);
227      } else if (owl_message_is_type_aim(m)) {
228        if (owl_message_is_private(m)) {
229          owl_function_send_aimawymsg(owl_message_get_sender(m), owl_global_get_zaway_msg(&g));
230        }
231      }
232    }
233
234    /* ring the bell if it's a personal */
235    if (!strcmp(owl_global_get_personalbell(&g), "on")) {
236      if (!owl_message_is_loginout(m) &&
237          !owl_message_is_mail(m) &&
238          owl_message_is_personal(m)) {
239        owl_function_beep();
240      }
241    } else if (!strcmp(owl_global_get_personalbell(&g), "off")) {
242      /* do nothing */
243    } else {
244      f=owl_global_get_filter(&g, owl_global_get_personalbell(&g));
245      if (f && owl_filter_message_match(f, m)) {
246        owl_function_beep();
247      }
248    }
249
250    /* if it matches the alert filter, do the alert action */
251    f=owl_global_get_filter(&g, owl_global_get_alert_filter(&g));
252    if (f && owl_filter_message_match(f, m)) {
253      owl_function_command(owl_global_get_alert_action(&g));
254    }
255
256    /* if it's a zephyr login or logout, update the zbuddylist */
257    if (owl_message_is_type_zephyr(m) && owl_message_is_loginout(m)) {
258      if (owl_message_is_login(m)) {
259        owl_zbuddylist_adduser(owl_global_get_zephyr_buddylist(&g), owl_message_get_sender(m));
260      } else if (owl_message_is_logout(m)) {
261        owl_zbuddylist_deluser(owl_global_get_zephyr_buddylist(&g), owl_message_get_sender(m));
262      } else {
263        owl_function_error("Internal error: received login notice that is neither login nor logout");
264      }
265    }
266  }
267
268  /* let perl know about it */
269  owl_perlconfig_newmsg(m, NULL);
270  /* log the message if we need to */
271  owl_log_message(m);
272
273  return 1;
274}
275
276/*
277 * Process any new messages we have waiting in the message queue.
278 * Returns 1 if any messages were added to the message list, and 0 otherwise.
279 */
280int owl_process_messages(owl_ps_action *d, void *p)
281{
282  int newmsgs=0;
283  int followlast = owl_global_should_followlast(&g);
284  owl_message *m;
285
286  /* Grab incoming messages. */
287  while (owl_global_messagequeue_pending(&g)) {
288    m = owl_global_messagequeue_popmsg(&g);
289    if (owl_process_message(m))
290      newmsgs = 1;
291  }
292
293  if (newmsgs) {
294    /* follow the last message if we're supposed to */
295    if (followlast)
296      owl_function_lastmsg_noredisplay();
297
298    /* do the newmsgproc thing */
299    owl_function_do_newmsgproc();
300
301    /* redisplay if necessary */
302    /* this should be optimized to not run if the new messages won't be displayed */
303    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
304    sepbar(NULL);
305    if (owl_popwin_is_active(owl_global_get_popwin(&g))) {
306      owl_popwin_refresh(owl_global_get_popwin(&g));
307      /* TODO: this is a broken kludge */
308      if (owl_global_get_viewwin(&g)) {
309        owl_viewwin_redisplay(owl_global_get_viewwin(&g), 0);
310      }
311    }
312    owl_global_set_needrefresh(&g);
313  }
314  return newmsgs;
315}
316
317void owl_process_input(const owl_io_dispatch *d, void *data)
318{
319  owl_input j;
320  WINDOW *typwin;
321
322  typwin = owl_global_get_curs_typwin(&g);
323
324  while (1) {
325    j.ch = wgetch(typwin);
326    if (j.ch == ERR) return;
327
328    j.uch = '\0';
329    if (j.ch >= KEY_MIN && j.ch <= KEY_MAX) {
330      /* This is a curses control character. */
331    }
332    else if (j.ch > 0x7f && j.ch < 0xfe) {
333      /* Pull in a full utf-8 character. */
334      int bytes, i;
335      char utf8buf[7];
336      memset(utf8buf, '\0', 7);
337     
338      utf8buf[0] = j.ch;
339     
340      if ((j.ch & 0xc0) && (~j.ch & 0x20)) bytes = 2;
341      else if ((j.ch & 0xe0) && (~j.ch & 0x10)) bytes = 3;
342      else if ((j.ch & 0xf0) && (~j.ch & 0x08)) bytes = 4;
343      else if ((j.ch & 0xf8) && (~j.ch & 0x04)) bytes = 5;
344      else if ((j.ch & 0xfc) && (~j.ch & 0x02)) bytes = 6;
345      else bytes = 1;
346     
347      for (i = 1; i < bytes; i++) {
348        int tmp =  wgetch(typwin);
349        /* If what we got was not a byte, or not a continuation byte */
350        if (tmp > 0xff || !(tmp & 0x80 && ~tmp & 0x40)) {
351          /* ill-formed UTF-8 code unit subsequence, put back the
352             char we just got. */
353          ungetch(tmp);
354          j.ch = ERR;
355          break;
356        }
357        utf8buf[i] = tmp;
358      }
359     
360      if (j.ch != ERR) {
361        if (g_utf8_validate(utf8buf, -1, NULL)) {
362          j.uch = g_utf8_get_char(utf8buf);
363        }
364        else {
365          j.ch = ERR;
366        }
367      }
368    }
369    else if (j.ch <= 0x7f) {
370      j.uch = j.ch;
371    }
372
373    owl_process_input_char(j);
374  }
375}
376
377void sig_handler(int sig, siginfo_t *si, void *data)
378{
379  if (sig==SIGWINCH) {
380    /* we can't inturrupt a malloc here, so it just sets a flag
381     * schedulding a resize for later
382     */
383    owl_function_resize();
384  } else if (sig==SIGPIPE || sig==SIGCHLD) {
385    /* Set a flag and some info that we got the sigpipe
386     * so we can record that we got it and why... */
387    owl_global_set_errsignal(&g, sig, si);
388  } else if (sig==SIGTERM || sig==SIGHUP) {
389    owl_function_quit();
390  }
391}
392
393void sigint_handler(int sig, siginfo_t *si, void *data)
394{
395  owl_global_set_interrupted(&g);
396}
397
398void owl_register_signal_handlers(void) {
399  struct sigaction sigact;
400
401  /* signal handler */
402  /*sigact.sa_handler=sig_handler;*/
403  sigact.sa_sigaction=sig_handler;
404  sigemptyset(&sigact.sa_mask);
405  sigact.sa_flags=SA_SIGINFO;
406  sigaction(SIGWINCH, &sigact, NULL);
407  sigaction(SIGALRM, &sigact, NULL);
408  sigaction(SIGPIPE, &sigact, NULL);
409  sigaction(SIGTERM, &sigact, NULL);
410  sigaction(SIGHUP, &sigact, NULL);
411
412  sigact.sa_sigaction=sigint_handler;
413  sigaction(SIGINT, &sigact, NULL);
414}
415
416#if OWL_STDERR_REDIR
417
418/* Replaces stderr with a pipe so that we can read from it.
419 * Returns the fd of the pipe from which stderr can be read. */
420int stderr_replace(void)
421{
422  int pipefds[2];
423  if (0 != pipe(pipefds)) {
424    perror("pipe");
425    owl_function_debugmsg("stderr_replace: pipe FAILED\n");
426    return -1;
427  }
428    owl_function_debugmsg("stderr_replace: pipe: %d,%d\n", pipefds[0], pipefds[1]);
429  if (-1 == dup2(pipefds[1], 2 /*stderr*/)) {
430    owl_function_debugmsg("stderr_replace: dup2 FAILED (%s)\n", strerror(errno));
431    perror("dup2");
432    return -1;
433  }
434  return pipefds[0];
435}
436
437/* Sends stderr (read from rfd) messages to the error console */
438void stderr_redirect_handler(const owl_io_dispatch *d, void *data)
439{
440  int navail, bread;
441  char buf[4096];
442  int rfd = d->fd;
443  char *err;
444
445  if (rfd<0) return;
446  if (-1 == ioctl(rfd, FIONREAD, &navail)) {
447    return;
448  }
449  /*owl_function_debugmsg("stderr_redirect: navail = %d\n", navail);*/
450  if (navail <= 0) return;
451  if (navail > sizeof(buf)-1) {
452    navail = sizeof(buf)-1;
453  }
454  bread = read(rfd, buf, navail);
455  if (buf[navail-1] != '\0') {
456    buf[navail] = '\0';
457  }
458
459  err = owl_sprintf("[stderr]\n%s", buf);
460
461  owl_function_log_err(err);
462  owl_free(err);
463}
464
465#endif /* OWL_STDERR_REDIR */
466
467void owl_zephyr_buddycheck_timer(owl_timer *t, void *data)
468{
469  if (owl_global_is_pseudologins(&g)) {
470    owl_function_debugmsg("Doing zephyr buddy check");
471    owl_function_zephyr_buddy_check(1);
472  }
473}
474
475
476int main(int argc, char **argv, char **env)
477{
478  WINDOW *recwin, *sepwin, *typwin, *msgwin;
479  owl_editwin *tw;
480  owl_popwin *pw;
481  int argcsave;
482  const char *const *argvsave;
483  char *perlout, *perlerr;
484  const owl_style *s;
485  const char *dir;
486  owl_options opts;
487
488  if (!GLIB_CHECK_VERSION (2, 12, 0))
489    g_error ("GLib version 2.12.0 or above is needed.");
490
491  argcsave=argc;
492  argvsave=strs(argv);
493
494  setlocale(LC_ALL, "");
495
496  memset(&opts, 0, sizeof opts);
497  opts.load_initial_subs = 1;
498  owl_parse_options(argc, argv, &opts);
499  g.load_initial_subs = opts.load_initial_subs;
500
501  owl_function_debugmsg("startup: Finished parsing arguments");
502
503  owl_register_signal_handlers();
504  owl_start_curses();
505
506  /* owl global init */
507  owl_global_init(&g);
508  if (opts.rm_debug) unlink(OWL_DEBUG_FILE);
509  if (opts.debug) owl_global_set_debug_on(&g);
510  if (opts.confdir) owl_global_set_confdir(&g, opts.confdir);
511  owl_function_debugmsg("startup: first available debugging message");
512  owl_global_set_startupargs(&g, argcsave, argvsave);
513  owl_global_set_haveaim(&g);
514
515  /* register STDIN dispatch; throw away return, we won't need it */
516  owl_select_add_io_dispatch(STDIN, OWL_IO_READ, &owl_process_input, NULL, NULL);
517  owl_zephyr_initialize();
518
519#if OWL_STDERR_REDIR
520  /* Do this only after we've started curses up... */
521  owl_function_debugmsg("startup: doing stderr redirection");
522  owl_select_add_io_dispatch(stderr_replace(), OWL_IO_READ, &stderr_redirect_handler, NULL, NULL);
523#endif
524
525  /* create the owl directory, in case it does not exist */
526  owl_function_debugmsg("startup: creating owl directory, if not present");
527  dir=owl_global_get_confdir(&g);
528  mkdir(dir, S_IRWXU);
529
530  /* set the tty, either from the command line, or by figuring it out */
531  owl_function_debugmsg("startup: setting tty name");
532  if (opts.tty) {
533    owl_global_set_tty(&g, opts.tty);
534  } else {
535    owl_global_set_tty(&g, owl_util_get_default_tty());
536  }
537
538  /* Initialize perl */
539  owl_function_debugmsg("startup: processing config file");
540
541  owl_global_pop_context(&g);
542  owl_global_push_context(&g, OWL_CTX_READCONFIG, NULL, NULL);
543
544  perlerr=owl_perlconfig_initperl(opts.configfile, &argc, &argv, &env);
545  if (perlerr) {
546    endwin();
547    fprintf(stderr, "Internal perl error: %s\n", perlerr);
548    fflush(stderr);
549    printf("Internal perl error: %s\n", perlerr);
550    fflush(stdout);
551    exit(1);
552  }
553
554  owl_global_complete_setup(&g);
555
556  owl_setup_default_filters();
557
558  /* set the current view */
559  owl_function_debugmsg("startup: setting the current view");
560  owl_view_create(owl_global_get_current_view(&g), "main",
561                  owl_global_get_filter(&g, "all"),
562                  owl_global_get_style_by_name(&g, "default"));
563
564  /* AIM init */
565  owl_function_debugmsg("startup: doing AIM initialization");
566  owl_aim_init();
567
568  /* execute the startup function in the configfile */
569  owl_function_debugmsg("startup: executing perl startup, if applicable");
570  perlout = owl_perlconfig_execute("BarnOwl::Hooks::_startup();");
571  if (perlout) owl_free(perlout);
572
573  /* hold on to the window names for convenience */
574  msgwin=owl_global_get_curs_msgwin(&g);
575  recwin=owl_global_get_curs_recwin(&g);
576  sepwin=owl_global_get_curs_sepwin(&g);
577  typwin=owl_global_get_curs_typwin(&g);
578  tw=owl_global_get_typwin(&g);
579
580  /* welcome message */
581  owl_function_debugmsg("startup: creating splash message");
582  owl_function_adminmsg("",
583    "-----------------------------------------------------------------------\n"
584    "Welcome to barnowl version " OWL_VERSION_STRING ".  Press 'h' for on-line help.\n"
585    "To see a quick introduction, type ':show quickstart'.                  \n"
586    "                                                                       \n"
587    "BarnOwl is free software. Type ':show license' for more                \n"
588    "information.                                                     ^ ^   \n"
589    "                                                                 OvO   \n"
590    "Please report any bugs or suggestions to bug-barnowl@mit.edu    (   )  \n"
591    "-----------------------------------------------------------------m-m---\n"
592  );
593  sepbar(NULL);
594
595  /* process the startup file */
596  owl_function_debugmsg("startup: processing startup file");
597  owl_function_source(NULL);
598
599  wrefresh(sepwin);
600
601  /* Set the default style */
602  owl_function_debugmsg("startup: setting startup and default style");
603  if (0 != strcmp(owl_global_get_default_style(&g), "__unspecified__")) {
604    /* the style was set by the user: leave it alone */
605  } else {
606    owl_global_set_default_style(&g, "default");
607  }
608
609  owl_function_debugmsg("startup: set style for the view: %s", owl_global_get_default_style(&g));
610  s = owl_global_get_style_by_name(&g, owl_global_get_default_style(&g));
611  if(s)
612      owl_view_set_style(owl_global_get_current_view(&g), s);
613  else
614      owl_function_error("No such style: %s", owl_global_get_default_style(&g));
615
616  owl_function_debugmsg("startup: setting context interactive");
617
618  owl_global_pop_context(&g);
619  owl_global_push_context(&g, OWL_CTX_READCONFIG|OWL_CTX_RECV, NULL, "recv");
620
621  owl_select_add_timer(180, 180, owl_zephyr_buddycheck_timer, NULL, NULL);
622
623  /* If we ever deprecate the mainloop hook, remove this. */
624  owl_select_add_timer(0, 1, owl_perlconfig_mainloop, NULL, NULL);
625
626  owl_select_add_pre_select_action(owl_process_messages, NULL, NULL);
627
628  owl_function_debugmsg("startup: entering main loop");
629  /* main loop */
630  while (1) {
631
632    /* if a resize has been scheduled, deal with it */
633    owl_global_resize(&g, 0, 0);
634
635    /* these are here in case a resize changes the windows */
636    msgwin=owl_global_get_curs_msgwin(&g);
637    recwin=owl_global_get_curs_recwin(&g);
638    sepwin=owl_global_get_curs_sepwin(&g);
639    typwin=owl_global_get_curs_typwin(&g);
640
641    /* if a popwin just came up, refresh it */
642    pw=owl_global_get_popwin(&g);
643    if (owl_popwin_is_active(pw) && owl_popwin_needs_first_refresh(pw)) {
644      owl_popwin_refresh(pw);
645      owl_popwin_no_needs_first_refresh(pw);
646      owl_global_set_needrefresh(&g);
647      /* TODO: this is a broken kludge */
648      if (owl_global_get_viewwin(&g)) {
649        owl_viewwin_redisplay(owl_global_get_viewwin(&g), 0);
650      }
651    }
652
653    /* update the terminal if we need to */
654    if (owl_global_is_needrefresh(&g)) {
655      /* leave the cursor in the appropriate window */
656      if (owl_global_is_typwin_active(&g)) {
657        owl_function_set_cursor(typwin);
658      } else {
659        owl_function_set_cursor(sepwin);
660      }
661      doupdate();
662      owl_global_set_noneedrefresh(&g);
663    }
664
665    /* select on FDs we know about. */
666    owl_select();
667
668    /* Log any error signals */
669    {
670      siginfo_t si;
671      int signum;
672      if ((signum = owl_global_get_errsignal_and_clear(&g, &si)) > 0) {
673        owl_function_error("Got unexpected signal: %d %s  (code: %d band: %ld  errno: %d)",
674                           signum, signum==SIGPIPE?"SIGPIPE":"SIG????",
675                           si.si_code, si.si_band, si.si_errno);
676      }
677    }
678
679  }
680}
Note: See TracBrowser for help on using the repository browser.