/* * 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 #include #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