]> ncurses.scripts.mit.edu Git - ncurses.git/blobdiff - ncurses/tinfo/tinfo_driver.c
ncurses 5.9 - patch 20111001
[ncurses.git] / ncurses / tinfo / tinfo_driver.c
index fbd769d5008374df95157d77561c999c94fedc3d..589df2e036a3beb788a5a026a784ced320921d97 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * Copyright (c) 2008-2009,2010 Free Software Foundation, Inc.              *
+ * Copyright (c) 2008-2010,2011 Free Software Foundation, Inc.              *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -50,7 +50,7 @@
 # endif
 #endif
 
-MODULE_ID("$Id: tinfo_driver.c,v 1.7 2010/01/16 16:56:16 tom Exp $")
+MODULE_ID("$Id: tinfo_driver.c,v 1.15 2011/08/13 16:11:15 tom Exp $")
 
 /*
  * SCO defines TIOCGSIZE and the corresponding struct.  Other systems (SunOS,
@@ -106,54 +106,6 @@ drv_doupdate(TERMINAL_CONTROL_BLOCK * TCB)
     return TINFO_DOUPDATE(TCB->csp);
 }
 
-#define ret_error(code, fmt, arg)      if (errret) {\
-                                           *errret = code;\
-                                           return(FALSE); \
-                                       } else {\
-                                           fprintf(stderr, fmt, arg);\
-                                           exit(EXIT_FAILURE);\
-                                       }
-
-#define ret_error0(code, msg)          if (errret) {\
-                                           *errret = code;\
-                                           return(FALSE);\
-                                       } else {\
-                                           fprintf(stderr, msg);\
-                                           exit(EXIT_FAILURE);\
-                                       }
-
-#if USE_DATABASE || USE_TERMCAP
-/*
- * Return 1 if entry found, 0 if not found, -1 if database not accessible,
- * just like tgetent().
- */
-static int
-grab_entry(const char *const tn, TERMTYPE *const tp)
-{
-    char filename[PATH_MAX];
-    int status = _nc_read_entry(tn, filename, tp);
-
-    /*
-     * If we have an entry, force all of the cancelled strings to null
-     * pointers so we don't have to test them in the rest of the library.
-     * (The terminfo compiler bypasses this logic, since it must know if
-     * a string is cancelled, for merging entries).
-     */
-    if (status == TGETENT_YES) {
-       unsigned n;
-       for_each_boolean(n, tp) {
-           if (!VALID_BOOLEAN(tp->Booleans[n]))
-               tp->Booleans[n] = FALSE;
-       }
-       for_each_string(n, tp) {
-           if (tp->Strings[n] == CANCELLED_STRING)
-               tp->Strings[n] = ABSENT_STRING;
-       }
-    }
-    return (status);
-}
-#endif
-
 static bool
 drv_CanHandle(TERMINAL_CONTROL_BLOCK * TCB, const char *tname, int *errret)
 {
@@ -168,7 +120,7 @@ drv_CanHandle(TERMINAL_CONTROL_BLOCK * TCB, const char *tname, int *errret)
     TCB->magic = TCBMAGIC;
 
 #if (USE_DATABASE || USE_TERMCAP)
-    status = grab_entry(tname, &termp->type);
+    status = _nc_setup_tinfo(tname, &termp->type);
 #else
     status = TGETENT_NO;
 #endif
@@ -188,7 +140,7 @@ drv_CanHandle(TERMINAL_CONTROL_BLOCK * TCB, const char *tname, int *errret)
        if (status == TGETENT_ERR) {
            ret_error0(status, "terminals database is inaccessible\n");
        } else if (status == TGETENT_NO) {
-           ret_error(status, "'%s': unknown terminal type.\n", tname);
+           ret_error1(status, "unknown terminal type.\n", tname);
        }
     }
     result = TRUE;
@@ -201,10 +153,20 @@ drv_CanHandle(TERMINAL_CONTROL_BLOCK * TCB, const char *tname, int *errret)
        _nc_tinfo_cmdch(termp, *command_character);
 
     if (generic_type) {
-       ret_error(TGETENT_NO, "'%s': I need something more specific.\n", tname);
+       /*
+        * BSD 4.3's termcap contains mis-typed "gn" for wy99.  Do a sanity
+        * check before giving up.
+        */
+       if ((VALID_STRING(cursor_address)
+            || (VALID_STRING(cursor_down) && VALID_STRING(cursor_home)))
+           && VALID_STRING(clear_screen)) {
+           ret_error1(TGETENT_YES, "terminal is not really generic.\n", tname);
+       } else {
+           ret_error1(TGETENT_NO, "I need something more specific.\n", tname);
+       }
     }
     if (hard_copy) {
-       ret_error(TGETENT_YES, "'%s': I can't handle hardcopy terminals.\n", tname);
+       ret_error1(TGETENT_YES, "I can't handle hardcopy terminals.\n", tname);
     }
 
     return result;
@@ -392,25 +354,14 @@ drv_size(TERMINAL_CONTROL_BLOCK * TCB, int *linep, int *colp)
     /* figure out the size of the screen */
     T(("screen size: terminfo lines = %d columns = %d", lines, columns));
 
