pc-hack

PC HACK 3.61 source code (archival)
git clone http://frotz.net/git/pc-hack.git
Log | Files | Refs

tgetstr.c (6266B)


      1 /************************************************************************
      2  *									*
      3  *			Copyright (c) 1982, Fred Fish			*
      4  *			    All Rights Reserved				*
      5  *									*
      6  *	This software and/or documentation is released for public	*
      7  *	distribution for personal, non-commercial use only.		*
      8  *	Limited rights to use, modify, and redistribute are hereby	*
      9  *	granted for non-commercial purposes, provided that all		*
     10  *	copyright notices remain intact and all changes are clearly	*
     11  *	documented.  The author makes no warranty of any kind with	*
     12  *	respect to this product and explicitly disclaims any implied	*
     13  *	warranties of merchantability or fitness for any particular	*
     14  *	purpose.							*
     15  *									*
     16  ************************************************************************
     17  */
     18 
     19 
     20 /*
     21  *  LIBRARY FUNCTION
     22  *
     23  *	tgetstr   extract string capability from termcap entry
     24  *
     25  *  KEY WORDS
     26  *
     27  *	termcap
     28  *
     29  *  SYNOPSIS
     30  *
     31  *	char *tgetstr(id,area)
     32  *	char *id;
     33  *	char **area;
     34  *
     35  *  DESCRIPTION
     36  *
     37  *	Gets the string capability for <id>, placing it in
     38  *	the buffer at *area, and advancing *area to point
     39  *	to next available storage.
     40  *
     41  *	For example, if the following capabilities are
     42  *	in the termcap file:
     43  *
     44  *		ZZ=zzzz
     45  *		YY=yyyyyy
     46  *		WW=www
     47  *
     48  *	then successive calls using YY, ZZ, and WW will
     49  *	build the following buffer:
     50  *
     51  *		yyyyyy0zzzz0www0
     52  *
     53  *	The first call will return a pointer to yyyyyy, the
     54  *	second will return a pointer to zzzz and the third
     55  *	will return a pointer to www.  Note that each
     56  *	string is null terminated, as are all C strings.
     57  *
     58  *	Characters preceded by the carot character (\136)
     59  *	are mapped into the corresponding control character.
     60  *	For example, the two character sequence ^A becomes
     61  *	a single control-A (\001) character.
     62  *
     63  *	The escape character is the normal C backslash and
     64  *	the normal C escape sequences are recognized, along
     65  *	with a special sequence for the ASCII escape character
     66  *	(\033).  The recognized sequences are:
     67  *
     68  *		\E   =>  '\033'  (ASCII escape character)
     69  *		\b   =>  '\010'  (ASCII backspace character)
     70  *		\f   =>  '\014'  (ASCII form feed character)
     71  *		\n   =>  '\012'  (ASCII newline/linefeed char)
     72  *		\r   =>  '\015'  (ASCII carriage return char)
     73  *		\t   =>  '\011'  (ASCII tab character)
     74  *		\ddd =>  '\ddd'  (arbitrary ASCII digit)
     75  *		\x   =>  'x'     (ordinary ASCII character)
     76  *
     77  */
     78 
     79 #include <stdio.h>
     80 # ifdef MSDOS
     81 # define index strchr
     82 # endif
     83 
     84 extern char *_tcpbuf;		/* Termcap entry buffer pointer */
     85 
     86 /*
     87  *  PSEUDO CODE
     88  *
     89  *	Begin tgetstr
     90  *	    Initialize pointer to the termcap entry buffer.
     91  *	    While there is a field to process
     92  *		Skip over the field separator character.
     93  *		If this is the entry we want then
     94  *		    If the entry is not a string then
     95  *			Return NULL.
     96  *		    Else
     97  *			Transfer string and rtn pointer.
     98  *		    End if
     99  *		End if
    100  *	    End while
    101  *	    Return NULL
    102  *	End tgetstr
    103  *
    104  */
    105 
    106 char *tgetstr(id,area)
    107 char *id;
    108 char **area;
    109 {
    110     char *bp;
    111     extern char *index();
    112     char *decode();
    113 
    114     bp = _tcpbuf;
    115     while ((bp = index(bp,':')) != NULL) {
    116 	bp++;
    117 	if (*bp++ == id[0] && *bp != NULL && *bp++ == id[1]) {
    118 	    if (*bp != NULL && *bp++ != '=') {
    119 		return(NULL);
    120 	    } else {
    121 		return(decode(bp,area));
    122 	    }
    123 	}
    124     }
    125     return(NULL);
    126 }
    127 
    128 /*
    129  *  INTERNAL FUNCTION
    130  *
    131  *	decode   transfer string capability, decoding escapes
    132  *
    133  *  SYNOPSIS
    134  *
    135  *	static char *decode(bp,area)
    136  *	char *bp;
    137  *	char **area;
    138  *
    139  *  DESCRIPTION
    140  *
    141  *	Transfers the string capability, up to the next ':'
    142  *	character, or null, to the buffer pointed to by
    143  *	the pointer in *area.  Note that the initial
    144  *	value of *area and *area is updated to point
    145  *	to the next available location after the null
    146  *	terminating the transfered string.
    147  *
    148  *  BUGS
    149  *
    150  *	There is no overflow checking done on the destination
    151  *	buffer, so it better be large enough to hold
    152  *	all expected strings.
    153  *
    154  */
    155 
    156 /*
    157  *  PSEUDO CODE
    158  *
    159  *	Begin decode
    160  *	    Initialize the transfer pointer.
    161  *	    While there is an input character left to process
    162  *		Switch on input character
    163  *		Case ESCAPE:
    164  *		    Decode and xfer the escaped sequence.
    165  *		    Break
    166  *		Case CONTROLIFY:
    167  *		    Controlify and xfer the next character.
    168  *		    Advance the buffer pointer.
    169  *		    Break
    170  *		Default:
    171  *		    Xfer a normal character.
    172  *		End switch
    173  *	    End while
    174  *	    Null terminate the output string.
    175  *	    Remember where the output string starts.
    176  *	    Update the output buffer pointer.
    177  *	    Return pointer to the output string.
    178  *	End decode
    179  *
    180  */
    181 
    182 static char *decode(bp,area)
    183 char *bp;
    184 char **area;
    185 {
    186     char *cp, *bgn;
    187     char *do_esc();
    188 
    189     cp = *area;
    190     while (*bp != NULL && *bp != ':') {
    191 	switch(*bp) {
    192 	case '\\':
    193 	    bp = do_esc(cp++,++bp);
    194 	    break;
    195 	case '^':
    196 	    *cp++ = *++bp & 037;
    197 	    bp++;
    198 	    break;
    199 	default:
    200 	    *cp++ = *bp++;
    201 	    break;
    202 	}
    203     }
    204     *cp++ = NULL;
    205     bgn = *area;
    206     *area = cp;
    207     return(bgn);
    208 }
    209 
    210 /*
    211  *  INTERNAL FUNCTION
    212  *
    213  *	do_esc    process an escaped sequence
    214  *
    215  *  SYNOPSIS
    216  *
    217  *	char *do_esc(out,in);
    218  *	char *out;
    219  *	char *in;
    220  *
    221  *  DESCRIPTION
    222  *
    223  *	Processes an escape sequence pointed to by
    224  *	in, transfering it to location pointed to
    225  *	by out, and updating the pointer to in.
    226  *
    227  */
    228 
    229 /*
    230  *  PSEUDO CODE
    231  *
    232  *	Begin do_esc
    233  *	    If the first character is not a NULL then
    234  *		If is a digit then
    235  *		    Set value to zero.
    236  *		    For up to 3 digits
    237  *		        Accumulate the sum.
    238  *		    End for
    239  *		    Transfer the sum.
    240  *	        Else if character is in remap list then
    241  *		    Transfer the remapped character.
    242  *		    Advance the input pointer once.
    243  *	        Else
    244  *		    Simply transfer the character.
    245  *	        End if
    246  *	    End if
    247  *	    Return updated input pointer.
    248  *	End do_esc
    249  *
    250  */
    251 
    252 static char *maplist = {
    253     "E\033b\bf\fn\nr\rt\t"
    254 };
    255 
    256 char *do_esc(out,in)
    257 char *out;
    258 char *in;
    259 {
    260     int count;
    261     char ch;
    262     char *cp;
    263     extern int isdigit();
    264 
    265     if (*in != NULL) {
    266 	if (isdigit(*in)) {
    267 	    ch = 0;
    268 	    for (count = 0; count < 3 && isdigit(*in); in++) {
    269 		 ch <<= 3;
    270 		 ch |= (*in - '0');
    271 	    }
    272 	    *out++ = ch;
    273 	} else if ((cp = index(maplist,*in)) != NULL) {
    274 	    *out++ = *++cp;
    275 	    in++;
    276 	} else {
    277 	    *out++ = *in++;
    278 	}
    279     }
    280     return(in);
    281 }