X-Git-Url: https://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=ncurses%2Ftinfo%2Ftinfo_driver.c;h=fb6496f0c986250d63e0755ba18ba907764117bc;hp=d45ef0b6d7a279d5975878a2a8c706551573b7f9;hb=c0e5fbfcce224693b3effdd295ee49b6b761b754;hpb=10539f5afe94d8ff488516ca7f9861af7c800bfb diff --git a/ncurses/tinfo/tinfo_driver.c b/ncurses/tinfo/tinfo_driver.c index d45ef0b6..fb6496f0 100644 --- a/ncurses/tinfo/tinfo_driver.c +++ b/ncurses/tinfo/tinfo_driver.c @@ -1,5 +1,6 @@ /**************************************************************************** - * Copyright (c) 2008-2009,2010 Free Software Foundation, Inc. * + * Copyright 2018-2020,2021 Thomas E. Dickey * + * Copyright 2008-2016,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 * @@ -28,12 +29,13 @@ /**************************************************************************** * Author: Juergen Pfeifer * - * * + * and: Thomas E. Dickey * ****************************************************************************/ #include -#define CUR ((TERMINAL*)TCB)->type. +#define CUR TerminalType((TERMINAL*)TCB). #include +#include /* ospeed */ #if HAVE_NANOSLEEP #include @@ -50,7 +52,7 @@ # endif #endif -MODULE_ID("$Id: tinfo_driver.c,v 1.9 2010/04/10 16:11:17 tom Exp $") +MODULE_ID("$Id: tinfo_driver.c,v 1.72 2021/06/17 21:30:22 tom Exp $") /* * SCO defines TIOCGSIZE and the corresponding struct. Other systems (SunOS, @@ -93,7 +95,7 @@ NCURSES_EXPORT_VAR(int) COLORS = 0; #define TCBMAGIC NCDRV_MAGIC(NCDRV_TINFO) #define AssertTCB() assert(TCB!=0 && TCB->magic==TCBMAGIC) -#define SetSP() assert(TCB->csp!=0); sp = TCB->csp +#define SetSP() assert(TCB->csp!=0); sp = TCB->csp; (void) sp /* * This routine needs to do all the work to make curscr look @@ -106,53 +108,49 @@ drv_doupdate(TERMINAL_CONTROL_BLOCK * TCB) return TINFO_DOUPDATE(TCB->csp); } -#define ret_error(code, fmt, arg) if (errret) {\ - *errret = code;\ - return(FALSE); \ - } else {\ - fprintf(stderr, fmt, arg);\ - exit(EXIT_FAILURE);\ - } - -#define ret_error0(code, msg) if (errret) {\ - *errret = code;\ - return(FALSE);\ - } else {\ - fprintf(stderr, msg);\ - exit(EXIT_FAILURE);\ - } - -#if USE_DATABASE || USE_TERMCAP -/* - * Return 1 if entry found, 0 if not found, -1 if database not accessible, - * just like tgetent(). - */ -static int -grab_entry(const char *const tn, TERMTYPE *const tp) +static const char * +drv_Name(TERMINAL_CONTROL_BLOCK * TCB) { - char filename[PATH_MAX]; - int status = _nc_read_entry(tn, filename, tp); + (void) TCB; + return "tinfo"; +} - /* - * If we have an entry, force all of the cancelled strings to null - * pointers so we don't have to test them in the rest of the library. - * (The terminfo compiler bypasses this logic, since it must know if - * a string is cancelled, for merging entries). - */ - if (status == TGETENT_YES) { - unsigned n; - for_each_boolean(n, tp) { - if (!VALID_BOOLEAN(tp->Booleans[n])) - tp->Booleans[n] = FALSE; - } - for_each_string(n, tp) { - if (tp->Strings[n] == CANCELLED_STRING) - tp->Strings[n] = ABSENT_STRING; - } +static void +get_baudrate(TERMINAL *termp) +{ + int my_ospeed; + int result; + if (GET_TTY(termp->Filedes, &termp->Nttyb) == OK) { +#ifdef TERMIOS + termp->Nttyb.c_oflag &= (unsigned) (~OFLAGS_TABS); +#elif defined(EXP_WIN32_DRIVER) + /* noop */ +#else + termp->Nttyb.sg_flags &= (unsigned) (~XTABS); +#endif } - return (status); -} +#ifdef USE_OLD_TTY + result = (int) cfgetospeed(&(termp->Nttyb)); + my_ospeed = (NCURSES_OSPEED) _nc_ospeed(result); +#else /* !USE_OLD_TTY */ +#ifdef TERMIOS + my_ospeed = (NCURSES_OSPEED) cfgetospeed(&(termp->Nttyb)); +#elif defined(EXP_WIN32_DRIVER) + /* noop */ + my_ospeed = 0; +#else + my_ospeed = (NCURSES_OSPEED) termp->Nttyb.sg_ospeed; +#endif + result = _nc_baudrate(my_ospeed); #endif + termp->_baudrate = result; + ospeed = (NCURSES_OSPEED) my_ospeed; +} + +#undef SETUP_FAIL +#define SETUP_FAIL FALSE + +#define NO_COPY {} static bool drv_CanHandle(TERMINAL_CONTROL_BLOCK * TCB, const char *tname, int *errret) @@ -162,23 +160,29 @@ drv_CanHandle(TERMINAL_CONTROL_BLOCK * TCB, const char *tname, int *errret) TERMINAL *termp; SCREEN *sp; + START_TRACE(); + T((T_CALLED("tinfo::drv_CanHandle(%p)"), (void *) TCB)); + assert(TCB != 0 && tname != 0); termp = (TERMINAL *) TCB; sp = TCB->csp; TCB->magic = TCBMAGIC; -#if (USE_DATABASE || USE_TERMCAP) - status = grab_entry(tname, &termp->type); +#if (NCURSES_USE_DATABASE || NCURSES_USE_TERMCAP) + status = _nc_setup_tinfo(tname, &TerminalType(termp)); + T(("_nc_setup_tinfo returns %d", status)); #else + T(("no database available")); status = TGETENT_NO; #endif /* try fallback list if entry on disk */ if (status != TGETENT_YES) { - const TERMTYPE *fallback = _nc_fallback(tname); + const TERMTYPE2 *fallback = _nc_fallback2(tname); if (fallback) { - termp->type = *fallback; + T(("found fallback entry")); + TerminalType(termp) = *fallback; status = TGETENT_YES; } } @@ -188,30 +192,69 @@ drv_CanHandle(TERMINAL_CONTROL_BLOCK * TCB, const char *tname, int *errret) if (status == TGETENT_ERR) { ret_error0(status, "terminals database is inaccessible\n"); } else if (status == TGETENT_NO) { - ret_error(status, "'%s': unknown terminal type.\n", tname); + ret_error1(status, "unknown terminal type.\n", + tname, NO_COPY); + } else { + ret_error0(status, "unexpected return-code\n"); } } result = TRUE; +#if NCURSES_EXT_NUMBERS + _nc_export_termtype2(&termp->type, &TerminalType(termp)); +#endif #if !USE_REENTRANT - strncpy(ttytype, termp->type.term_names, NAMESIZE - 1); - ttytype[NAMESIZE - 1] = '\0'; + save_ttytype(termp); #endif if (command_character) _nc_tinfo_cmdch(termp, *command_character); + /* + * If an application calls setupterm() rather than initscr() or + * newterm(), we will not have the def_prog_mode() call in + * _nc_setupscreen(). Do it now anyway, so we can initialize the + * baudrate. + */ + if (sp == 0 && NC_ISATTY(termp->Filedes)) { + get_baudrate(termp); + } +#if NCURSES_EXT_NUMBERS +#define cleanup_termtype() \ + _nc_free_termtype2(&TerminalType(termp)); \ + _nc_free_termtype(&termp->type) +#else +#define cleanup_termtype() \ + _nc_free_termtype2(&TerminalType(termp)) +#endif + if (generic_type) { - ret_error(TGETENT_NO, "'%s': I need something more specific.\n", tname); + /* + * BSD 4.3's termcap contains mis-typed "gn" for wy99. Do a sanity + * check before giving up. + */ + if ((VALID_STRING(cursor_address) + || (VALID_STRING(cursor_down) && VALID_STRING(cursor_home))) + && VALID_STRING(clear_screen)) { + cleanup_termtype(); + ret_error1(TGETENT_YES, "terminal is not really generic.\n", + tname, NO_COPY); + } else { + cleanup_termtype(); + ret_error1(TGETENT_NO, "I need something more specific.\n", + tname, NO_COPY); + } } if (hard_copy) { - ret_error(TGETENT_YES, "'%s': I can't handle hardcopy terminals.\n", tname); + cleanup_termtype(); + ret_error1(TGETENT_YES, "I can't handle hardcopy terminals.\n", + tname, NO_COPY); } - return result; + returnBool(result); } static int -drv_dobeepflash(TERMINAL_CONTROL_BLOCK * TCB, bool beepFlag) +drv_dobeepflash(TERMINAL_CONTROL_BLOCK * TCB, int beepFlag) { SCREEN *sp; int res = ERR; @@ -222,22 +265,18 @@ drv_dobeepflash(TERMINAL_CONTROL_BLOCK * TCB, bool beepFlag) /* FIXME: should make sure that we are not in altchar mode */ if (beepFlag) { if (bell) { - res = NCURSES_SP_NAME(_nc_putp) (NCURSES_SP_ARGx "bell", bell); + res = NCURSES_PUTP2("bell", bell); NCURSES_SP_NAME(_nc_flush) (sp); } else if (flash_screen) { - res = NCURSES_SP_NAME(_nc_putp) (NCURSES_SP_ARGx - "flash_screen", - flash_screen); + res = NCURSES_PUTP2("flash_screen", flash_screen); NCURSES_SP_NAME(_nc_flush) (sp); } } else { if (flash_screen) { - res = NCURSES_SP_NAME(_nc_putp) (NCURSES_SP_ARGx - "flash_screen", - flash_screen); + res = NCURSES_PUTP2("flash_screen", flash_screen); NCURSES_SP_NAME(_nc_flush) (sp); } else if (bell) { - res = NCURSES_SP_NAME(_nc_putp) (NCURSES_SP_ARGx "bell", bell); + res = NCURSES_PUTP2("bell", bell); NCURSES_SP_NAME(_nc_flush) (sp); } } @@ -290,8 +329,8 @@ drv_defaultcolors(TERMINAL_CONTROL_BLOCK * TCB, int fg, int bg) sp->_has_sgr_39_49 = (NCURSES_SP_NAME(tigetflag) (NCURSES_SP_ARGx "AX") == TRUE); - sp->_default_fg = isDefaultColor(fg) ? COLOR_DEFAULT : (fg & C_MASK); - sp->_default_bg = isDefaultColor(bg) ? COLOR_DEFAULT : (bg & C_MASK); + sp->_default_fg = isDefaultColor(fg) ? COLOR_DEFAULT : fg; + sp->_default_bg = isDefaultColor(bg) ? COLOR_DEFAULT : bg; if (sp->_color_pairs != 0) { bool save = sp->_default_color; sp->_default_color = TRUE; @@ -309,7 +348,7 @@ drv_defaultcolors(TERMINAL_CONTROL_BLOCK * TCB, int fg, int bg) static void drv_setcolor(TERMINAL_CONTROL_BLOCK * TCB, - bool fore, + int fore, int color, NCURSES_SP_OUTC outc) { @@ -322,23 +361,23 @@ drv_setcolor(TERMINAL_CONTROL_BLOCK * TCB, if (set_a_foreground) { TPUTS_TRACE("set_a_foreground"); NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx - TPARM_1(set_a_foreground, color), 1, outc); + TIPARM_1(set_a_foreground, color), 1, outc); } else { TPUTS_TRACE("set_foreground"); NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx - TPARM_1(set_foreground, - toggled_colors(color)), 1, outc); + TIPARM_1(set_foreground, + toggled_colors(color)), 1, outc); } } else { if (set_a_background) { TPUTS_TRACE("set_a_background"); NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx - TPARM_1(set_a_background, color), 1, outc); + TIPARM_1(set_a_background, color), 1, outc); } else { TPUTS_TRACE("set_background"); NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx - TPARM_1(set_background, - toggled_colors(color)), 1, outc); + TIPARM_1(set_background, + toggled_colors(color)), 1, outc); } } } @@ -353,7 +392,7 @@ drv_rescol(TERMINAL_CONTROL_BLOCK * TCB) SetSP(); if (orig_pair != 0) { - NCURSES_SP_NAME(_nc_putp) (NCURSES_SP_ARGx "orig_pair", orig_pair); + NCURSES_PUTP2("orig_pair", orig_pair); result = TRUE; } return result; @@ -369,7 +408,7 @@ drv_rescolors(TERMINAL_CONTROL_BLOCK * TCB) SetSP(); if (orig_colors != 0) { - NCURSES_SP_NAME(_nc_putp) (NCURSES_SP_ARGx "orig_colors", orig_colors); + NCURSES_PUTP2("orig_colors", orig_colors); result = TRUE; } return result; @@ -380,22 +419,33 @@ drv_size(TERMINAL_CONTROL_BLOCK * TCB, int *linep, int *colp) { SCREEN *sp; bool useEnv = TRUE; + bool useTioctl = TRUE; AssertTCB(); sp = TCB->csp; /* can be null here */ if (sp) { useEnv = sp->_use_env; - } else + useTioctl = sp->use_tioctl; + } else { useEnv = _nc_prescreen.use_env; + useTioctl = _nc_prescreen.use_tioctl; + } +#ifdef EXP_WIN32_DRIVER + /* If we are here, then Windows console is used in terminfo mode. + We need to figure out the size using the console API + */ + _nc_console_size(linep, colp); + T(("screen size: winconsole lines = %d columns = %d", *linep, *colp)); +#else /* figure out the size of the screen */ T(("screen size: terminfo lines = %d columns = %d", lines, columns)); *linep = (int) lines; *colp = (int) columns; - - if (useEnv) { +#endif + if (useEnv || useTioctl) { int value; #ifdef __EMX__ @@ -403,7 +453,9 @@ drv_size(TERMINAL_CONTROL_BLOCK * TCB, int *linep, int *colp) int screendata[2]; _scrsize(screendata); *colp = screendata[0]; - *linep = screendata[1]; + *linep = ((sp != 0 && sp->_filtered) + ? 1 + : screendata[1]); T(("EMX screen size: environment LINES = %d COLUMNS = %d", *linep, *colp)); } @@ -412,7 +464,7 @@ drv_size(TERMINAL_CONTROL_BLOCK * TCB, int *linep, int *colp) /* try asking the OS */ { TERMINAL *termp = (TERMINAL *) TCB; - if (isatty(termp->Filedes)) { + if (NC_ISATTY(termp->Filedes)) { STRUCT_WINSIZE size; errno = 0; @@ -432,19 +484,33 @@ drv_size(TERMINAL_CONTROL_BLOCK * TCB, int *linep, int *colp) } #endif /* HAVE_SIZECHANGE */ - /* - * Finally, look for environment variables. - * - * Solaris lets users override either dimension with an environment - * variable. - */ - if ((value = _nc_getenv_num("LINES")) > 0) { - *linep = value; - T(("screen size: environment LINES = %d", *linep)); - } - if ((value = _nc_getenv_num("COLUMNS")) > 0) { - *colp = value; - T(("screen size: environment COLUMNS = %d", *colp)); + if (useEnv) { + if (useTioctl) { + /* + * If environment variables are used, update them. + */ + if ((sp == 0 || !sp->_filtered) && _nc_getenv_num("LINES") > 0) { + _nc_setenv_num("LINES", *linep); + } + if (_nc_getenv_num("COLUMNS") > 0) { + _nc_setenv_num("COLUMNS", *colp); + } + } + + /* + * Finally, look for environment variables. + * + * Solaris lets users override either dimension with an environment + * variable. + */ + if ((value = _nc_getenv_num("LINES")) > 0) { + *linep = value; + T(("screen size: environment LINES = %d", *linep)); + } + if ((value = _nc_getenv_num("COLUMNS")) > 0) { + *colp = value; + T(("screen size: environment COLUMNS = %d", *colp)); + } } /* if we can't get dynamic info about the size, use static */ @@ -495,7 +561,7 @@ drv_setsize(TERMINAL_CONTROL_BLOCK * TCB, int l, int c) } static int -drv_sgmode(TERMINAL_CONTROL_BLOCK * TCB, bool setFlag, TTY * buf) +drv_sgmode(TERMINAL_CONTROL_BLOCK * TCB, int setFlag, TTY * buf) { SCREEN *sp = TCB->csp; TERMINAL *_term = (TERMINAL *) TCB; @@ -529,7 +595,7 @@ drv_sgmode(TERMINAL_CONTROL_BLOCK * TCB, bool setFlag, TTY * buf) } static int -drv_mode(TERMINAL_CONTROL_BLOCK * TCB, bool progFlag, bool defFlag) +drv_mode(TERMINAL_CONTROL_BLOCK * TCB, int progFlag, int defFlag) { SCREEN *sp; TERMINAL *_term = (TERMINAL *) TCB; @@ -547,9 +613,11 @@ drv_mode(TERMINAL_CONTROL_BLOCK * TCB, bool progFlag, bool defFlag) */ if ((drv_sgmode(TCB, FALSE, &(_term->Nttyb)) == OK)) { #ifdef TERMIOS - _term->Nttyb.c_oflag &= ~OFLAGS_TABS; + _term->Nttyb.c_oflag &= (unsigned) ~OFLAGS_TABS; +#elif defined(EXP_WIN32_DRIVER) + /* noop */ #else - _term->Nttyb.sg_flags &= ~XTABS; + _term->Nttyb.sg_flags &= (unsigned) ~XTABS; #endif code = OK; } @@ -559,7 +627,6 @@ drv_mode(TERMINAL_CONTROL_BLOCK * TCB, bool progFlag, bool defFlag) if (sp) { if (sp->_keypad_on) _nc_keypad(sp, TRUE); - NC_BUFFERED(sp, TRUE); } code = OK; } @@ -574,6 +641,8 @@ drv_mode(TERMINAL_CONTROL_BLOCK * TCB, bool progFlag, bool defFlag) #ifdef TERMIOS if (_term->Ottyb.c_oflag & OFLAGS_TABS) tab = back_tab = NULL; +#elif defined(EXP_WIN32_DRIVER) + /* noop */ #else if (_term->Ottyb.sg_flags & XTABS) tab = back_tab = NULL; @@ -585,7 +654,6 @@ drv_mode(TERMINAL_CONTROL_BLOCK * TCB, bool progFlag, bool defFlag) if (sp) { _nc_keypad(sp, FALSE); NCURSES_SP_NAME(_nc_flush) (sp); - NC_BUFFERED(sp, FALSE); } code = drv_sgmode(TCB, TRUE, &(_term->Ottyb)); } @@ -652,15 +720,13 @@ drv_screen_init(SCREEN *sp) static void drv_init(TERMINAL_CONTROL_BLOCK * TCB) { - SCREEN *sp; TERMINAL *trm; AssertTCB(); trm = (TERMINAL *) TCB; - sp = TCB->csp; - TCB->info.initcolor = initialize_color; + TCB->info.initcolor = VALID_STRING(initialize_color); TCB->info.canchange = can_change; TCB->info.hascolor = ((VALID_NUMERIC(max_colors) && VALID_NUMERIC(max_pairs) && (((set_foreground != NULL) @@ -688,8 +754,8 @@ drv_init(TERMINAL_CONTROL_BLOCK * TCB) * _nc_setupscreen(). Do it now anyway, so we can initialize the * baudrate. */ - if (isatty(trm->Filedes)) { - TCB->drv->mode(TCB, TRUE, TRUE); + if (NC_ISATTY(trm->Filedes)) { + TCB->drv->td_mode(TCB, TRUE, TRUE); } } @@ -697,7 +763,7 @@ drv_init(TERMINAL_CONTROL_BLOCK * TCB) #define InPalette(n) ((n) >= 0 && (n) < MAX_PALETTE) static void -drv_initpair(TERMINAL_CONTROL_BLOCK * TCB, short pair, short f, short b) +drv_initpair(TERMINAL_CONTROL_BLOCK * TCB, int pair, int f, int b) { SCREEN *sp; @@ -713,12 +779,11 @@ drv_initpair(TERMINAL_CONTROL_BLOCK * TCB, short pair, short f, short b) tp[f].red, tp[f].green, tp[f].blue, tp[b].red, tp[b].green, tp[b].blue)); - NCURSES_SP_NAME(_nc_putp) (NCURSES_SP_ARGx - "initialize_pair", - TPARM_7(initialize_pair, - pair, - tp[f].red, tp[f].green, tp[f].blue, - tp[b].red, tp[b].green, tp[b].blue)); + NCURSES_PUTP2("initialize_pair", + TIPARM_7(initialize_pair, + pair, + tp[f].red, tp[f].green, tp[f].blue, + tp[b].red, tp[b].green, tp[b].blue)); } } @@ -744,29 +809,28 @@ default_bg(SCREEN *sp) static void drv_initcolor(TERMINAL_CONTROL_BLOCK * TCB, - short color, short r, short g, short b) + int color, int r, int g, int b) { SCREEN *sp = TCB->csp; AssertTCB(); if (initialize_color != NULL) { - NCURSES_SP_NAME(_nc_putp) (NCURSES_SP_ARGx - "initialize_color", - TPARM_4(initialize_color, color, r, g, b)); + NCURSES_PUTP2("initialize_color", + TIPARM_4(initialize_color, color, r, g, b)); } } static void drv_do_color(TERMINAL_CONTROL_BLOCK * TCB, - short old_pair, - short pair, - bool reverse, + int old_pair, + int pair, + int reverse, NCURSES_SP_OUTC outc) { SCREEN *sp = TCB->csp; - NCURSES_COLOR_T fg = COLOR_DEFAULT; - NCURSES_COLOR_T bg = COLOR_DEFAULT; - NCURSES_COLOR_T old_fg, old_bg; + int fg = COLOR_DEFAULT; + int bg = COLOR_DEFAULT; + int old_fg, old_bg; AssertTCB(); if (sp == 0) @@ -778,22 +842,16 @@ drv_do_color(TERMINAL_CONTROL_BLOCK * TCB, if (set_color_pair) { TPUTS_TRACE("set_color_pair"); NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx - TPARM_1(set_color_pair, pair), 1, outc); + TIPARM_1(set_color_pair, pair), 1, outc); return; } else if (sp != 0) { - NCURSES_SP_NAME(pair_content) (NCURSES_SP_ARGx - (short) pair, - &fg, - &bg); + _nc_pair_content(SP_PARM, pair, &fg, &bg); } } if (old_pair >= 0 && sp != 0 - && NCURSES_SP_NAME(pair_content) (NCURSES_SP_ARGx - old_pair, - &old_fg, - &old_bg) !=ERR) { + && _nc_pair_content(SP_PARM, old_pair, &old_fg, &old_bg) != ERR) { if ((isDefaultColor(fg) && !isDefaultColor(old_fg)) || (isDefaultColor(bg) && !isDefaultColor(old_bg))) { #if NCURSES_EXT_FUNCS @@ -822,13 +880,13 @@ drv_do_color(TERMINAL_CONTROL_BLOCK * TCB, #if NCURSES_EXT_FUNCS if (isDefaultColor(fg)) - fg = (NCURSES_COLOR_T) default_fg(sp); + fg = default_fg(sp); if (isDefaultColor(bg)) - bg = (NCURSES_COLOR_T) default_bg(sp); + bg = default_bg(sp); #endif if (reverse) { - NCURSES_COLOR_T xx = fg; + int xx = fg; fg = bg; bg = xx; } @@ -864,12 +922,9 @@ drv_initmouse(TERMINAL_CONTROL_BLOCK * TCB) /* we know how to recognize mouse events under "xterm" */ if (sp != 0) { - if (key_mouse != 0) { - if (!strcmp(key_mouse, xterm_kmous) - || strstr(TerminalOf(sp)->type.term_names, "xterm") != 0) { - init_xterm_mouse(sp); - } - } else if (strstr(TerminalOf(sp)->type.term_names, "xterm") != 0) { + if (NonEmpty(key_mouse)) { + init_xterm_mouse(sp); + } else if (strstr(SP_TERMTYPE term_names, "xterm") != 0) { if (_nc_add_to_try(&(sp->_keytry), xterm_kmous, KEY_MOUSE) == OK) init_xterm_mouse(sp); } @@ -877,7 +932,9 @@ drv_initmouse(TERMINAL_CONTROL_BLOCK * TCB) } static int -drv_testmouse(TERMINAL_CONTROL_BLOCK * TCB, int delay) +drv_testmouse(TERMINAL_CONTROL_BLOCK * TCB, + int delay + EVENTLIST_2nd(_nc_eventlist * evl)) { int rc = 0; SCREEN *sp; @@ -892,11 +949,18 @@ drv_testmouse(TERMINAL_CONTROL_BLOCK * TCB, int delay) } else #endif { - rc = TCBOf(sp)->drv->twait(TCBOf(sp), - TWAIT_MASK, - delay, - (int *) 0 +#ifdef EXP_WIN32_DRIVER + rc = _nc_console_testmouse(sp, + _nc_console_handle(sp->_ifd), + delay EVENTLIST_2nd(evl)); +#else + rc = TCBOf(sp)->drv->td_twait(TCBOf(sp), + TWAIT_MASK, + delay, + (int *) 0 + EVENTLIST_2nd(evl)); +#endif #if USE_SYSMOUSE if ((sp->_mouse_type == M_SYSMOUSE) && (sp->_sysmouse_head < sp->_sysmouse_tail) @@ -914,7 +978,7 @@ drv_mvcur(TERMINAL_CONTROL_BLOCK * TCB, int yold, int xold, int ynew, int xnew) { SCREEN *sp = TCB->csp; AssertTCB(); - return TINFO_MVCUR(sp, yold, xold, ynew, xnew); + return NCURSES_SP_NAME(_nc_mvcur) (sp, yold, xold, ynew, xnew); } static void @@ -924,22 +988,21 @@ drv_hwlabel(TERMINAL_CONTROL_BLOCK * TCB, int labnum, char *text) AssertTCB(); if (labnum > 0 && labnum <= num_labels) { - NCURSES_SP_NAME(_nc_putp) (NCURSES_SP_ARGx - "plab_norm", - TPARM_2(plab_norm, labnum, text)); + NCURSES_PUTP2("plab_norm", + TPARM_2(plab_norm, labnum, text)); } } static void -drv_hwlabelOnOff(TERMINAL_CONTROL_BLOCK * TCB, bool OnFlag) +drv_hwlabelOnOff(TERMINAL_CONTROL_BLOCK * TCB, int OnFlag) { SCREEN *sp = TCB->csp; AssertTCB(); if (OnFlag) { - NCURSES_SP_NAME(_nc_putp) (NCURSES_SP_ARGx "label_on", label_on); + NCURSES_PUTP2("label_on", label_on); } else { - NCURSES_SP_NAME(_nc_putp) (NCURSES_SP_ARGx "label_off", label_off); + NCURSES_PUTP2("label_off", label_off); } } @@ -980,6 +1043,11 @@ drv_conattr(TERMINAL_CONTROL_BLOCK * TCB) if (sp && sp->_coloron) attrs |= A_COLOR; +#if USE_ITALIC + if (enter_italics_mode) + attrs |= A_ITALIC; +#endif + return (attrs); } @@ -988,12 +1056,18 @@ drv_setfilter(TERMINAL_CONTROL_BLOCK * TCB) { AssertTCB(); - clear_screen = 0; - cursor_down = parm_down_cursor = 0; - cursor_address = 0; - cursor_up = parm_up_cursor = 0; - row_address = 0; - cursor_home = carriage_return; + /* *INDENT-EQLS* */ + clear_screen = ABSENT_STRING; + cursor_address = ABSENT_STRING; + cursor_down = ABSENT_STRING; + cursor_up = ABSENT_STRING; + parm_down_cursor = ABSENT_STRING; + parm_up_cursor = ABSENT_STRING; + row_address = ABSENT_STRING; + cursor_home = carriage_return; + + if (back_color_erase) + clr_eos = ABSENT_STRING; } static void @@ -1004,7 +1078,7 @@ drv_initacs(TERMINAL_CONTROL_BLOCK * TCB, chtype *real_map, chtype *fake_map) AssertTCB(); assert(sp != 0); if (ena_acs != NULL) { - NCURSES_SP_NAME(_nc_putp) (NCURSES_SP_ARGx "ena_acs", ena_acs); + NCURSES_PUTP2("ena_acs", ena_acs); } #if NCURSES_EXT_FUNCS /* @@ -1023,7 +1097,7 @@ drv_initacs(TERMINAL_CONTROL_BLOCK * TCB, chtype *real_map, chtype *fake_map) size_t i; for (i = 1; i < ACS_LEN; ++i) { if (real_map[i] == 0) { - real_map[i] = i; + real_map[i] = (chtype) i; if (real_map != fake_map) { if (sp != 0) sp->_screen_acs_map[i] = TRUE; @@ -1040,8 +1114,13 @@ drv_initacs(TERMINAL_CONTROL_BLOCK * TCB, chtype *real_map, chtype *fake_map) while (i + 1 < length) { if (acs_chars[i] != 0 && UChar(acs_chars[i]) < ACS_LEN) { real_map[UChar(acs_chars[i])] = UChar(acs_chars[i + 1]) | A_ALTCHARSET; - if (sp != 0) + T(("#%d real_map[%s] = %s", + (int) i, + _tracechar(UChar(acs_chars[i])), + _tracechtype(real_map[UChar(acs_chars[i])]))); + if (sp != 0) { sp->_screen_acs_map[UChar(acs_chars[i])] = TRUE; + } } i += 2; } @@ -1071,7 +1150,6 @@ drv_initacs(TERMINAL_CONTROL_BLOCK * TCB, chtype *real_map, chtype *fake_map) ? "DIFF" : "SAME"), _nc_visbuf(show)); - _nc_unlock_global(tracef); } #endif /* TRACE */ @@ -1106,16 +1184,7 @@ _nc_cookie_init(SCREEN *sp) if (magic_cookie_glitch > 0) { /* tvi, wyse */ - sp->_xmc_triggers = sp->_ok_attributes & ( - A_STANDOUT | - A_UNDERLINE | - A_REVERSE | - A_BLINK | - A_DIM | - A_BOLD | - A_INVIS | - A_PROTECT - ); + sp->_xmc_triggers = sp->_ok_attributes & XMC_CONFLICT; #if 0 /* * We "should" treat colors as an attribute. The wyse350 (and its @@ -1189,23 +1258,47 @@ drv_twait(TERMINAL_CONTROL_BLOCK * TCB, AssertTCB(); SetSP(); - +#ifdef EXP_WIN32_DRIVER + return _nc_console_twait(sp, + _nc_console_handle(sp->_ifd), + mode, + milliseconds, + timeleft EVENTLIST_2nd(evl)); +#else return _nc_timed_wait(sp, mode, milliseconds, timeleft EVENTLIST_2nd(evl)); +#endif } static int drv_read(TERMINAL_CONTROL_BLOCK * TCB, int *buf) { SCREEN *sp; - unsigned char c2 = 0; int n; +#ifndef EXP_WIN32_DRIVER + unsigned char c2 = 0; +#endif AssertTCB(); assert(buf); SetSP(); - n = read(sp->_ifd, &c2, 1); +# if USE_PTHREADS_EINTR + if ((pthread_self) && (pthread_kill) && (pthread_equal)) + _nc_globals.read_thread = pthread_self(); +# endif +#ifdef EXP_WIN32_DRIVER + n = _nc_console_read(sp, + _nc_console_handle(sp->_ifd), + buf); +#else + n = (int) read(sp->_ifd, &c2, (size_t) 1); +#endif +#if USE_PTHREADS_EINTR + _nc_globals.read_thread = 0; +#endif +#ifndef EXP_WIN32_DRIVER *buf = (int) c2; +#endif return n; } @@ -1222,6 +1315,8 @@ drv_nap(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED, int ms) request = remaining; } } +#elif defined(EXP_WIN32_DRIVER) + Sleep((DWORD) ms); #else _nc_timed_wait(0, 0, ms, (int *) 0 EVENTLIST_2nd(0)); #endif @@ -1234,7 +1329,7 @@ __nc_putp(SCREEN *sp, const char *name GCC_UNUSED, const char *value) int rc = ERR; if (value) { - rc = NCURSES_SP_NAME(_nc_putp) (NCURSES_SP_ARGx name, value); + rc = NCURSES_PUTP2(name, value); } return rc; } @@ -1250,7 +1345,7 @@ __nc_putp_flush(SCREEN *sp, const char *name, const char *value) } static int -drv_kpad(TERMINAL_CONTROL_BLOCK * TCB, bool flag) +drv_kpad(TERMINAL_CONTROL_BLOCK * TCB, int flag) { int ret = ERR; SCREEN *sp; @@ -1276,7 +1371,7 @@ drv_kpad(TERMINAL_CONTROL_BLOCK * TCB, bool flag) } static int -drv_keyok(TERMINAL_CONTROL_BLOCK * TCB, int c, bool flag) +drv_keyok(TERMINAL_CONTROL_BLOCK * TCB, int c, int flag) { SCREEN *sp; int code = ERR; @@ -1289,28 +1384,65 @@ drv_keyok(TERMINAL_CONTROL_BLOCK * TCB, int c, bool flag) if (c >= 0) { unsigned ch = (unsigned) c; if (flag) { - while ((s = _nc_expand_try(sp->_key_ok, ch, &count, 0)) != 0 - && _nc_remove_key(&(sp->_key_ok), ch)) { - code = _nc_add_to_try(&(sp->_keytry), s, ch); - free(s); - count = 0; - if (code != OK) - break; + while ((s = _nc_expand_try(sp->_key_ok, + ch, &count, (size_t) 0)) != 0) { + if (_nc_remove_key(&(sp->_key_ok), ch)) { + code = _nc_add_to_try(&(sp->_keytry), s, ch); + free(s); + count = 0; + if (code != OK) + break; + } else { + free(s); + } } } else { - while ((s = _nc_expand_try(sp->_keytry, ch, &count, 0)) != 0 - && _nc_remove_key(&(sp->_keytry), ch)) { - code = _nc_add_to_try(&(sp->_key_ok), s, ch); - free(s); - count = 0; - if (code != OK) - break; + while ((s = _nc_expand_try(sp->_keytry, + ch, &count, (size_t) 0)) != 0) { + if (_nc_remove_key(&(sp->_keytry), ch)) { + code = _nc_add_to_try(&(sp->_key_ok), s, ch); + free(s); + count = 0; + if (code != OK) + break; + } else { + free(s); + } } } } return (code); } +static int +drv_cursorSet(TERMINAL_CONTROL_BLOCK * TCB, int vis) +{ + SCREEN *sp; + int code = ERR; + + AssertTCB(); + SetSP(); + + T((T_CALLED("tinfo:drv_cursorSet(%p,%d)"), (void *) SP_PARM, vis)); + + if (SP_PARM != 0 && IsTermInfo(SP_PARM)) { + switch (vis) { + case 2: + code = NCURSES_PUTP2_FLUSH("cursor_visible", cursor_visible); + break; + case 1: + code = NCURSES_PUTP2_FLUSH("cursor_normal", cursor_normal); + break; + case 0: + code = NCURSES_PUTP2_FLUSH("cursor_invisible", cursor_invisible); + break; + } + } else { + code = ERR; + } + returnCode(code); +} + static bool drv_kyExist(TERMINAL_CONTROL_BLOCK * TCB, int key) { @@ -1325,6 +1457,7 @@ drv_kyExist(TERMINAL_CONTROL_BLOCK * TCB, int key) NCURSES_EXPORT_VAR (TERM_DRIVER) _nc_TINFO_DRIVER = { TRUE, + drv_Name, /* Name */ drv_CanHandle, /* CanHandle */ drv_init, /* init */ drv_release, /* release */ @@ -1358,5 +1491,69 @@ NCURSES_EXPORT_VAR (TERM_DRIVER) _nc_TINFO_DRIVER = { drv_nap, /* nap */ drv_kpad, /* kpad */ drv_keyok, /* kyOk */ - drv_kyExist /* kyExist */ + drv_kyExist, /* kyExist */ + drv_cursorSet /* cursorSet */ +}; + +#ifdef EXP_WIN32_DRIVER +/* + * The terminfo driver is mandatory and must always be present. + * So this is the natural place for the driver initialisation + * logic. + */ + +typedef struct DriverEntry { + const char *name; + TERM_DRIVER *driver; +} DRIVER_ENTRY; + +static DRIVER_ENTRY DriverTable[] = +{ +#ifdef _NC_WINDOWS + {"win32console", &_nc_WIN_DRIVER}, +#endif + {"tinfo", &_nc_TINFO_DRIVER} /* must be last */ }; + +NCURSES_EXPORT(int) +_nc_get_driver(TERMINAL_CONTROL_BLOCK * TCB, const char *name, int *errret) +{ + int code = ERR; + size_t i; + TERM_DRIVER *res = (TERM_DRIVER *) 0; + TERM_DRIVER *use = 0; + + T((T_CALLED("_nc_get_driver(%p, %s, %p)"), + (void *) TCB, NonNull(name), (void *) errret)); + + assert(TCB != 0); + + for (i = 0; i < SIZEOF(DriverTable); i++) { + res = DriverTable[i].driver; +#ifdef _NC_WINDOWS + if ((i + 1) == SIZEOF(DriverTable)) { + /* For Windows >= 10.0.17763 Windows Console interface implements + virtual Terminal functionality. + If on Windows td_CanHandle returned FALSE although the terminal + name is empty, we default to ms-terminal as tinfo TERM type. + */ + if (name == 0 || *name == 0 || (strcmp(name, "unknown") == 0)) { + name = MS_TERMINAL; + T(("Set TERM=%s", name)); + } + } +#endif + if (strcmp(DriverTable[i].name, res->td_name(TCB)) == 0) { + if (res->td_CanHandle(TCB, name, errret)) { + use = res; + break; + } + } + } + if (use != 0) { + TCB->drv = use; + code = OK; + } + returnCode(code); +} +#endif /* EXP_WIN32_DRIVER */