267 lines
4.5 KiB
C
267 lines
4.5 KiB
C
/*
|
|
* tputs.c
|
|
*
|
|
* By Ross Ridge
|
|
* Public Domain
|
|
* 92/06/04 11:41:15
|
|
*
|
|
* Output a terminal capability string with any needed padding
|
|
*
|
|
*/
|
|
|
|
#include "defs.h"
|
|
#include <term.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#ifdef USE_SCCS_IDS
|
|
static const char SCCSid[] = "@(#) mytinfo tputs.c 3.3 92/06/04 public domain, By Ross Ridge";
|
|
#endif
|
|
|
|
#ifdef TEST
|
|
#define def_prog_mode() (OK)
|
|
#define _norm_output() ((void)(0))
|
|
#define _lit_output() (1)
|
|
#endif
|
|
|
|
/*
|
|
* BITSPERCHAR (as actually transmitted over a serial line) is usually 10
|
|
* (not 8). 1 stop bit, 1 start bit, 7 data bits, and one parity bit.
|
|
*/
|
|
|
|
#define BITSPERCHAR 10
|
|
|
|
#ifdef USE_FAKE_STDIO
|
|
#undef putchar
|
|
#endif
|
|
|
|
#ifdef USE_PROTOTYPES
|
|
#define PUTCHAR(c) (outc == (int (*)(int)) NULL ? (putchar(c)):(*outc)(c))
|
|
#else
|
|
#define PUTCHAR(c) (outc == (int (*)()) NULL ? (putchar(c)):(*outc)(c))
|
|
#endif
|
|
|
|
int
|
|
tputs(sp, count, outc)
|
|
register const char *sp;
|
|
int count;
|
|
#ifdef USE_PROTOTYPES
|
|
register int (*outc)(int);
|
|
#else
|
|
register int (*outc)();
|
|
#endif
|
|
{
|
|
register int l;
|
|
register long cnt;
|
|
int must_pad, multiply_pad;
|
|
int forced_lit = 0;
|
|
|
|
/* some programmes expect this behaviour from tputs */
|
|
if (sp == NULL) {
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "tputs: NULL\n");
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
if (cur_term->termcap) {
|
|
_figure_termcap();
|
|
}
|
|
|
|
while(*sp != '\0') {
|
|
switch(*sp) {
|
|
case '\\':
|
|
switch(*++sp) {
|
|
case 'n': PUTCHAR('\n'); sp++; break;
|
|
case 'b': PUTCHAR('\b'); sp++; break;
|
|
case 't': PUTCHAR('\t'); sp++; break;
|
|
case 'r': PUTCHAR('\r'); sp++; break;
|
|
case 'f': PUTCHAR('\f'); sp++; break;
|
|
case 'l': PUTCHAR('\012'); sp++; break;
|
|
case 's': PUTCHAR(' '); sp++; break;
|
|
case 'e': case 'E': PUTCHAR('\033'); sp++; break;
|
|
|
|
case '^':
|
|
case '\\':
|
|
case ',':
|
|
case ':':
|
|
case '\'':
|
|
case '$':
|
|
PUTCHAR(*sp++);
|
|
break;
|
|
|
|
case '0':
|
|
if (*(sp + 1) < '0' || *(sp + 1) > '7') {
|
|
PUTCHAR('\200'); /* I'd prefer \0 */
|
|
sp++;
|
|
break;
|
|
}
|
|
;/* FALLTHROUGH */
|
|
case '1': case '2': case '3': case '4':
|
|
case '5': case '6': case '7':
|
|
l = *sp++ - '0';
|
|
if (*sp >= '0' && *sp <= '7') {
|
|
l = l * 8 + (*sp++ - '0');
|
|
if (*sp >= '0' && *sp <= '7')
|
|
l = l * 8 + (*sp++ - '0');
|
|
}
|
|
PUTCHAR(l);
|
|
break;
|
|
|
|
case '\0':
|
|
PUTCHAR('\\');
|
|
break;
|
|
|
|
case '@':
|
|
if (!forced_lit)
|
|
forced_lit = _lit_output();
|
|
sp++;
|
|
break;
|
|
|
|
default:
|
|
PUTCHAR('\\');
|
|
PUTCHAR(*sp++);
|
|
break;
|
|
}
|
|
break;
|
|
case '^':
|
|
if (*++sp == '\0')
|
|
break;
|
|
l = *sp - '@';
|
|
if (l > 31)
|
|
l -= 32;
|
|
if (l < 0 || l > 31) {
|
|
PUTCHAR('^');
|
|
PUTCHAR(*sp++);
|
|
} else {
|
|
PUTCHAR(l);
|
|
sp++;
|
|
}
|
|
break;
|
|
case '$':
|
|
if (*++sp != '<') {
|
|
PUTCHAR('$');
|
|
break;
|
|
}
|
|
must_pad = 0;
|
|
multiply_pad = 0;
|
|
l = 0;
|
|
sp++;
|
|
while (isdigit(*sp))
|
|
l = l * 10 + (*sp++ - '0');
|
|
l *= 10;
|
|
if (*sp == '.') {
|
|
sp++;
|
|
if (isdigit(*sp))
|
|
l += *sp++ - '0';
|
|
}
|
|
if (*sp == '/') {
|
|
must_pad = 1;
|
|
if (*++sp == '*') {
|
|
multiply_pad = 1;
|
|
sp++;
|
|
}
|
|
} else if (*sp == '*') {
|
|
multiply_pad = 1;
|
|
if (*++sp == '/') {
|
|
must_pad = 1;
|
|
sp++;
|
|
}
|
|
}
|
|
if (*sp != '>') {
|
|
PUTCHAR('p');
|
|
PUTCHAR('a');
|
|
PUTCHAR('d');
|
|
PUTCHAR('?');
|
|
break;
|
|
}
|
|
sp++;
|
|
#ifdef TEST
|
|
printf("\nl = %d", l);
|
|
#endif
|
|
if (cur_term->pad || must_pad) {
|
|
cnt = ((long) l * cur_term->baudrate
|
|
* (multiply_pad ? count : 1)
|
|
+ (10000L * BITSPERCHAR / 2L))
|
|
/ (10000L * BITSPERCHAR);
|
|
#ifdef TEST
|
|
printf("; cnt = %ld\n", cnt);
|
|
#endif
|
|
while(cnt--)
|
|
PUTCHAR(cur_term->padch);
|
|
}
|
|
#ifdef TEST
|
|
printf("\n");
|
|
#endif
|
|
break;
|
|
default:
|
|
PUTCHAR(*sp++);
|
|
}
|
|
}
|
|
if (forced_lit)
|
|
_norm_output();
|
|
return OK;
|
|
}
|
|
|
|
int
|
|
putp(str)
|
|
char *str; {
|
|
#ifdef USE_PROTOTYPES
|
|
return(tputs(str, 1,(int (*)(int)) NULL));
|
|
#else
|
|
return(tputs(str, 1,(int (*)()) NULL));
|
|
#endif
|
|
}
|
|
|
|
#ifdef TEST
|
|
|
|
TERMINAL test_term, *cur_term = &test_term;
|
|
|
|
int
|
|
#ifdef USE_PROTOTYPES
|
|
putch(char c)
|
|
#else
|
|
putch(c)
|
|
char c;
|
|
#endif
|
|
{
|
|
if (c & 0x80) {
|
|
printf("\\%03o", c);
|
|
} else if (c < 32) {
|
|
printf("^%c", c + '@');
|
|
} else if (c == 127) {
|
|
printf("^?");
|
|
} else {
|
|
putchar(c);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
char line[MAX_LINE];
|
|
|
|
int
|
|
main(argc, argv)
|
|
int argc;
|
|
char **argv; {
|
|
test_term.termcap = 0;
|
|
test_term.baudrate = 1200;
|
|
test_term.pad = 0;
|
|
test_term.padch = 0;
|
|
if (argc > 1)
|
|
test_term.baudrate = atoi(argv[1]);
|
|
if (argc > 2)
|
|
test_term.padch = argv[2][0];
|
|
if (argc > 3)
|
|
test_term.pad = 1;
|
|
|
|
putchar('\n');
|
|
|
|
while(fgets(line, sizeof(line), stdin) != NULL) {
|
|
line[strlen(line)-1] = '\0';
|
|
tputs(line, 7, putch);
|
|
putchar('\n');
|
|
}
|
|
return 0;
|
|
}
|
|
#endif
|