1 /****************************************************************************
2 * Copyright 2018-2019,2020 Thomas E. Dickey *
3 * Copyright 2008-2016,2017 Free Software Foundation, Inc. *
4 * *
5 * Permission is hereby granted, free of charge, to any person obtaining a *
6 * copy of this software and associated documentation files (the *
7 * "Software"), to deal in the Software without restriction, including *
8 * without limitation the rights to use, copy, modify, merge, publish, *
9 * distribute, distribute with modifications, sublicense, and/or sell *
10 * copies of the Software, and to permit persons to whom the Software is *
11 * furnished to do so, subject to the following conditions: *
12 * *
13 * The above copyright notice and this permission notice shall be included *
14 * in all copies or substantial portions of the Software. *
15 * *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
19 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
22 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
23 * *
24 * Except as contained in this notice, the name(s) of the above copyright *
25 * holders shall not be used in advertising or otherwise to promote the *
26 * sale, use or other dealings in this Software without prior written *
27 * authorization. *
28 ****************************************************************************/
29
30 /****************************************************************************
31 * Author: Juergen Pfeifer *
32 * and: Thomas E. Dickey *
33 ****************************************************************************/
34
35 #include <curses.priv.h>
36 #define CUR TerminalType((TERMINAL*)TCB).
37 #include <tic.h>
38 #include <termcap.h> /* ospeed */
39
40 #if HAVE_NANOSLEEP
41 #include <time.h>
42 #if HAVE_SYS_TIME_H
43 #include <sys/time.h> /* needed for MacOS X DP3 */
44 #endif
45 #endif
46
47 #if HAVE_SIZECHANGE
48 # if !defined(sun) || !TERMIOS
49 # if HAVE_SYS_IOCTL_H
50 # include <sys/ioctl.h>
51 # endif
52 # endif
53 #endif
54
55 MODULE_ID("$Id: tinfo_driver.c,v 1.67 2020/02/02 23:34:34 tom Exp $")
56
57 /*
58 * SCO defines TIOCGSIZE and the corresponding struct. Other systems (SunOS,
59 * Solaris, IRIX) define TIOCGWINSZ and struct winsize.
60 */
61 #ifdef TIOCGSIZE
62 # define IOCTL_WINSIZE TIOCGSIZE
63 # define STRUCT_WINSIZE struct ttysize
64 # define WINSIZE_ROWS(n) (int)n.ts_lines
65 # define WINSIZE_COLS(n) (int)n.ts_cols
66 #else
67 # ifdef TIOCGWINSZ
68 # define IOCTL_WINSIZE TIOCGWINSZ
69 # define STRUCT_WINSIZE struct winsize
70 # define WINSIZE_ROWS(n) (int)n.ws_row
71 # define WINSIZE_COLS(n) (int)n.ws_col
72 # endif
73 #endif
74
75 /*
76 * These should be screen structure members. They need to be globals for
77 * historical reasons. So we assign them in start_color() and also in
78 * set_term()'s screen-switching logic.
79 */
80 #if USE_REENTRANT
NCURSES_EXPORT(int)81 NCURSES_EXPORT(int)
82 NCURSES_PUBLIC_VAR(COLOR_PAIRS) (void)
83 {
84 return CURRENT_SCREEN ? CURRENT_SCREEN->_pair_count : -1;
85 }
86 NCURSES_EXPORT(int)
NCURSES_PUBLIC_VAR(COLORS)87 NCURSES_PUBLIC_VAR(COLORS) (void)
88 {
89 return CURRENT_SCREEN ? CURRENT_SCREEN->_color_count : -1;
90 }
91 #else
92 NCURSES_EXPORT_VAR(int) COLOR_PAIRS = 0;
93 NCURSES_EXPORT_VAR(int) COLORS = 0;
94 #endif
95
96 #define TCBMAGIC NCDRV_MAGIC(NCDRV_TINFO)
97 #define AssertTCB() assert(TCB!=0 && TCB->magic==TCBMAGIC)
98 #define SetSP() assert(TCB->csp!=0); sp = TCB->csp; (void) sp
99
100 /*
101 * This routine needs to do all the work to make curscr look
102 * like newscr.
103 */
104 static int
drv_doupdate(TERMINAL_CONTROL_BLOCK * TCB)105 drv_doupdate(TERMINAL_CONTROL_BLOCK * TCB)
106 {
107 AssertTCB();
108 return TINFO_DOUPDATE(TCB->csp);
109 }
110
111 static const char *
drv_Name(TERMINAL_CONTROL_BLOCK * TCB)112 drv_Name(TERMINAL_CONTROL_BLOCK * TCB)
113 {
114 (void) TCB;
115 return "tinfo";
116 }
117
118 static void
get_baudrate(TERMINAL * termp)119 get_baudrate(TERMINAL *termp)
120 {
121 int my_ospeed;
122 int result;
123 if (GET_TTY(termp->Filedes, &termp->Nttyb) == OK) {
124 #ifdef TERMIOS
125 termp->Nttyb.c_oflag &= (unsigned) (~OFLAGS_TABS);
126 #else
127 termp->Nttyb.sg_flags &= (unsigned) (~XTABS);
128 #endif
129 }
130 #ifdef USE_OLD_TTY
131 result = (int) cfgetospeed(&(termp->Nttyb));
132 my_ospeed = (NCURSES_OSPEED) _nc_ospeed(result);
133 #else /* !USE_OLD_TTY */
134 #ifdef TERMIOS
135 my_ospeed = (NCURSES_OSPEED) cfgetospeed(&(termp->Nttyb));
136 #else
137 my_ospeed = (NCURSES_OSPEED) termp->Nttyb.sg_ospeed;
138 #endif
139 result = _nc_baudrate(my_ospeed);
140 #endif
141 termp->_baudrate = result;
142 ospeed = (NCURSES_OSPEED) my_ospeed;
143 }
144
145 #undef SETUP_FAIL
146 #define SETUP_FAIL FALSE
147
148 #define NO_COPY {}
149
150 static bool
drv_CanHandle(TERMINAL_CONTROL_BLOCK * TCB,const char * tname,int * errret)151 drv_CanHandle(TERMINAL_CONTROL_BLOCK * TCB, const char *tname, int *errret)
152 {
153 bool result = FALSE;
154 int status;
155 TERMINAL *termp;
156 SCREEN *sp;
157
158 START_TRACE();
159 T((T_CALLED("tinfo::drv_CanHandle(%p)"), (void *) TCB));
160
161 assert(TCB != 0 && tname != 0);
162 termp = (TERMINAL *) TCB;
163 sp = TCB->csp;
164 TCB->magic = TCBMAGIC;
165
166 #if (NCURSES_USE_DATABASE || NCURSES_USE_TERMCAP)
167 status = _nc_setup_tinfo(tname, &TerminalType(termp));
168 T(("_nc_setup_tinfo returns %d", status));
169 #else
170 T(("no database available"));
171 status = TGETENT_NO;
172 #endif
173
174 /* try fallback list if entry on disk */
175 if (status != TGETENT_YES) {
176 const TERMTYPE2 *fallback = _nc_fallback2(tname);
177
178 if (fallback) {
179 T(("found fallback entry"));
180 TerminalType(termp) = *fallback;
181 status = TGETENT_YES;
182 }
183 }
184
185 if (status != TGETENT_YES) {
186 NCURSES_SP_NAME(del_curterm) (NCURSES_SP_ARGx termp);
187 if (status == TGETENT_ERR) {
188 ret_error0(status, "terminals database is inaccessible\n");
189 } else if (status == TGETENT_NO) {
190 ret_error1(status, "unknown terminal type.\n",
191 tname, NO_COPY);
192 } else {
193 ret_error0(status, "unexpected return-code\n");
194 }
195 }
196 result = TRUE;
197 #if NCURSES_EXT_NUMBERS
198 _nc_export_termtype2(&termp->type, &TerminalType(termp));
199 #endif
200 #if !USE_REENTRANT
201 save_ttytype(termp);
202 #endif
203
204 if (command_character)
205 _nc_tinfo_cmdch(termp, *command_character);
206
207 /*
208 * If an application calls setupterm() rather than initscr() or
209 * newterm(), we will not have the def_prog_mode() call in
210 * _nc_setupscreen(). Do it now anyway, so we can initialize the
211 * baudrate.
212 */
213 if (sp == 0 && NC_ISATTY(termp->Filedes)) {
214 get_baudrate(termp);
215 }
216 #if NCURSES_EXT_NUMBERS
217 #define cleanup_termtype() \
218 _nc_free_termtype2(&TerminalType(termp)); \
219 _nc_free_termtype(&termp->type)
220 #else
221 #define cleanup_termtype() \
222 _nc_free_termtype2(&TerminalType(termp))
223 #endif
224
225 if (generic_type) {
226 /*
227 * BSD 4.3's termcap contains mis-typed "gn" for wy99. Do a sanity
228 * check before giving up.
229 */
230 if ((VALID_STRING(cursor_address)
231 || (VALID_STRING(cursor_down) && VALID_STRING(cursor_home)))
232 && VALID_STRING(clear_screen)) {
233 cleanup_termtype();
234 ret_error1(TGETENT_YES, "terminal is not really generic.\n",
235 tname, NO_COPY);
236 } else {
237 cleanup_termtype();
238 ret_error1(TGETENT_NO, "I need something more specific.\n",
239 tname, NO_COPY);
240 }
241 }
242 if (hard_copy) {
243 cleanup_termtype();
244 ret_error1(TGETENT_YES, "I can't handle hardcopy terminals.\n",
245 tname, NO_COPY);
246 }
247
248 returnBool(result);
249 }
250
251 static int
drv_dobeepflash(TERMINAL_CONTROL_BLOCK * TCB,int beepFlag)252 drv_dobeepflash(TERMINAL_CONTROL_BLOCK * TCB, int beepFlag)
253 {
254 SCREEN *sp;
255 int res = ERR;
256
257 AssertTCB();
258 SetSP();
259
260 /* FIXME: should make sure that we are not in altchar mode */
261 if (beepFlag) {
262 if (bell) {
263 res = NCURSES_PUTP2("bell", bell);
264 NCURSES_SP_NAME(_nc_flush) (sp);
265 } else if (flash_screen) {
266 res = NCURSES_PUTP2("flash_screen", flash_screen);
267 NCURSES_SP_NAME(_nc_flush) (sp);
268 }
269 } else {
270 if (flash_screen) {
271 res = NCURSES_PUTP2("flash_screen", flash_screen);
272 NCURSES_SP_NAME(_nc_flush) (sp);
273 } else if (bell) {
274 res = NCURSES_PUTP2("bell", bell);
275 NCURSES_SP_NAME(_nc_flush) (sp);
276 }
277 }
278 return res;
279 }
280
281 /*
282 * SVr4 curses is known to interchange color codes (1,4) and (3,6), possibly
283 * to maintain compatibility with a pre-ANSI scheme. The same scheme is
284 * also used in the FreeBSD syscons.
285 */
286 static int
toggled_colors(int c)287 toggled_colors(int c)
288 {
289 if (c < 16) {
290 static const int table[] =
291 {0, 4, 2, 6, 1, 5, 3, 7,
292 8, 12, 10, 14, 9, 13, 11, 15};
293 c = table[c];
294 }
295 return c;
296 }
297
298 static int
drv_print(TERMINAL_CONTROL_BLOCK * TCB,char * data,int len)299 drv_print(TERMINAL_CONTROL_BLOCK * TCB, char *data, int len)
300 {
301 SCREEN *sp;
302
303 AssertTCB();
304 SetSP();
305 #if NCURSES_EXT_FUNCS
306 return NCURSES_SP_NAME(mcprint) (TCB->csp, data, len);
307 #else
308 return ERR;
309 #endif
310 }
311
312 static int
drv_defaultcolors(TERMINAL_CONTROL_BLOCK * TCB,int fg,int bg)313 drv_defaultcolors(TERMINAL_CONTROL_BLOCK * TCB, int fg, int bg)
314 {
315 SCREEN *sp;
316 int code = ERR;
317
318 AssertTCB();
319 SetSP();
320
321 if (sp != 0 && orig_pair && orig_colors && (initialize_pair != 0)) {
322 #if NCURSES_EXT_FUNCS
323 sp->_default_color = isDefaultColor(fg) || isDefaultColor(bg);
324 sp->_has_sgr_39_49 = (NCURSES_SP_NAME(tigetflag) (NCURSES_SP_ARGx
325 "AX")
326 == TRUE);
327 sp->_default_fg = isDefaultColor(fg) ? COLOR_DEFAULT : fg;
328 sp->_default_bg = isDefaultColor(bg) ? COLOR_DEFAULT : bg;
329 if (sp->_color_pairs != 0) {
330 bool save = sp->_default_color;
331 sp->_default_color = TRUE;
332 NCURSES_SP_NAME(init_pair) (NCURSES_SP_ARGx
333 0,
334 (short)fg,
335 (short)bg);
336 sp->_default_color = save;
337 }
338 #endif
339 code = OK;
340 }
341 return (code);
342 }
343
344 static void
drv_setcolor(TERMINAL_CONTROL_BLOCK * TCB,int fore,int color,NCURSES_SP_OUTC outc)345 drv_setcolor(TERMINAL_CONTROL_BLOCK * TCB,
346 int fore,
347 int color,
348 NCURSES_SP_OUTC outc)
349 {
350 SCREEN *sp;
351
352 AssertTCB();
353 SetSP();
354
355 if (fore) {
356 if (set_a_foreground) {
357 TPUTS_TRACE("set_a_foreground");
358 NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx
359 TPARM_1(set_a_foreground, color), 1, outc);
360 } else {
361 TPUTS_TRACE("set_foreground");
362 NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx
363 TPARM_1(set_foreground,
364 toggled_colors(color)), 1, outc);
365 }
366 } else {
367 if (set_a_background) {
368 TPUTS_TRACE("set_a_background");
369 NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx
370 TPARM_1(set_a_background, color), 1, outc);
371 } else {
372 TPUTS_TRACE("set_background");
373 NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx
374 TPARM_1(set_background,
375 toggled_colors(color)), 1, outc);
376 }
377 }
378 }
379
380 static bool
drv_rescol(TERMINAL_CONTROL_BLOCK * TCB)381 drv_rescol(TERMINAL_CONTROL_BLOCK * TCB)
382 {
383 bool result = FALSE;
384 SCREEN *sp;
385
386 AssertTCB();
387 SetSP();
388
389 if (orig_pair != 0) {
390 NCURSES_PUTP2("orig_pair", orig_pair);
391 result = TRUE;
392 }
393 return result;
394 }
395
396 static bool
drv_rescolors(TERMINAL_CONTROL_BLOCK * TCB)397 drv_rescolors(TERMINAL_CONTROL_BLOCK * TCB)
398 {
399 int result = FALSE;
400 SCREEN *sp;
401
402 AssertTCB();
403 SetSP();
404
405 if (orig_colors != 0) {
406 NCURSES_PUTP2("orig_colors", orig_colors);
407 result = TRUE;
408 }
409 return result;
410 }
411
412 static int
drv_size(TERMINAL_CONTROL_BLOCK * TCB,int * linep,int * colp)413 drv_size(TERMINAL_CONTROL_BLOCK * TCB, int *linep, int *colp)
414 {
415 SCREEN *sp;
416 bool useEnv = TRUE;
417 bool useTioctl = TRUE;
418
419 AssertTCB();
420 sp = TCB->csp; /* can be null here */
421
422 if (sp) {
423 useEnv = sp->_use_env;
424 useTioctl = sp->use_tioctl;
425 } else {
426 useEnv = _nc_prescreen.use_env;
427 useTioctl = _nc_prescreen.use_tioctl;
428 }
429
430 /* figure out the size of the screen */
431 T(("screen size: terminfo lines = %d columns = %d", lines, columns));
432
433 *linep = (int) lines;
434 *colp = (int) columns;
435
436 if (useEnv || useTioctl) {
437 int value;
438
439 #ifdef __EMX__
440 {
441 int screendata[2];
442 _scrsize(screendata);
443 *colp = screendata[0];
444 *linep = ((sp != 0 && sp->_filtered)
445 ? 1
446 : screendata[1]);
447 T(("EMX screen size: environment LINES = %d COLUMNS = %d",
448 *linep, *colp));
449 }
450 #endif
451 #if HAVE_SIZECHANGE
452 /* try asking the OS */
453 {
454 TERMINAL *termp = (TERMINAL *) TCB;
455 if (NC_ISATTY(termp->Filedes)) {
456 STRUCT_WINSIZE size;
457
458 errno = 0;
459 do {
460 if (ioctl(termp->Filedes, IOCTL_WINSIZE, &size) >= 0) {
461 *linep = ((sp != 0 && sp->_filtered)
462 ? 1
463 : WINSIZE_ROWS(size));
464 *colp = WINSIZE_COLS(size);
465 T(("SYS screen size: environment LINES = %d COLUMNS = %d",
466 *linep, *colp));
467 break;
468 }
469 } while
470 (errno == EINTR);
471 }
472 }
473 #endif /* HAVE_SIZECHANGE */
474
475 if (useEnv) {
476 if (useTioctl) {
477 /*
478 * If environment variables are used, update them.
479 */
480 if ((sp == 0 || !sp->_filtered) && _nc_getenv_num("LINES") > 0) {
481 _nc_setenv_num("LINES", *linep);
482 }
483 if (_nc_getenv_num("COLUMNS") > 0) {
484 _nc_setenv_num("COLUMNS", *colp);
485 }
486 }
487
488 /*
489 * Finally, look for environment variables.
490 *
491 * Solaris lets users override either dimension with an environment
492 * variable.
493 */
494 if ((value = _nc_getenv_num("LINES")) > 0) {
495 *linep = value;
496 T(("screen size: environment LINES = %d", *linep));
497 }
498 if ((value = _nc_getenv_num("COLUMNS")) > 0) {
499 *colp = value;
500 T(("screen size: environment COLUMNS = %d", *colp));
501 }
502 }
503
504 /* if we can't get dynamic info about the size, use static */
505 if (*linep <= 0) {
506 *linep = (int) lines;
507 }
508 if (*colp <= 0) {
509 *colp = (int) columns;
510 }
511
512 /* the ultimate fallback, assume fixed 24x80 size */
513 if (*linep <= 0) {
514 *linep = 24;
515 }
516 if (*colp <= 0) {
517 *colp = 80;
518 }
519
520 /*
521 * Put the derived values back in the screen-size caps, so
522 * tigetnum() and tgetnum() will do the right thing.
523 */
524 lines = (short) (*linep);
525 columns = (short) (*colp);
526 }
527
528 T(("screen size is %dx%d", *linep, *colp));
529 return OK;
530 }
531
532 static int
drv_getsize(TERMINAL_CONTROL_BLOCK * TCB,int * l,int * c)533 drv_getsize(TERMINAL_CONTROL_BLOCK * TCB, int *l, int *c)
534 {
535 AssertTCB();
536 assert(l != 0 && c != 0);
537 *l = lines;
538 *c = columns;
539 return OK;
540 }
541
542 static int
drv_setsize(TERMINAL_CONTROL_BLOCK * TCB,int l,int c)543 drv_setsize(TERMINAL_CONTROL_BLOCK * TCB, int l, int c)
544 {
545 AssertTCB();
546 lines = (short) l;
547 columns = (short) c;
548 return OK;
549 }
550
551 static int
drv_sgmode(TERMINAL_CONTROL_BLOCK * TCB,int setFlag,TTY * buf)552 drv_sgmode(TERMINAL_CONTROL_BLOCK * TCB, int setFlag, TTY * buf)
553 {
554 SCREEN *sp = TCB->csp;
555 TERMINAL *_term = (TERMINAL *) TCB;
556 int result = OK;
557
558 AssertTCB();
559 if (setFlag) {
560 for (;;) {
561 if (SET_TTY(_term->Filedes, buf) != 0) {
562 if (errno == EINTR)
563 continue;
564 if (errno == ENOTTY) {
565 if (sp)
566 sp->_notty = TRUE;
567 }
568 result = ERR;
569 }
570 break;
571 }
572 } else {
573 for (;;) {
574 if (GET_TTY(_term->Filedes, buf) != 0) {
575 if (errno == EINTR)
576 continue;
577 result = ERR;
578 }
579 break;
580 }
581 }
582 return result;
583 }
584
585 static int
drv_mode(TERMINAL_CONTROL_BLOCK * TCB,int progFlag,int defFlag)586 drv_mode(TERMINAL_CONTROL_BLOCK * TCB, int progFlag, int defFlag)
587 {
588 SCREEN *sp;
589 TERMINAL *_term = (TERMINAL *) TCB;
590 int code = ERR;
591
592 AssertTCB();
593 sp = TCB->csp;
594
595 if (progFlag) /* prog mode */
596 {
597 if (defFlag) {
598 /* def_prog_mode */
599 /*
600 * Turn off the XTABS bit in the tty structure if it was on.
601 */
602 if ((drv_sgmode(TCB, FALSE, &(_term->Nttyb)) == OK)) {
603 #ifdef TERMIOS
604 _term->Nttyb.c_oflag &= (unsigned) ~OFLAGS_TABS;
605 #else
606 _term->Nttyb.sg_flags &= (unsigned) ~XTABS;
607 #endif
608 code = OK;
609 }
610 } else {
611 /* reset_prog_mode */
612 if (drv_sgmode(TCB, TRUE, &(_term->Nttyb)) == OK) {
613 if (sp) {
614 if (sp->_keypad_on)
615 _nc_keypad(sp, TRUE);
616 }
617 code = OK;
618 }
619 }
620 } else { /* shell mode */
621 if (defFlag) {
622 /* def_shell_mode */
623 /*
624 * If XTABS was on, remove the tab and backtab capabilities.
625 */
626 if (drv_sgmode(TCB, FALSE, &(_term->Ottyb)) == OK) {
627 #ifdef TERMIOS
628 if (_term->Ottyb.c_oflag & OFLAGS_TABS)
629 tab = back_tab = NULL;
630 #else
631 if (_term->Ottyb.sg_flags & XTABS)
632 tab = back_tab = NULL;
633 #endif
634 code = OK;
635 }
636 } else {
637 /* reset_shell_mode */
638 if (sp) {
639 _nc_keypad(sp, FALSE);
640 NCURSES_SP_NAME(_nc_flush) (sp);
641 }
642 code = drv_sgmode(TCB, TRUE, &(_term->Ottyb));
643 }
644 }
645 return (code);
646 }
647
648 static void
drv_wrap(SCREEN * sp)649 drv_wrap(SCREEN *sp)
650 {
651 if (sp) {
652 sp->_mouse_wrap(sp);
653 NCURSES_SP_NAME(_nc_screen_wrap) (sp);
654 NCURSES_SP_NAME(_nc_mvcur_wrap) (sp); /* wrap up cursor addressing */
655 }
656 }
657
658 static void
drv_release(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED)659 drv_release(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED)
660 {
661 }
662
663 # define SGR0_TEST(mode) (mode != 0) && (exit_attribute_mode == 0 || strcmp(mode, exit_attribute_mode))
664
665 static void
drv_screen_init(SCREEN * sp)666 drv_screen_init(SCREEN *sp)
667 {
668 TERMINAL_CONTROL_BLOCK *TCB = TCBOf(sp);
669
670 AssertTCB();
671
672 /*
673 * Check for mismatched graphic-rendition capabilities. Most SVr4
674 * terminfo trees contain entries that have rmul or rmso equated to
675 * sgr0 (Solaris curses copes with those entries). We do this only
676 * for curses, since many termcap applications assume that
677 * smso/rmso and smul/rmul are paired, and will not function
678 * properly if we remove rmso or rmul. Curses applications
679 * shouldn't be looking at this detail.
680 */
681 sp->_use_rmso = SGR0_TEST(exit_standout_mode);
682 sp->_use_rmul = SGR0_TEST(exit_underline_mode);
683
684 /*
685 * Check whether we can optimize scrolling under dumb terminals in
686 * case we do not have any of these capabilities, scrolling
687 * optimization will be useless.
688 */
689 sp->_scrolling = ((scroll_forward && scroll_reverse) ||
690 ((parm_rindex ||
691 parm_insert_line ||
692 insert_line) &&
693 (parm_index ||
694 parm_delete_line ||
695 delete_line)));
696
697 NCURSES_SP_NAME(baudrate) (sp);
698
699 NCURSES_SP_NAME(_nc_mvcur_init) (sp);
700 /* initialize terminal to a sane state */
701 NCURSES_SP_NAME(_nc_screen_init) (sp);
702 }
703
704 static void
drv_init(TERMINAL_CONTROL_BLOCK * TCB)705 drv_init(TERMINAL_CONTROL_BLOCK * TCB)
706 {
707 TERMINAL *trm;
708
709 AssertTCB();
710
711 trm = (TERMINAL *) TCB;
712
713 TCB->info.initcolor = VALID_STRING(initialize_color);
714 TCB->info.canchange = can_change;
715 TCB->info.hascolor = ((VALID_NUMERIC(max_colors) && VALID_NUMERIC(max_pairs)
716 && (((set_foreground != NULL)
717 && (set_background != NULL))
718 || ((set_a_foreground != NULL)
719 && (set_a_background != NULL))
720 || set_color_pair)) ? TRUE : FALSE);
721
722 TCB->info.caninit = !(exit_ca_mode && non_rev_rmcup);
723
724 TCB->info.maxpairs = VALID_NUMERIC(max_pairs) ? max_pairs : 0;
725 TCB->info.maxcolors = VALID_NUMERIC(max_colors) ? max_colors : 0;
726 TCB->info.numlabels = VALID_NUMERIC(num_labels) ? num_labels : 0;
727 TCB->info.labelwidth = VALID_NUMERIC(label_width) ? label_width : 0;
728 TCB->info.labelheight = VALID_NUMERIC(label_height) ? label_height : 0;
729 TCB->info.nocolorvideo = VALID_NUMERIC(no_color_video) ? no_color_video
730 : 0;
731 TCB->info.tabsize = VALID_NUMERIC(init_tabs) ? (int) init_tabs : 8;
732
733 TCB->info.defaultPalette = hue_lightness_saturation ? _nc_hls_palette : _nc_cga_palette;
734
735 /*
736 * If an application calls setupterm() rather than initscr() or
737 * newterm(), we will not have the def_prog_mode() call in
738 * _nc_setupscreen(). Do it now anyway, so we can initialize the
739 * baudrate.
740 */
741 if (NC_ISATTY(trm->Filedes)) {
742 TCB->drv->td_mode(TCB, TRUE, TRUE);
743 }
744 }
745
746 #define MAX_PALETTE 8
747 #define InPalette(n) ((n) >= 0 && (n) < MAX_PALETTE)
748
749 static void
drv_initpair(TERMINAL_CONTROL_BLOCK * TCB,int pair,int f,int b)750 drv_initpair(TERMINAL_CONTROL_BLOCK * TCB, int pair, int f, int b)
751 {
752 SCREEN *sp;
753
754 AssertTCB();
755 SetSP();
756
757 if ((initialize_pair != NULL) && InPalette(f) && InPalette(b)) {
758 const color_t *tp = InfoOf(sp).defaultPalette;
759
760 TR(TRACE_ATTRS,
761 ("initializing pair: pair = %d, fg=(%d,%d,%d), bg=(%d,%d,%d)",
762 pair,
763 tp[f].red, tp[f].green, tp[f].blue,
764 tp[b].red, tp[b].green, tp[b].blue));
765
766 NCURSES_PUTP2("initialize_pair",
767 TPARM_7(initialize_pair,
768 pair,
769 tp[f].red, tp[f].green, tp[f].blue,
770 tp[b].red, tp[b].green, tp[b].blue));
771 }
772 }
773
774 static int
default_fg(SCREEN * sp)775 default_fg(SCREEN *sp)
776 {
777 #if NCURSES_EXT_FUNCS
778 return (sp != 0) ? sp->_default_fg : COLOR_WHITE;
779 #else
780 return COLOR_WHITE;
781 #endif
782 }
783
784 static int
default_bg(SCREEN * sp)785 default_bg(SCREEN *sp)
786 {
787 #if NCURSES_EXT_FUNCS
788 return sp != 0 ? sp->_default_bg : COLOR_BLACK;
789 #else
790 return COLOR_BLACK;
791 #endif
792 }
793
794 static void
drv_initcolor(TERMINAL_CONTROL_BLOCK * TCB,int color,int r,int g,int b)795 drv_initcolor(TERMINAL_CONTROL_BLOCK * TCB,
796 int color, int r, int g, int b)
797 {
798 SCREEN *sp = TCB->csp;
799
800 AssertTCB();
801 if (initialize_color != NULL) {
802 NCURSES_PUTP2("initialize_color",
803 TPARM_4(initialize_color, color, r, g, b));
804 }
805 }
806
807 static void
drv_do_color(TERMINAL_CONTROL_BLOCK * TCB,int old_pair,int pair,int reverse,NCURSES_SP_OUTC outc)808 drv_do_color(TERMINAL_CONTROL_BLOCK * TCB,
809 int old_pair,
810 int pair,
811 int reverse,
812 NCURSES_SP_OUTC outc)
813 {
814 SCREEN *sp = TCB->csp;
815 int fg = COLOR_DEFAULT;
816 int bg = COLOR_DEFAULT;
817 int old_fg, old_bg;
818
819 AssertTCB();
820 if (sp == 0)
821 return;
822
823 if (pair < 0 || pair >= COLOR_PAIRS) {
824 return;
825 } else if (pair != 0) {
826 if (set_color_pair) {
827 TPUTS_TRACE("set_color_pair");
828 NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx
829 TPARM_1(set_color_pair, pair), 1, outc);
830 return;
831 } else if (sp != 0) {
832 _nc_pair_content(SP_PARM, pair, &fg, &bg);
833 }
834 }
835
836 if (old_pair >= 0
837 && sp != 0
838 && _nc_pair_content(SP_PARM, old_pair, &old_fg, &old_bg) != ERR) {
839 if ((isDefaultColor(fg) && !isDefaultColor(old_fg))
840 || (isDefaultColor(bg) && !isDefaultColor(old_bg))) {
841 #if NCURSES_EXT_FUNCS
842 /*
843 * A minor optimization - but extension. If "AX" is specified in
844 * the terminal description, treat it as screen's indicator of ECMA
845 * SGR 39 and SGR 49, and assume the two sequences are independent.
846 */
847 if (sp->_has_sgr_39_49
848 && isDefaultColor(old_bg)
849 && !isDefaultColor(old_fg)) {
850 NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx "\033[39m", 1, outc);
851 } else if (sp->_has_sgr_39_49
852 && isDefaultColor(old_fg)
853 && !isDefaultColor(old_bg)) {
854 NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx "\033[49m", 1, outc);
855 } else
856 #endif
857 drv_rescol(TCB);
858 }
859 } else {
860 drv_rescol(TCB);
861 if (old_pair < 0)
862 return;
863 }
864
865 #if NCURSES_EXT_FUNCS
866 if (isDefaultColor(fg))
867 fg = default_fg(sp);
868 if (isDefaultColor(bg))
869 bg = default_bg(sp);
870 #endif
871
872 if (reverse) {
873 int xx = fg;
874 fg = bg;
875 bg = xx;
876 }
877
878 TR(TRACE_ATTRS, ("setting colors: pair = %d, fg = %d, bg = %d", pair,
879 fg, bg));
880
881 if (!isDefaultColor(fg)) {
882 drv_setcolor(TCB, TRUE, fg, outc);
883 }
884 if (!isDefaultColor(bg)) {
885 drv_setcolor(TCB, FALSE, bg, outc);
886 }
887 }
888
889 #define xterm_kmous "\033[M"
890 static void
init_xterm_mouse(SCREEN * sp)891 init_xterm_mouse(SCREEN *sp)
892 {
893 sp->_mouse_type = M_XTERM;
894 sp->_mouse_xtermcap = NCURSES_SP_NAME(tigetstr) (NCURSES_SP_ARGx "XM");
895 if (!VALID_STRING(sp->_mouse_xtermcap))
896 sp->_mouse_xtermcap = "\033[?1000%?%p1%{1}%=%th%el%;";
897 }
898
899 static void
drv_initmouse(TERMINAL_CONTROL_BLOCK * TCB)900 drv_initmouse(TERMINAL_CONTROL_BLOCK * TCB)
901 {
902 SCREEN *sp;
903
904 AssertTCB();
905 SetSP();
906
907 /* we know how to recognize mouse events under "xterm" */
908 if (sp != 0) {
909 if (NonEmpty(key_mouse)) {
910 init_xterm_mouse(sp);
911 } else if (strstr(SP_TERMTYPE term_names, "xterm") != 0) {
912 if (_nc_add_to_try(&(sp->_keytry), xterm_kmous, KEY_MOUSE) == OK)
913 init_xterm_mouse(sp);
914 }
915 }
916 }
917
918 static int
drv_testmouse(TERMINAL_CONTROL_BLOCK * TCB,int delay EVENTLIST_2nd (_nc_eventlist * evl))919 drv_testmouse(TERMINAL_CONTROL_BLOCK * TCB,
920 int delay
921 EVENTLIST_2nd(_nc_eventlist * evl))
922 {
923 int rc = 0;
924 SCREEN *sp;
925
926 AssertTCB();
927 SetSP();
928
929 #if USE_SYSMOUSE
930 if ((sp->_mouse_type == M_SYSMOUSE)
931 && (sp->_sysmouse_head < sp->_sysmouse_tail)) {
932 rc = TW_MOUSE;
933 } else
934 #endif
935 {
936 rc = TCBOf(sp)->drv->td_twait(TCBOf(sp),
937 TWAIT_MASK,
938 delay,
939 (int *) 0
940 EVENTLIST_2nd(evl));
941 #if USE_SYSMOUSE
942 if ((sp->_mouse_type == M_SYSMOUSE)
943 && (sp->_sysmouse_head < sp->_sysmouse_tail)
944 && (rc == 0)
945 && (errno == EINTR)) {
946 rc |= TW_MOUSE;
947 }
948 #endif
949 }
950 return rc;
951 }
952
953 static int
drv_mvcur(TERMINAL_CONTROL_BLOCK * TCB,int yold,int xold,int ynew,int xnew)954 drv_mvcur(TERMINAL_CONTROL_BLOCK * TCB, int yold, int xold, int ynew, int xnew)
955 {
956 SCREEN *sp = TCB->csp;
957 AssertTCB();
958 return NCURSES_SP_NAME(_nc_mvcur) (sp, yold, xold, ynew, xnew);
959 }
960
961 static void
drv_hwlabel(TERMINAL_CONTROL_BLOCK * TCB,int labnum,char * text)962 drv_hwlabel(TERMINAL_CONTROL_BLOCK * TCB, int labnum, char *text)
963 {
964 SCREEN *sp = TCB->csp;
965
966 AssertTCB();
967 if (labnum > 0 && labnum <= num_labels) {
968 NCURSES_PUTP2("plab_norm",
969 TPARM_2(plab_norm, labnum, text));
970 }
971 }
972
973 static void
drv_hwlabelOnOff(TERMINAL_CONTROL_BLOCK * TCB,int OnFlag)974 drv_hwlabelOnOff(TERMINAL_CONTROL_BLOCK * TCB, int OnFlag)
975 {
976 SCREEN *sp = TCB->csp;
977
978 AssertTCB();
979 if (OnFlag) {
980 NCURSES_PUTP2("label_on", label_on);
981 } else {
982 NCURSES_PUTP2("label_off", label_off);
983 }
984 }
985
986 static chtype
drv_conattr(TERMINAL_CONTROL_BLOCK * TCB)987 drv_conattr(TERMINAL_CONTROL_BLOCK * TCB)
988 {
989 SCREEN *sp = TCB->csp;
990 chtype attrs = A_NORMAL;
991
992 AssertTCB();
993 if (enter_alt_charset_mode)
994 attrs |= A_ALTCHARSET;
995
996 if (enter_blink_mode)
997 attrs |= A_BLINK;
998
999 if (enter_bold_mode)
1000 attrs |= A_BOLD;
1001
1002 if (enter_dim_mode)
1003 attrs |= A_DIM;
1004
1005 if (enter_reverse_mode)
1006 attrs |= A_REVERSE;
1007
1008 if (enter_standout_mode)
1009 attrs |= A_STANDOUT;
1010
1011 if (enter_protected_mode)
1012 attrs |= A_PROTECT;
1013
1014 if (enter_secure_mode)
1015 attrs |= A_INVIS;
1016
1017 if (enter_underline_mode)
1018 attrs |= A_UNDERLINE;
1019
1020 if (sp && sp->_coloron)
1021 attrs |= A_COLOR;
1022
1023 #if USE_ITALIC
1024 if (enter_italics_mode)
1025 attrs |= A_ITALIC;
1026 #endif
1027
1028 return (attrs);
1029 }
1030
1031 static void
drv_setfilter(TERMINAL_CONTROL_BLOCK * TCB)1032 drv_setfilter(TERMINAL_CONTROL_BLOCK * TCB)
1033 {
1034 AssertTCB();
1035
1036 /* *INDENT-EQLS* */
1037 clear_screen = ABSENT_STRING;
1038 cursor_address = ABSENT_STRING;
1039 cursor_down = ABSENT_STRING;
1040 cursor_up = ABSENT_STRING;
1041 parm_down_cursor = ABSENT_STRING;
1042 parm_up_cursor = ABSENT_STRING;
1043 row_address = ABSENT_STRING;
1044 cursor_home = carriage_return;
1045
1046 if (back_color_erase)
1047 clr_eos = ABSENT_STRING;
1048 }
1049
1050 static void
drv_initacs(TERMINAL_CONTROL_BLOCK * TCB,chtype * real_map,chtype * fake_map)1051 drv_initacs(TERMINAL_CONTROL_BLOCK * TCB, chtype *real_map, chtype *fake_map)
1052 {
1053 SCREEN *sp = TCB->csp;
1054
1055 AssertTCB();
1056 assert(sp != 0);
1057 if (ena_acs != NULL) {
1058 NCURSES_PUTP2("ena_acs", ena_acs);
1059 }
1060 #if NCURSES_EXT_FUNCS
1061 /*
1062 * Linux console "supports" the "PC ROM" character set by the coincidence
1063 * that smpch/rmpch and smacs/rmacs have the same values. ncurses has
1064 * no codepage support (see SCO Merge for an example). Outside of the
1065 * values defined in acsc, there are no definitions for the "PC ROM"
1066 * character set (assumed by some applications to be codepage 437), but we
1067 * allow those applications to use those codepoints.
1068 *
1069 * test/blue.c uses this feature.
1070 */
1071 #define PCH_KLUDGE(a,b) (a != 0 && b != 0 && !strcmp(a,b))
1072 if (PCH_KLUDGE(enter_pc_charset_mode, enter_alt_charset_mode) &&
1073 PCH_KLUDGE(exit_pc_charset_mode, exit_alt_charset_mode)) {
1074 size_t i;
1075 for (i = 1; i < ACS_LEN; ++i) {
1076 if (real_map[i] == 0) {
1077 real_map[i] = (chtype) i;
1078 if (real_map != fake_map) {
1079 if (sp != 0)
1080 sp->_screen_acs_map[i] = TRUE;
1081 }
1082 }
1083 }
1084 }
1085 #endif
1086
1087 if (acs_chars != NULL) {
1088 size_t i = 0;
1089 size_t length = strlen(acs_chars);
1090
1091 while (i + 1 < length) {
1092 if (acs_chars[i] != 0 && UChar(acs_chars[i]) < ACS_LEN) {
1093 real_map[UChar(acs_chars[i])] = UChar(acs_chars[i + 1]) | A_ALTCHARSET;
1094 T(("#%d real_map[%s] = %s",
1095 (int) i,
1096 _tracechar(UChar(acs_chars[i])),
1097 _tracechtype(real_map[UChar(acs_chars[i])])));
1098 if (sp != 0) {
1099 sp->_screen_acs_map[UChar(acs_chars[i])] = TRUE;
1100 }
1101 }
1102 i += 2;
1103 }
1104 }
1105 #ifdef TRACE
1106 /* Show the equivalent mapping, noting if it does not match the
1107 * given attribute, whether by re-ordering or duplication.
1108 */
1109 if (USE_TRACEF(TRACE_CALLS)) {
1110 size_t n, m;
1111 char show[ACS_LEN * 2 + 1];
1112 for (n = 1, m = 0; n < ACS_LEN; n++) {
1113 if (real_map[n] != 0) {
1114 show[m++] = (char) n;
1115 show[m++] = (char) ChCharOf(real_map[n]);
1116 }
1117 }
1118 show[m] = 0;
1119 if (acs_chars == NULL || strcmp(acs_chars, show))
1120 _tracef("%s acs_chars %s",
1121 (acs_chars == NULL) ? "NULL" : "READ",
1122 _nc_visbuf(acs_chars));
1123 _tracef("%s acs_chars %s",
1124 (acs_chars == NULL)
1125 ? "NULL"
1126 : (strcmp(acs_chars, show)
1127 ? "DIFF"
1128 : "SAME"),
1129 _nc_visbuf(show));
1130 _nc_unlock_global(tracef);
1131 }
1132 #endif /* TRACE */
1133 }
1134
1135 #define ENSURE_TINFO(sp) (TCBOf(sp)->drv->isTerminfo)
1136
1137 NCURSES_EXPORT(void)
_nc_cookie_init(SCREEN * sp)1138 _nc_cookie_init(SCREEN *sp)
1139 {
1140 bool support_cookies = USE_XMC_SUPPORT;
1141 TERMINAL_CONTROL_BLOCK *TCB = (TERMINAL_CONTROL_BLOCK *) (sp->_term);
1142
1143 if (sp == 0 || !ENSURE_TINFO(sp))
1144 return;
1145
1146 #if USE_XMC_SUPPORT
1147 /*
1148 * If we have no magic-cookie support compiled-in, or if it is suppressed
1149 * in the environment, reset the support-flag.
1150 */
1151 if (magic_cookie_glitch >= 0) {
1152 if (getenv("NCURSES_NO_MAGIC_COOKIE") != 0) {
1153 support_cookies = FALSE;
1154 }
1155 }
1156 #endif
1157
1158 if (!support_cookies && magic_cookie_glitch >= 0) {
1159 T(("will disable attributes to work w/o magic cookies"));
1160 }
1161
1162 if (magic_cookie_glitch > 0) { /* tvi, wyse */
1163
1164 sp->_xmc_triggers = sp->_ok_attributes & XMC_CONFLICT;
1165 #if 0
1166 /*
1167 * We "should" treat colors as an attribute. The wyse350 (and its
1168 * clones) appear to be the only ones that have both colors and magic
1169 * cookies.
1170 */
1171 if (has_colors()) {
1172 sp->_xmc_triggers |= A_COLOR;
1173 }
1174 #endif
1175 sp->_xmc_suppress = sp->_xmc_triggers & (chtype) ~(A_BOLD);
1176
1177 T(("magic cookie attributes %s", _traceattr(sp->_xmc_suppress)));
1178 /*
1179 * Supporting line-drawing may be possible. But make the regular
1180 * video attributes work first.
1181 */
1182 acs_chars = ABSENT_STRING;
1183 ena_acs = ABSENT_STRING;
1184 enter_alt_charset_mode = ABSENT_STRING;
1185 exit_alt_charset_mode = ABSENT_STRING;
1186 #if USE_XMC_SUPPORT
1187 /*
1188 * To keep the cookie support simple, suppress all of the optimization
1189 * hooks except for clear_screen and the cursor addressing.
1190 */
1191 if (support_cookies) {
1192 clr_eol = ABSENT_STRING;
1193 clr_eos = ABSENT_STRING;
1194 set_attributes = ABSENT_STRING;
1195 }
1196 #endif
1197 } else if (magic_cookie_glitch == 0) { /* hpterm */
1198 }
1199
1200 /*
1201 * If magic cookies are not supported, cancel the strings that set
1202 * video attributes.
1203 */
1204 if (!support_cookies && magic_cookie_glitch >= 0) {
1205 magic_cookie_glitch = ABSENT_NUMERIC;
1206 set_attributes = ABSENT_STRING;
1207 enter_blink_mode = ABSENT_STRING;
1208 enter_bold_mode = ABSENT_STRING;
1209 enter_dim_mode = ABSENT_STRING;
1210 enter_reverse_mode = ABSENT_STRING;
1211 enter_standout_mode = ABSENT_STRING;
1212 enter_underline_mode = ABSENT_STRING;
1213 }
1214
1215 /* initialize normal acs before wide, since we use mapping in the latter */
1216 #if !USE_WIDEC_SUPPORT
1217 if (_nc_unicode_locale() && _nc_locale_breaks_acs(sp->_term)) {
1218 acs_chars = NULL;
1219 ena_acs = NULL;
1220 enter_alt_charset_mode = NULL;
1221 exit_alt_charset_mode = NULL;
1222 set_attributes = NULL;
1223 }
1224 #endif
1225 }
1226
1227 static int
drv_twait(TERMINAL_CONTROL_BLOCK * TCB,int mode,int milliseconds,int * timeleft EVENTLIST_2nd (_nc_eventlist * evl))1228 drv_twait(TERMINAL_CONTROL_BLOCK * TCB,
1229 int mode,
1230 int milliseconds,
1231 int *timeleft
1232 EVENTLIST_2nd(_nc_eventlist * evl))
1233 {
1234 SCREEN *sp;
1235
1236 AssertTCB();
1237 SetSP();
1238
1239 return _nc_timed_wait(sp, mode, milliseconds, timeleft EVENTLIST_2nd(evl));
1240 }
1241
1242 static int
drv_read(TERMINAL_CONTROL_BLOCK * TCB,int * buf)1243 drv_read(TERMINAL_CONTROL_BLOCK * TCB, int *buf)
1244 {
1245 SCREEN *sp;
1246 unsigned char c2 = 0;
1247 int n;
1248
1249 AssertTCB();
1250 assert(buf);
1251 SetSP();
1252
1253 # if USE_PTHREADS_EINTR
1254 if ((pthread_self) && (pthread_kill) && (pthread_equal))
1255 _nc_globals.read_thread = pthread_self();
1256 # endif
1257 n = (int) read(sp->_ifd, &c2, (size_t) 1);
1258 #if USE_PTHREADS_EINTR
1259 _nc_globals.read_thread = 0;
1260 #endif
1261 *buf = (int) c2;
1262 return n;
1263 }
1264
1265 static int
drv_nap(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED,int ms)1266 drv_nap(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED, int ms)
1267 {
1268 #if HAVE_NANOSLEEP
1269 {
1270 struct timespec request, remaining;
1271 request.tv_sec = ms / 1000;
1272 request.tv_nsec = (ms % 1000) * 1000000;
1273 while (nanosleep(&request, &remaining) == -1
1274 && errno == EINTR) {
1275 request = remaining;
1276 }
1277 }
1278 #else
1279 _nc_timed_wait(0, 0, ms, (int *) 0 EVENTLIST_2nd(0));
1280 #endif
1281 return OK;
1282 }
1283
1284 static int
__nc_putp(SCREEN * sp,const char * name GCC_UNUSED,const char * value)1285 __nc_putp(SCREEN *sp, const char *name GCC_UNUSED, const char *value)
1286 {
1287 int rc = ERR;
1288
1289 if (value) {
1290 rc = NCURSES_PUTP2(name, value);
1291 }
1292 return rc;
1293 }
1294
1295 static int
__nc_putp_flush(SCREEN * sp,const char * name,const char * value)1296 __nc_putp_flush(SCREEN *sp, const char *name, const char *value)
1297 {
1298 int rc = __nc_putp(sp, name, value);
1299 if (rc != ERR) {
1300 NCURSES_SP_NAME(_nc_flush) (sp);
1301 }
1302 return rc;
1303 }
1304
1305 static int
drv_kpad(TERMINAL_CONTROL_BLOCK * TCB,int flag)1306 drv_kpad(TERMINAL_CONTROL_BLOCK * TCB, int flag)
1307 {
1308 int ret = ERR;
1309 SCREEN *sp;
1310
1311 AssertTCB();
1312
1313 sp = TCB->csp;
1314
1315 if (sp) {
1316 if (flag) {
1317 (void) __nc_putp_flush(sp, "keypad_xmit", keypad_xmit);
1318 } else if (!flag && keypad_local) {
1319 (void) __nc_putp_flush(sp, "keypad_local", keypad_local);
1320 }
1321 if (flag && !sp->_tried) {
1322 _nc_init_keytry(sp);
1323 sp->_tried = TRUE;
1324 }
1325 ret = OK;
1326 }
1327
1328 return ret;
1329 }
1330
1331 static int
drv_keyok(TERMINAL_CONTROL_BLOCK * TCB,int c,int flag)1332 drv_keyok(TERMINAL_CONTROL_BLOCK * TCB, int c, int flag)
1333 {
1334 SCREEN *sp;
1335 int code = ERR;
1336 int count = 0;
1337 char *s;
1338
1339 AssertTCB();
1340 SetSP();
1341
1342 if (c >= 0) {
1343 unsigned ch = (unsigned) c;
1344 if (flag) {
1345 while ((s = _nc_expand_try(sp->_key_ok,
1346 ch, &count, (size_t) 0)) != 0) {
1347 if (_nc_remove_key(&(sp->_key_ok), ch)) {
1348 code = _nc_add_to_try(&(sp->_keytry), s, ch);
1349 free(s);
1350 count = 0;
1351 if (code != OK)
1352 break;
1353 } else {
1354 free(s);
1355 }
1356 }
1357 } else {
1358 while ((s = _nc_expand_try(sp->_keytry,
1359 ch, &count, (size_t) 0)) != 0) {
1360 if (_nc_remove_key(&(sp->_keytry), ch)) {
1361 code = _nc_add_to_try(&(sp->_key_ok), s, ch);
1362 free(s);
1363 count = 0;
1364 if (code != OK)
1365 break;
1366 } else {
1367 free(s);
1368 }
1369 }
1370 }
1371 }
1372 return (code);
1373 }
1374
1375 static int
drv_cursorSet(TERMINAL_CONTROL_BLOCK * TCB,int vis)1376 drv_cursorSet(TERMINAL_CONTROL_BLOCK * TCB, int vis)
1377 {
1378 SCREEN *sp;
1379 int code = ERR;
1380
1381 AssertTCB();
1382 SetSP();
1383
1384 T((T_CALLED("tinfo:drv_cursorSet(%p,%d)"), (void *) SP_PARM, vis));
1385
1386 if (SP_PARM != 0 && IsTermInfo(SP_PARM)) {
1387 switch (vis) {
1388 case 2:
1389 code = NCURSES_PUTP2_FLUSH("cursor_visible", cursor_visible);
1390 break;
1391 case 1:
1392 code = NCURSES_PUTP2_FLUSH("cursor_normal", cursor_normal);
1393 break;
1394 case 0:
1395 code = NCURSES_PUTP2_FLUSH("cursor_invisible", cursor_invisible);
1396 break;
1397 }
1398 } else {
1399 code = ERR;
1400 }
1401 returnCode(code);
1402 }
1403
1404 static bool
drv_kyExist(TERMINAL_CONTROL_BLOCK * TCB,int key)1405 drv_kyExist(TERMINAL_CONTROL_BLOCK * TCB, int key)
1406 {
1407 bool res = FALSE;
1408
1409 AssertTCB();
1410 if (TCB->csp)
1411 res = TINFO_HAS_KEY(TCB->csp, key) == 0 ? FALSE : TRUE;
1412
1413 return res;
1414 }
1415
1416 NCURSES_EXPORT_VAR (TERM_DRIVER) _nc_TINFO_DRIVER = {
1417 TRUE,
1418 drv_Name, /* Name */
1419 drv_CanHandle, /* CanHandle */
1420 drv_init, /* init */
1421 drv_release, /* release */
1422 drv_size, /* size */
1423 drv_sgmode, /* sgmode */
1424 drv_conattr, /* conattr */
1425 drv_mvcur, /* hwcur */
1426 drv_mode, /* mode */
1427 drv_rescol, /* rescol */
1428 drv_rescolors, /* rescolors */
1429 drv_setcolor, /* color */
1430 drv_dobeepflash, /* doBeepOrFlash */
1431 drv_initpair, /* initpair */
1432 drv_initcolor, /* initcolor */
1433 drv_do_color, /* docolor */
1434 drv_initmouse, /* initmouse */
1435 drv_testmouse, /* testmouse */
1436 drv_setfilter, /* setfilter */
1437 drv_hwlabel, /* hwlabel */
1438 drv_hwlabelOnOff, /* hwlabelOnOff */
1439 drv_doupdate, /* update */
1440 drv_defaultcolors, /* defaultcolors */
1441 drv_print, /* print */
1442 drv_getsize, /* getsize */
1443 drv_setsize, /* setsize */
1444 drv_initacs, /* initacs */
1445 drv_screen_init, /* scinit */
1446 drv_wrap, /* scexit */
1447 drv_twait, /* twait */
1448 drv_read, /* read */
1449 drv_nap, /* nap */
1450 drv_kpad, /* kpad */
1451 drv_keyok, /* kyOk */
1452 drv_kyExist, /* kyExist */
1453 drv_cursorSet /* cursorSet */
1454 };
1455