?? output.c
字號:
/*** Copyright (C) 1991, 1997 Free Software Foundation, Inc.** ** This file is part of TACK.** ** TACK is free software; you can redistribute it and/or modify** it under the terms of the GNU General Public License as published by** the Free Software Foundation; either version 2, or (at your option)** any later version.** ** TACK is distributed in the hope that it will be useful,** but WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the** GNU General Public License for more details.** ** You should have received a copy of the GNU General Public License** along with TACK; see the file COPYING. If not, write to** the Free Software Foundation, Inc., 59 Temple Place - Suite 330,** Boston, MA 02111-1307, USA.*//* screen formatting and I/O utility functions */#include <tack.h>#include <time.h>MODULE_ID("$Id: output.c,v 1.8 2003/10/25 20:43:43 tom Exp $")/* globals */long char_sent; /* number of characters sent */int char_count; /* counts characters */int line_count; /* counts line feeds */int expand_chars; /* length of expand() string */int replace_mode; /* used to output replace mode padding */int can_go_home; /* TRUE if we can fashion a home command */int can_clear_screen; /* TRUE if we can somehow clear the screen */int raw_characters_sent; /* Total output characters */int log_count; /* Number of characters on a log line *//* translate mode default strings */#define TM_carriage_return TM_string[0].value#define TM_cursor_down TM_string[1].value#define TM_scroll_forward TM_string[2].value#define TM_newline TM_string[3].value#define TM_cursor_left TM_string[4].value#define TM_bell TM_string[5].value#define TM_form_feed TM_string[6].value#define TM_tab TM_string[7].valuestruct default_string_list TM_string[TM_last] = { {"cr", "\r", 0}, {"cud1", "\n", 0}, {"ind", "\n", 0}, {"nel", "\r\n", 0}, {"cub1", "\b", 0}, {"bel", "\007", 0}, {"ff", "\f", 0}, {"ht", "\t", 0}};static const char *c0[32] = { "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL", "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI", "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB", "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US"};static const char *c1[32] = { "", "", "", "", "IND", "NEL", "SSA", "ESA", "HTS", "HTJ", "VTS", "PLD", "PLU", "RI", "SS2", "SS3", "DCS", "PU1", "PU2", "STS", "CCH", "MW", "SPA", "EPA", "", "", "", "CSI", "ST", "OSC", "PM", "APC"};intgetnext(int mask){ /* get the next character without scan mode conversion */ int ch; unsigned char buf; tc_putp(req_for_input); fflush(stdout); if (nodelay_read) while (1) { ch = read(fileno(stdin), &buf, 1); if (ch == -1) return EOF; if (ch == 1) return buf; } ch = getchar(); if (ch == EOF) return EOF; return ch & mask;}intgetchp(int mask){ /* read a character with scan mode conversion */ if (scan_mode) { tc_putp(req_for_input); fflush(stdout); return scan_key(); } else return getnext(mask);}/*** tc_putch(c)**** Output one character*/inttc_putch(int c){ char_sent++; raw_characters_sent++; putchar(c); if ((raw_characters_sent & 31) == 31) { fflush(stdout); } if (log_fp) { /* terminal output logging */ c = UChar(c); if (c < 32) { fprintf(log_fp, "<%s>", c0[c]); log_count += 5; } else if (c < 127) { fprintf(log_fp, "%c", c); log_count += 1; } else { fprintf(log_fp, "<%02x>", c); log_count += 4; } if (c == '\n' || log_count >= 80) { fprintf(log_fp, "\n"); log_count = 0; } } return (c);}/*** tt_tputs(string, reps)**** Output a string with tputs() translation.** Use this function inside timing tests.*/voidtt_tputs(const char *string, int reps){ int i; if (string) { for (i = 0; i < TT_MAX; i++) { if (i >= ttp) { tt_cap[i] = string; tt_affected[i] = reps; tt_count[i] = 1; tt_delay[i] = msec_cost(string, reps); ttp++; break; } if (string == tt_cap[i] && reps == tt_affected[i]) { tt_count[i]++; tt_delay_used += tt_delay[i]; break; } } (void) tputs(string, reps, tc_putch); }}/*** tt_putp(string)**** Output a string with tputs() translation.** Use this function inside timing tests.*/voidtt_putp(const char *string){ tt_tputs(string, 1);}/*** tt_putparm(string, reps, arg1, arg2)**** Send tt_tputs(tparm(string, args1, arg2), reps)** Use this function inside timing tests.*/voidtt_putparm( NCURSES_CONST char *string, int reps, int arg1, int arg2){ int i; if (string) { for (i = 0; i < TT_MAX; i++) { if (i >= ttp) { tt_cap[i] = string; tt_affected[i] = reps; tt_count[i] = 1; tt_delay[i] = msec_cost(string, reps); ttp++; break; } if (string == tt_cap[i] && reps == tt_affected[i]) { tt_count[i]++; tt_delay_used += tt_delay[i]; break; } } (void) tputs(tparm((NCURSES_CONST char *)string, arg1, arg2), reps, tc_putch); }}/*** tc_putp(string)**** Output a string with tputs() translation.** Use this function instead of putp() so we can track** the actual number of characters sent.*/inttc_putp(const char *string){ return tputs(string, 1, tc_putch);}voidput_this(int c){ /* output one character (with padding) */ tc_putch(c); if (char_padding && replace_mode) tt_putp(char_padding);}voidput_cr(void){ if (translate_mode && carriage_return) { tt_putp(carriage_return); } else { tt_putp(TM_carriage_return); } char_count = 0;}voidput_lf(void){ /* send a linefeed (only works in RAW or CBREAK mode) */ if (translate_mode && cursor_down) { tt_putp(cursor_down); } else { tt_putp(TM_cursor_down); } line_count++;}voidput_ind(void){ /* scroll forward (only works in RAW or CBREAK mode) */ if (translate_mode && scroll_forward) { tt_putp(scroll_forward); } else { tt_putp(TM_scroll_forward); } line_count++;}/*** put_crlf()**** Send (nel) or <cr> <lf>*/voidput_crlf(void){ if (translate_mode && newline) { tt_putp(newline); } else { tt_putp(TM_newline); } char_count = 0; line_count++;}/*** put_new_lines(count)**** Send a number of newlines. (nel)*/voidput_newlines(int n){ while (n-- > 0) { put_crlf(); }}/*** putchp(character)**** Send one character to the terminal.** This function does translation of control characters.*/voidputchp(int c){ switch (c) { case '\b': if (translate_mode && cursor_left) { tt_putp(cursor_left); } else { tt_putp(TM_cursor_left); } char_count--; break; case 7: if (translate_mode && bell) { tt_putp(bell); } else { tt_putp(TM_bell); } break; case '\f': if (translate_mode && form_feed) { tt_putp(form_feed); } else { tt_putp(TM_form_feed); } char_count = 0; line_count++; break; case '\n': put_crlf(); break; case '\r': put_cr(); break; case '\t': if (translate_mode && tab) { tt_putp(tab); } else { tt_putp(TM_tab); } char_count = ((char_count / 8) + 1) * 8; break; default: put_this(c); char_count++; break; }}voidput_str(const char *s){ /* send the string to the terminal */ for (; *s; putchp(*s++));}voidputln(const char *s){ /* output a string followed by a CR LF */ for (; *s; putchp(*s++)); put_crlf();}voidput_columns(const char *s, int len, int w){ /* put out s in column format */ int l; if (char_count + w > columns) { put_crlf(); } l = char_count % w; if (l) { while (l < w) { putchp(' '); l++; } } if (char_count && char_count + len >= columns) { put_crlf(); } l = char_count; put_str(s); char_count = l + len;}/*** ptext(string)**** Output a string but do not assume the terminal will wrap to a** new line. Break the line at a word boundary then send a CR LF.** This is more esthetic on 40 column terminals.*/voidptext(const char *s){ const char *t; while (*s) { for (t = s + 1; *t > ' '; t++); if ((char_count != 0) && ((t - s) + char_count >= columns)) { put_crlf(); while (*s == ' ') s++; } while (s < t) { putchp(*s++); } }}voidput_dec(char *f, int i){ /* print a line with a decimal number in it */ char tm[128]; sprintf(tm, f, i / 10, i % 10); ptext(tm);}voidthree_digit(char *tx, int i){ /* convert the decimal number to a string of at least 3 digits */ if (i < 1000) sprintf(tx, "%d.%d", i / 10, i % 10); else sprintf(tx, "%d", i / 10);}voidptextln(const char *s){ /* print the text using ptext() then add a CR LF */ ptext(s); put_crlf();}static voidexpand_one(int ch, char **v){ /* expand one character */ char *t = *v; if (ch & 0x80) { /* dump it in octal (yuck) */ *t++ = '\\'; *t++ = '0' + ((ch >> 6) & 3); *t++ = '0' + ((ch >> 3) & 7); *t++ = '0' + (ch & 7); expand_chars += 4; } else if (ch == 127) { /* DEL */ *t++ = '^'; *t++ = '?'; expand_chars += 2; } else if (ch >= ' ') { *t++ = ch; expand_chars++; } else { /* control characters */ *t++ = '^'; *t++ = ch + '@'; expand_chars += 2; } *v = t;}char *expand(const char *s){ /* convert the string to printable form */ static char buf[4096]; char *t, *v; int ch; if (magic_cookie_glitch <= 0 && exit_attribute_mode) { v = enter_reverse_mode; } else { v = NULL; } expand_chars = 0; t = buf; if (s) { for (; (ch = *s); s++) { if ((ch & 0x80) && v) { /* print it in reverse video mode */ strcpy(t, liberated(tparm(v))); for (; *t; t++); expand_one(ch & 0x7f, &t); strcpy(t, liberated(tparm(exit_attribute_mode))); for (; *t; t++); } else { expand_one(ch, &t); } } } *t = '\0'; return buf;}char *print_expand(char *s){ /* convert the string to 7-bit printable form */ static char buf[4096]; char *t; int ch; expand_chars = 0; t = buf; if (s) { for (; (ch = *s); s++) { expand_one(ch, &t); } } *t = '\0'; return buf;}char *expand_to(char *s, int l){ /* expand s to length l */ char *t; for (s = t = expand(s); *t; t++); for (; expand_chars < l; expand_chars++) { *t++ = ' '; } *t = '\0'; return s;}char *hex_expand_to(char *s, int l){ /* expand s to length l in hex */ static char buf[4096]; char *t; for (t = buf; *s; s++) { sprintf(t, "%02X ", UChar(*s)); t += 3; if (t - buf > (int) sizeof(buf) - 4) { break; } } for (; t - buf < l;) { *t++ = ' '; } *t = '\0'; expand_chars = t - buf; return buf;}char *expand_command(const char *c){ /* expand an ANSI escape sequence */ static char buf[256]; int i, j, ch; char *s; s = buf; for (i = FALSE; (ch = UChar(*c)) != 0; c++) { if (i) { *s++ = ' '; } i = TRUE; if (ch < 32) { j = UChar(c[1]); if (ch == '\033' && j >= '@' && j <= '_') { ch = j - '@'; c++; for (j = 0; (*s = c1[ch][j++]); s++); } else for (j = 0; (*s = c0[ch][j++]); s++); } else { *s++ = ch; j = UChar(c[1]); if (ch >= '0' && ch <= '9' && j >= '0' && j <= '9') { i = FALSE; } } } *s = '\0'; return buf;}/*** go_home()**** Move the cursor to the home position*/voidgo_home(void){ int i; if (cursor_home) tt_putp(cursor_home); else if (cursor_address) tt_putparm(cursor_address, lines, 0, 0); else if (row_address) { /* use (vpa) */ put_cr(); tt_putparm(row_address, 1, 0, 0); } else if (cursor_up && cursor_to_ll) { tt_putp(cursor_to_ll); for (i = 1; i < lines; i++) { tt_putp(cursor_up); } } else { can_go_home = FALSE; return; } char_count = line_count = 0; can_go_home = TRUE;}voidhome_down(void){ /* move the cursor to the lower left hand corner */ int i; if (cursor_to_ll) tt_putp(cursor_to_ll); else if (cursor_address) tt_putparm(cursor_address, lines, lines - 1, 0); else if (row_address) { /* use (vpa) */ put_cr(); tt_putparm(row_address, 1, lines - 1, 0); } else if (cursor_down && cursor_home) { tt_putp(cursor_home); for (i = 1; i < lines; i++) tt_putp(cursor_down); } else return; char_count = 0; line_count = lines - 1;}voidput_clear(void){ /* clear the screen */ int i; if (clear_screen) tt_tputs(clear_screen, lines); else if (clr_eos && can_go_home) { go_home(); tt_tputs(clr_eos, lines); } else if (scroll_forward && !over_strike && (can_go_home || cursor_up)) { /* clear the screen by scrolling */ put_cr(); if (cursor_to_ll) { tt_putp(cursor_to_ll); } else if (cursor_address) { tt_putparm(cursor_address, lines, lines - 1, 0); } else if (row_address) { tt_putparm(row_address, 1, lines - 1, 0); } else { for (i = 1; i < lines; i++) { tt_putp(scroll_forward); } } for (i = 1; i < lines; i++) { tt_putp(scroll_forward); } if (can_go_home) { go_home(); } else { for (i = 1; i < lines; i++) { tt_putp(cursor_up); } } } else { can_clear_screen = FALSE; return; } char_count = line_count = 0; can_clear_screen = TRUE;}/*** wait_here()**** read one character from the input stream** If the terminal is not in RAW mode then this function will** wait for a <cr> or <lf>.*/intwait_here(void){ char ch, cc[64]; char message[16]; int i, j; for (i = 0; i < (int) sizeof(cc); i++) { cc[i] = ch = getchp(STRIP_PARITY); if (ch == '\r' || ch == '\n') { put_crlf(); char_sent = 0; return cc[i ? i - 1 : 0]; } if (ch >= ' ') { if (stty_query(TTY_CHAR_MODE)) { put_crlf(); char_sent = 0; return ch; } continue; } if (ch == 023) { /* Control S */ /* ignore control S, but tell me about it */ while (ch == 023 || ch == 021) { ch = getchp(STRIP_PARITY); if (i < (int) sizeof(cc)) cc[++i] = ch; } put_str("\nThe terminal sent a ^S -"); for (j = 0; j <= i; j++) { sprintf(message, " %02X", cc[j] & 0xFF); put_str(message); } put_crlf(); i = -1; } else if (ch != 021) { /* Not Control Q */ /* could be abort character */ spin_flush(); if (tty_can_sync == SYNC_TESTED) { (void) tty_sync_error(); } else { put_str("\n? "); } } } return '?';}/*** read_string(buffer, length)**** Read a string of characters from the input stream.*/voidread_string( char *buf, int length){ int ch, i; for (i = 0; i < length - 1; ) { ch = getchp(STRIP_PARITY); if (ch == '\r' || ch == '\n') { break; } if (ch == '\b' || ch == 127) { if (i) { putchp('\b'); putchp(' '); putchp('\b'); i--; } } else { buf[i++] = ch; putchp(ch); } } buf[i] = '\0'; put_crlf(); char_sent = 0;}/*** maybe_wait(lines)**** wait if near the end of the screen, then clear screen*/void maybe_wait(int n){ if (line_count + n >= lines) { if (char_sent != 0) { ptext("Go? "); (void) wait_here(); } put_clear(); } else { put_crlf(); }}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -