home *** CD-ROM | disk | FTP | other *** search
- /* TERMLIB: Terminal independant database.
- *
- * 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.
- */
- #include <stdio.h>
- #include <ctype.h>
- #include "termlib.h"
-
- /* tgoto.c (libtermlib.a)
- *
- */
-
- char *
- tgoto(cm, col, line)
- char *cm; /* cm string, from termcap */
- int col, /* column, x position */
- line; /* line, y position */
- {
- char *_addfmt(),
- 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=='\004' || /* UNIX hates */
- line=='\0') {
- 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);
- }
-