/**************************************************************************** * Copyright (c) 2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * * "Software"), to deal in the Software without restriction, including * * without limitation the rights to use, copy, modify, merge, publish, * * distribute, distribute with modifications, sublicense, and/or sell * * copies of the Software, and to permit persons to whom the Software is * * furnished to do so, subject to the following conditions: * * * * The above copyright notice and this permission notice shall be included * * in all copies or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * * * Except as contained in this notice, the name(s) of the above copyright * * holders shall not be used in advertising or otherwise to promote the * * sale, use or other dealings in this Software without prior written * * authorization. * ****************************************************************************/ /* * $Id: sp_tinfo.c,v 1.21 2017/06/17 21:19:25 tom Exp $ * * TOTO: add option for non-sp-funcs interface */ #define USE_TINFO #include #if HAVE_TPUTS_SP /* * The higher-level curses library stores a TERMINAL* inside SCREEN, but the * latter is opaque. This structure helps us keep the two associated. */ typedef struct { const char *name; FILE *fp; SCREEN *sp; TERMINAL *term; int (*outc) (SCREEN *, int); } MYDATA; static bool opt_n = FALSE; /* true to suppress new_prescr */ static bool opt_t = FALSE; /* true to use termcap */ static int my_outc(SCREEN *sp, int ch) { (void) sp; return fputc(ch, stdout); } static int my_errc(SCREEN *sp, int ch) { (void) sp; return fputc(ch, stderr); } static MYDATA * initialize(const char *name, FILE *output) { MYDATA *result = typeCalloc(MYDATA, 1); int error; result->fp = output; result->name = name; result->outc = (fileno(output) == 1) ? my_outc : my_errc; result->sp = opt_n ? NULL : new_prescr(); if (opt_t) { char *temp = strdup(name); tgetent_sp(result->sp, temp, name); free(temp); } else { setupterm((NCURSES_CONST char *) name, fileno(output), &error); } result->term = cur_term; return result; } static void show_flag(MYDATA * data, const char *name, int value) { if (value < 0) { fprintf(data->fp, " %s = (unknown)\n", name); } else if (value == 0) { fprintf(data->fp, " %s = false\n", name); } else { fprintf(data->fp, " %s = true\n", name); } } #define TC_PARMS data->sp, (NCURSES_CONST char *)tc #define TI_PARMS data->sp, (NCURSES_CONST char *)ti static void show_cap_flag(MYDATA * data, const char *ti, const char *tc) { const char *name = (opt_t ? tc : ti); show_flag(data, name, (opt_t ? tgetflag_sp(TC_PARMS) : tigetflag_sp(TI_PARMS))); } static void show_number(MYDATA * data, const char *name, int value) { if (value <= -2) { fprintf(data->fp, " %s = (unknown)\n", name); } else if (value <= -1) { fprintf(data->fp, " %s = (missing)\n", name); } else { fprintf(data->fp, " %s = %d\n", name, value); } } static void show_cap_number(MYDATA * data, const char *ti, const char *tc) { const char *name = (opt_t ? tc : ti); show_number(data, name, (opt_t ? tgetnum_sp(TC_PARMS) : tigetnum_sp(TI_PARMS))); } static void show_string(MYDATA * data, const char *name, const char *value) { fprintf(data->fp, " %s = ", name); if (value == 0) { fprintf(data->fp, "(missing)"); } else if (value == (char *) -1) { fprintf(data->fp, "(canceled)"); } else { int ch; while ((ch = UChar(*value++)) != '\0') { if (ch < 32) { fprintf(data->fp, "^%c", ch | '@'); } else if (ch == 127) { fprintf(data->fp, "^?"); } else if (ch > 127) { fprintf(data->fp, "\\%03o", ch); } else { fprintf(data->fp, "%c", ch); } } } fprintf(data->fp, "\n"); } static void show_cap_string(MYDATA * data, const char *ti, const char *tc) { const char *name = (opt_t ? tc : ti); char tcapjunk[1024]; char *tcap_ptr = tcapjunk; show_string(data, name, (opt_t ? tgetstr_sp(TC_PARMS, &tcap_ptr) : tigetstr_sp(TI_PARMS))); } static void show_char(MYDATA * data, const char *name, int value) { if (value < 0) { show_string(data, name, "(missing)"); } else { char temp[2]; temp[0] = (char) value; temp[1] = '\0'; show_string(data, name, temp); } } static void do_stuff(MYDATA * data) { char *s; SCREEN *sp = data->sp; int my_code = 1234; const char *my_text = "\033[?m"; set_curterm_sp(sp, data->term); /* putp always goes to standard output */ putp_sp(sp, "Hello "); putp_sp(sp, data->name); putp_sp(sp, "!\n"); fprintf(data->fp, "Term: %s\n", termname_sp(sp)); fprintf(data->fp, "Long: %s\n", longname_sp(sp)); show_cap_flag(data, "am", "am"); show_cap_number(data, "lines", "li"); show_cap_string(data, "clear", "cl"); show_cap_string(data, "tbc", "ct"); show_flag(data, "has_ic", has_ic_sp(sp)); show_flag(data, "has_il", has_il_sp(sp)); show_number(data, "baudrate", baudrate_sp(sp)); show_char(data, "erase ch", erasechar_sp(sp)); show_char(data, "kill ch", killchar_sp(sp)); show_string(data, "unctrl", unctrl_sp(sp, 033)); fflush(data->fp); define_key_sp(sp, my_text, my_code); has_key_sp(sp, 0); key_defined_sp(sp, my_text); if ((s = keybound_sp(sp, my_code, 0)) != 0) free(s); keyname_sp(sp, '?'); keyok_sp(sp, my_code, FALSE); keyok_sp(sp, my_code, TRUE); savetty_sp(sp); def_shell_mode_sp(sp); /* * These functions are low-level settings for ncurses. */ set_tabsize_sp(sp, 5); /* waddch */ typeahead_sp(sp, FALSE); /* waddch */ use_env_sp(sp, FALSE); /* newterm */ use_tioctl_sp(sp, FALSE); /* newterm */ intrflush_sp(sp, 0, 0); /* wgetch */ flushinp_sp(sp); /* waddch */ halfdelay_sp(sp, 5); /* wgetch */ /* * These manipulate the terminal modes, mainly for wgetch. */ cbreak_sp(sp); raw_sp(sp); def_prog_mode_sp(sp); delay_output_sp(sp, 200); napms_sp(sp, 10); nocbreak_sp(sp); noqiflush_sp(sp); noraw_sp(sp); qiflush_sp(sp); resetty_sp(sp); tputs_sp(sp, "{reset-mode}\n", 0, data->outc); reset_prog_mode_sp(sp); curs_set_sp(sp, 0); tputs_sp(sp, "{prog-mode}\n", 0, data->outc); reset_shell_mode_sp(sp); tputs_sp(sp, "{shell-mode}\n", 0, data->outc); } static void cleanup(MYDATA * data) { set_curterm(data->term); del_curterm(data->term); #if !NO_LEAKS free(data->sp); /* cannot use delscreen in tinfo */ #endif free(data); } static void usage(void) { static const char *tbl[] = { "Usage: sp_tinfo [output] [error]", "", "Options:", " -n suppress call to new_prescr()", " -t use termcap functions rather than terminfo", NULL }; size_t n; for (n = 0; n < SIZEOF(tbl); ++n) { fprintf(stderr, "%s\n", tbl[n]); } ExitProgram(EXIT_FAILURE); } int main(int argc, char *argv[]) { MYDATA *my_out; MYDATA *my_err; int n; while ((n = getopt(argc, argv, "nt")) != -1) { switch (n) { case 'n': opt_n = TRUE; break; case 't': opt_t = TRUE; break; default: usage(); /* NOTREACHED */ } } argv += (optind - 1); argc -= (optind - 1); if (argc > 3) usage(); my_out = initialize((argc > 1) ? argv[1] : "vt100", stdout); my_err = initialize((argc > 2) ? argv[2] : "ansi", stderr); do_stuff(my_out); do_stuff(my_err); cleanup(my_out); cleanup(my_err); ExitProgram(EXIT_SUCCESS); } #else int main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED) { fprintf(stderr, "This program requires the low-level ncurses sp-funcs tputs_sp\n"); ExitProgram(EXIT_FAILURE); } #endif