X-Git-Url: http://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=ncurses%2Ftinfo%2Flib_termcap.c;h=c03a601f49689e262d73a4a6211f3bb9c2e02dac;hp=8238b368eea3e581a2e6b23bda576ea9434e8005;hb=46722468f47c2b77b3987729b4bcf2321cccfd01;hpb=0eb88fc5281804773e2a0c7a488a4452463535ce diff --git a/ncurses/tinfo/lib_termcap.c b/ncurses/tinfo/lib_termcap.c index 8238b368..c03a601f 100644 --- a/ncurses/tinfo/lib_termcap.c +++ b/ncurses/tinfo/lib_termcap.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998 Free Software Foundation, Inc. * + * Copyright (c) 1998-2001,2002 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 * @@ -29,25 +29,80 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * + * * + * some of the code in here was contributed by: * + * Magnus Bengtsson, d6mbeng@dtek.chalmers.se (Nov'93) * ****************************************************************************/ +#define __INTERNAL_CAPS_VISIBLE #include #include #include +#include -#define __INTERNAL_CAPS_VISIBLE #include -MODULE_ID("$Id: lib_termcap.c,v 1.29 1999/09/05 01:06:43 tom Exp $") +MODULE_ID("$Id: lib_termcap.c,v 1.43 2002/05/25 12:24:13 tom Exp $") -/* - some of the code in here was contributed by: - Magnus Bengtsson, d6mbeng@dtek.chalmers.se -*/ +#define CSI 233 +#define ESC 033 /* ^[ */ +#define L_BRACK '[' +#define SHIFT_OUT 017 /* ^N */ -char *UP; -char *BC; +NCURSES_EXPORT_VAR(char *) UP = 0; +NCURSES_EXPORT_VAR(char *) BC = 0; + +static char *fix_me = 0; + +static char * +set_attribute_9(int flag) +{ + const char *result; + + if ((result = tparm(set_attributes, 0, 0, 0, 0, 0, 0, 0, 0, flag)) == 0) + result = ""; + return strdup(result); +} + +static int +is_csi(char *s) +{ + if (UChar(s[0]) == CSI) + return 1; + else if (s[0] == ESC && s[1] == L_BRACK) + return 2; + return 0; +} + +static char * +skip_zero(char *s) +{ + if (s[0] == '0') { + if (s[1] == ';') + s += 2; + else if (isalpha(UChar(s[1]))) + s += 1; + } + return s; +} + +static bool +similar_sgr(char *a, char *b) +{ + int csi_a = is_csi(a); + int csi_b = is_csi(b); + + if (csi_a != 0 && csi_b != 0 && csi_a == csi_b) { + a += csi_a; + b += csi_b; + if (*a != *b) { + a = skip_zero(a); + b = skip_zero(b); + } + } + return strcmp(a, b) == 0; +} /*************************************************************************** * @@ -64,29 +119,97 @@ char *BC; * ***************************************************************************/ -int tgetent(char *bufp GCC_UNUSED, const char *name) +NCURSES_EXPORT(int) +tgetent(char *bufp GCC_UNUSED, const char *name) { -int errcode; + int errcode; + + T((T_CALLED("tgetent()"))); + + setupterm((NCURSES_CONST char *) name, STDOUT_FILENO, &errcode); - T((T_CALLED("tgetent()"))); + PC = 0; + UP = 0; + BC = 0; + fix_me = 0; - setupterm((NCURSES_CONST char *)name, STDOUT_FILENO, &errcode); + if (errcode == 1) { - if (errcode == 1) { + if (cursor_left) + if ((backspaces_with_bs = !strcmp(cursor_left, "\b")) == 0) + backspace_if_not_bs = cursor_left; - if (cursor_left) - if ((backspaces_with_bs = !strcmp(cursor_left, "\b")) == 0) - backspace_if_not_bs = cursor_left; + /* we're required to export these */ + if (pad_char != NULL) + PC = pad_char[0]; + if (cursor_up != NULL) + UP = cursor_up; + if (backspace_if_not_bs != NULL) + BC = backspace_if_not_bs; - /* we're required to export these */ - if (pad_char != NULL) - PC = pad_char[0]; - if (cursor_up != NULL) - UP = cursor_up; - if (backspace_if_not_bs != NULL) - BC = backspace_if_not_bs; + /* + * While 'sgr0' is the "same" as termcap 'me', there is a compatibility + * issue. The sgr/sgr0 capabilities include setting/clearing alternate + * character set mode. A termcap application cannot use sgr, so sgr0 + * strings that reset alternate character set mode will be + * misinterpreted. Here, we remove those from the more common + * ISO/ANSI/VT100 entries, which have sgr0 agreeing with sgr. + */ + if (exit_attribute_mode != 0 + && set_attributes != 0) { + char *on = set_attribute_9(1); + char *off = set_attribute_9(0); + char *tmp; + size_t i, j, k; - (void) baudrate(); /* sets ospeed as a side-effect */ + if (similar_sgr(off, exit_attribute_mode) + && !similar_sgr(off, on)) { + TR(TRACE_DATABASE, ("adjusting sgr0 : %s", _nc_visbuf(off))); + FreeIfNeeded(fix_me); + fix_me = off; + for (i = 0; off[i] != '\0'; ++i) { + if (on[i] != off[i]) { + j = strlen(off); + k = strlen(on); + while (j != 0 + && k != 0 + && off[j - 1] == on[k - 1]) { + --j, --k; + } + while (off[j] != '\0') { + off[i++] = off[j++]; + } + off[i] = '\0'; + break; + } + } + /* SGR 10 would reset to normal font */ + if ((i = is_csi(off)) != 0 + && off[strlen(off) - 1] == 'm') { + tmp = skip_zero(off + i); + if (tmp[0] == '1' + && skip_zero(tmp + 1) != tmp + 1) { + i = tmp - off; + if (off[i - 1] == ';') + i--; + j = skip_zero(tmp + 1) - off; + while (off[j] != '\0') { + off[i++] = off[j++]; + } + off[i] = '\0'; + } + } + TR(TRACE_DATABASE, ("...adjusted me : %s", _nc_visbuf(fix_me))); + if (!strcmp(fix_me, exit_attribute_mode)) { + TR(TRACE_DATABASE, ("...same result, discard")); + free(fix_me); + fix_me = 0; + } + } + free(on); + } + + (void) baudrate(); /* sets ospeed as a side-effect */ /* LINT_PREPRO #if 0*/ @@ -94,8 +217,8 @@ int errcode; /* LINT_PREPRO #endif*/ - } - returnCode(errcode); + } + returnCode(errcode); } /*************************************************************************** @@ -107,22 +230,23 @@ int errcode; * ***************************************************************************/ -int tgetflag(NCURSES_CONST char *id) +NCURSES_EXPORT(int) +tgetflag(NCURSES_CONST char *id) { -int i; - - T((T_CALLED("tgetflag(%s)"), id)); - if (cur_term != 0) { - TERMTYPE *tp = &(cur_term->type); - for_each_boolean(i, tp) { - const char *capname = ExtBoolname(tp, i, boolcodes); - if (!strncmp(id, capname, 2)) { - /* setupterm forces invalid booleans to false */ - returnCode(tp->Booleans[i]); - } + int i; + + T((T_CALLED("tgetflag(%s)"), id)); + if (cur_term != 0) { + TERMTYPE *tp = &(cur_term->type); + for_each_boolean(i, tp) { + const char *capname = ExtBoolname(tp, i, boolcodes); + if (!strncmp(id, capname, 2)) { + /* setupterm forces invalid booleans to false */ + returnCode(tp->Booleans[i]); } } - returnCode(0); /* Solaris does this */ + } + returnCode(0); /* Solaris does this */ } /*************************************************************************** @@ -134,23 +258,24 @@ int i; * ***************************************************************************/ -int tgetnum(NCURSES_CONST char *id) +NCURSES_EXPORT(int) +tgetnum(NCURSES_CONST char *id) { -int i; - - T((T_CALLED("tgetnum(%s)"), id)); - if (cur_term != 0) { - TERMTYPE *tp = &(cur_term->type); - for_each_number(i, tp) { - const char *capname = ExtNumname(tp, i, numcodes); - if (!strncmp(id, capname, 2)) { - if (!VALID_NUMERIC(tp->Numbers[i])) - return -1; - returnCode(tp->Numbers[i]); - } + int i; + + T((T_CALLED("tgetnum(%s)"), id)); + if (cur_term != 0) { + TERMTYPE *tp = &(cur_term->type); + for_each_number(i, tp) { + const char *capname = ExtNumname(tp, i, numcodes); + if (!strncmp(id, capname, 2)) { + if (!VALID_NUMERIC(tp->Numbers[i])) + returnCode(ABSENT_NUMERIC); + returnCode(tp->Numbers[i]); } } - returnCode(ERR); + } + returnCode(ABSENT_NUMERIC); } /*************************************************************************** @@ -162,43 +287,36 @@ int i; * ***************************************************************************/ -char *tgetstr(NCURSES_CONST char *id, char **area) +NCURSES_EXPORT(char *) +tgetstr(NCURSES_CONST char *id, char **area) { -int i; - - T((T_CALLED("tgetstr(%s,%p)"), id, area)); - if (cur_term != 0) { - TERMTYPE *tp = &(cur_term->type); - for_each_string(i, tp) { - const char *capname = ExtStrname(tp, i, strcodes); - T(("trying %s", capname)); - if (!strncmp(id, capname, 2)) { - T(("found match : %s", _nc_visbuf(tp->Strings[i]))); - /* setupterm forces cancelled strings to null */ + int i; + char *result = NULL; + + T((T_CALLED("tgetstr(%s,%p)"), id, area)); + if (cur_term != 0) { + TERMTYPE *tp = &(cur_term->type); + for_each_string(i, tp) { + const char *capname = ExtStrname(tp, i, strcodes); + if (!strncmp(id, capname, 2)) { + result = tp->Strings[i]; + TR(TRACE_DATABASE, ("found match : %s", _nc_visbuf(result))); + /* setupterm forces canceled strings to null */ + if (VALID_STRING(result)) { + if (result == exit_attribute_mode + && fix_me != 0) { + result = fix_me; + TR(TRACE_DATABASE, ("altered to : %s", _nc_visbuf(result))); + } if (area != 0 - && *area != 0 - && VALID_STRING(tp->Strings[i])) { - (void) strcpy(*area, tp->Strings[i]); + && *area != 0) { + (void) strcpy(*area, result); *area += strlen(*area) + 1; } - returnPtr(tp->Strings[i]); } + break; } } - returnPtr(NULL); -} - -/* - * char * - * tgoto(string, x, y) - * - * Retained solely for upward compatibility. Note the intentional - * reversing of the last two arguments. - * - */ - -char *tgoto(const char *string, int x, int y) -{ - T((T_CALLED("tgoto(%s,%d,%d)"), string, x, y)); - returnPtr(tparm((NCURSES_CONST char *)string, y, x)); + } + returnPtr(result); }