Manual pages: mcmcdiffmceditmcview

root/lib/tty/tty-slang.c

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

DEFINITIONS

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

   1 /*
   2    Interface to the terminal controlling library.
   3    Slang wrapper.
   4 
   5    Copyright (C) 2005-2025
   6    Free Software Foundation, Inc.
   7 
   8    Written by:
   9    Andrew Borodin <aborodin@vmail.ru>, 2009
  10    Egmont Koblinger <egmont@gmail.com>, 2010
  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 <https://www.gnu.org/licenses/>.
  26  */
  27 
  28 /** \file
  29  *  \brief Source: S-Lang-based tty layer of Midnight Commander
  30  */
  31 
  32 #include <config.h>
  33 
  34 #include <limits.h>  // MB_LEN_MAX
  35 #include <stdio.h>
  36 #include <stdlib.h>
  37 #include <string.h>
  38 #include <sys/types.h>  // size_t
  39 #include <unistd.h>
  40 #ifdef HAVE_SYS_IOCTL_H
  41 #include <sys/ioctl.h>
  42 #endif
  43 #include <termios.h>
  44 
  45 #include "lib/global.h"
  46 #include "lib/strutil.h"  // str_term_form
  47 #include "lib/util.h"     // is_printable()
  48 
  49 #include "tty-internal.h"  // mc_tty_normalize_from_utf8()
  50 #include "tty.h"
  51 #include "color.h"
  52 #include "color-slang.h"
  53 #include "color-internal.h"
  54 #include "mouse.h"  // Gpm_Event is required in key.h
  55 #include "key.h"    // define_sequence
  56 #include "win.h"
  57 
  58 /*** global variables ****************************************************************************/
  59 
  60 /* If true program softkeys (HP terminals only) on startup and after every
  61    command ran in the subshell to the description found in the termcap/terminfo
  62    database */
  63 int reset_hp_softkeys = 0;
  64 
  65 /*** file scope macro definitions ****************************************************************/
  66 
  67 #ifndef SLTT_MAX_SCREEN_COLS
  68 #define SLTT_MAX_SCREEN_COLS 512
  69 #endif
  70 
  71 #ifndef SLTT_MAX_SCREEN_ROWS
  72 #define SLTT_MAX_SCREEN_ROWS 512
  73 #endif
  74 
  75 /*** file scope type declarations ****************************************************************/
  76 
  77 /*** forward declarations (file scope functions) *************************************************/
  78 
  79 /*** file scope variables ************************************************************************/
  80 
  81 /* Various saved termios settings that we control here */
  82 static struct termios boot_mode;
  83 static struct termios new_mode;
  84 
  85 /* Controls whether we should wait for input in tty_lowlevel_getch */
  86 static gboolean no_slang_delay;
  87 
  88 static gboolean slsmg_active = FALSE;
  89 
  90 /* This table describes which capabilities we want and which values we
  91  * assign to them.
  92  */
  93 static const struct
  94 {
  95     int key_code;
  96     const char *key_name;
  97 } key_table[] = {
  98     { KEY_F (0), "k0" },
  99     { KEY_F (1), "k1" },
 100     { KEY_F (2), "k2" },
 101     { KEY_F (3), "k3" },
 102     { KEY_F (4), "k4" },
 103     { KEY_F (5), "k5" },
 104     { KEY_F (6), "k6" },
 105     { KEY_F (7), "k7" },
 106     { KEY_F (8), "k8" },
 107     { KEY_F (9), "k9" },
 108     { KEY_F (10), "k;" },
 109     { KEY_F (11), "F1" },
 110     { KEY_F (12), "F2" },
 111     { KEY_F (13), "F3" },
 112     { KEY_F (14), "F4" },
 113     { KEY_F (15), "F5" },
 114     { KEY_F (16), "F6" },
 115     { KEY_F (17), "F7" },
 116     { KEY_F (18), "F8" },
 117     { KEY_F (19), "F9" },
 118     { KEY_F (20), "FA" },
 119     { KEY_IC, "kI" },
 120     { KEY_NPAGE, "kN" },
 121     { KEY_PPAGE, "kP" },
 122     { KEY_LEFT, "kl" },
 123     { KEY_RIGHT, "kr" },
 124     { KEY_UP, "ku" },
 125     { KEY_DOWN, "kd" },
 126     { KEY_DC, "kD" },
 127     { KEY_BACKSPACE, "kb" },
 128     { KEY_HOME, "kh" },
 129     { KEY_END, "@7" },
 130     {
 131         0,
 132         NULL,
 133     },
 134 };
 135 
 136 /* --------------------------------------------------------------------------------------------- */
 137 /*** file scope functions ************************************************************************/
 138 /* --------------------------------------------------------------------------------------------- */
 139 
 140 static void
 141 tty_setup_sigwinch (void (*handler) (int))
     /* [previous][next][first][last][top][bottom][index][help]  */
 142 {
 143     (void) SLsignal (SIGWINCH, handler);
 144     tty_create_winch_pipe ();
 145 }
 146 
 147 /* --------------------------------------------------------------------------------------------- */
 148 
 149 static void
 150 sigwinch_handler (int dummy)
     /* [previous][next][first][last][top][bottom][index][help]  */
 151 {
 152     ssize_t n = 0;
 153 
 154     (void) dummy;
 155 
 156     n = write (sigwinch_pipe[1], "", 1);
 157     (void) n;
 158 
 159     (void) SLsignal (SIGWINCH, sigwinch_handler);
 160 }
 161 
 162 /* --------------------------------------------------------------------------------------------- */
 163 
 164 /* HP Terminals have capabilities (pfkey, pfloc, pfx) to program function keys.
 165    elm 2.4pl15 invoked with the -K option utilizes these softkeys and the
 166    consequence is that function keys don't work in MC sometimes...
 167    Unfortunately I don't now the one and only escape sequence to turn off.
 168    softkeys (elm uses three different capabilities to turn on softkeys and two.
 169    capabilities to turn them off)..
 170    Among other things elm uses the pair we already use in slang_keypad. That's.
 171    the reason why I call slang_reset_softkeys from slang_keypad. In lack of
 172    something better the softkeys are programmed to their defaults from the
 173    termcap/terminfo database.
 174    The escape sequence to program the softkeys is taken from elm and it is.
 175    hardcoded because neither slang nor ncurses 4.1 know how to 'printf' this.
 176    sequence. -- Norbert
 177  */
 178 
 179 static void
 180 slang_reset_softkeys (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 181 {
 182     int key;
 183     static const char display[] = "                ";
 184     char tmp[BUF_SMALL];
 185 
 186     for (key = 1; key < 9; key++)
 187     {
 188         char *send;
 189 
 190         g_snprintf (tmp, sizeof (tmp), "k%d", key);
 191         send = SLtt_tgetstr (tmp);
 192         if (send != NULL)
 193         {
 194             g_snprintf (tmp, sizeof (tmp), ESC_STR "&f%dk%dd%dL%s%s", key,
 195                         (int) (sizeof (display) - 1), (int) strlen (send), display, send);
 196             SLtt_write_string (tmp);
 197         }
 198     }
 199 }
 200 
 201 /* --------------------------------------------------------------------------------------------- */
 202 
 203 static void
 204 do_define_key (int code, const char *strcap)
     /* [previous][next][first][last][top][bottom][index][help]  */
 205 {
 206     char *seq;
 207 
 208     seq = SLtt_tgetstr ((SLFUTURE_CONST char *) strcap);
 209     if (seq != NULL)
 210         define_sequence (code, seq, MCKEY_NOACTION);
 211 }
 212 
 213 /* --------------------------------------------------------------------------------------------- */
 214 
 215 static void
 216 load_terminfo_keys (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 217 {
 218     int i;
 219 
 220     for (i = 0; key_table[i].key_code; i++)
 221         do_define_key (key_table[i].key_code, key_table[i].key_name);
 222 }
 223 
 224 /* --------------------------------------------------------------------------------------------- */
 225 
 226 static int
 227 get_maybe_acs (mc_tty_char_t c, gboolean *alt_char)
     /* [previous][next][first][last][top][bottom][index][help]  */
 228 {
 229     *alt_char = TRUE;
 230 
 231     switch (c)
 232     {
 233     case MC_ACS_HLINE:
 234         return SLSMG_HLINE_CHAR;
 235     case MC_ACS_VLINE:
 236         return SLSMG_VLINE_CHAR;
 237     case MC_ACS_ULCORNER:
 238         return SLSMG_ULCORN_CHAR;
 239     case MC_ACS_URCORNER:
 240         return SLSMG_URCORN_CHAR;
 241     case MC_ACS_LLCORNER:
 242         return SLSMG_LLCORN_CHAR;
 243     case MC_ACS_LRCORNER:
 244         return SLSMG_LRCORN_CHAR;
 245     case MC_ACS_LTEE:
 246         return SLSMG_LTEE_CHAR;
 247     case MC_ACS_RTEE:
 248         return SLSMG_RTEE_CHAR;
 249     case MC_ACS_TTEE:
 250         return SLSMG_UTEE_CHAR;
 251     case MC_ACS_BTEE:
 252         return SLSMG_DTEE_CHAR;
 253     case MC_ACS_PLUS:
 254         return SLSMG_PLUS_CHAR;
 255 
 256     default:
 257         *alt_char = FALSE;
 258         return c;
 259     }
 260 }
 261 
 262 /* --------------------------------------------------------------------------------------------- */
 263 /*** public functions ****************************************************************************/
 264 /* --------------------------------------------------------------------------------------------- */
 265 
 266 void
 267 tty_init (gboolean mouse_enable, gboolean is_xterm)
     /* [previous][next][first][last][top][bottom][index][help]  */
 268 {
 269     SLtt_Ignore_Beep = 1;
 270 
 271     SLutf8_enable (-1);  // has to be called first before any of the other functions.
 272     SLtt_get_terminfo ();
 273     /*
 274      * If the terminal in not in terminfo but begins with a well-known
 275      * string such as "linux" or "xterm" S-Lang will go on, but the
 276      * terminal size and several other variables won't be initialized
 277      * (as of S-Lang 1.4.4). Detect it and abort. Also detect extremely
 278      * small screen dimensions.
 279      */
 280     if ((COLS < 10)
 281         || (LINES < 5)
 282 #if SLANG_VERSION < 20303
 283         /* Beginning from pre2.3.3-8 (55f58798c267d76a1b93d0d916027b71a10ac1ee),
 284            these limitations were eliminated. */
 285         || (COLS > SLTT_MAX_SCREEN_COLS) || (LINES > SLTT_MAX_SCREEN_ROWS)
 286 #endif
 287     )
 288     {
 289         fprintf (stderr,
 290                  _ ("Screen size %dx%d is not supported.\n"
 291                     "Check the TERM environment variable.\n"),
 292                  COLS, LINES);
 293         exit (EXIT_FAILURE);
 294     }
 295 
 296     tcgetattr (fileno (stdin), &boot_mode);
 297     // 255 = ignore abort char; XCTRL('g') for abort char = ^g
 298     SLang_init_tty (XCTRL ('g'), 1, 0);
 299 
 300     if (mc_global.tty.ugly_line_drawing)
 301         SLtt_Has_Alt_Charset = 0;
 302 
 303     tcgetattr (SLang_TT_Read_FD, &new_mode);
 304 
 305     tty_reset_prog_mode ();
 306     load_terminfo_keys ();
 307 
 308     SLtt_Blink_Mode = (tty_use_256colors (NULL) || tty_use_truecolors (NULL)) ? 1 : 0;
 309 
 310     tty_start_interrupt_key ();
 311 
 312     // It's the small part from the previous init_key()
 313     init_key_input_fd ();
 314 
 315     /* For 8-bit locales, NCurses handles 154 (0x9A) symbol properly, while S-Lang
 316      * requires SLsmg_Display_Eight_Bit >= 154 (OR manual filtering if xterm display
 317      * detected - but checking TERM would fail under screen, OR running xterm
 318      * with allowC1Printable).
 319      */
 320     tty_display_8bit (FALSE);
 321 
 322     SLsmg_init_smg ();
 323     slsmg_active = TRUE;
 324     if (!mouse_enable)
 325         use_mouse_p = MOUSE_DISABLED;
 326     tty_init_xterm_support (is_xterm);  // do it before tty_enter_ca_mode() call
 327     tty_enter_ca_mode ();
 328     tty_keypad (TRUE);
 329     tty_nodelay (FALSE);
 330 
 331     tty_setup_sigwinch (sigwinch_handler);
 332 }
 333 
 334 /* --------------------------------------------------------------------------------------------- */
 335 
 336 void
 337 tty_shutdown (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 338 {
 339     char *op_cap;
 340 
 341     tty_destroy_winch_pipe ();
 342     tty_reset_shell_mode ();
 343     tty_noraw_mode ();
 344     tty_keypad (FALSE);
 345     tty_reset_screen ();
 346     tty_exit_ca_mode ();
 347     SLang_reset_tty ();
 348     slsmg_active = FALSE;
 349 
 350     /* Load the op capability to reset the colors to those that were
 351      * active when the program was started up
 352      */
 353     op_cap = SLtt_tgetstr ((SLFUTURE_CONST char *) "op");
 354     if (op_cap != NULL)
 355     {
 356         fputs (op_cap, stdout);
 357         fflush (stdout);
 358     }
 359 }
 360 
 361 /* --------------------------------------------------------------------------------------------- */
 362 
 363 void
 364 tty_enter_ca_mode (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 365 {
 366     // S-Lang handles alternate screen switching and cursor position saving
 367 }
 368 
 369 /* --------------------------------------------------------------------------------------------- */
 370 
 371 void
 372 tty_exit_ca_mode (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 373 {
 374     // S-Lang handles alternate screen switching and cursor position restoring
 375 }
 376 
 377 /* --------------------------------------------------------------------------------------------- */
 378 
 379 void
 380 tty_change_screen_size (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 381 {
 382     SLtt_get_screen_size ();
 383     if (slsmg_active)
 384         SLsmg_reinit_smg ();
 385 
 386 #ifdef ENABLE_SUBSHELL
 387     if (mc_global.tty.use_subshell)
 388         tty_resize (mc_global.tty.subshell_pty);
 389 #endif
 390 }
 391 
 392 /* --------------------------------------------------------------------------------------------- */
 393 /* Done each time we come back from done mode */
 394 
 395 void
 396 tty_reset_prog_mode (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 397 {
 398     tcsetattr (SLang_TT_Read_FD, TCSANOW, &new_mode);
 399     SLsmg_init_smg ();
 400     slsmg_active = TRUE;
 401     SLsmg_touch_lines (0, LINES);
 402 }
 403 
 404 /* --------------------------------------------------------------------------------------------- */
 405 /* Called each time we want to shutdown slang screen manager */
 406 
 407 void
 408 tty_reset_shell_mode (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 409 {
 410     tcsetattr (SLang_TT_Read_FD, TCSANOW, &boot_mode);
 411 }
 412 
 413 /* --------------------------------------------------------------------------------------------- */
 414 
 415 void
 416 tty_raw_mode (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 417 {
 418     tcsetattr (SLang_TT_Read_FD, TCSANOW, &new_mode);
 419 }
 420 
 421 /* --------------------------------------------------------------------------------------------- */
 422 
 423 void
 424 tty_noraw_mode (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 425 {
 426 }
 427 
 428 /* --------------------------------------------------------------------------------------------- */
 429 
 430 void
 431 tty_noecho (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 432 {
 433 }
 434 
 435 /* --------------------------------------------------------------------------------------------- */
 436 
 437 int
 438 tty_flush_input (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 439 {
 440     return 0;  // OK
 441 }
 442 
 443 /* --------------------------------------------------------------------------------------------- */
 444 
 445 void
 446 tty_keypad (gboolean set)
     /* [previous][next][first][last][top][bottom][index][help]  */
 447 {
 448     char *keypad_string;
 449 
 450     keypad_string = SLtt_tgetstr ((SLFUTURE_CONST char *) (set ? "ks" : "ke"));
 451     if (keypad_string != NULL)
 452         SLtt_write_string (keypad_string);
 453     if (set && reset_hp_softkeys)
 454         slang_reset_softkeys ();
 455 }
 456 
 457 /* --------------------------------------------------------------------------------------------- */
 458 
 459 void
 460 tty_nodelay (gboolean set)
     /* [previous][next][first][last][top][bottom][index][help]  */
 461 {
 462     no_slang_delay = set;
 463 }
 464 
 465 /* --------------------------------------------------------------------------------------------- */
 466 
 467 int
 468 tty_baudrate (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 469 {
 470     return SLang_TT_Baud_Rate;
 471 }
 472 
 473 /* --------------------------------------------------------------------------------------------- */
 474 
 475 int
 476 tty_lowlevel_getch (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 477 {
 478     int c;
 479 
 480     if (no_slang_delay && (SLang_input_pending (0) == 0))
 481         return -1;
 482 
 483     c = SLang_getkey ();
 484     if (c == SLANG_GETKEY_ERROR)
 485     {
 486         fprintf (stderr,
 487                  "SLang_getkey returned SLANG_GETKEY_ERROR\n"
 488                  "Assuming EOF on stdin and exiting\n");
 489         exit (EXIT_FAILURE);
 490     }
 491 
 492     return c;
 493 }
 494 
 495 /* --------------------------------------------------------------------------------------------- */
 496 
 497 int
 498 tty_reset_screen (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 499 {
 500     SLsmg_reset_smg ();
 501     slsmg_active = FALSE;
 502     return 0;  // OK
 503 }
 504 
 505 /* --------------------------------------------------------------------------------------------- */
 506 
 507 void
 508 tty_touch_screen (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 509 {
 510     SLsmg_touch_lines (0, LINES);
 511 }
 512 
 513 /* --------------------------------------------------------------------------------------------- */
 514 
 515 void
 516 tty_gotoyx (int y, int x)
     /* [previous][next][first][last][top][bottom][index][help]  */
 517 {
 518     SLsmg_gotorc (y, x);
 519 }
 520 
 521 /* --------------------------------------------------------------------------------------------- */
 522 
 523 void
 524 tty_getyx (int *py, int *px)
     /* [previous][next][first][last][top][bottom][index][help]  */
 525 {
 526     *py = SLsmg_get_row ();
 527     *px = SLsmg_get_column ();
 528 }
 529 
 530 /* --------------------------------------------------------------------------------------------- */
 531 
 532 void
 533 tty_draw_hline (int y, int x, mc_tty_char_t ch, int len)
     /* [previous][next][first][last][top][bottom][index][help]  */
 534 {
 535     int x1;
 536 
 537     if (y < 0 || y >= LINES || x >= COLS)
 538         return;
 539 
 540     x1 = x;
 541 
 542     if (x < 0)
 543     {
 544         len += x;
 545         if (len <= 0)
 546             return;
 547         x = 0;
 548     }
 549 
 550     SLsmg_gotorc (y, x);
 551 
 552     if ((mc_global.utf8_display && ch == 0x2500) || ch == MC_ACS_HLINE)
 553         SLsmg_draw_hline (len);
 554     else
 555         while (len-- != 0)
 556             tty_print_char (ch);
 557 
 558     SLsmg_gotorc (y, x1);
 559 }
 560 
 561 /* --------------------------------------------------------------------------------------------- */
 562 
 563 void
 564 tty_draw_vline (int y, int x, mc_tty_char_t ch, int len)
     /* [previous][next][first][last][top][bottom][index][help]  */
 565 {
 566     int y1;
 567 
 568     if (x < 0 || x >= COLS || y >= LINES)
 569         return;
 570 
 571     y1 = y;
 572 
 573     if (y < 0)
 574     {
 575         len += y;
 576         if (len <= 0)
 577             return;
 578         y = 0;
 579     }
 580 
 581     SLsmg_gotorc (y, x);
 582 
 583     if ((mc_global.utf8_display && ch == 0x2502) || ch == MC_ACS_VLINE)
 584         SLsmg_draw_vline (len);
 585     else
 586     {
 587         int pos = 0;
 588 
 589         while (len-- != 0)
 590         {
 591             SLsmg_gotorc (y + pos, x);
 592             tty_print_char (ch);
 593             pos++;
 594         }
 595     }
 596 
 597     SLsmg_gotorc (y1, x);
 598 }
 599 
 600 /* --------------------------------------------------------------------------------------------- */
 601 
 602 void
 603 tty_fill_region (int y, int x, int rows, int cols, unsigned char ch)
     /* [previous][next][first][last][top][bottom][index][help]  */
 604 {
 605     SLsmg_fill_region (y, x, rows, cols, ch);
 606 }
 607 
 608 /* --------------------------------------------------------------------------------------------- */
 609 
 610 void
 611 tty_colorize_area (int y, int x, int rows, int cols, int color)
     /* [previous][next][first][last][top][bottom][index][help]  */
 612 {
 613     if (use_colors)
 614         SLsmg_set_color_in_region (color, y, x, rows, cols);
 615 }
 616 
 617 /* --------------------------------------------------------------------------------------------- */
 618 
 619 void
 620 tty_display_8bit (gboolean what)
     /* [previous][next][first][last][top][bottom][index][help]  */
 621 {
 622     SLsmg_Display_Eight_Bit = what ? 128 : 160;
 623 }
 624 
 625 /* --------------------------------------------------------------------------------------------- */
 626 
 627 void
 628 tty_print_char (mc_tty_char_t c)
     /* [previous][next][first][last][top][bottom][index][help]  */
 629 {
 630     gboolean alt_char = FALSE;
 631     int char_maybe_acs = c;
 632 
 633     if (!mc_global.utf8_display)
 634         char_maybe_acs = get_maybe_acs (char_maybe_acs, &alt_char);
 635 
 636     if (alt_char)
 637         SLsmg_draw_object (SLsmg_get_row (), SLsmg_get_column (), char_maybe_acs);
 638     else
 639         SLsmg_write_char ((SLwchar_Type) ((unsigned int) char_maybe_acs));
 640 }
 641 
 642 /* --------------------------------------------------------------------------------------------- */
 643 
 644 void
 645 tty_print_anychar (mc_tty_char_t c)
     /* [previous][next][first][last][top][bottom][index][help]  */
 646 {
 647     if (c > 255)
 648     {
 649         char str[MB_LEN_MAX + 1];
 650         int res;
 651 
 652         res = g_unichar_to_utf8 (c, str);
 653         if (res == 0)
 654         {
 655             str[0] = '.';
 656             str[1] = '\0';
 657         }
 658         else
 659         {
 660             str[res] = '\0';
 661         }
 662         SLsmg_write_string ((char *) str_term_form (str));
 663     }
 664     else
 665     {
 666         if (!is_printable (c))
 667             c = '.';
 668         SLsmg_write_char ((SLwchar_Type) ((unsigned int) c));
 669     }
 670 }
 671 
 672 /* --------------------------------------------------------------------------------------------- */
 673 
 674 void
 675 tty_print_string (const char *s)
     /* [previous][next][first][last][top][bottom][index][help]  */
 676 {
 677     SLsmg_write_string ((char *) str_term_form (s));
 678 }
 679 
 680 /* --------------------------------------------------------------------------------------------- */
 681 
 682 void
 683 tty_printf (const char *fmt, ...)
     /* [previous][next][first][last][top][bottom][index][help]  */
 684 {
 685     va_list args;
 686 
 687     va_start (args, fmt);
 688     SLsmg_vprintf ((char *) fmt, args);
 689     va_end (args);
 690 }
 691 
 692 /* --------------------------------------------------------------------------------------------- */
 693 
 694 /* Although S-Lang uses the terminfo database by default (through its own parser), it expects
 695  * termcap codes to access standard capabilities. Nevertheless, it can also access extended
 696  * terminfo capabilities (including those that have no termcap equivalent, i.e., whose names
 697  * are longer than two characters).
 698  */
 699 
 700 /* --------------------------------------------------------------------------------------------- */
 701 
 702 int
 703 tty_tigetflag (const char *terminfo_cap, const char *termcap_cap)
     /* [previous][next][first][last][top][bottom][index][help]  */
 704 {
 705     return SLtt_tgetflag ((SLFUTURE_CONST char *) (termcap_cap ? termcap_cap : terminfo_cap));
 706 }
 707 
 708 /* --------------------------------------------------------------------------------------------- */
 709 
 710 int
 711 tty_tigetnum (const char *terminfo_cap, const char *termcap_cap)
     /* [previous][next][first][last][top][bottom][index][help]  */
 712 {
 713     return SLtt_tgetnum ((SLFUTURE_CONST char *) (termcap_cap ? termcap_cap : terminfo_cap));
 714 }
 715 
 716 /* --------------------------------------------------------------------------------------------- */
 717 
 718 char *
 719 tty_tigetstr (const char *terminfo_cap, const char *termcap_cap)
     /* [previous][next][first][last][top][bottom][index][help]  */
 720 {
 721     return SLtt_tgetstr ((SLFUTURE_CONST char *) (termcap_cap ? termcap_cap : terminfo_cap));
 722 }
 723 
 724 /* --------------------------------------------------------------------------------------------- */
 725 
 726 void
 727 tty_refresh (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 728 {
 729     SLsmg_refresh ();
 730 }
 731 
 732 /* --------------------------------------------------------------------------------------------- */
 733 
 734 void
 735 tty_beep (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 736 {
 737     SLtt_beep ();
 738 }
 739 
 740 /* --------------------------------------------------------------------------------------------- */

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