From: Ken Hornstein Date: Fri, 3 Jan 2014 04:59:57 +0000 (-0500) Subject: Convert all of the terminal functions over to terminfo(5) instead of X-Git-Url: https://diplodocus.org/git/nmh/commitdiff_plain/20ce29e738d1a15764197559d256a85ef89d85d7?ds=sidebyside;hp=ba7796abbe501657d955f1ad64238f8c57f2f26f Convert all of the terminal functions over to terminfo(5) instead of the older termcap. Move the terminal-specific code from fmt_compile.c to terminal.c, so it is all in one place. --- diff --git a/h/prototypes.h b/h/prototypes.h index d56ef30c..0c583109 100644 --- a/h/prototypes.h +++ b/h/prototypes.h @@ -113,6 +113,24 @@ char *get_charset(void); char *getcpy (const char *); char *get_default_editor(void); char *getfolder(int); + +/* + * Get a string from the terminfo database for the current terminal. + * + * Retrieve the specified terminfo capability and return a string that + * can be output to the terminal. The string returned has already been + * processed by tputs(), so it is safe to output directly. The return + * value of this function is valid until the next call. + * + * Arguments: + * + * capability - The name of a terminfo capability (see terminfo(5)). + * + * Returns a tputs-processed string, or NULL if terminal initialization failed + * or the capability wasn't found. + */ +char *get_term_stringcap(char *capability); + /* * Lock open/close routines. * @@ -154,6 +172,11 @@ char *m_mktemp2(const char *, const char *, int *, FILE **); void m_unknown(m_getfld_state_t *, FILE *); int makedir (char *); char *message_id (time_t, int); + +/* + * Clear the screen, using the appropriate entry from the terminfo database + */ +void nmh_clear_screen(void); char *nmh_getpass(const char *); char *norm_charmap(char *); char *new_fs (char *, char *, char *); @@ -280,7 +303,6 @@ char *SystemName(void); int annotate (char *, char *, char *, int, int, int, int); void annolist(char *, char *, char *, int); void annopreserve(int); -void clear_screen(void); void m_pclose(void); int make_intermediates(char *); int mhl(int, char **); diff --git a/sbr/fmt_compile.c b/sbr/fmt_compile.c index c4476f8d..7392c8c6 100644 --- a/sbr/fmt_compile.c +++ b/sbr/fmt_compile.c @@ -49,9 +49,6 @@ #include #include -#include -#include - #ifdef HAVE_SYS_TIME_H # include #endif @@ -69,10 +66,6 @@ static struct comp *cm; /* most recent comp ref */ static struct ftable *ftbl; /* most recent func ref */ static int ncomp; static int infunction; /* function nesting cnt */ -static int termstatus = 0; /* 0=uninit,1=ok,-1=fail */ -static char *termcbuf = NULL; /* Capability output str */ -static char *termcbufp = NULL; /* Capability buf ptr */ -static size_t termcbufsz = 0; /* Size of termcbuf */ extern struct mailname fmt_mnull; @@ -91,7 +84,8 @@ extern struct mailname fmt_mnull; #define TF_LMBOX 11 /* special - get full local mailbox */ #define TF_BOLD 12 /* special - enter terminal bold mode */ #define TF_UNDERLN 13 /* special - enter underline mode */ -#define TF_RESET 14 /* special - reset terminal modes */ +#define TF_STNDOUT 14 /* special - enter underline mode */ +#define TF_RESET 15 /* special - reset terminal modes */ /* ftable->flags */ /* NB that TFL_PUTS is also used to decide whether the test @@ -227,6 +221,7 @@ static struct ftable functable[] = { { "bold", TF_BOLD, FT_LS_LIT, 0, TFL_PUTS }, { "underline", TF_UNDERLN,FT_LS_LIT, 0, TFL_PUTS }, + { "standout", TF_STNDOUT,FT_LS_LIT, 0, TFL_PUTS }, { "resetterm", TF_RESET, FT_LS_LIT, 0, TFL_PUTS }, { NULL, 0, 0, 0, 0 } @@ -302,9 +297,6 @@ static char *do_loop(char *); static char *do_if(char *); static void free_component(struct comp *); static void free_comptable(void); -static void initialize_terminfo(void); -static void get_term_stringcap(struct ftable *, char *); -static int termbytes(int); /* * Lookup a function name in the functable @@ -649,15 +641,19 @@ do_func(char *sp) break; case TF_BOLD: - get_term_stringcap(t, "bold"); + LS(t->f_type, get_term_stringcap("bold")); break; case TF_UNDERLN: - get_term_stringcap(t, "smul"); + LS(t->f_type, get_term_stringcap("smul")); + break; + + case TF_STNDOUT: + LS(t->f_type, get_term_stringcap("smso")); break; case TF_RESET: - get_term_stringcap(t, "sgr0"); + LS(t->f_type, get_term_stringcap("sgr0")); break; case TF_NOW: @@ -1063,102 +1059,3 @@ free_component(struct comp *cm) free(cm); } } - -/* - * These functions handles the case of outputting terminal strings depending - * on the terminfo setting. - */ - -/* - * We should only be called if we haven't yet called setupterm() - */ - -void -initialize_terminfo(void) -{ - int errret, rc; - - rc = setupterm(NULL, fileno(stdout), &errret); - - if (rc != 0 || errret != 1) - termstatus = -1; - else - termstatus = 1; -} - -/* - * Place the results of the specified string entry into the str register. - * - * Arguments are: - * - * t - Pointer to instruction table entry (used to create fmt instruction) - * cap - Name of terminfo capability to insert (e.g., "bold", or "sgr0"). - * - * This ended up being more complicated than I hoped. You need to fetch the - * entry via tigetstr(), but there MAY be a padding format embedded in what - * gets returned by tigetstr(), so you have to run it through tputs(). - * And of course tputs() is designed to output to a terminal, so you have - * capture every byte output by the tputs() callback to get the final - * string to write to the format engine. - * - * If padding bytes are NULs that will be a problem for us, but some quick - * experimentation suggests that padding bytes are mostly a non-issue anymore. - * If they still crop up we'll have to figure out how to deal with them. - */ - -void -get_term_stringcap(struct ftable *t, char *cap) -{ - char *parm; - - /* - * Common to all functions; initialize the termcap if we need it. - * If it didn't initialize successfully, return silently - */ - - if (termstatus == 0) - initialize_terminfo(); - - termcbufp = termcbuf; - - if (termstatus == -1) - goto out; - - parm = tigetstr(cap); - - if (parm == (char *) -1 || parm == NULL) { - goto out; - } - - tputs(parm, 1, termbytes); - -out: - termcbufp = '\0'; - - LS(t->f_type, termcbuf); -} - -/* - * Store a sequence of characters in our local buffer - */ - -static int -termbytes(int c) -{ - size_t offset; - - /* - * Bump up the buffer size if we've reached the end (leave room for - * a trailing NUL) - */ - - if ((offset = termcbufp - termcbuf) - 1 >= termcbufsz) { - termcbufsz += 64; - termcbuf = mh_xrealloc(termcbuf, termcbufsz); - termcbufp = termcbuf + offset; - } - - *termcbufp++ = c; - - return 0; -} diff --git a/sbr/terminal.c b/sbr/terminal.c index 9ab81e0d..7226a88f 100644 --- a/sbr/terminal.c +++ b/sbr/terminal.c @@ -8,8 +8,10 @@ */ #include +#include #include +#include /* It might be better to tie this to the termcap_curses_order in configure.ac. It would be fine to check for ncurses/termcap.h @@ -19,70 +21,58 @@ #elif defined (HAVE_NCURSES_TERMCAP_H) # include #endif +#include #ifdef WINSIZE_IN_PTEM # include # include #endif -#if BUFSIZ<2048 -# define TXTSIZ 2048 -#else -# define TXTSIZ BUFSIZ -#endif - static int initLI = 0; static int initCO = 0; -static int LI = 40; /* number of lines */ -static int CO = 80; /* number of colums */ -static char *CL = NULL; /* termcap string to clear screen */ -static char *SE = NULL; /* termcap string to end standout mode */ -static char *SO = NULL; /* termcap string to begin standout mode */ +static int LI = 40; /* number of lines */ +static int CO = 80; /* number of colums */ +static char *clear = NULL; /* terminfo string to clear screen */ +static char *standend = NULL; /* terminfo string to end standout mode */ +static char *standbegin = NULL; /* terminfo string to begin standout mode */ +static int termstatus = 0; /* terminfo initialization status */ +static char *termcbuf = NULL; /* tputs() output buffer */ +static char *termcbufp = NULL; /* tputs() output buffer pointer */ +static size_t termcbufsz = 0; /* Size of termcbuf */ -static char termcap[TXTSIZ]; +static void initialize_terminfo(void); +static int termbytes(int); +/* + * Initialize the terminfo library. + */ static void -read_termcap(void) +initialize_terminfo(void) { - char *cp; - char *term; + int errret, rc; -#ifndef TGETENT_ACCEPTS_NULL - char termbuf[TXTSIZ]; -#endif + if (termstatus) + return; - static int inited = 0; + rc = setupterm(NULL, fileno(stdout), &errret); - if (inited++) - return; - - if (!(term = getenv ("TERM"))) - return; - -/* - * If possible, we let tgetent allocate its own termcap buffer - */ -#ifdef TGETENT_ACCEPTS_NULL - if (tgetent (NULL, term) != TGETENT_SUCCESS) + if (rc != 0 || errret != 1) { + termstatus = -1; return; -#else - if (tgetent (termbuf, term) != TGETENT_SUCCESS) - return; -#endif + } else { + termstatus = 1; + } - if (!initCO && (CO = tgetnum ("co")) <= 0) + if (!initCO && (CO = tigetnum ("cols")) <= 0) CO = 80; - if (!initLI && (LI = tgetnum ("li")) <= 0) + if (!initLI && (LI = tigetnum ("lines")) <= 0) LI = 24; - cp = termcap; - CL = tgetstr ("cl", &cp); - if (tgetnum ("sg") <= 0) { - SE = tgetstr ("se", &cp); - SO = tgetstr ("so", &cp); - } + clear = tigetstr ("clear"); + standbegin = tigetstr ("smso"); + standend = tigetstr ("rmso"); } @@ -99,7 +89,7 @@ sc_width (void) initCO++; } else #endif /* TIOCGWINSZ */ - read_termcap(); + initialize_terminfo(); return CO; } @@ -116,7 +106,7 @@ sc_length (void) initLI++; else #endif /* TIOCGWINSZ */ - read_termcap(); + initialize_terminfo(); return LI; } @@ -130,12 +120,12 @@ outc (int c) void -clear_screen (void) +nmh_clear_screen (void) { - read_termcap (); + initialize_terminfo (); - if (CL) - tputs (CL, LI, outc); + if (clear) + tputs (clear, LI, outc); else { printf ("\f"); } @@ -152,18 +142,72 @@ SOprintf (char *fmt, ...) { va_list ap; - read_termcap (); - if (!(SO && SE)) + initialize_terminfo (); + if (!(standbegin && standend)) return NOTOK; - tputs (SO, 1, outc); + tputs (standbegin, 1, outc); va_start(ap, fmt); vprintf (fmt, ap); va_end(ap); - tputs (SE, 1, outc); + tputs (standend, 1, outc); return OK; } +/* + * Return the specified capability as a string that has already been + * processed with tputs(). + */ + +char * +get_term_stringcap(char *capability) +{ + char *parm; + + initialize_terminfo(); + + if (termstatus == -1) + return NULL; + + termcbufp = termcbuf; + + parm = tigetstr(capability); + + if (parm == (char *) -1 || parm == NULL) { + return NULL; + } + + tputs(parm, 1, termbytes); + + termcbufp = '\0'; + + return termcbuf; +} + +/* + * Store a sequence of characters in our local buffer + */ + +static int +termbytes(int c) +{ + size_t offset; + + /* + * Bump up the buffer size if we've reached the end (leave room for + * a trailing NUL) + */ + + if ((offset = termcbufp - termcbuf) - 1 >= termcbufsz) { + termcbufsz += 64; + termcbuf = mh_xrealloc(termcbuf, termcbufsz); + termcbufp = termcbuf + offset; + } + + *termcbufp++ = c; + + return 0; +} diff --git a/uip/mhlsbr.c b/uip/mhlsbr.c index b6b7a627..6a1c3db7 100644 --- a/uip/mhlsbr.c +++ b/uip/mhlsbr.c @@ -531,7 +531,7 @@ mhl (int argc, char **argv) } if (clearflg > 0 && ontty == NOTTY) - clear_screen (); + nmh_clear_screen (); if (ontty == PITTY) m_pclose (); @@ -956,7 +956,7 @@ mhlfile (FILE *fp, char *mname, int ofilen, int ofilec) if (ofilec > 1) { if (ofilen > 1) { if ((global.c_flags & CLEARSCR)) - clear_screen (); + nmh_clear_screen (); else printf ("\n\n\n"); } @@ -978,7 +978,7 @@ mhlfile (FILE *fp, char *mname, int ofilen, int ofilec) } if (strchr(buf, '\n')) { if ((global.c_flags & CLEARSCR)) - clear_screen (); + nmh_clear_screen (); } else printf ("\n"); @@ -989,7 +989,7 @@ mhlfile (FILE *fp, char *mname, int ofilen, int ofilec) if (ofilen > 1) { printf ("\n\n\n"); if (clearflg > 0) - clear_screen (); + nmh_clear_screen (); } printf (">>> %s\n\n", mname); } @@ -1485,7 +1485,7 @@ putch (char ch, long flags) read (fileno (stdout), buf, sizeof(buf)); if (strchr(buf, '\n')) { if (global.c_flags & CLEARSCR) - clear_screen (); + nmh_clear_screen (); row = 0; } else { putchar ('\n'); diff --git a/uip/mshcmds.c b/uip/mshcmds.c index f91f277a..3a5f98fa 100644 --- a/uip/mshcmds.c +++ b/uip/mshcmds.c @@ -2070,7 +2070,7 @@ scancmd (char **args) } if (clearsw) - clear_screen (); + nmh_clear_screen (); } diff --git a/uip/scan.c b/uip/scan.c index 6a134631..1f487cdd 100644 --- a/uip/scan.c +++ b/uip/scan.c @@ -37,12 +37,6 @@ DEFINE_SWITCH_ARRAY(SCAN, switches); #undef X -/* - * prototypes - */ -void clear_screen(void); /* from termsbr.c */ - - int main (int argc, char **argv) { @@ -288,7 +282,7 @@ main (int argc, char **argv) ivector_free (seqnum); folder_free (mp); /* free folder/message structure */ if (clearflag) - clear_screen (); + nmh_clear_screen (); done (0); return 1;