+2006-12-16 Bruno Haible <bruno@clisp.org>
+
+ * m4/termcap.m4 (gl_TERMCAP_BODY): Also test for the terminfo
+ functions.
+ * lib/termcap.h (setupterm, tigetnum, tigetflag, tigetstr): New
+ declarations.
+ * lib/term-ostream.oo.c (xstrdup0) [HAVE_TERMINFO]: Handle (char*)-1
+ return value from tigetstr.
+ (term_ostream_create) [HAVE_TERMINFO]: Prefer the terminfo API.
+
2006-12-16 Bruno Haible <bruno@clisp.org>
* lib/term-ostream.oo.c (term_ostream_create): Fix tgetstr argument
static inline char *
xstrdup0 (const char *str)
{
- return (str != NULL ? xstrdup (str) : NULL);
+ if (str == NULL)
+ return NULL;
+#if HAVE_TERMINFO
+ if (str == (const char *)(-1))
+ return NULL;
+#endif
+ return xstrdup (str);
}
term_ostream_t
term = getenv ("TERM");
if (term != NULL && term[0] != '\0')
{
+ /* When the terminfo function are available, we prefer them over the
+ termcap functions because
+ 1. they don't risk a buffer overflow,
+ 2. on OSF/1, for TERM=xterm, the tiget* functions provide access
+ to the number of colors and the color escape sequences, whereas
+ the tget* functions don't provide them. */
+#if HAVE_TERMINFO
+ int err = 1;
+
+ if (setupterm (term, fd, &err) || err == 1)
+ {
+ /* Retrieve particular values depending on the terminal type. */
+ stream->max_colors = tigetnum ("colors");
+ stream->no_color_video = tigetnum ("ncv");
+ stream->set_a_foreground = xstrdup0 (tigetstr ("setaf"));
+ stream->set_foreground = xstrdup0 (tigetstr ("setf"));
+ stream->set_a_background = xstrdup0 (tigetstr ("setab"));
+ stream->set_background = xstrdup0 (tigetstr ("setb"));
+ stream->orig_pair = xstrdup0 (tigetstr ("op"));
+ stream->enter_bold_mode = xstrdup0 (tigetstr ("bold"));
+ stream->enter_italics_mode = xstrdup0 (tigetstr ("sitm"));
+ stream->exit_italics_mode = xstrdup0 (tigetstr ("ritm"));
+ stream->enter_underline_mode = xstrdup0 (tigetstr ("smul"));
+ stream->exit_underline_mode = xstrdup0 (tigetstr ("rmul"));
+ stream->exit_attribute_mode = xstrdup0 (tigetstr ("sgr0"));
+ }
+#else
struct { char buf[1024]; char canary[4]; } termcapbuf;
int retval;
stream->exit_underline_mode = xstrdup0 (tgetstr ("ue", TEBP));
stream->exit_attribute_mode = xstrdup0 (tgetstr ("me", TEBP));
-#ifdef __BEOS__
+# ifdef __BEOS__
/* The BeOS termcap entry for "beterm" is broken: For "AF" and "AB"
it contains balues in terminfo syntax but the system's tparam()
function understands only the termcap syntax. */
free (stream->set_a_background);
stream->set_a_background = xstrdup ("\033[4%dm");
}
-#endif
+# endif
/* Done with tgetstr. Detect possible buffer overflow. */
#undef TEBP
/* Buffer overflow! */
abort ();
}
+#endif
}
/* Infer the capabilities. */
Also, if AREA != NULL, stores it at *AREA and advances *AREA. */
extern const char * tgetstr (const char *id, char **area);
+#if HAVE_TERMINFO
+
+/* Gets the capability information for terminal type TYPE and prepares FD.
+ Returns 0 if successful, -1 upon error. If ERRP is non-NULL, also returns
+ an error indicator in *ERRP; otherwise an error is signalled. */
+extern int setupterm (const char *type, int fd, int *errp);
+
+/* Retrieves the value of a numerical capability.
+ Returns -1 if it is not available, -2 if ID is invalid. */
+extern int tigetnum (const char *id);
+
+/* Retrieves the value of a boolean capability.
+ Returns 1 if it available, 0 if not available, -1 if ID is invalid. */
+extern int tigetflag (const char *id);
+
+/* Retrieves the value of a string capability.
+ Returns NULL if it is not available, (char *)(-1) if ID is invalid. */
+extern const char * tigetstr (const char *id);
+
+#endif
+
#if HAVE_TPARAM
/* API provided by GNU termcap in <termcap.h>. */
-# termcap.m4 serial 3 (gettext-0.16.2)
+# termcap.m4 serial 4 (gettext-0.16.2)
dnl Copyright (C) 2000-2002, 2006 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl because libtermcap is unsecure by design and obsolete since 1994.
dnl libcurses is useless: all platforms which have libcurses also have
dnl libtermcap, and libcurses is unusable on some old Unices.
+ dnl Some systems have the terminfo functions setupterm(), tigetnum(),
+ dnl tigetstr(), tigetflag() in the same library.
dnl Some systems, like BeOS, use GNU termcap, which has tparam() instead of
dnl tparm().
AC_SUBST([LTLIBTERMCAP])
AC_SUBST([INCTERMCAP])
+ dnl Test whether the terminfo functions are available from the same library.
+ AC_CACHE_CHECK([for terminfo functions], [gl_cv_func_terminfo], [
+ gl_save_LIBS="$LIBS"
+ LIBS="$LIBS $LIBTERMCAP"
+ gl_save_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $INCTERMCAP"
+ AC_TRY_LINK([extern
+ #ifdef __cplusplus
+ "C"
+ #endif
+ int setupterm (const char *, int, int *);
+ extern
+ #ifdef __cplusplus
+ "C"
+ #endif
+ int tigetnum (const char *);
+ extern
+ #ifdef __cplusplus
+ "C"
+ #endif
+ int tigetflag (const char *);
+ extern
+ #ifdef __cplusplus
+ "C"
+ #endif
+ const char * tigetstr (const char *);
+ ], [return setupterm ("xterm", 0, (int *)0)
+ + tigetnum ("colors") + tigetflag ("hc") + * tigetstr("oc");],
+ [gl_cv_func_terminfo=yes], [gl_cv_func_terminfo=no])
+ CPPFLAGS="$gl_save_CPPFLAGS"
+ LIBS="$gl_save_LIBS"
+ ])
+ if test $gl_cv_func_terminfo = yes; then
+ AC_DEFINE([HAVE_TERMINFO], 1,
+ [Define if setupterm(), tigetnum(), tigetstr(), tigetflag()
+ are among the termcap library functions.])
+ fi
+
dnl Test against the old GNU termcap, which provides a tparam() function
dnl instead of the classical tparm() function.
AC_CACHE_CHECK([for tparam], [gl_cv_func_tparam], [