-    if (!useEnv) {
-       *linep = (int) lines;
-       *colp = (int) columns;
-    } else {                   /* usually want to query LINES and COLUMNS from environment */
-       int value;
+    *linep = (int) lines;
+    *colp = (int) columns;
 
-       *linep = *colp = 0;
-
-       /* first, look for environment variables */
-       if ((value = _nc_getenv_num("LINES")) > 0) {
-           *linep = value;
-       }
-       if ((value = _nc_getenv_num("COLUMNS")) > 0) {
-           *colp = value;
-       }
-       T(("screen size: environment LINES = %d COLUMNS = %d", *linep, *colp));
+    if (useEnv) {
+       int value;
 
 #ifdef __EMX__
-       if (*linep <= 0 || *colp <= 0) {
+       {
            int screendata[2];
            _scrsize(screendata);
            *colp = screendata[0];
@@ -420,34 +371,44 @@ drv_size(TERMINAL_CONTROL_BLOCK * TCB, int *linep, int *colp)
        }
 #endif
 #if HAVE_SIZECHANGE
-       /* if that didn't work, maybe we can try asking the OS */
-       if (*linep <= 0 || *colp <= 0) {
+       /* try asking the OS */
+       {
            TERMINAL *termp = (TERMINAL *) TCB;
            if (isatty(termp->Filedes)) {
                STRUCT_WINSIZE size;
 
                errno = 0;
                do {
-                   if (ioctl(termp->Filedes, IOCTL_WINSIZE, &size) < 0
-                       && errno != EINTR)
-                       goto failure;
+                   if (ioctl(termp->Filedes, IOCTL_WINSIZE, &size) >= 0) {
+                       *linep = ((sp != 0 && sp->_filtered)
+                                 ? 1
+                                 : WINSIZE_ROWS(size));
+                       *colp = WINSIZE_COLS(size);
+                       T(("SYS screen size: environment LINES = %d COLUMNS = %d",
+                          *linep, *colp));
+                       break;
+                   }
                } while
                    (errno == EINTR);
-
-               /*
-                * Solaris lets users override either dimension with an
-                * environment variable.
-                */
-               if (*linep <= 0)
-                   *linep = (sp != 0 && sp->_filtered) ? 1 : WINSIZE_ROWS(size);
-               if (*colp <= 0)
-                   *colp = WINSIZE_COLS(size);
            }
-           /* FALLTHRU */
-         failure:;
        }
 #endif /* HAVE_SIZECHANGE */
 
+       /*
+        * Finally, look for environment variables.
+        *
+        * Solaris lets users override either dimension with an environment
+        * variable.
+        */
+       if ((value = _nc_getenv_num("LINES")) > 0) {
+           *linep = value;
+           T(("screen size: environment LINES = %d", *linep));
+       }
+       if ((value = _nc_getenv_num("COLUMNS")) > 0) {
+           *colp = value;
+           T(("screen size: environment COLUMNS = %d", *colp));
+       }
+
        /* if we can't get dynamic info about the size, use static */
        if (*linep <= 0) {
            *linep = (int) lines;
@@ -548,9 +509,9 @@ drv_mode(TERMINAL_CONTROL_BLOCK * TCB, bool progFlag, bool defFlag)
             */
            if ((drv_sgmode(TCB, FALSE, &(_term->Nttyb)) == OK)) {
 #ifdef TERMIOS
-               _term->Nttyb.c_oflag &= ~OFLAGS_TABS;
+               _term->Nttyb.c_oflag &= (unsigned) ~OFLAGS_TABS;
 #else
-               _term->Nttyb.sg_flags &= ~XTABS;
+               _term->Nttyb.sg_flags &= (unsigned) ~XTABS;
 #endif
                code = OK;
            }
@@ -877,6 +838,39 @@ drv_initmouse(TERMINAL_CONTROL_BLOCK * TCB)
     }
 }
 
+static int
+drv_testmouse(TERMINAL_CONTROL_BLOCK * TCB, int delay)
+{
+    int rc = 0;
+    SCREEN *sp;
+
+    AssertTCB();
+    SetSP();
+
+#if USE_SYSMOUSE
+    if ((sp->_mouse_type == M_SYSMOUSE)
+       && (sp->_sysmouse_head < sp->_sysmouse_tail)) {
+       rc = TW_MOUSE;
+    } else
+#endif
+    {
+       rc = TCBOf(sp)->drv->twait(TCBOf(sp),
+                                  TWAIT_MASK,
+                                  delay,
+                                  (int *) 0
+                                  EVENTLIST_2nd(evl));
+#if USE_SYSMOUSE
+       if ((sp->_mouse_type == M_SYSMOUSE)
+           && (sp->_sysmouse_head < sp->_sysmouse_tail)
+           && (rc == 0)
+           && (errno == EINTR)) {
+           rc |= TW_MOUSE;
+       }
+#endif
+    }
+    return rc;
+}
+
 static int
 drv_mvcur(TERMINAL_CONTROL_BLOCK * TCB, int yold, int xold, int ynew, int xnew)
 {
@@ -1172,7 +1166,14 @@ drv_read(TERMINAL_CONTROL_BLOCK * TCB, int *buf)
     assert(buf);
     SetSP();
 
+# if USE_PTHREADS_EINTR
+    if ((pthread_self) && (pthread_kill) && (pthread_equal))
+       _nc_globals.read_thread = pthread_self();
+# endif
     n = read(sp->_ifd, &c2, 1);
+#if USE_PTHREADS_EINTR
+    _nc_globals.read_thread = 0;
+#endif
     *buf = (int) c2;
     return n;
 }
@@ -1309,6 +1310,7 @@ NCURSES_EXPORT_VAR (TERM_DRIVER) _nc_TINFO_DRIVER = {
        drv_initcolor,          /* initcolor */
        drv_do_color,           /* docolor */
        drv_initmouse,          /* initmouse */
+       drv_testmouse,          /* testmouse */
        drv_setfilter,          /* setfilter */
        drv_hwlabel,            /* hwlabel */
        drv_hwlabelOnOff,       /* hwlabelOnOff */