termlib.c
资源名称:vim53src.zip [点击查看]
上传用户:gddssl
上传日期:2007-01-06
资源大小:1003k
文件大小:14k
源码类别:
编辑器/阅读器
开发平台:
DOS
- /* vi:set ts=8 sts=4 sw=4: */
- /*
- * The following software is (C) 1984 Peter da Silva, the Mad Australian, in
- * the public domain. It may be re-distributed for any purpose with the
- * inclusion of this notice.
- */
- /* Modified by Bram Moolenaar for use with VIM - Vi Improved. */
- /* A few bugs removed by Olaf 'Rhialto' Seibert. */
- /* TERMLIB: Terminal independant database. */
- #include "vim.h"
- #include "termlib.pro"
- #if !defined(AMIGA) && !defined(VMS) && !defined(macintosh) && !defined(RISCOS)
- # include <sgtty.h>
- #endif
- static int getent __ARGS((char *, char *, FILE *, int));
- static int nextent __ARGS((char *, FILE *, int));
- static int _match __ARGS((char *, char *));
- static char *_addfmt __ARGS((char *, char *, int));
- static char *_find __ARGS((char *, char *));
- /*
- * Global variables for termlib
- */
- char *tent; /* Pointer to terminal entry, set by tgetent */
- char PC = 0; /* Pad character, default NULL */
- char *UP = 0, *BC = 0; /* Pointers to UP and BC strings from database */
- short ospeed; /* Baud rate (1-16, 1=300, 16=19200), as in stty */
- /*
- * Module: tgetent
- *
- * Purpose: Get termcap entry for <term> into buffer at <tbuf>.
- *
- * Calling conventions: char tbuf[TBUFSZ+], term=canonical name for terminal.
- *
- * Returned values: 1 = success, -1 = can't open file,
- * 0 = can't find terminal.
- *
- * Notes:
- * - Should probably supply static buffer.
- * - Uses environment variables "TERM" and "TERMCAP". If TERM = term (that is,
- * if the argument matches the environment) then it looks at TERMCAP.
- * - If TERMCAP begins with a slash, then it assumes this is the file to
- * search rather than /etc/termcap.
- * - If TERMCAP does not begin with a slash, and it matches TERM, then this is
- * used as the entry.
- * - This could be simplified considerably for non-UNIX systems.
- */
- #ifndef TERMCAPFILE
- # ifdef AMIGA
- # define TERMCAPFILE "s:termcap"
- # else
- # define TERMCAPFILE "/etc/termcap"
- # endif
- #endif
- tgetent(tbuf, term)
- char *tbuf; /* Buffer to hold termcap entry, TBUFSZ bytes max */
- char *term; /* Name of terminal */
- {
- char tcbuf[32]; /* Temp buffer to handle */
- char *tcptr = tcbuf; /* extended entries */
- char *tcap = TERMCAPFILE; /* Default termcap file */
- char *tmp;
- FILE *termcap;
- int retval = 0;
- int len;
- if ((tmp = (char *)mch_getenv((char_u *)"TERMCAP")) != NULL)
- {
- if (*tmp == '/') /* TERMCAP = name of termcap file */
- {
- tcap = tmp ;
- #if defined(AMIGA)
- /* Convert /usr/share/lib/termcap to usr:share/lib/termcap */
- tcap++;
- tmp = strchr(tcap, '/');
- if (tmp)
- *tmp = ':';
- #endif
- }
- else /* TERMCAP = termcap entry itself */
- {
- int tlen = strlen(term);
- while (*tmp && *tmp != ':') /* Check if TERM matches */
- {
- char *nexttmp;
- while (*tmp == '|')
- tmp++;
- nexttmp = _find(tmp, ":|"); /* Rhialto */
- if (tmp+tlen == nexttmp && _match(tmp, term) == tlen)
- {
- strcpy(tbuf, tmp);
- tent = tbuf;
- return 1;
- }
- else
- tmp = nexttmp;
- }
- }
- }
- if (!(termcap = fopen(tcap, "r")))
- {
- strcpy(tbuf, tcap);
- return -1;
- }
- len = 0;
- while (getent(tbuf + len, term, termcap, TBUFSZ - len))
- {
- tcptr = tcbuf; /* Rhialto */
- if ((term = tgetstr("tc", &tcptr))) /* extended entry */
- {
- rewind(termcap);
- len = strlen(tbuf);
- }
- else
- {
- retval = 1;
- tent = tbuf; /* reset it back to the beginning */
- break;
- }
- }
- fclose(termcap);
- return retval;
- }
- static int
- getent(tbuf, term, termcap, buflen)
- char *tbuf, *term;
- FILE *termcap;
- int buflen;
- {
- char *tptr;
- int tlen = strlen(term);
- while (nextent(tbuf, termcap, buflen)) /* For each possible entry */
- {
- tptr = tbuf;
- while (*tptr && *tptr != ':') /* : terminates name field */
- {
- char *nexttptr;
- while (*tptr == '|') /* | seperates names */
- tptr++;
- nexttptr = _find(tptr, ":|"); /* Rhialto */
- if (tptr + tlen == nexttptr &&
- _match(tptr, term) == tlen) /* FOUND! */
- {
- tent = tbuf;
- return 1;
- }
- else /* Look for next name */
- tptr = nexttptr;
- }
- }
- return 0;
- }
- static int
- nextent(tbuf, termcap, buflen) /* Read 1 entry from TERMCAP file */
- char *tbuf;
- FILE *termcap;
- int buflen;
- {
- char *lbuf = tbuf; /* lbuf=line buffer */
- /* read lines straight into buffer */
- while (lbuf < tbuf+buflen && /* There's room and */
- fgets(lbuf, (int)(tbuf+buflen-lbuf), termcap)) /* another line */
- {
- int llen = strlen(lbuf);
- if (*lbuf == '#') /* eat comments */
- continue;
- if (lbuf[-1] == ':' && /* and whitespace */
- lbuf[0] == 't' &&
- lbuf[1] == ':')
- {
- strcpy(lbuf, lbuf+2);
- llen -= 2;
- }
- if (lbuf[llen-2] == '\') /* and continuations */
- lbuf += llen-2;
- else
- {
- lbuf[llen-1]=0; /* no continuation, return */
- return 1;
- }
- }
- return 0; /* ran into end of file */
- }
- /*
- * Module: tgetflag
- *
- * Purpose: returns flag true or false as to the existence of a given entry.
- * used with 'bs', 'am', etc...
- *
- * Calling conventions: id is the 2 character capability id.
- *
- * Returned values: 1 for success, 0 for failure.
- */
- tgetflag(id)
- char *id;
- {
- char buf[256], *ptr = buf;
- return tgetstr(id, &ptr) ? 1 : 0;
- }
- /*
- * Module: tgetnum
- *
- * Purpose: get numeric value such as 'li' or 'co' from termcap.
- *
- * Calling conventions: id = 2 character id.
- *
- * Returned values: -1 for failure, else numerical value.
- */
- tgetnum(id)
- char *id;
- {
- char *ptr, buf[256];
- ptr = buf;
- if (tgetstr(id, &ptr))
- return atoi(buf);
- else
- return 0;
- }
- /*
- * Module: tgetstr
- *
- * Purpose: get terminal capability string from database.
- *
- * Calling conventions: id is the two character capability id.
- * (*buf) points into a hold buffer for the
- * id. the capability is copied into the buffer
- * and (*buf) is advanced to point to the next
- * free byte in the buffer.
- *
- * Returned values: 0 = no such entry, otherwise returns original
- * (*buf) (now a pointer to the string).
- *
- * Notes
- * It also decodes certain escape sequences in the buffer.
- * they should be obvious from the code:
- * E = escape.
- * n, r, t, f, b match the 'c' escapes.
- * ^x matches control-x (^@...^_).
- * nnn matches nnn octal.
- * x, where x is anything else, matches x. I differ
- * from the standard library here, in that I allow ^: to match
- * :.
- *
- */
- char *
- tgetstr(id, buf)
- char *id, **buf;
- {
- int len = strlen(id);
- char *tmp=tent;
- char *hold;
- int i;
- do {
- tmp = _find(tmp, ":"); /* For each field */
- while (*tmp == ':') /* skip empty fields */
- tmp++;
- if (!*tmp)
- break;
- if (_match(id, tmp) == len) {
- tmp += len; /* find '=' '@' or '#' */
- if (*tmp == '@') /* :xx@: entry for tc */
- return 0; /* deleted entry */
- hold= *buf;
- while (*++tmp && *tmp != ':') { /* not at end of field */
- switch(*tmp) {
- case '\': /* Expand escapes here */
- switch(*++tmp) {
- case 0: /* ignore backslashes */
- tmp--; /* at end of entry */
- break; /* shouldn't happen */
- case 'e':
- case 'E': /* ESC */
- *(*buf)++ = ' 33';
- break;
- case 'n': /* n */
- *(*buf)++ = 'n';
- break;
- case 'r': /* r */
- *(*buf)++ = 'r';
- break;
- case 't': /* t */
- *(*buf)++ = 't';
- break;
- case 'b': /* b */
- *(*buf)++ = 'b';
- break;
- case 'f': /* f */
- *(*buf)++ = 'f';
- break;
- case '0': /* nnn */
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- **buf = 0;
- /* get up to three digits */
- for (i = 0; i < 3 && isdigit(*tmp); ++i)
- **buf = **buf * 8 + *tmp++ - '0';
- (*buf)++;
- tmp--;
- break;
- default: /* x, for all other x */
- *(*buf)++= *tmp;
- }
- break;
- case '^': /* control characters */
- *(*buf)++ = *++tmp - '@';
- break;
- default:
- *(*buf)++ = *tmp;
- }
- }
- *(*buf)++ = 0;
- return hold;
- }
- } while (*tmp);
- return 0;
- }
- /*
- * Module: tgoto
- *
- * Purpose: decode cm cursor motion string.
- *
- * Calling conventions: cm is cursor motion string. line, col, are the
- * desired destination.
- *
- * Returned values: a string pointing to the decoded string, or "OOPS" if it
- * cannot be decoded.
- *
- * Notes
- * The accepted escapes are:
- * %d as in printf, 0 origin.
- * %2, %3 like %02d, %03d in printf.
- * %. like %c
- * %+x adds <x> to value, then %.
- * %>xy if value>x, adds y. No output.
- * %i increments line& col, no output.
- * %r reverses order of line&col. No output.
- * %% prints as a single %.
- * %n exclusive or row & col with 0140.
- * %B BCD, no output.
- * %D reverse coding (x-2*(x%16)), no output.
- */
- char *
- tgoto(cm, col, line)
- char *cm; /* cm string, from termcap */
- int col, /* column, x position */
- line; /* line, y position */
- {
- char gx, gy, /* x, y */
- *ptr, /* pointer in 'cm' */
- reverse = 0, /* reverse flag */
- *bufp, /* pointer in returned string */
- addup = 0, /* add upline */
- addbak = 0, /* add backup */
- c;
- static char buffer[32];
- if (!cm)
- return "OOPS"; /* Kludge, but standard */
- bufp = buffer;
- ptr = cm;
- while (*ptr) {
- if ((c = *ptr++) != '%') { /* normal char */
- *bufp++ = c;
- } else { /* % escape */
- switch(c = *ptr++) {
- case 'd': /* decimal */
- bufp = _addfmt(bufp, "%d", line);
- line = col;
- break;
- case '2': /* 2 digit decimal */
- bufp = _addfmt(bufp, "%02d", line);
- line = col;
- break;
- case '3': /* 3 digit decimal */
- bufp = _addfmt(bufp, "%03d", line);
- line = col;
- break;
- case '>': /* %>xy: if >x, add y */
- gx = *ptr++;
- gy = *ptr++;
- if (col>gx) col += gy;
- if (line>gx) line += gy;
- break;
- case '+': /* %+c: add c */
- line += *ptr++;
- case '.': /* print x/y */
- if (line == 't' || /* these are */
- line == 'n' || /* chars that */
- line == ' 04' || /* UNIX hates */
- line == ' ') {
- line++; /* so go to next pos */
- if (reverse == (line == col))
- addup=1; /* and mark UP */
- else
- addbak=1; /* or BC */
- }
- *bufp++=line;
- line = col;
- break;
- case 'r': /* r: reverse */
- gx = line;
- line = col;
- col = gx;
- reverse = 1;
- break;
- case 'i': /* increment (1-origin screen) */
- col++;
- line++;
- break;
- case '%': /* %%=% literally */
- *bufp++='%';
- break;
- case 'n': /* magic DM2500 code */
- line ^= 0140;
- col ^= 0140;
- break;
- case 'B': /* bcd encoding */
- line = line/10<<4+line%10;
- col = col/10<<4+col%10;
- break;
- case 'D': /* magic Delta Data code */
- line = line-2*(line&15);
- col = col-2*(col&15);
- break;
- default: /* Unknown escape */
- return "OOPS";
- }
- }
- }
- if (addup) /* add upline */
- if (UP) {
- ptr=UP;
- while (isdigit(*ptr) || *ptr == '.')
- ptr++;
- if (*ptr == '*')
- ptr++;
- while (*ptr)
- *bufp++ = *ptr++;
- }
- if (addbak) /* add backspace */
- if (BC) {
- ptr=BC;
- while (isdigit(*ptr) || *ptr == '.')
- ptr++;
- if (*ptr == '*')
- ptr++;
- while (*ptr)
- *bufp++ = *ptr++;
- }
- else
- *bufp++='b';
- *bufp = 0;
- return(buffer);
- }
- /*
- * Module: tputs
- *
- * Purpose: decode padding information
- *
- * Calling conventions: cp = string to be padded, affcnt = # of items affected
- * (lines, characters, whatever), outc = routine to output 1 character.
- *
- * Returned values: none
- *
- * Notes
- * cp has padding information ahead of it, in the form
- * nnnTEXT or nnn*TEXT. nnn is the number of milliseconds to delay,
- * and may be a decimal (nnn.mmm). If the asterisk is given, then
- * the delay is multiplied by afcnt. The delay is produced by outputting
- * a number of nulls (or other padding char) after printing the
- * TEXT.
- *
- */
- long _bauds[16]={
- 0, 50, 75, 110,
- 134, 150, 200, 300,
- 600, 1200, 1800, 2400,
- 4800, 9600, 19200, 19200 };
- tputs(cp, affcnt, outc)
- char *cp; /* string to print */
- int affcnt; /* Number of lines affected */
- void (*outc) __ARGS((unsigned int));/* routine to output 1 character */
- {
- long frac, /* 10^(#digits after decimal point) */
- counter, /* digits */
- atol __ARGS((const char *));
- if (isdigit(*cp)) {
- counter = 0;
- frac = 1000;
- while (isdigit(*cp))
- counter = counter * 10L + (long)(*cp++ - '0');
- if (*cp == '.')
- while (isdigit(*++cp)) {
- counter = counter * 10L + (long)(*cp++ - '0');
- frac = frac * 10;
- }
- if (*cp!='*') { /* multiply by affected lines */
- if (affcnt>1) affcnt = 1;
- }
- else
- cp++;
- /* Calculate number of characters for padding counter/frac ms delay */
- if (ospeed)
- counter = (counter * _bauds[ospeed] * (long)affcnt) / frac;
- while (*cp) /* output string */
- (*outc)(*cp++);
- if (ospeed)
- while (counter--) /* followed by pad characters */
- (*outc)(PC);
- }
- else
- while (*cp)
- (*outc)(*cp++);
- return 0;
- }
- /*
- * Module: tutil.c
- *
- * Purpose: Utility routines for TERMLIB functions.
- *
- */
- static int
- _match(s1, s2) /* returns length of text common to s1 and s2 */
- char *s1, *s2;
- {
- int i = 0;
- while (s1[i] && s1[i] == s2[i])
- i++;
- return i;
- }
- /*
- * finds next c in s that's a member of set, returns pointer
- */
- static char *
- _find(s, set)
- char *s, *set;
- {
- for(; *s; s++)
- {
- char *ptr = set;
- while (*ptr && *s != *ptr)
- ptr++;
- if (*ptr)
- return s;
- }
- return s;
- }
- /*
- * add val to buf according to format fmt
- */
- static char *
- _addfmt(buf, fmt, val)
- char *buf, *fmt;
- int val;
- {
- sprintf(buf, fmt, val);
- while (*buf)
- buf++;
- return buf;
- }