root/lib/tty/tty-ncurses.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. tty_setup_sigwinch
  2. sigwinch_handler
  3. mc_tty_normalize_lines_char
  4. tty_init
  5. tty_shutdown
  6. tty_enter_ca_mode
  7. tty_exit_ca_mode
  8. tty_change_screen_size
  9. tty_reset_prog_mode
  10. tty_reset_shell_mode
  11. tty_raw_mode
  12. tty_noraw_mode
  13. tty_noecho
  14. tty_flush_input
  15. tty_keypad
  16. tty_nodelay
  17. tty_baudrate
  18. tty_lowlevel_getch
  19. tty_reset_screen
  20. tty_touch_screen
  21. tty_gotoyx
  22. tty_getyx
  23. tty_draw_hline
  24. tty_draw_vline
  25. tty_fill_region
  26. tty_set_alt_charset
  27. tty_display_8bit
  28. tty_print_char
  29. tty_print_anychar
  30. tty_print_alt_char
  31. tty_print_string
  32. tty_printf
  33. tty_tgetstr
  34. tty_refresh
  35. tty_beep

   1 /*
   2    Interface to the terminal controlling library.
   3    Ncurses wrapper.
   4 
   5    Copyright (C) 2005-2020
   6    Free Software Foundation, Inc.
   7 
   8    Written by:
   9    Andrew Borodin <aborodin@vmail.ru>, 2009.
  10    Ilia Maslakov <il.smind@gmail.com>, 2009.
  11 
  12    This file is part of the Midnight Commander.
  13 
  14    The Midnight Commander is free software: you can redistribute it
  15    and/or modify it under the terms of the GNU General Public License as
  16    published by the Free Software Foundation, either version 3 of the License,
  17    or (at your option) any later version.
  18 
  19    The Midnight Commander is distributed in the hope that it will be useful,
  20    but WITHOUT ANY WARRANTY; without even the implied warranty of
  21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  22    GNU General Public License for more details.
  23 
  24    You should have received a copy of the GNU General Public License
  25    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  26  */
  27 
  28 /** \file
  29  *  \brief Source: NCurses-based tty layer of Midnight-commander
  30  */
  31 
  32 #include <config.h>
  33 
  34 #include <stdlib.h>
  35 #include <stdarg.h>
  36 #include <signal.h>
  37 #ifdef HAVE_SYS_IOCTL_H
  38 #include <sys/ioctl.h>
  39 #endif
  40 #include <termios.h>
  41 
  42 #include "lib/global.h"
  43 #include "lib/strutil.h"        /* str_term_form */
  44 
  45 #ifndef WANT_TERM_H
  46 #define WANT_TERM_H
  47 #endif
  48 
  49 #include "tty-internal.h"       /* mc_tty_normalize_from_utf8() */
  50 #include "tty.h"
  51 #include "color-internal.h"
  52 #include "key.h"
  53 #include "mouse.h"
  54 #include "win.h"
  55 
  56 /* include at last !!! */
  57 #ifdef WANT_TERM_H
  58 #ifdef HAVE_NCURSES_TERM_H
  59 #include <ncurses/term.h>
  60 #else
  61 #include <term.h>
  62 #endif /* HAVE_NCURSES_TERM_H */
  63 #endif /* WANT_TERM_H */
  64 
  65 /*** global variables ****************************************************************************/
  66 
  67 /*** file scope macro definitions ****************************************************************/
  68 
  69 #if !defined(CTRL)
  70 #define CTRL(x) ((x) & 0x1f)
  71 #endif
  72 
  73 #define yx_in_screen(y, x) \
  74     (y >= 0 && y < LINES && x >= 0 && x < COLS)
  75 
  76 /*** global variables ****************************************************************************/
  77 
  78 /*** file scope type declarations ****************************************************************/
  79 
  80 /*** file scope variables ************************************************************************/
  81 
  82 /* ncurses supports cursor positions only within window */
  83 /* We use our own cursor coordinates to support partially visible widgets */
  84 static int mc_curs_row, mc_curs_col;
  85 
  86 /*** file scope functions ************************************************************************/
  87 /* --------------------------------------------------------------------------------------------- */
  88 
  89 /* --------------------------------------------------------------------------------------------- */
  90 
  91 static void
  92 tty_setup_sigwinch (void (*handler) (int))
     /* [previous][next][first][last][top][bottom][index][help]  */
  93 {
  94 #if (NCURSES_VERSION_MAJOR >= 4) && defined (SIGWINCH)
  95     struct sigaction act, oact;
  96 
  97     memset (&act, 0, sizeof (act));
  98     act.sa_handler = handler;
  99     sigemptyset (&act.sa_mask);
 100 #ifdef SA_RESTART
 101     act.sa_flags = SA_RESTART;
 102 #endif /* SA_RESTART */
 103     sigaction (SIGWINCH, &act, &oact);
 104 #endif /* SIGWINCH */
 105 
 106     tty_create_winch_pipe ();
 107 }
 108 
 109 /* --------------------------------------------------------------------------------------------- */
 110 
 111 static void
 112 sigwinch_handler (int dummy)
     /* [previous][next][first][last][top][bottom][index][help]  */
 113 {
 114     ssize_t n = 0;
 115 
 116     (void) dummy;
 117 
 118     n = write (sigwinch_pipe[1], "", 1);
 119     (void) n;
 120 }
 121 
 122 /* --------------------------------------------------------------------------------------------- */
 123 /*** public functions ****************************************************************************/
 124 /* --------------------------------------------------------------------------------------------- */
 125 
 126 int
 127 mc_tty_normalize_lines_char (const char *ch)
     /* [previous][next][first][last][top][bottom][index][help]  */
 128 {
 129     char *str2;
 130     int res;
 131 
 132     struct mc_tty_lines_struct
 133     {
 134         const char *line;
 135         int line_code;
 136     } const lines_codes[] = {
 137         {"\342\224\230", ACS_LRCORNER}, /* ┌ */
 138         {"\342\224\224", ACS_LLCORNER}, /* └ */
 139         {"\342\224\220", ACS_URCORNER}, /* ┐ */
 140         {"\342\224\214", ACS_ULCORNER}, /* ┘ */
 141         {"\342\224\234", ACS_LTEE},     /* ├ */
 142         {"\342\224\244", ACS_RTEE},     /* ┤ */
 143         {"\342\224\254", ACS_TTEE},     /* ┬ */
 144         {"\342\224\264", ACS_BTEE},     /* ┴ */
 145         {"\342\224\200", ACS_HLINE},    /* ─ */
 146         {"\342\224\202", ACS_VLINE},    /* │ */
 147         {"\342\224\274", ACS_PLUS},     /* ┼ */
 148 
 149         {"\342\225\235", ACS_LRCORNER | A_BOLD},        /* ╔ */
 150         {"\342\225\232", ACS_LLCORNER | A_BOLD},        /* ╚ */
 151         {"\342\225\227", ACS_URCORNER | A_BOLD},        /* ╗ */
 152         {"\342\225\224", ACS_ULCORNER | A_BOLD},        /* ╝ */
 153         {"\342\225\237", ACS_LTEE | A_BOLD},    /* ╟ */
 154         {"\342\225\242", ACS_RTEE | A_BOLD},    /* ╢ */
 155         {"\342\225\244", ACS_TTEE | A_BOLD},    /* ╤ */
 156         {"\342\225\247", ACS_BTEE | A_BOLD},    /* ╧ */
 157         {"\342\225\220", ACS_HLINE | A_BOLD},   /* ═ */
 158         {"\342\225\221", ACS_VLINE | A_BOLD},   /* ║ */
 159 
 160         {NULL, 0}
 161     };
 162 
 163     if (ch == NULL)
 164         return (int) ' ';
 165 
 166     for (res = 0; lines_codes[res].line; res++)
 167     {
 168         if (strcmp (ch, lines_codes[res].line) == 0)
 169             return lines_codes[res].line_code;
 170     }
 171 
 172     str2 = mc_tty_normalize_from_utf8 (ch);
 173     res = g_utf8_get_char_validated (str2, -1);
 174 
 175     if (res < 0)
 176         res = (unsigned char) str2[0];
 177     g_free (str2);
 178 
 179     return res;
 180 }
 181 
 182 /* --------------------------------------------------------------------------------------------- */
 183 
 184 void
 185 tty_init (gboolean mouse_enable, gboolean is_xterm)
     /* [previous][next][first][last][top][bottom][index][help]  */
 186 {
 187     struct termios mode;
 188 
 189     initscr ();
 190 
 191 #ifdef HAVE_ESCDELAY
 192     /*
 193      * If ncurses exports the ESCDELAY variable, it should be set to
 194      * a low value, or you'll experience a delay in processing escape
 195      * sequences that are recognized by mc (e.g. Esc-Esc).  On the other
 196      * hand, making ESCDELAY too small can result in some sequences
 197      * (e.g. cursor arrows) being reported as separate keys under heavy
 198      * processor load, and this can be a problem if mc hasn't learned
 199      * them in the "Learn Keys" dialog.  The value is in milliseconds.
 200      */
 201     ESCDELAY = 200;
 202 #endif /* HAVE_ESCDELAY */
 203 
 204     tcgetattr (STDIN_FILENO, &mode);
 205     /* use Ctrl-g to generate SIGINT */
 206     mode.c_cc[VINTR] = CTRL ('g');      /* ^g */
 207     /* disable SIGQUIT to allow use Ctrl-\ key */
 208     mode.c_cc[VQUIT] = NULL_VALUE;
 209     tcsetattr (STDIN_FILENO, TCSANOW, &mode);
 210 
 211     /* curses remembers the "in-program" modes after this call */
 212     def_prog_mode ();
 213 
 214     tty_start_interrupt_key ();
 215 
 216     if (!mouse_enable)
 217         use_mouse_p = MOUSE_DISABLED;
 218     tty_init_xterm_support (is_xterm);  /* do it before tty_enter_ca_mode() call */
 219     tty_enter_ca_mode ();
 220     tty_raw_mode ();
 221     noecho ();
 222     keypad (stdscr, TRUE);
 223     nodelay (stdscr, FALSE);
 224 
 225     tty_setup_sigwinch (sigwinch_handler);
 226 }
 227 
 228 /* --------------------------------------------------------------------------------------------- */
 229 
 230 void
 231 tty_shutdown (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 232 {
 233     tty_destroy_winch_pipe ();
 234     tty_reset_shell_mode ();
 235     tty_noraw_mode ();
 236     tty_keypad (FALSE);
 237     tty_reset_screen ();
 238     tty_exit_ca_mode ();
 239 }
 240 
 241 /* --------------------------------------------------------------------------------------------- */
 242 
 243 void
 244 tty_enter_ca_mode (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 245 {
 246     if (mc_global.tty.xterm_flag && smcup != NULL)
 247     {
 248         fprintf (stdout, /* ESC_STR ")0" */ ESC_STR "7" ESC_STR "[?47h");
 249         fflush (stdout);
 250     }
 251 }
 252 
 253 /* --------------------------------------------------------------------------------------------- */
 254 
 255 void
 256 tty_exit_ca_mode (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 257 {
 258     if (mc_global.tty.xterm_flag && rmcup != NULL)
 259     {
 260         fprintf (stdout, ESC_STR "[?47l" ESC_STR "8" ESC_STR "[m");
 261         fflush (stdout);
 262     }
 263 }
 264 
 265 /* --------------------------------------------------------------------------------------------- */
 266 
 267 void
 268 tty_change_screen_size (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 269 {
 270 #if defined(TIOCGWINSZ) && NCURSES_VERSION_MAJOR >= 4
 271     struct winsize winsz;
 272 
 273     winsz.ws_col = winsz.ws_row = 0;
 274 
 275 #ifndef NCURSES_VERSION
 276     tty_noraw_mode ();
 277     tty_reset_screen ();
 278 #endif
 279 
 280     /* Ioctl on the STDIN_FILENO */
 281     ioctl (fileno (stdout), TIOCGWINSZ, &winsz);
 282     if (winsz.ws_col != 0 && winsz.ws_row != 0)
 283     {
 284 #if defined(NCURSES_VERSION) && defined(HAVE_RESIZETERM)
 285         resizeterm (winsz.ws_row, winsz.ws_col);
 286         clearok (stdscr, TRUE); /* sigwinch's should use a semaphore! */
 287 #else
 288         COLS = winsz.ws_col;
 289         LINES = winsz.ws_row;
 290 #endif
 291     }
 292 #endif /* defined(TIOCGWINSZ) || NCURSES_VERSION_MAJOR >= 4 */
 293 
 294 #ifdef ENABLE_SUBSHELL
 295     if (mc_global.tty.use_subshell)
 296         tty_resize (mc_global.tty.subshell_pty);
 297 #endif
 298 }
 299 
 300 /* --------------------------------------------------------------------------------------------- */
 301 
 302 void
 303 tty_reset_prog_mode (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 304 {
 305     reset_prog_mode ();
 306 }
 307 
 308 /* --------------------------------------------------------------------------------------------- */
 309 
 310 void
 311 tty_reset_shell_mode (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 312 {
 313     reset_shell_mode ();
 314 }
 315 
 316 /* --------------------------------------------------------------------------------------------- */
 317 
 318 void
 319 tty_raw_mode (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 320 {
 321     raw ();                     /* FIXME: uneeded? */
 322     cbreak ();
 323 }
 324 
 325 /* --------------------------------------------------------------------------------------------- */
 326 
 327 void
 328 tty_noraw_mode (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 329 {
 330     nocbreak ();                /* FIXME: unneeded? */
 331     noraw ();
 332 }
 333 
 334 /* --------------------------------------------------------------------------------------------- */
 335 
 336 void
 337 tty_noecho (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 338 {
 339     noecho ();
 340 }
 341 
 342 /* --------------------------------------------------------------------------------------------- */
 343 
 344 int
 345 tty_flush_input (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 346 {
 347     return flushinp ();
 348 }
 349 
 350 /* --------------------------------------------------------------------------------------------- */
 351 
 352 void
 353 tty_keypad (gboolean set)
     /* [previous][next][first][last][top][bottom][index][help]  */
 354 {
 355     keypad (stdscr, (bool) set);
 356 }
 357 
 358 /* --------------------------------------------------------------------------------------------- */
 359 
 360 void
 361 tty_nodelay (gboolean set)
     /* [previous][next][first][last][top][bottom][index][help]  */
 362 {
 363     nodelay (stdscr, (bool) set);
 364 }
 365 
 366 /* --------------------------------------------------------------------------------------------- */
 367 
 368 int
 369 tty_baudrate (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 370 {
 371     return baudrate ();
 372 }
 373 
 374 /* --------------------------------------------------------------------------------------------- */
 375 
 376 int
 377 tty_lowlevel_getch (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 378 {
 379     return getch ();
 380 }
 381 
 382 /* --------------------------------------------------------------------------------------------- */
 383 
 384 int
 385 tty_reset_screen (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 386 {
 387     return endwin ();
 388 }
 389 
 390 /* --------------------------------------------------------------------------------------------- */
 391 
 392 void
 393 tty_touch_screen (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 394 {
 395     touchwin (stdscr);
 396 }
 397 
 398 /* --------------------------------------------------------------------------------------------- */
 399 
 400 void
 401 tty_gotoyx (int y, int x)
     /* [previous][next][first][last][top][bottom][index][help]  */
 402 {
 403     mc_curs_row = y;
 404     mc_curs_col = x;
 405 
 406     if (y < 0)
 407         y = 0;
 408     if (y >= LINES)
 409         y = LINES - 1;
 410 
 411     if (x < 0)
 412         x = 0;
 413     if (x >= COLS)
 414         x = COLS - 1;
 415 
 416     move (y, x);
 417 }
 418 
 419 /* --------------------------------------------------------------------------------------------- */
 420 
 421 void
 422 tty_getyx (int *py, int *px)
     /* [previous][next][first][last][top][bottom][index][help]  */
 423 {
 424     *py = mc_curs_row;
 425     *px = mc_curs_col;
 426 }
 427 
 428 /* --------------------------------------------------------------------------------------------- */
 429 
 430 void
 431 tty_draw_hline (int y, int x, int ch, int len)
     /* [previous][next][first][last][top][bottom][index][help]  */
 432 {
 433     int x1;
 434 
 435     if (y < 0 || y >= LINES || x >= COLS)
 436         return;
 437 
 438     x1 = x;
 439 
 440     if (x < 0)
 441     {
 442         len += x;
 443         if (len <= 0)
 444             return;
 445         x = 0;
 446     }
 447 
 448     if ((chtype) ch == ACS_HLINE)
 449         ch = mc_tty_frm[MC_TTY_FRM_HORIZ];
 450 
 451     move (y, x);
 452     hline (ch, len);
 453     move (y, x1);
 454 
 455     mc_curs_row = y;
 456     mc_curs_col = x1;
 457 }
 458 
 459 /* --------------------------------------------------------------------------------------------- */
 460 
 461 void
 462 tty_draw_vline (int y, int x, int ch, int len)
     /* [previous][next][first][last][top][bottom][index][help]  */
 463 {
 464     int y1;
 465 
 466     if (x < 0 || x >= COLS || y >= LINES)
 467         return;
 468 
 469     y1 = y;
 470 
 471     if (y < 0)
 472     {
 473         len += y;
 474         if (len <= 0)
 475             return;
 476         y = 0;
 477     }
 478 
 479     if ((chtype) ch == ACS_VLINE)
 480         ch = mc_tty_frm[MC_TTY_FRM_VERT];
 481 
 482     move (y, x);
 483     vline (ch, len);
 484     move (y1, x);
 485 
 486     mc_curs_row = y1;
 487     mc_curs_col = x;
 488 }
 489 
 490 /* --------------------------------------------------------------------------------------------- */
 491 
 492 void
 493 tty_fill_region (int y, int x, int rows, int cols, unsigned char ch)
     /* [previous][next][first][last][top][bottom][index][help]  */
 494 {
 495     int i;
 496 
 497     if (y < 0)
 498     {
 499         rows += y;
 500 
 501         if (rows <= 0)
 502             return;
 503 
 504         y = 0;
 505     }
 506 
 507     if (x < 0)
 508     {
 509         cols += x;
 510 
 511         if (cols <= 0)
 512             return;
 513 
 514         x = 0;
 515     }
 516 
 517     if (y + rows > LINES)
 518         rows = LINES - y;
 519     if (x + cols > COLS)
 520         cols = COLS - x;
 521 
 522     for (i = 0; i < rows; i++)
 523     {
 524         move (y + i, x);
 525         hline (ch, cols);
 526     }
 527 
 528     move (y, x);
 529 
 530     mc_curs_row = y;
 531     mc_curs_col = x;
 532 }
 533 
 534 /* --------------------------------------------------------------------------------------------- */
 535 
 536 void
 537 tty_set_alt_charset (gboolean alt_charset)
     /* [previous][next][first][last][top][bottom][index][help]  */
 538 {
 539     (void) alt_charset;
 540 }
 541 
 542 /* --------------------------------------------------------------------------------------------- */
 543 
 544 void
 545 tty_display_8bit (gboolean what)
     /* [previous][next][first][last][top][bottom][index][help]  */
 546 {
 547     meta (stdscr, (int) what);
 548 }
 549 
 550 /* --------------------------------------------------------------------------------------------- */
 551 
 552 void
 553 tty_print_char (int c)
     /* [previous][next][first][last][top][bottom][index][help]  */
 554 {
 555     if (yx_in_screen (mc_curs_row, mc_curs_col))
 556         addch (c);
 557     mc_curs_col++;
 558 }
 559 
 560 /* --------------------------------------------------------------------------------------------- */
 561 
 562 void
 563 tty_print_anychar (int c)
     /* [previous][next][first][last][top][bottom][index][help]  */
 564 {
 565     if (mc_global.utf8_display || c > 255)
 566     {
 567         int res;
 568         unsigned char str[UTF8_CHAR_LEN + 1];
 569 
 570         res = g_unichar_to_utf8 (c, (char *) str);
 571         if (res == 0)
 572         {
 573             if (yx_in_screen (mc_curs_row, mc_curs_col))
 574                 addch ('.');
 575             mc_curs_col++;
 576         }
 577         else
 578         {
 579             const char *s;
 580 
 581             str[res] = '\0';
 582             s = str_term_form ((char *) str);
 583 
 584             if (yx_in_screen (mc_curs_row, mc_curs_col))
 585                 addstr (s);
 586 
 587             if (g_unichar_iswide (c))
 588                 mc_curs_col += 2;
 589             else if (!g_unichar_iszerowidth (c))
 590                 mc_curs_col++;
 591         }
 592     }
 593     else
 594     {
 595         if (yx_in_screen (mc_curs_row, mc_curs_col))
 596             addch (c);
 597         mc_curs_col++;
 598     }
 599 }
 600 
 601 /* --------------------------------------------------------------------------------------------- */
 602 
 603 void
 604 tty_print_alt_char (int c, gboolean single)
     /* [previous][next][first][last][top][bottom][index][help]  */
 605 {
 606     if (yx_in_screen (mc_curs_row, mc_curs_col))
 607     {
 608         if ((chtype) c == ACS_VLINE)
 609             c = mc_tty_frm[single ? MC_TTY_FRM_VERT : MC_TTY_FRM_DVERT];
 610         else if ((chtype) c == ACS_HLINE)
 611             c = mc_tty_frm[single ? MC_TTY_FRM_HORIZ : MC_TTY_FRM_DHORIZ];
 612         else if ((chtype) c == ACS_LTEE)
 613             c = mc_tty_frm[single ? MC_TTY_FRM_LEFTMIDDLE : MC_TTY_FRM_DLEFTMIDDLE];
 614         else if ((chtype) c == ACS_RTEE)
 615             c = mc_tty_frm[single ? MC_TTY_FRM_RIGHTMIDDLE : MC_TTY_FRM_DRIGHTMIDDLE];
 616         else if ((chtype) c == ACS_ULCORNER)
 617             c = mc_tty_frm[single ? MC_TTY_FRM_LEFTTOP : MC_TTY_FRM_DLEFTTOP];
 618         else if ((chtype) c == ACS_LLCORNER)
 619             c = mc_tty_frm[single ? MC_TTY_FRM_LEFTBOTTOM : MC_TTY_FRM_DLEFTBOTTOM];
 620         else if ((chtype) c == ACS_URCORNER)
 621             c = mc_tty_frm[single ? MC_TTY_FRM_RIGHTTOP : MC_TTY_FRM_DRIGHTTOP];
 622         else if ((chtype) c == ACS_LRCORNER)
 623             c = mc_tty_frm[single ? MC_TTY_FRM_RIGHTBOTTOM : MC_TTY_FRM_DRIGHTBOTTOM];
 624         else if ((chtype) c == ACS_PLUS)
 625             c = mc_tty_frm[MC_TTY_FRM_CROSS];
 626 
 627         addch (c);
 628     }
 629 
 630     mc_curs_col++;
 631 }
 632 
 633 /* --------------------------------------------------------------------------------------------- */
 634 
 635 void
 636 tty_print_string (const char *s)
     /* [previous][next][first][last][top][bottom][index][help]  */
 637 {
 638     int len;
 639     int start = 0;
 640 
 641     s = str_term_form (s);
 642     len = str_term_width1 (s);
 643 
 644     /* line is upper or below the screen or entire line is before or after screen */
 645     if (mc_curs_row < 0 || mc_curs_row >= LINES || mc_curs_col + len <= 0 || mc_curs_col >= COLS)
 646     {
 647         mc_curs_col += len;
 648         return;
 649     }
 650 
 651     /* skip invisible left part */
 652     if (mc_curs_col < 0)
 653     {
 654         start = -mc_curs_col;
 655         len += mc_curs_col;
 656         mc_curs_col = 0;
 657     }
 658 
 659     mc_curs_col += len;
 660     if (mc_curs_col >= COLS)
 661         len = COLS - (mc_curs_col - len);
 662 
 663     addstr (str_term_substring (s, start, len));
 664 }
 665 
 666 /* --------------------------------------------------------------------------------------------- */
 667 
 668 void
 669 tty_printf (const char *fmt, ...)
     /* [previous][next][first][last][top][bottom][index][help]  */
 670 {
 671     va_list args;
 672     char buf[BUF_1K];           /* FIXME: is it enough? */
 673 
 674     va_start (args, fmt);
 675     g_vsnprintf (buf, sizeof (buf), fmt, args);
 676     va_end (args);
 677     tty_print_string (buf);
 678 }
 679 
 680 /* --------------------------------------------------------------------------------------------- */
 681 
 682 char *
 683 tty_tgetstr (const char *cap)
     /* [previous][next][first][last][top][bottom][index][help]  */
 684 {
 685     char *unused = NULL;
 686 
 687     return tgetstr ((NCURSES_CONST char *) cap, &unused);
 688 }
 689 
 690 /* --------------------------------------------------------------------------------------------- */
 691 
 692 void
 693 tty_refresh (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 694 {
 695     refresh ();
 696     doupdate ();
 697 }
 698 
 699 /* --------------------------------------------------------------------------------------------- */
 700 
 701 void
 702 tty_beep (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 703 {
 704     beep ();
 705 }
 706 
 707 /* --------------------------------------------------------------------------------------------- */

/* [previous][next][first][last][top][bottom][index][help]  */