X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/8fde62c18c3e90bdea3cac671877f30ee9fcfa81..e8fee30c4f5ca621344982e771ea51445c09b2c8:/src/termcap.c diff --git a/src/termcap.c b/src/termcap.c index 9462122677..2ad31d7b96 100644 --- a/src/termcap.c +++ b/src/termcap.c @@ -1,5 +1,6 @@ /* Work-alike for termcap, plus extra features. - Copyright (C) 1985, 1986, 1993, 1994 Free Software Foundation, Inc. + Copyright (C) 1985, 1986, 1993, 1994, 1995, 2000, 2001, 2002, 2003, + 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -13,25 +14,28 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. */ /* Emacs config.h may rename various library functions such as malloc. */ #ifdef HAVE_CONFIG_H - #include +#endif + +#ifdef emacs +#include /* xmalloc is here */ /* Get the O_* definitions for open et al. */ #include -#ifdef USG5 +#ifdef HAVE_FCNTL_H #include #endif - -#else /* not HAVE_CONFIG_H */ - -#if defined(HAVE_STRING_H) || defined(STDC_HEADERS) -#define bcopy(s, d, n) memcpy ((d), (s), (n)) +#ifdef HAVE_UNISTD_H +#include #endif +#else /* not emacs */ + #ifdef STDC_HEADERS #include #include @@ -41,14 +45,19 @@ char *malloc (); char *realloc (); #endif +/* Do this after the include, in case string.h prototypes bcopy. */ +#if (defined(HAVE_STRING_H) || defined(STDC_HEADERS)) && !defined(bcopy) +#define bcopy(s, d, n) memcpy ((d), (s), (n)) +#endif + #ifdef HAVE_UNISTD_H #include #endif -#ifdef _POSIX_VERSION +#ifdef HAVE_FCNTL_H #include #endif -#endif /* not HAVE_CONFIG_H */ +#endif /* not emacs */ #ifndef NULL #define NULL (char *) 0 @@ -75,8 +84,8 @@ int bufsize = 128; #endif #endif -#ifndef TERMCAP_NAME -#define TERMCAP_NAME "/etc/termcap" +#ifndef TERMCAP_FILE +#define TERMCAP_FILE "/etc/termcap" #endif #ifndef emacs @@ -169,6 +178,17 @@ tgetstr (cap, area) return tgetst1 (ptr, area); } +#ifdef IS_EBCDIC_HOST +/* Table, indexed by a character in range 0200 to 0300 with 0200 subtracted, + gives meaning of character following \, or a space if no special meaning. + Sixteen characters per line within the string. */ + +static char esctab[] + = " \057\026 \047\014 \ + \025 \015 \ + \005 \013 \ + "; +#else /* Table, indexed by a character in range 0100 to 0140 with 0100 subtracted, gives meaning of character following \, or a space if no special meaning. Eight characters per line within the string. */ @@ -178,6 +198,7 @@ static char esctab[] \012 \ \015 \011 \013 \ "; +#endif /* PTR points to a string value inside a termcap entry. Copy that value, processing \ and ^ abbreviations, @@ -219,7 +240,13 @@ tgetst1 (ptr, area) while ((c = *p++) && c != ':' && c != '\n') { if (c == '^') - c = *p++ & 037; + { + c = *p++; + if (c == '?') + c = 0177; + else + c &= 037; + } else if (c == '\\') { c = *p++; @@ -235,15 +262,70 @@ tgetst1 (ptr, area) p++; } } +#ifdef IS_EBCDIC_HOST + else if (c >= 0200 && c < 0360) + { + c1 = esctab[(c & ~0100) - 0200]; + if (c1 != ' ') + c = c1; + } +#else else if (c >= 0100 && c < 0200) { c1 = esctab[(c & ~040) - 0100]; if (c1 != ' ') c = c1; } +#endif } *r++ = c; } + + /* Sometimes entries have "%pN" which means use parameter N in the + next %-substitution. If all such N are continuous in the range + [1,9] we can remove each "%pN" because they are redundant, thus + reducing bandwidth requirements. True, Emacs is well beyond the + days of 150baud teletypes, but some of its users aren't much so. + + This pass could probably be integrated into the one above but + abbreviation expansion makes that effort a little more hairy than + its worth; this is cleaner. */ + { + register int last_p_param = 0; + int remove_p_params = 1; + struct { char *beg; int len; } cut[11]; + + for (cut[0].beg = p = ret; p < r - 3; p++) + { + if (!remove_p_params) + break; + if (*p == '%' && *(p + 1) == 'p') + { + if (*(p + 2) - '0' == 1 + last_p_param) + { + cut[last_p_param].len = p - cut[last_p_param].beg; + last_p_param++; + p += 3; + cut[last_p_param].beg = p; + } + else /* not continuous: bail */ + remove_p_params = 0; + if (last_p_param > 10) /* too many: bail */ + remove_p_params = 0; + } + } + if (remove_p_params && last_p_param) + { + register int i; + char *wp; + + cut[last_p_param].len = r - cut[last_p_param].beg; + for (i = 0, wp = ret; i <= last_p_param; wp += cut[i++].len) + bcopy (cut[i].beg, wp, cut[i].len); + r = wp; + } + } + *r = '\0'; /* Update *AREA. */ if (area) @@ -253,25 +335,26 @@ tgetst1 (ptr, area) /* Outputting a string with padding. */ +#ifndef emacs short ospeed; /* If OSPEED is 0, we use this as the actual baud rate. */ int tputs_baud_rate; +#endif + char PC; +#ifndef emacs /* Actual baud rate if positive; - baud rate / 100 if negative. */ -static short speeds[] = +static int speeds[] = { -#ifdef VMS - 0, 50, 75, 110, 134, 150, -3, -6, -12, -18, - -20, -24, -36, -48, -72, -96, -192 -#else /* not VMS */ 0, 50, 75, 110, 135, 150, -2, -3, -6, -12, - -18, -24, -48, -96, -192, -384 -#endif /* not VMS */ + -18, -24, -48, -96, -192, -288, -384, -576, -1152 }; +#endif /* not emacs */ + void tputs (str, nlines, outfun) register char *str; @@ -282,8 +365,12 @@ tputs (str, nlines, outfun) register int speed; #ifdef emacs - extern baud_rate; + extern EMACS_INT baud_rate; speed = baud_rate; + /* For quite high speeds, convert to the smaller + units to avoid overflow. */ + if (speed > 10000) + speed = - speed / 100; #else if (ospeed == 0) speed = tputs_baud_rate; @@ -312,11 +399,14 @@ tputs (str, nlines, outfun) while (*str) (*outfun) (*str++); - /* padcount is now in units of tenths of msec. */ - padcount *= speeds[ospeed]; + /* PADCOUNT is now in units of tenths of msec. + SPEED is measured in characters per 10 seconds + or in characters per .1 seconds (if negative). + We use the smaller units for larger speeds to avoid overflow. */ + padcount *= speed; padcount += 500; padcount /= 1000; - if (speeds[ospeed] < 0) + if (speed < 0) padcount = -padcount; else { @@ -330,7 +420,7 @@ tputs (str, nlines, outfun) /* Finding the termcap entry in the termcap data base. */ -struct buffer +struct termcap_buffer { char *beg; int size; @@ -346,33 +436,6 @@ static char *gobble_line (); static int compare_contin (); static int name_match (); -#ifdef VMS - -#include -#include -#include - -static int -valid_filename_p (fn) - char *fn; -{ - struct FAB fab = cc$rms_fab; - struct NAM nam = cc$rms_nam; - char esa[NAM$C_MAXRSS]; - - fab.fab$l_fna = fn; - fab.fab$b_fns = strlen(fn); - fab.fab$l_nam = &nam; - fab.fab$l_fop = FAB$M_NAM; - - nam.nam$l_esa = esa; - nam.nam$b_ess = sizeof esa; - - return SYS$PARSE(&fab, 0, 0) == RMS$_NORMAL; -} - -#else /* !VMS */ - #ifdef MSDOS /* MW, May 1993 */ static int valid_filename_p (fn) @@ -384,8 +447,6 @@ valid_filename_p (fn) #define valid_filename_p(fn) (*(fn) == '/') #endif -#endif /* !VMS */ - /* Find the termcap entry data for terminal type NAME and store it in the block that BP points to. Record its address for future use. @@ -403,13 +464,13 @@ tgetent (bp, name) { register char *termcap_name; register int fd; - struct buffer buf; + struct termcap_buffer buf; register char *bp1; - char *bp2; + char *tc_search_point; char *term; int malloc_size = 0; register int c; - char *tcenv; /* TERMCAP value, if it contains :tc=. */ + char *tcenv = NULL; /* TERMCAP value, if it contains :tc=. */ char *indirect = NULL; /* Terminal type in :tc= in TERMCAP value. */ int filep; @@ -429,6 +490,11 @@ tgetent (bp, name) } #endif /* INTERNAL_TERMINAL */ + /* For compatibility with programs like `less' that want to + put data in the termcap buffer themselves as a fallback. */ + if (bp) + term_entry = bp; + termcap_name = getenv ("TERMCAP"); if (termcap_name && *termcap_name == '\0') termcap_name = NULL; @@ -466,7 +532,7 @@ tgetent (bp, name) } if (!termcap_name || !filep) - termcap_name = TERMCAP_NAME; + termcap_name = TERMCAP_FILE; /* Here we know we must search a file and termcap_name has its name. */ @@ -488,7 +554,7 @@ tgetent (bp, name) malloc_size = indirect ? strlen (tcenv) + 1 : buf.size; bp = (char *) xmalloc (malloc_size); } - bp1 = bp; + tc_search_point = bp1 = bp; if (indirect) /* Copy the data from the environment variable. */ @@ -516,14 +582,13 @@ tgetent (bp, name) /* If BP is malloc'd by us, make sure it is big enough. */ if (malloc_size) { - malloc_size = bp1 - bp + buf.size; - termcap_name = (char *) xrealloc (bp, malloc_size); - bp1 += termcap_name - bp; - bp = termcap_name; + int offset1 = bp1 - bp, offset2 = tc_search_point - bp; + malloc_size = offset1 + buf.size; + bp = termcap_name = (char *) xrealloc (bp, malloc_size); + bp1 = termcap_name + offset1; + tc_search_point = termcap_name + offset2; } - bp2 = bp1; - /* Copy the line of the entry from buf into bp. */ termcap_name = buf.ptr; while ((*bp1++ = c = *termcap_name++) && c != '\n') @@ -537,7 +602,8 @@ tgetent (bp, name) /* Does this entry refer to another terminal type's entry? If something is found, copy it into heap and null-terminate it. */ - term = tgetst1 (find_capability (bp2, "tc"), (char **) 0); + tc_search_point = find_capability (tc_search_point, "tc"); + term = tgetst1 (tc_search_point, (char **) 0); } close (fd); @@ -548,8 +614,6 @@ tgetent (bp, name) ret: term_entry = bp; - if (malloc_size) - return (int) bp; return 1; } @@ -563,7 +627,7 @@ static int scan_file (str, fd, bufp) char *str; int fd; - register struct buffer *bufp; + register struct termcap_buffer *bufp; { register char *end; @@ -659,7 +723,7 @@ compare_contin (str1, str2) static char * gobble_line (fd, bufp, append_end) int fd; - register struct buffer *bufp; + register struct termcap_buffer *bufp; char *append_end; { register char *end; @@ -761,3 +825,5 @@ tprint (cap) #endif /* TEST */ +/* arch-tag: c2e8d427-2271-4fac-95fe-411857238b80 + (do not change this comment) */