X-Git-Url: https://ncurses.scripts.mit.edu/?a=blobdiff_plain;f=ncurses%2Ftinfo%2Flib_termcap.c;h=d03488cf1c3ccc2bc69fd8cd6a8bed847bd2e51b;hb=a8987e73ec254703634802b4f7ee30d3a485524d;hp=ecec2865fbae7359fd07015dddeddd3ebe143396;hpb=c633e5103a29a38532cf1925257b91cea33fd090;p=ncurses.git diff --git a/ncurses/tinfo/lib_termcap.c b/ncurses/tinfo/lib_termcap.c index ecec2865..d03488cf 100644 --- a/ncurses/tinfo/lib_termcap.c +++ b/ncurses/tinfo/lib_termcap.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998,1999,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2002,2003 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.37 2000/09/16 20:30:16 tom Exp $") +MODULE_ID("$Id: lib_termcap.c,v 1.44 2003/05/24 21:10:28 tom Exp $") + +#define CSI 233 +#define ESC 033 /* ^[ */ +#define L_BRACK '[' +#define SHIFT_OUT 017 /* ^N */ -/* - some of the code in here was contributed by: - Magnus Bengtsson, d6mbeng@dtek.chalmers.se -*/ +NCURSES_EXPORT_VAR(char *) UP = 0; +NCURSES_EXPORT_VAR(char *) BC = 0; -char *UP = 0; -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,7 +119,7 @@ char *BC = 0; * ***************************************************************************/ -int +NCURSES_EXPORT(int) tgetent(char *bufp GCC_UNUSED, const char *name) { int errcode; @@ -73,6 +128,11 @@ tgetent(char *bufp GCC_UNUSED, const char *name) setupterm((NCURSES_CONST char *) name, STDOUT_FILENO, &errcode); + PC = 0; + UP = 0; + BC = 0; + fix_me = 0; + if (errcode == 1) { if (cursor_left) @@ -87,6 +147,68 @@ tgetent(char *bufp GCC_UNUSED, const char *name) 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; + + 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 @@ -108,10 +230,10 @@ tgetent(char *bufp GCC_UNUSED, const char *name) * ***************************************************************************/ -int +NCURSES_EXPORT(int) tgetflag(NCURSES_CONST char *id) { - int i; + unsigned i; T((T_CALLED("tgetflag(%s)"), id)); if (cur_term != 0) { @@ -136,10 +258,10 @@ tgetflag(NCURSES_CONST char *id) * ***************************************************************************/ -int +NCURSES_EXPORT(int) tgetnum(NCURSES_CONST char *id) { - int i; + unsigned i; T((T_CALLED("tgetnum(%s)"), id)); if (cur_term != 0) { @@ -165,10 +287,11 @@ tgetnum(NCURSES_CONST char *id) * ***************************************************************************/ -char * +NCURSES_EXPORT(char *) tgetstr(NCURSES_CONST char *id, char **area) { - int i; + unsigned i; + char *result = NULL; T((T_CALLED("tgetstr(%s,%p)"), id, area)); if (cur_term != 0) { @@ -176,17 +299,24 @@ tgetstr(NCURSES_CONST char *id, char **area) for_each_string(i, tp) { const char *capname = ExtStrname(tp, i, strcodes); if (!strncmp(id, capname, 2)) { - TR(TRACE_DATABASE,("found match : %s", _nc_visbuf(tp->Strings[i]))); + result = tp->Strings[i]; + TR(TRACE_DATABASE, ("found match : %s", _nc_visbuf(result))); /* setupterm forces canceled strings to null */ - if (area != 0 - && *area != 0 - && VALID_STRING(tp->Strings[i])) { - (void) strcpy(*area, tp->Strings[i]); - *area += strlen(*area) + 1; + 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) { + (void) strcpy(*area, result); + *area += strlen(*area) + 1; + } } - returnPtr(tp->Strings[i]); + break; } } } - returnPtr(NULL); + returnPtr(result); }