/************************************************************************ * * * Copyright (c) 1982, Fred Fish * * All Rights Reserved * * * * This software and/or documentation is released for public * * distribution for personal, non-commercial use only. * * Limited rights to use, modify, and redistribute are hereby * * granted for non-commercial purposes, provided that all * * copyright notices remain intact and all changes are clearly * * documented. The author makes no warranty of any kind with * * respect to this product and explicitly disclaims any implied * * warranties of merchantability or fitness for any particular * * purpose. * * * ************************************************************************ */ /* Modified: * 30-Apr-86 Mic Kaczmarczik * Use ctype.h macros instead of the function isdigit(). * * 28-Jul-88 Tom Hageman * Use _tfind(), include "_termcap.h", check for octal digits * in do_esc() (depends on ASCII character coding) * March 1990 [TRH] * Adapt for FASTCAP -- string de-escaping is done by tgetent. * * (See Log at end) */ #ifdef RCS_ID static const char rcsid[] = "$Id: tgetstr.c,v 1.4 1993/04/07 01:37:42 tom Exp tom $"; #endif /* * LIBRARY FUNCTION * * tgetstr extract string capability from termcap entry * * KEY WORDS * * termcap * * SYNOPSIS * * char *tgetstr(cap, area) * const char *cap; * char **area; * * DESCRIPTION * * Gets the string capability for , placing it in * the buffer at *area, and advancing *area to point * to next available storage. * * For example, if the following capabilities are * in the termcap file: * * ZZ=zzzz * YY=yyyyyy * WW=www * * then successive calls using YY, ZZ, and WW will * build the following buffer: * * yyyyyy0zzzz0www0 * * The first call will return a pointer to yyyyyy, the * second will return a pointer to zzzz and the third * will return a pointer to www. Note that each * string is null terminated, as are all C strings. * * Characters preceded by the carot character (\136) * are mapped into the corresponding control character. * For example, the two character sequence ^A becomes * a single control-A (\001) character. * * The escape character is the normal C backslash and * the normal C escape sequences are recognized, along * with a special sequence for the ASCII escape character * (\033). The recognized sequences are: * * \E => '\033' (ASCII escape character) * \b => '\010' (ASCII backspace character) * \f => '\014' (ASCII form feed character) * \n => '\012' (ASCII newline/linefeed char) * \r => '\015' (ASCII carriage return char) * \t => '\011' (ASCII tab character) * \v => '\013' (ASCII vertical tab character) * \ddd => '\ddd' (arbitrary ASCII digit) * \x => 'x' (ordinary ASCII character) * * BUGS * * There is no overflow checking done on the destination * buffer, so it better be large enough to hold * all expected strings. * */ #include "_termcap.h" /* * PSEUDO CODE * * Begin tgetstr * Find the entry we want in the termcap entry buffer. * If found, and the entry is a string then * Initialize the transfer pointer. #if FASTCAP * Copy the string to transfer buffer. #else * While there is an input character left to process * Switch on input character * Case ESCAPE: * Decode and xfer the escaped sequence. * Break * Case CONTROLIFY: * Controlify and xfer the next character. * Advance the buffer pointer. * Break * Default: * Xfer a normal character. * End switch * End while * Null terminate the output string. #endif * Remember where the output string starts. * Update the output buffer pointer. * Return pointer to the output string. * End If * Return NULL * End tgetstr * */ char * tgetstr(cap, area) const char *cap; char **area; { register char *s; if ((s = _tcpfind(cap)) && *s++ == '=') { register char *d; register char **a = area; #if FASTCAP # if (TCP & DYNALLOC) char *where; if (a == NULL) { for (d = s; *d++; ) ; /* count chars in string. */ if ((*(a = &where) = malloc((size_t)(d - s))) == NULL) return NULL; } # endif /* (TCP & DYNALLOC) */ d = *a; while (*d++ = *s++) ; /* copy */ #else /* !FASTCAP */ char *_tdo_esc __(( char *_(out), const char *_(in) )); # if (TCP & DYNALLOC) char *where; if (a == NULL) { register int n = 0; register char *base = s; char dummy; /* first pass counts chars in the result string. */ for (d = &dummy; ++n, *s != ':' && *s != '\0'; ) { switch (*s++) { case '\\': s = _tdo_esc(d, s); break; case '^': s++; break; default: break; } } s = base; if ((*(a = &where) = malloc(n)) == NULL) return NULL; } # endif /* (TCP & DYNALLOC) */ d = *a; for (; *s != ':' && *s != '\0'; d++) { switch (*d = *s++) { case '\\': s = _tdo_esc(d, s); break; case '^': *d = *s++ & 037; break; default: break; } } *d++ = '\0'; #endif /* FASTCAP */ s = *a, *a = d; return s; } return NULL; } #if ! FASTCAP /* * INTERNAL FUNCTION * * _tdo_esc process an escaped sequence * * SYNOPSIS * * char *_tdo_esc (out,in); * char *out; * const char *in; * * DESCRIPTION * * Processes an escape sequence pointed to by * in, transfering it to location pointed to * by out, and updating the pointer to in. * */ /* * PSEUDO CODE * * Begin _tdo_esc * If the first character is a digit then * Set value to zero. * For up to 3 digits * Accumulate the sum. * End for * Transfer the sum. * Else * Scan remap list for character * If character in remap list then * Transfer the remapped character. * Else * Simply transfer the character. * End if * End if * Return updated input pointer. * End do_esc * */ #define isoctal(c) ('0' <= (c) && (c) < '8') char * _tdo_esc(out,in) char *out; register const char *in; { register char ch = *in++; if (isoctal(ch)) { register int count = 3; ch &= 7; while (isoctal(*in) && --count) ch = (ch << 3) + (*in++ & 7); } else { register char *s = "E\33e\33b\bf\fn\nr\rt\tv\va\7s "; do { if (*s++ == ch) { ch = *s; break; } } while (*s++); } *out = ch; return(in); } #endif /* ! FASTCAP */ /*======================================================================* * $Log: tgetstr.c,v $ * Revision 1.4 1993/04/07 01:37:42 tom * (do_esc): add \e, \s; fix typo in RCS Log. * *======================================================================*/