428
+ − 1 /* Communication module for TTY terminals.
+ − 2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
+ − 3 Copyright (C) 1995 Sun Microsystems, Inc.
793
+ − 4 Copyright (C) 1995, 1996, 2002 Ben Wing.
428
+ − 5 Copyright (C) 1996 Chuck Thompson.
+ − 6
+ − 7 This file is part of XEmacs.
+ − 8
+ − 9 XEmacs is free software; you can redistribute it and/or modify it
+ − 10 under the terms of the GNU General Public License as published by the
+ − 11 Free Software Foundation; either version 2, or (at your option) any
+ − 12 later version.
+ − 13
+ − 14 XEmacs is distributed in the hope that it will be useful, but WITHOUT
+ − 15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ − 16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ − 17 for more details.
+ − 18
+ − 19 You should have received a copy of the GNU General Public License
+ − 20 along with XEmacs; see the file COPYING. If not, write to
+ − 21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ − 22 Boston, MA 02111-1307, USA. */
+ − 23
+ − 24 /* Synched up with: Not completely synched with FSF. Mostly divergent
+ − 25 from FSF. */
+ − 26
+ − 27 /* This file has been Mule-ized. */
+ − 28
+ − 29 /* Written by Chuck Thompson. */
+ − 30 /* Color support added by Ben Wing. */
+ − 31
+ − 32 #include <config.h>
+ − 33 #include "lisp.h"
+ − 34
+ − 35 #include "buffer.h"
872
+ − 36 #include "device-impl.h"
428
+ − 37 #include "events.h"
+ − 38 #include "faces.h"
872
+ − 39 #include "frame-impl.h"
428
+ − 40 #include "glyphs.h"
+ − 41 #include "lstream.h"
+ − 42 #include "redisplay.h"
+ − 43 #include "sysdep.h"
+ − 44 #include "window.h"
+ − 45
872
+ − 46 #include "console-tty-impl.h"
+ − 47 #include "objects-tty-impl.h"
800
+ − 48
859
+ − 49 #include "syssignal.h"
+ − 50
428
+ − 51 /* These headers #define all kinds of common words like "columns"...
+ − 52 What a bunch of losers. If we were to include them, we'd have to
+ − 53 include them last to prevent them from messing up our own header
+ − 54 files (struct slot names, etc.). But it turns out that there are
+ − 55 other conflicts as well on some systems, so screw it: we'll just
+ − 56 re-declare the routines we use and assume the code in this file is
+ − 57 invoking them correctly. */
+ − 58 /* # include <curses.h> */
+ − 59 /* # include <term.h> */
442
+ − 60 EXTERN_C int tgetent (const char *, const char *);
+ − 61 EXTERN_C int tgetflag (const char *);
+ − 62 EXTERN_C int tgetnum (const char *);
+ − 63 EXTERN_C char *tgetstr (const char *, char **);
+ − 64 EXTERN_C void tputs (const char *, int, void (*)(int));
+ − 65
428
+ − 66 #define FORCE_CURSOR_UPDATE(c) send_string_to_tty_console (c, 0, 0)
+ − 67 #define OUTPUTN(c, a, n) \
+ − 68 do { \
+ − 69 cmputc_console = c; \
+ − 70 FORCE_CURSOR_UPDATE (c); \
+ − 71 tputs (a, n, cmputc); \
+ − 72 } while (0)
+ − 73 #define OUTPUT1(c, a) OUTPUTN (c, a, 1)
+ − 74 #define OUTPUTN_IF(c, a, n) \
+ − 75 do { \
+ − 76 cmputc_console = c; \
+ − 77 FORCE_CURSOR_UPDATE (c); \
+ − 78 if (a) \
+ − 79 tputs (a, n, cmputc); \
+ − 80 } while (0)
+ − 81 #define OUTPUT1_IF(c, a) OUTPUTN_IF (c, a, 1)
+ − 82
867
+ − 83 static void tty_output_ichar_dynarr (struct window *w,
428
+ − 84 struct display_line *dl,
867
+ − 85 Ichar_dynarr *buf, int xpos,
428
+ − 86 face_index findex,
+ − 87 int cursor);
867
+ − 88 static void tty_output_ibyte_string (struct window *w,
428
+ − 89 struct display_line *dl,
867
+ − 90 Ibyte *str, Bytecount len,
428
+ − 91 int xpos, face_index findex,
+ − 92 int cursor);
+ − 93 static void tty_turn_on_face (struct window *w, face_index findex);
+ − 94 static void tty_turn_off_face (struct window *w, face_index findex);
+ − 95 static void tty_turn_on_frame_face (struct frame *f, Lisp_Object face);
+ − 96 static void tty_turn_off_frame_face (struct frame *f, Lisp_Object face);
+ − 97
+ − 98 static void term_get_fkeys (Lisp_Object keymap, char **address);
+ − 99
+ − 100 /*****************************************************************************
+ − 101 tty_text_width
+ − 102
3571
+ − 103 Non-Mule TTYs don't have fonts (that we use at least), so everything
428
+ − 104 is considered to be fixed width -- in other words, we return LEN.
+ − 105 Under Mule, however, a character can still cover more than one
867
+ − 106 column, so we use ichar_string_displayed_columns().
428
+ − 107 ****************************************************************************/
+ − 108 static int
3571
+ − 109 tty_text_width (struct frame *f, struct face_cachel *UNUSED (cachel),
2286
+ − 110 const Ichar *str, Charcount len)
428
+ − 111 {
3571
+ − 112 struct console *c = XCONSOLE(FRAME_CONSOLE (f));
+ − 113
+ − 114 if (CONSOLE_TTY_MULTIPLE_WIDTH (c))
+ − 115 {
+ − 116 return ichar_string_displayed_columns (str, len);
+ − 117 }
+ − 118
+ − 119 return len;
428
+ − 120 }
+ − 121
+ − 122 /*****************************************************************************
+ − 123 tty_divider_height
+ − 124
+ − 125 Return the width of the horizontal divider. This is a function
+ − 126 because divider_height is a console method.
+ − 127 ****************************************************************************/
+ − 128 static int
+ − 129 tty_divider_height (void)
+ − 130 {
+ − 131 return 1;
+ − 132 }
+ − 133
+ − 134 /*****************************************************************************
+ − 135 tty_eol_cursor_width
+ − 136
+ − 137 Return the width of the end-of-line cursor. This is a function
+ − 138 because eol_cursor_width is a console method.
+ − 139 ****************************************************************************/
+ − 140 static int
+ − 141 tty_eol_cursor_width (void)
+ − 142 {
+ − 143 return 1;
+ − 144 }
+ − 145
+ − 146 /*****************************************************************************
442
+ − 147 tty_frame_output_begin
428
+ − 148
+ − 149 Perform any necessary initialization prior to an update.
+ − 150 ****************************************************************************/
2286
+ − 151 #ifdef HAVE_TERMIOS
+ − 152 #define TERMIOS_MAYBE_UNUSED(decl) UNUSED(decl)
+ − 153 #else
+ − 154 #define TERMIOS_MAYBE_UNUSED(decl) decl
+ − 155 #endif
+ − 156
428
+ − 157 #ifdef DEBUG_XEMACS
2286
+ − 158 void tty_frame_output_begin (struct frame *TERMIOS_MAYBE_UNUSED(f));
428
+ − 159 void
+ − 160 #else
+ − 161 static void
+ − 162 #endif
2286
+ − 163 tty_frame_output_begin (struct frame *TERMIOS_MAYBE_UNUSED(f))
428
+ − 164 {
+ − 165 #ifndef HAVE_TERMIOS
+ − 166 /* Termcap requires `ospeed' to be a global variable so we have to
+ − 167 always set it for whatever tty console we are actually currently
+ − 168 working with. */
442
+ − 169 ospeed = DEVICE_TTY_DATA (XDEVICE (FRAME_DEVICE (f)))->ospeed;
428
+ − 170 #endif
+ − 171 }
+ − 172
+ − 173 /*****************************************************************************
442
+ − 174 tty_frame_output_end
428
+ − 175
+ − 176 Perform any necessary flushing of queues when an update has completed.
+ − 177 ****************************************************************************/
+ − 178 #ifdef DEBUG_XEMACS
442
+ − 179 void tty_frame_output_end (struct frame *f);
428
+ − 180 void
+ − 181 #else
+ − 182 static void
+ − 183 #endif
442
+ − 184 tty_frame_output_end (struct frame *f)
428
+ − 185 {
442
+ − 186 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
428
+ − 187
+ − 188 CONSOLE_TTY_CURSOR_X (c) = CONSOLE_TTY_FINAL_CURSOR_X (c);
+ − 189 CONSOLE_TTY_CURSOR_Y (c) = CONSOLE_TTY_FINAL_CURSOR_Y (c);
+ − 190 FORCE_CURSOR_UPDATE (c);
+ − 191 Lstream_flush (XLSTREAM (CONSOLE_TTY_DATA (c)->outstream));
+ − 192 }
+ − 193
+ − 194 static void
+ − 195 tty_set_final_cursor_coords (struct frame *f, int y, int x)
+ − 196 {
+ − 197 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
+ − 198
+ − 199 CONSOLE_TTY_FINAL_CURSOR_X (c) = x;
+ − 200 CONSOLE_TTY_FINAL_CURSOR_Y (c) = y;
+ − 201 }
+ − 202
+ − 203 /*****************************************************************************
+ − 204 tty_output_display_block
+ − 205
+ − 206 Given a display line, a block number for that start line, output all
+ − 207 runes between start and end in the specified display block.
+ − 208 ****************************************************************************/
+ − 209 static void
+ − 210 tty_output_display_block (struct window *w, struct display_line *dl, int block,
+ − 211 int start, int end, int start_pixpos,
2286
+ − 212 int cursor_start, int UNUSED (cursor_width),
+ − 213 int UNUSED (cursor_height))
428
+ − 214 {
+ − 215 struct frame *f = XFRAME (w->frame);
3479
+ − 216 Ichar_dynarr *buf;
428
+ − 217
+ − 218 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
+ − 219 rune_dynarr *rba = db->runes;
+ − 220 struct rune *rb;
+ − 221
+ − 222 int elt = start;
+ − 223 face_index findex;
+ − 224 int xpos;
+ − 225
+ − 226 rb = Dynarr_atp (rba, elt);
+ − 227
+ − 228 if (!rb)
+ − 229 {
+ − 230 /* Nothing to do so don't do anything. */
+ − 231 return;
+ − 232 }
+ − 233 else
+ − 234 {
+ − 235 findex = rb->findex;
+ − 236 xpos = rb->xpos;
+ − 237 }
+ − 238
+ − 239 if (end < 0)
+ − 240 end = Dynarr_length (rba);
+ − 241
3479
+ − 242 buf = Dynarr_new (Ichar);
428
+ − 243
+ − 244 while (elt < end && Dynarr_atp (rba, elt)->xpos < start_pixpos)
+ − 245 {
+ − 246 elt++;
+ − 247 findex = Dynarr_atp (rba, elt)->findex;
+ − 248 xpos = Dynarr_atp (rba, elt)->xpos;
+ − 249 }
+ − 250
+ − 251 while (elt < end)
+ − 252 {
+ − 253 rb = Dynarr_atp (rba, elt);
+ − 254
+ − 255 if (rb->findex == findex && rb->type == RUNE_CHAR
+ − 256 && rb->object.chr.ch != '\n'
+ − 257 && (rb->cursor_type != CURSOR_ON
+ − 258 || NILP (w->text_cursor_visible_p)))
+ − 259 {
+ − 260 Dynarr_add (buf, rb->object.chr.ch);
+ − 261 elt++;
+ − 262 }
+ − 263 else
+ − 264 {
+ − 265 if (Dynarr_length (buf))
+ − 266 {
867
+ − 267 tty_output_ichar_dynarr (w, dl, buf, xpos, findex, 0);
428
+ − 268 xpos = rb->xpos;
+ − 269 }
+ − 270 Dynarr_reset (buf);
+ − 271
+ − 272 if (rb->type == RUNE_CHAR)
+ − 273 {
+ − 274 findex = rb->findex;
+ − 275 xpos = rb->xpos;
+ − 276
+ − 277 if (rb->object.chr.ch == '\n')
+ − 278 {
+ − 279 /* Clear in case a cursor was formerly here. */
+ − 280
+ − 281 Dynarr_add (buf, ' ');
867
+ − 282 tty_output_ichar_dynarr (w, dl, buf, rb->xpos,
428
+ − 283 DEFAULT_INDEX, 0);
+ − 284 Dynarr_reset (buf);
+ − 285
+ − 286 cmgoto (f, dl->ypos - 1, rb->xpos);
+ − 287
+ − 288 elt++;
+ − 289 }
+ − 290 else if (rb->cursor_type == CURSOR_ON)
+ − 291 {
+ − 292 /* There is not a distinct eol cursor on tty's. */
+ − 293
+ − 294 Dynarr_add (buf, rb->object.chr.ch);
867
+ − 295 tty_output_ichar_dynarr (w, dl, buf, xpos, findex, 0);
428
+ − 296 Dynarr_reset (buf);
+ − 297
+ − 298 cmgoto (f, dl->ypos - 1, xpos);
+ − 299
+ − 300 xpos += rb->width;
+ − 301 elt++;
+ − 302 }
+ − 303 }
+ − 304 /* #### RUNE_HLINE is actually a little more complicated than this
+ − 305 but at the moment it is only used to draw a turned off
+ − 306 modeline and this will suffice for that. */
+ − 307 else if (rb->type == RUNE_BLANK || rb->type == RUNE_HLINE)
+ − 308 {
867
+ − 309 Ichar ch_to_add;
428
+ − 310 int size = rb->width;
+ − 311
+ − 312 if (rb->type == RUNE_BLANK)
+ − 313 ch_to_add = ' ';
+ − 314 else
+ − 315 ch_to_add = '-';
+ − 316
+ − 317 while (size--)
+ − 318 Dynarr_add (buf, ch_to_add);
867
+ − 319 tty_output_ichar_dynarr (w, dl, buf, rb->xpos, findex, 0);
428
+ − 320
+ − 321 if (xpos >= cursor_start
+ − 322 && cursor_start < xpos + Dynarr_length (buf))
+ − 323 {
+ − 324 cmgoto (f, dl->ypos - 1, cursor_start);
+ − 325 }
+ − 326
+ − 327 Dynarr_reset (buf);
+ − 328
+ − 329 elt++;
+ − 330 if (elt < end)
+ − 331 {
+ − 332 rb = Dynarr_atp (rba, elt);
+ − 333
+ − 334 findex = rb->findex;
+ − 335 xpos = rb->xpos;
+ − 336 }
+ − 337 }
+ − 338 else if (rb->type == RUNE_DGLYPH)
+ − 339 {
+ − 340 Lisp_Object window;
+ − 341 Lisp_Object instance;
+ − 342
793
+ − 343 window = wrap_window (w);
428
+ − 344 instance = glyph_image_instance (rb->object.dglyph.glyph,
793
+ − 345 window, ERROR_ME_DEBUG_WARN, 1);
428
+ − 346
+ − 347 if (IMAGE_INSTANCEP (instance))
442
+ − 348 {
+ − 349 switch (XIMAGE_INSTANCE_TYPE (instance))
428
+ − 350 {
442
+ − 351 case IMAGE_MONO_PIXMAP:
+ − 352 case IMAGE_COLOR_PIXMAP:
+ − 353 case IMAGE_SUBWINDOW:
+ − 354 case IMAGE_WIDGET:
+ − 355 /* just do nothing here */
+ − 356 break;
428
+ − 357
442
+ − 358 case IMAGE_NOTHING:
+ − 359 /* nothing is as nothing does */
+ − 360 break;
428
+ − 361
442
+ − 362 case IMAGE_TEXT:
+ − 363 case IMAGE_POINTER:
+ − 364 default:
2500
+ − 365 ABORT ();
428
+ − 366 }
442
+ − 367 IMAGE_INSTANCE_OPTIMIZE_OUTPUT
+ − 368 (XIMAGE_INSTANCE (instance)) = 0;
+ − 369 }
428
+ − 370
+ − 371 xpos += rb->width;
+ − 372 elt++;
+ − 373 }
+ − 374 else
2500
+ − 375 ABORT ();
428
+ − 376 }
+ − 377 }
+ − 378
+ − 379 if (Dynarr_length (buf))
867
+ − 380 tty_output_ichar_dynarr (w, dl, buf, xpos, findex, 0);
428
+ − 381 Dynarr_free (buf);
+ − 382
+ − 383 }
+ − 384
+ − 385
+ − 386
+ − 387 /*****************************************************************************
+ − 388 tty_output_vertical_divider
+ − 389
+ − 390 Draw a vertical divider down the right side of the given window.
+ − 391 ****************************************************************************/
+ − 392 static void
2286
+ − 393 tty_output_vertical_divider (struct window *w, int UNUSED (clear))
428
+ − 394 {
+ − 395 /* Divider width can either be 0 or 1 on TTYs */
+ − 396 if (window_divider_width (w))
+ − 397 {
+ − 398 struct frame *f = XFRAME (w->frame);
+ − 399 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
+ − 400 int line;
+ − 401 int y_top = WINDOW_TEXT_TOP (w);
+ − 402 int y_bot = WINDOW_TEXT_BOTTOM (w);
+ − 403 unsigned char divv = '|';
+ − 404
+ − 405 tty_turn_on_face (w, MODELINE_INDEX);
+ − 406 for (line = y_top; line < y_bot; line++)
+ − 407 {
+ − 408 cmgoto (f, line, WINDOW_TEXT_RIGHT (w));
+ − 409 send_string_to_tty_console (c, &divv, 1);
+ − 410 TTY_INC_CURSOR_X (c, 1);
+ − 411 }
+ − 412
+ − 413 /* Draw the divider in the modeline. */
+ − 414 cmgoto (f, y_bot, WINDOW_TEXT_RIGHT (w));
+ − 415 send_string_to_tty_console (c, &divv, 1);
+ − 416 TTY_INC_CURSOR_X (c, 1);
+ − 417 tty_turn_off_face (w, MODELINE_INDEX);
+ − 418 }
+ − 419 }
+ − 420
+ − 421 /****************************************************************************
+ − 422 tty_clear_region
+ − 423
+ − 424 Clear the area in the box defined by the given parameters.
+ − 425 ****************************************************************************/
+ − 426 static void
2286
+ − 427 tty_clear_region (Lisp_Object window, struct device* UNUSED (d),
+ − 428 struct frame * f, face_index findex, int x, int y,
+ − 429 int width, int height, Lisp_Object UNUSED (fcolor),
+ − 430 Lisp_Object UNUSED (bcolor),
+ − 431 Lisp_Object UNUSED (background_pixmap))
428
+ − 432 {
+ − 433 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
+ − 434 int line;
+ − 435 struct window* w = XWINDOW (window);
+ − 436
+ − 437 tty_turn_on_face (w, findex);
+ − 438 for (line = y; line < y + height; line++)
+ − 439 {
+ − 440 int col;
+ − 441
+ − 442 cmgoto (f, line, x);
+ − 443
+ − 444 if (window_is_leftmost (w)
+ − 445 && window_is_rightmost (w)
+ − 446 && TTY_SE (c).clr_to_eol)
+ − 447 {
+ − 448 OUTPUT1 (c, TTY_SE (c).clr_to_eol);
+ − 449 }
+ − 450 else
+ − 451 {
+ − 452 unsigned char sp = ' ';
+ − 453 /* #### Of course, this is all complete and utter crap. */
+ − 454 for (col = x; col < x + width; col++)
+ − 455 send_string_to_tty_console (c, &sp, 1);
+ − 456 TTY_INC_CURSOR_X (c, width);
+ − 457 }
+ − 458 }
+ − 459 tty_turn_off_face (w, findex);
+ − 460 cmgoto (f, y, x);
+ − 461 }
+ − 462
+ − 463 /*****************************************************************************
+ − 464 tty_clear_to_window_end
+ − 465
+ − 466 Clear the area between ypos1 and ypos2. Each margin area and the
+ − 467 text area is handled separately since they may each have their own
+ − 468 background color.
+ − 469 ****************************************************************************/
+ − 470 static void
+ − 471 tty_clear_to_window_end (struct window *w, int ypos1, int ypos2)
+ − 472 {
+ − 473 struct frame *f = XFRAME (w->frame);
+ − 474 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
+ − 475 int x, width;
+ − 476
+ − 477 x = WINDOW_TEXT_LEFT (w);
+ − 478 width = WINDOW_TEXT_WIDTH (w);
+ − 479
+ − 480 if (window_is_rightmost (w))
+ − 481 {
+ − 482 /* #### Optimize to use clr_to_eol function of tty if available, if
+ − 483 the window is the entire width of the frame. */
+ − 484 /* #### Is this actually an optimization? */
+ − 485 int line;
+ − 486 tty_turn_on_face (w, DEFAULT_INDEX);
+ − 487 for (line = ypos1; line < ypos2; line++)
+ − 488 {
+ − 489 cmgoto (XFRAME (w->frame), line, x);
+ − 490 OUTPUT1 (c, TTY_SE (c).clr_to_eol);
+ − 491 }
+ − 492 tty_turn_off_face (w, DEFAULT_INDEX);
+ − 493 }
+ − 494 else
+ − 495 {
793
+ − 496 Lisp_Object window = wrap_window (w);
428
+ − 497
+ − 498 redisplay_clear_region (window, DEFAULT_INDEX, x, ypos1, width, ypos2 - ypos1);
+ − 499 }
+ − 500 }
+ − 501
+ − 502 /****************************************************************************
+ − 503 tty_clear_frame
+ − 504
+ − 505 Clear the entire frame.
+ − 506 ****************************************************************************/
+ − 507 static void
+ − 508 tty_clear_frame (struct frame *f)
+ − 509 {
+ − 510 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
+ − 511
+ − 512 tty_turn_on_frame_face (f, Vdefault_face);
+ − 513 if (TTY_SE (c).clr_frame)
+ − 514 {
+ − 515 OUTPUT1 (c, TTY_SE (c).clr_frame);
+ − 516 CONSOLE_TTY_REAL_CURSOR_X (c) = 0;
+ − 517 CONSOLE_TTY_REAL_CURSOR_Y (c) = 0;
+ − 518 #ifdef NOT_SURE
+ − 519 FRAME_CURSOR_X (f) = 0;
+ − 520 FRAME_CURSOR_Y (f) = 0;
+ − 521 #endif
+ − 522 }
+ − 523 else
+ − 524 {
+ − 525 #ifdef NOT_SURE
+ − 526 internal_cursor_to (f, 0, 0);
+ − 527 clear_to_end (f);
+ − 528 #else
+ − 529 /* #### Not implemented. */
442
+ − 530 stderr_out ("Not yet.\n");
428
+ − 531 #endif
+ − 532 }
+ − 533 tty_turn_off_frame_face (f, Vdefault_face);
+ − 534 }
+ − 535
+ − 536 static void
867
+ − 537 tty_output_ibyte_string (struct window *w, struct display_line *dl,
2286
+ − 538 Ibyte *str, Bytecount len, int xpos,
+ − 539 face_index findex, int UNUSED (cursor))
428
+ − 540 {
+ − 541 struct frame *f = XFRAME (w->frame);
+ − 542 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
3571
+ − 543 int incing = CONSOLE_TTY_MULTIPLE_WIDTH (c) ?
+ − 544 ibyte_string_displayed_columns (str, len) :
+ − 545 bytecount_to_charcount(str, len);
428
+ − 546
+ − 547 /* First position the cursor. */
+ − 548 cmgoto (f, dl->ypos - 1, xpos);
+ − 549
+ − 550 /* Enable any face properties. */
+ − 551 tty_turn_on_face (w, findex);
+ − 552
+ − 553 send_string_to_tty_console (c, str, len);
3571
+ − 554 TTY_INC_CURSOR_X (c, incing);
428
+ − 555
+ − 556 /* Turn the face properties back off. */
+ − 557 tty_turn_off_face (w, findex);
+ − 558 }
+ − 559
867
+ − 560 static Ibyte_dynarr *tty_output_ichar_dynarr_dynarr;
428
+ − 561
+ − 562 /*****************************************************************************
867
+ − 563 tty_output_ichar_dynarr
428
+ − 564
+ − 565 Given a string and a starting position, output that string in the
+ − 566 given face. If cursor is true, draw a cursor around the string.
+ − 567 ****************************************************************************/
+ − 568 static void
867
+ − 569 tty_output_ichar_dynarr (struct window *w, struct display_line *dl,
+ − 570 Ichar_dynarr *buf, int xpos, face_index findex,
428
+ − 571 int cursor)
+ − 572 {
867
+ − 573 if (!tty_output_ichar_dynarr_dynarr)
+ − 574 tty_output_ichar_dynarr_dynarr = Dynarr_new (Ibyte);
428
+ − 575 else
867
+ − 576 Dynarr_reset (tty_output_ichar_dynarr_dynarr);
428
+ − 577
867
+ − 578 convert_ichar_string_into_ibyte_dynarr (Dynarr_atp (buf, 0),
428
+ − 579 Dynarr_length (buf),
867
+ − 580 tty_output_ichar_dynarr_dynarr);
428
+ − 581
867
+ − 582 tty_output_ibyte_string (w, dl,
+ − 583 Dynarr_atp (tty_output_ichar_dynarr_dynarr, 0),
+ − 584 Dynarr_length (tty_output_ichar_dynarr_dynarr),
428
+ − 585 xpos, findex, cursor);
+ − 586 }
+ − 587
+ − 588 #if 0
+ − 589
867
+ − 590 static Ibyte_dynarr *sidcs_dynarr;
428
+ − 591
+ − 592 static void
+ − 593 substitute_in_dynamic_color_string (Lisp_Object spec, Lisp_Object string)
+ − 594 {
+ − 595 int i;
867
+ − 596 Ibyte *specdata = XSTRING_DATA (spec);
428
+ − 597 Bytecount speclen = XSTRING_LENGTH (spec);
+ − 598
+ − 599 if (!sidcs_dynarr)
867
+ − 600 sidcs_dynarr = Dynarr_new (Ibyte);
428
+ − 601 else
+ − 602 Dynarr_reset (sidcs_dynarr);
+ − 603
+ − 604 for (i = 0; i < speclen; i++)
+ − 605 {
+ − 606 if (specdata[i] == '%' && specdata[i+1] == '%')
+ − 607 {
+ − 608 Dynarr_add (sidcs_dynarr, '%');
+ − 609 i++;
+ − 610 }
+ − 611 else if (specdata[i] == '%' && specdata[i+1] == 's')
+ − 612 {
+ − 613 Dynarr_add_many (sidcs_dynarr,
+ − 614 XSTRING_DATA (string),
+ − 615 XSTRING_LENGTH (string));
+ − 616 i++;
+ − 617 }
+ − 618 else
+ − 619 Dynarr_add (sidcs_dynarr, specdata[i]);
+ − 620 }
+ − 621 }
+ − 622
+ − 623 #endif
+ − 624
+ − 625 static void
+ − 626 set_foreground_to (struct console *c, Lisp_Object sym)
+ − 627 {
+ − 628 Lisp_Object result;
867
+ − 629 Ibyte *escseq = 0;
428
+ − 630 Bytecount escseqlen = 0;
+ − 631
+ − 632 result = assq_no_quit (sym, Vtty_color_alist);
+ − 633 if (!NILP (result))
+ − 634 {
+ − 635 Lisp_Object esc_seq = XCAR (XCDR (result));
+ − 636 escseq = XSTRING_DATA (esc_seq);
+ − 637 escseqlen = XSTRING_LENGTH (esc_seq);
+ − 638 }
+ − 639 #if 0
+ − 640 else if (STRINGP (Vtty_dynamic_color_fg))
+ − 641 {
+ − 642 substitute_in_dynamic_color_string (Vtty_dynamic_color_fg,
+ − 643 Fsymbol_name (sym));
+ − 644 escseq = Dynarr_atp (sidcs_dynarr, 0);
+ − 645 escseqlen = Dynarr_length (sidcs_dynarr);
+ − 646 }
+ − 647 #endif
+ − 648
+ − 649 if (escseq)
+ − 650 {
+ − 651 send_string_to_tty_console (c, escseq, escseqlen);
+ − 652 }
+ − 653 }
+ − 654
+ − 655 static void
+ − 656 set_background_to (struct console *c, Lisp_Object sym)
+ − 657 {
+ − 658 Lisp_Object result;
867
+ − 659 Ibyte *escseq = 0;
428
+ − 660 Bytecount escseqlen = 0;
+ − 661
+ − 662 result = assq_no_quit (sym, Vtty_color_alist);
+ − 663 if (!NILP (result))
+ − 664 {
+ − 665 Lisp_Object esc_seq = XCDR (XCDR (result));
+ − 666 escseq = XSTRING_DATA (esc_seq);
+ − 667 escseqlen = XSTRING_LENGTH (esc_seq);
+ − 668 }
+ − 669 #if 0
+ − 670 else if (STRINGP (Vtty_dynamic_color_bg))
+ − 671 {
+ − 672 substitute_in_dynamic_color_string (Vtty_dynamic_color_bg,
+ − 673 Fsymbol_name (sym));
+ − 674 escseq = Dynarr_atp (sidcs_dynarr, 0);
+ − 675 escseqlen = Dynarr_length (sidcs_dynarr);
+ − 676 }
+ − 677 #endif
+ − 678
+ − 679 if (escseq)
+ − 680 {
+ − 681 send_string_to_tty_console (c, escseq, escseqlen);
+ − 682 }
+ − 683 }
+ − 684
+ − 685 static void
+ − 686 tty_turn_on_face_1 (struct console *c, int highlight_p,
+ − 687 int blinking_p, int dim_p, int underline_p,
+ − 688 int reverse_p, Lisp_Object cinst_fore,
+ − 689 Lisp_Object cinst_back)
+ − 690 {
+ − 691 if (highlight_p)
+ − 692 {
+ − 693 OUTPUT1_IF (c, TTY_SD (c).turn_on_bold);
+ − 694 }
+ − 695
+ − 696 if (blinking_p)
+ − 697 {
+ − 698 OUTPUT1_IF (c, TTY_SD (c).turn_on_blinking);
+ − 699 }
+ − 700
+ − 701 if (dim_p)
+ − 702 {
+ − 703 OUTPUT1_IF (c, TTY_SD (c).turn_on_dim);
+ − 704 }
+ − 705
+ − 706 if (underline_p)
+ − 707 {
+ − 708 /* #### punt for now if underline mode is glitchy */
+ − 709 if (!TTY_FLAGS (c).underline_width)
+ − 710 {
+ − 711 OUTPUT1_IF (c, TTY_SD (c).begin_underline);
+ − 712 }
+ − 713 }
+ − 714
+ − 715 if (reverse_p)
+ − 716 {
+ − 717 /* #### punt for now if standout mode is glitchy */
+ − 718 if (!TTY_FLAGS (c).standout_width)
+ − 719 {
+ − 720 OUTPUT1_IF (c, TTY_SD (c).begin_standout);
+ − 721 }
+ − 722 else
+ − 723 reverse_p = 0;
+ − 724 }
+ − 725
+ − 726 if (reverse_p)
+ − 727 {
+ − 728 Lisp_Object temp = cinst_fore;
+ − 729 cinst_fore = cinst_back;
+ − 730 cinst_back = temp;
+ − 731 }
+ − 732
+ − 733 if (COLOR_INSTANCEP (cinst_fore)
+ − 734 && !EQ (cinst_fore, Vthe_null_color_instance))
+ − 735 set_foreground_to (c, COLOR_INSTANCE_TTY_SYMBOL
+ − 736 (XCOLOR_INSTANCE (cinst_fore)));
+ − 737
+ − 738 if (COLOR_INSTANCEP (cinst_back)
+ − 739 && !EQ (cinst_back, Vthe_null_color_instance))
+ − 740 set_background_to (c, COLOR_INSTANCE_TTY_SYMBOL
+ − 741 (XCOLOR_INSTANCE (cinst_back)));
+ − 742 }
+ − 743
+ − 744 /*****************************************************************************
+ − 745 tty_turn_on_face
+ − 746
+ − 747 Turn on all set properties of the given face.
+ − 748 ****************************************************************************/
+ − 749 static void
+ − 750 tty_turn_on_face (struct window *w, face_index findex)
+ − 751 {
+ − 752 struct frame *f = XFRAME (w->frame);
+ − 753 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
+ − 754
+ − 755 tty_turn_on_face_1 (c,
+ − 756 WINDOW_FACE_CACHEL_HIGHLIGHT_P (w, findex),
+ − 757 WINDOW_FACE_CACHEL_BLINKING_P (w, findex),
+ − 758 WINDOW_FACE_CACHEL_DIM_P (w, findex),
+ − 759 WINDOW_FACE_CACHEL_UNDERLINE_P (w, findex),
+ − 760 WINDOW_FACE_CACHEL_REVERSE_P (w, findex),
+ − 761 WINDOW_FACE_CACHEL_FOREGROUND (w, findex),
+ − 762 WINDOW_FACE_CACHEL_BACKGROUND (w, findex));
+ − 763 }
+ − 764
+ − 765 /*****************************************************************************
+ − 766 tty_turn_off_face
+ − 767
+ − 768 Turn off all set properties of the given face (revert to default
+ − 769 face). We assume that tty_turn_on_face has been called for the given
+ − 770 face so that its properties are actually active.
+ − 771 ****************************************************************************/
+ − 772 static void
+ − 773 tty_turn_off_face (struct window *w, face_index findex)
+ − 774 {
+ − 775 struct frame *f = XFRAME (w->frame);
+ − 776 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
+ − 777
+ − 778 if (WINDOW_FACE_CACHEL_REVERSE_P (w, findex))
+ − 779 {
+ − 780 /* #### punt for now if standout mode is glitchy */
+ − 781 if (!TTY_FLAGS (c).standout_width)
+ − 782 {
+ − 783 OUTPUT1_IF (c, TTY_SD (c).end_standout);
+ − 784 }
+ − 785 }
+ − 786
+ − 787 if (WINDOW_FACE_CACHEL_UNDERLINE_P (w, findex))
+ − 788 {
+ − 789 /* #### punt for now if underline mode is glitchy */
+ − 790 if (!TTY_FLAGS (c).underline_width)
+ − 791 {
+ − 792 OUTPUT1_IF (c, TTY_SD (c).end_underline);
+ − 793 }
+ − 794 }
+ − 795
+ − 796 if (WINDOW_FACE_CACHEL_HIGHLIGHT_P (w, findex) ||
+ − 797 WINDOW_FACE_CACHEL_BLINKING_P (w, findex) ||
+ − 798 WINDOW_FACE_CACHEL_DIM_P (w, findex) ||
+ − 799 !EQ (WINDOW_FACE_CACHEL_FOREGROUND (w, findex),
+ − 800 Vthe_null_color_instance) ||
+ − 801 !EQ (WINDOW_FACE_CACHEL_BACKGROUND (w, findex),
+ − 802 Vthe_null_color_instance))
+ − 803 {
+ − 804 OUTPUT1_IF (c, TTY_SD (c).turn_off_attributes);
+ − 805 }
+ − 806 }
+ − 807
+ − 808 /*****************************************************************************
+ − 809 tty_turn_on_frame_face
+ − 810
+ − 811 Turn on all set properties of the given face.
+ − 812 ****************************************************************************/
+ − 813 static void
+ − 814 tty_turn_on_frame_face (struct frame *f, Lisp_Object face)
+ − 815 {
+ − 816 Lisp_Object frame;
+ − 817 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
+ − 818
793
+ − 819 frame = wrap_frame (f);
428
+ − 820 tty_turn_on_face_1 (c,
+ − 821 FACE_HIGHLIGHT_P (face, frame),
+ − 822 FACE_BLINKING_P (face, frame),
+ − 823 FACE_DIM_P (face, frame),
+ − 824 FACE_UNDERLINE_P (face, frame),
+ − 825 FACE_REVERSE_P (face, frame),
+ − 826 FACE_FOREGROUND (face, frame),
+ − 827 FACE_BACKGROUND (face, frame));
+ − 828 }
+ − 829
+ − 830 /*****************************************************************************
+ − 831 tty_turn_off_frame_face
+ − 832
+ − 833 Turn off all set properties of the given face (revert to default
+ − 834 face). We assume that tty_turn_on_face has been called for the given
+ − 835 face so that its properties are actually active.
+ − 836 ****************************************************************************/
+ − 837 static void
+ − 838 tty_turn_off_frame_face (struct frame *f, Lisp_Object face)
+ − 839 {
+ − 840 Lisp_Object frame;
+ − 841 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
+ − 842
793
+ − 843 frame = wrap_frame (f);
428
+ − 844
+ − 845 if (FACE_REVERSE_P (face, frame))
+ − 846 {
+ − 847 /* #### punt for now if standout mode is glitchy */
+ − 848 if (!TTY_FLAGS (c).standout_width)
+ − 849 {
+ − 850 OUTPUT1_IF (c, TTY_SD (c).end_standout);
+ − 851 }
+ − 852 }
+ − 853
+ − 854 if (FACE_UNDERLINE_P (face, frame))
+ − 855 {
+ − 856 /* #### punt for now if underline mode is glitchy */
+ − 857 if (!TTY_FLAGS (c).underline_width)
+ − 858 {
+ − 859 OUTPUT1_IF (c, TTY_SD (c).end_underline);
+ − 860 }
+ − 861 }
+ − 862
+ − 863 if (FACE_HIGHLIGHT_P (face, frame) ||
+ − 864 FACE_BLINKING_P (face, frame) ||
+ − 865 FACE_DIM_P (face, frame) ||
+ − 866 !EQ (FACE_FOREGROUND (face, frame), Vthe_null_color_instance) ||
+ − 867 !EQ (FACE_BACKGROUND (face, frame), Vthe_null_color_instance))
+ − 868 {
+ − 869 OUTPUT1_IF (c, TTY_SD (c).turn_off_attributes);
+ − 870 }
+ − 871 }
+ − 872
+ − 873 /*****************************************************************************
+ − 874 set_tty_modes
+ − 875
+ − 876 Sets up various parameters on tty modes.
+ − 877 ****************************************************************************/
+ − 878 void
+ − 879 set_tty_modes (struct console *c)
+ − 880 {
+ − 881 if (!CONSOLE_TTY_P (c))
+ − 882 return;
+ − 883
+ − 884 OUTPUT1_IF (c, TTY_SD (c).init_motion);
+ − 885 OUTPUT1_IF (c, TTY_SD (c).cursor_visible);
+ − 886 OUTPUT1_IF (c, TTY_SD (c).keypad_on);
+ − 887 }
+ − 888
+ − 889 /*****************************************************************************
+ − 890 reset_tty_modes
+ − 891
+ − 892 Restore default state of tty.
+ − 893 ****************************************************************************/
+ − 894 void
+ − 895 reset_tty_modes (struct console *c)
+ − 896 {
+ − 897 if (!CONSOLE_TTY_P (c))
+ − 898 return;
+ − 899
+ − 900 OUTPUT1_IF (c, TTY_SD (c).orig_pair);
+ − 901 OUTPUT1_IF (c, TTY_SD (c).keypad_off);
+ − 902 OUTPUT1_IF (c, TTY_SD (c).cursor_normal);
+ − 903 OUTPUT1_IF (c, TTY_SD (c).end_motion);
442
+ − 904
+ − 905 {
+ − 906 Lisp_Object frm = CONSOLE_SELECTED_FRAME (c);
+ − 907
+ − 908 if (!NILP (frm))
+ − 909 tty_frame_output_end (XFRAME (frm));
+ − 910 }
428
+ − 911 }
+ − 912
+ − 913 /*****************************************************************************
+ − 914 tty_redisplay_shutdown
+ − 915
+ − 916 Clear the frame and position the cursor properly for exiting.
+ − 917 ****************************************************************************/
+ − 918 void
+ − 919 tty_redisplay_shutdown (struct console *c)
+ − 920 {
+ − 921 Lisp_Object dev = CONSOLE_SELECTED_DEVICE (c);
+ − 922
+ − 923 if (!NILP (dev))
+ − 924 {
+ − 925 Lisp_Object frm = DEVICE_SELECTED_FRAME (XDEVICE (dev));
+ − 926
+ − 927 if (!NILP (frm))
+ − 928 {
+ − 929 struct frame *f = XFRAME (frm);
+ − 930
+ − 931 /* Clear the bottom line of the frame. */
+ − 932 redisplay_clear_region (FRAME_SELECTED_WINDOW (f), DEFAULT_INDEX, 0,
+ − 933 f->height, f->width, 1);
+ − 934
+ − 935 /* And then stick the cursor there. */
+ − 936 tty_set_final_cursor_coords (f, f->height, 0);
442
+ − 937 tty_frame_output_end (f);
428
+ − 938 }
+ − 939 }
+ − 940 }
+ − 941
+ − 942
+ − 943 /* #### Everything below here is old shit. It should either be moved
+ − 944 up or removed. */
+ − 945
+ − 946
444
+ − 947 #ifdef NOT_YET
428
+ − 948 /* FLAGS - these don't need to be console local since only one console
442
+ − 949 can be being updated at a time. */
428
+ − 950 static int insert_mode_on; /* nonzero if in insert mode */
+ − 951 static int standout_mode_on; /* nonzero if in standout mode */
+ − 952 static int underline_mode_on; /* nonzero if in underline mode */
+ − 953 static int alternate_mode_on; /* nonzero if in alternate char set */
+ − 954 static int attributes_on; /* nonzero if any attributes on */
+ − 955
+ − 956 static void
+ − 957 turn_on_insert (struct frame *f)
+ − 958 {
+ − 959 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
+ − 960
+ − 961 if (!insert_mode_on)
+ − 962 OUTPUT1_IF (c, TTY_SE (c).begin_ins_mode);
+ − 963 insert_mode_on = 1;
+ − 964 }
+ − 965
+ − 966 static void
+ − 967 turn_off_insert (struct frame *f)
+ − 968 {
+ − 969 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
+ − 970
+ − 971 if (insert_mode_on)
+ − 972 OUTPUT1 (c, TTY_SE (c).end_ins_mode);
+ − 973 insert_mode_on = 0;
+ − 974 }
+ − 975
+ − 976 static void
+ − 977 internal_cursor_to (struct frame *f, int row, int col)
+ − 978 {
+ − 979 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
+ − 980
+ − 981 if (!TTY_FLAGS (c).insert_mode_motion)
+ − 982 turn_off_insert (f);
+ − 983 if (!TTY_FLAGS (c).standout_motion)
+ − 984 {
+ − 985 turn_off_standout (f);
+ − 986 turn_off_underline (f);
+ − 987 turn_off_alternate (f);
+ − 988 }
+ − 989
+ − 990 cmgoto (f, row, col);
+ − 991 }
+ − 992
+ − 993 static void
+ − 994 clear_to_end (struct frame *f)
+ − 995 {
+ − 996 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
+ − 997
+ − 998 /* assumes cursor is already positioned */
+ − 999 if (TTY_SE (c).clr_from_cursor)
+ − 1000 {
+ − 1001 OUTPUT1 (c, TTY_SE (c).clr_from_cursor);
+ − 1002 }
+ − 1003 else
+ − 1004 {
+ − 1005 int line = FRAME_CURSOR_Y (f);
+ − 1006
+ − 1007 while (line < FRAME_HEIGHT (f))
+ − 1008 {
+ − 1009 internal_cursor_to (f, line, 0);
+ − 1010 OUTPUT1 (c, TTY_SE (c).clr_to_eol);
+ − 1011 }
+ − 1012 }
+ − 1013 }
+ − 1014 #endif /* 0 */
+ − 1015
+ − 1016 #if 0
+ − 1017 /*
+ − 1018 * clear from last visible line on window to window end (presumably
+ − 1019 * the line above window's modeline
+ − 1020 */
+ − 1021 static void
+ − 1022 tty_clear_window_end (struct window *w, int ystart, int yend)
+ − 1023 {
+ − 1024 struct console *c = XCONSOLE (WINDOW_CONSOLE (w));
+ − 1025 int line;
+ − 1026
+ − 1027 for (line = ystart; line < yend; line++)
+ − 1028 {
+ − 1029 cmgoto (XFRAME (w->frame), line, 0);
+ − 1030 OUTPUT1 (c, TTY_SE (c).clr_to_eol);
+ − 1031 }
+ − 1032 }
+ − 1033
+ − 1034 #endif /* 0 */
+ − 1035
+ − 1036 static int
+ − 1037 tty_flash (struct device *d)
+ − 1038 {
+ − 1039 struct console *c = XCONSOLE (DEVICE_CONSOLE (d));
+ − 1040 if (TTY_SD (c).visual_bell)
+ − 1041 {
+ − 1042 OUTPUT1 (c, TTY_SD (c).visual_bell);
+ − 1043 Lstream_flush (XLSTREAM (CONSOLE_TTY_DATA (c)->outstream));
+ − 1044 return 1;
+ − 1045 }
+ − 1046 else
+ − 1047 return 0;
+ − 1048 }
+ − 1049
+ − 1050 /*
+ − 1051 * tty_ring_bell - sound an audio beep.
+ − 1052 */
+ − 1053 static void
2286
+ − 1054 tty_ring_bell (struct device *d, int volume, int UNUSED (pitch),
+ − 1055 int UNUSED (duration))
428
+ − 1056 {
+ − 1057 struct console *c = XCONSOLE (DEVICE_CONSOLE (d));
+ − 1058
+ − 1059 if (volume)
+ − 1060 {
+ − 1061 OUTPUT1 (c, TTY_SD (c).audio_bell);
+ − 1062 Lstream_flush (XLSTREAM (CONSOLE_TTY_DATA (c)->outstream));
+ − 1063 }
+ − 1064 }
+ − 1065
+ − 1066
+ − 1067 int
+ − 1068 init_tty_for_redisplay (struct device *d, char *terminal_type)
+ − 1069 {
2367
+ − 1070 /* !!#### Mule-ize this */
428
+ − 1071 int status;
+ − 1072 char entry_buffer[2044];
+ − 1073 /* char temp_buffer[2044]; */
+ − 1074 char *bufptr;
+ − 1075 struct console *c = XCONSOLE (DEVICE_CONSOLE (d));
+ − 1076
+ − 1077 /* What we should really do is allocate just enough space for
+ − 1078 the actual strings that are stored; but this would require
+ − 1079 doing this after all the tgetstr()s and adjusting all the
+ − 1080 pointers. */
+ − 1081 CONSOLE_TTY_DATA (c)->term_entry_buffer = (char *) xmalloc (2044);
+ − 1082 bufptr = CONSOLE_TTY_DATA (c)->term_entry_buffer;
+ − 1083
442
+ − 1084 #ifdef SIGTTOU
428
+ − 1085 /* SIGTT* don't exist under win32 */
+ − 1086 EMACS_BLOCK_SIGNAL (SIGTTOU);
+ − 1087 #endif
+ − 1088 status = tgetent (entry_buffer, terminal_type);
442
+ − 1089 #ifdef SIGTTOU
428
+ − 1090 EMACS_UNBLOCK_SIGNAL (SIGTTOU);
+ − 1091 #endif
+ − 1092 #if 0
+ − 1093 if (status < 0)
+ − 1094 return TTY_UNABLE_OPEN_DATABASE;
+ − 1095 else if (status == 0)
+ − 1096 return TTY_TYPE_UNDEFINED;
+ − 1097 #endif
+ − 1098 /* Under Linux at least, <0 is returned for TTY_TYPE_UNDEFINED. --ben */
+ − 1099 if (status <= 0)
+ − 1100 return TTY_TYPE_UNDEFINED;
+ − 1101
+ − 1102 /*
+ − 1103 * Establish the terminal size.
+ − 1104 */
+ − 1105 /* First try to get the info from the system. If that fails, check
+ − 1106 the termcap entry. */
+ − 1107 get_tty_device_size (d, &CONSOLE_TTY_DATA (c)->width,
+ − 1108 &CONSOLE_TTY_DATA (c)->height);
+ − 1109
+ − 1110 if (CONSOLE_TTY_DATA (c)->width <= 0)
+ − 1111 CONSOLE_TTY_DATA (c)->width = tgetnum ("co");
+ − 1112 if (CONSOLE_TTY_DATA (c)->height <= 0)
+ − 1113 CONSOLE_TTY_DATA (c)->height = tgetnum ("li");
+ − 1114
+ − 1115 if (CONSOLE_TTY_DATA (c)->width <= 0 || CONSOLE_TTY_DATA (c)->height <= 0)
+ − 1116 return TTY_SIZE_UNSPECIFIED;
+ − 1117
+ − 1118 /*
+ − 1119 * Initialize cursor motion information.
+ − 1120 */
+ − 1121
+ − 1122 /* local cursor movement */
+ − 1123 TTY_CM (c).up = tgetstr ("up", &bufptr);
+ − 1124 TTY_CM (c).down = tgetstr ("do", &bufptr);
+ − 1125 TTY_CM (c).left = tgetstr ("le", &bufptr);
+ − 1126 TTY_CM (c).right = tgetstr ("nd", &bufptr);
+ − 1127 TTY_CM (c).home = tgetstr ("ho", &bufptr);
+ − 1128 TTY_CM (c).low_left = tgetstr ("ll", &bufptr);
+ − 1129 TTY_CM (c).car_return = tgetstr ("cr", &bufptr);
+ − 1130
+ − 1131 /* absolute cursor motion */
+ − 1132 TTY_CM (c).abs = tgetstr ("cm", &bufptr);
+ − 1133 TTY_CM (c).hor_abs = tgetstr ("ch", &bufptr);
+ − 1134 TTY_CM (c).ver_abs = tgetstr ("cv", &bufptr);
+ − 1135
+ − 1136 /* Verify that the terminal is powerful enough to run Emacs */
+ − 1137 if (!TTY_CM (c).abs)
+ − 1138 {
+ − 1139 if (!TTY_CM (c).up || !TTY_CM (c).down
+ − 1140 || !TTY_CM (c).left || !TTY_CM (c).right)
+ − 1141 return TTY_TYPE_INSUFFICIENT;
+ − 1142 }
+ − 1143
+ − 1144 /* parameterized local cursor movement */
+ − 1145 TTY_CM (c).multi_up = tgetstr ("UP", &bufptr);
+ − 1146 TTY_CM (c).multi_down = tgetstr ("DO", &bufptr);
+ − 1147 TTY_CM (c).multi_left = tgetstr ("LE", &bufptr);
+ − 1148 TTY_CM (c).multi_right = tgetstr ("RI", &bufptr);
+ − 1149
+ − 1150 /* scrolling */
+ − 1151 TTY_CM (c).scroll_forw = tgetstr ("sf", &bufptr);
+ − 1152 TTY_CM (c).scroll_back = tgetstr ("sr", &bufptr);
+ − 1153 TTY_CM (c).multi_scroll_forw = tgetstr ("SF", &bufptr);
+ − 1154 TTY_CM (c).multi_scroll_back = tgetstr ("SR", &bufptr);
+ − 1155 TTY_CM (c).set_scroll_region = tgetstr ("cs", &bufptr);
+ − 1156
+ − 1157
+ − 1158 /*
+ − 1159 * Initialize screen editing information.
+ − 1160 */
+ − 1161
+ − 1162 /* adding to the screen */
+ − 1163 TTY_SE (c).ins_line = tgetstr ("al", &bufptr);
+ − 1164 TTY_SE (c).multi_ins_line = tgetstr ("AL", &bufptr);
+ − 1165 TTY_SE (c).repeat = tgetstr ("rp", &bufptr);
+ − 1166 TTY_SE (c).begin_ins_mode = tgetstr ("im", &bufptr);
+ − 1167 TTY_SE (c).end_ins_mode = tgetstr ("ei", &bufptr);
+ − 1168 TTY_SE (c).ins_char = tgetstr ("ic", &bufptr);
+ − 1169 TTY_SE (c).multi_ins_char = tgetstr ("IC", &bufptr);
+ − 1170 TTY_SE (c).insert_pad = tgetstr ("ip", &bufptr);
+ − 1171
+ − 1172 /* deleting from the screen */
+ − 1173 TTY_SE (c).clr_frame = tgetstr ("cl", &bufptr);
+ − 1174 TTY_SE (c).clr_from_cursor = tgetstr ("cd", &bufptr);
+ − 1175 TTY_SE (c).clr_to_eol = tgetstr ("ce", &bufptr);
+ − 1176 TTY_SE (c).del_line = tgetstr ("dl", &bufptr);
+ − 1177 TTY_SE (c).multi_del_line = tgetstr ("DL", &bufptr);
+ − 1178 TTY_SE (c).del_char = tgetstr ("dc", &bufptr);
+ − 1179 TTY_SE (c).multi_del_char = tgetstr ("DC", &bufptr);
+ − 1180 TTY_SE (c).begin_del_mode = tgetstr ("dm", &bufptr);
+ − 1181 TTY_SE (c).end_del_mode = tgetstr ("ed", &bufptr);
+ − 1182 TTY_SE (c).erase_at_cursor = tgetstr ("ec", &bufptr);
+ − 1183
+ − 1184
+ − 1185 /*
+ − 1186 * Initialize screen display information.
+ − 1187 */
+ − 1188 TTY_SD (c).begin_standout = tgetstr ("so", &bufptr);
+ − 1189 TTY_SD (c).end_standout = tgetstr ("se", &bufptr);
+ − 1190 TTY_SD (c).begin_underline = tgetstr ("us", &bufptr);
+ − 1191 TTY_SD (c).end_underline = tgetstr ("ue", &bufptr);
+ − 1192 TTY_SD (c).begin_alternate = tgetstr ("as", &bufptr);
+ − 1193 TTY_SD (c).end_alternate = tgetstr ("ae", &bufptr);
+ − 1194 TTY_SD (c).turn_on_reverse = tgetstr ("mr", &bufptr);
+ − 1195 TTY_SD (c).turn_on_blinking = tgetstr ("mb", &bufptr);
+ − 1196 TTY_SD (c).turn_on_bold = tgetstr ("md", &bufptr);
+ − 1197 TTY_SD (c).turn_on_dim = tgetstr ("mh", &bufptr);
+ − 1198 TTY_SD (c).turn_off_attributes = tgetstr ("me", &bufptr);
+ − 1199 TTY_SD (c).orig_pair = tgetstr ("op", &bufptr);
+ − 1200
+ − 1201 TTY_SD (c).visual_bell = tgetstr ("vb", &bufptr);
+ − 1202 TTY_SD (c).audio_bell = tgetstr ("bl", &bufptr);
+ − 1203 if (!TTY_SD (c).audio_bell)
+ − 1204 {
+ − 1205 /* If audio_bell doesn't get set, then assume C-g. This is gross and
+ − 1206 ugly but is what Emacs has done from time immortal. */
+ − 1207 TTY_SD (c).audio_bell = "\07";
+ − 1208 }
+ − 1209
+ − 1210 TTY_SD (c).cursor_visible = tgetstr ("ve", &bufptr);
+ − 1211 TTY_SD (c).cursor_normal = tgetstr ("vs", &bufptr);
+ − 1212 TTY_SD (c).init_motion = tgetstr ("ti", &bufptr);
+ − 1213 TTY_SD (c).end_motion = tgetstr ("te", &bufptr);
+ − 1214 TTY_SD (c).keypad_on = tgetstr ("ks", &bufptr);
+ − 1215 TTY_SD (c).keypad_off = tgetstr ("ke", &bufptr);
+ − 1216
+ − 1217
+ − 1218 /*
+ − 1219 * Initialize additional terminal information.
+ − 1220 */
+ − 1221 TTY_FLAGS (c).must_write_spaces = tgetflag ("in");
+ − 1222 TTY_FLAGS (c).insert_mode_motion = tgetflag ("mi");
+ − 1223 TTY_FLAGS (c).standout_motion = tgetflag ("ms");
+ − 1224 TTY_FLAGS (c).memory_above_frame = tgetflag ("da");
+ − 1225 TTY_FLAGS (c).memory_below_frame = tgetflag ("db");
+ − 1226 TTY_FLAGS (c).standout_width = tgetnum ("sg");
+ − 1227 TTY_FLAGS (c).underline_width = tgetnum ("ug");
+ − 1228
+ − 1229 if (TTY_FLAGS (c).standout_width == -1)
+ − 1230 TTY_FLAGS (c).standout_width = 0;
+ − 1231 if (TTY_FLAGS (c).underline_width == -1)
+ − 1232 TTY_FLAGS (c).underline_width = 0;
+ − 1233
+ − 1234 TTY_FLAGS (c).meta_key =
+ − 1235 eight_bit_tty (d) ? tgetflag ("km") || tgetflag ("MT") ? 1 : 2 : 0;
+ − 1236
+ − 1237
+ − 1238 /*
+ − 1239 * Setup the costs tables for this tty console.
+ − 1240 */
+ − 1241 cm_cost_init (c);
+ − 1242
444
+ − 1243 #ifdef NOT_YET
428
+ − 1244 /*
+ − 1245 * Initialize local flags.
+ − 1246 */
+ − 1247 insert_mode_on = 0;
+ − 1248 standout_mode_on = 0;
+ − 1249 underline_mode_on = 0;
+ − 1250 alternate_mode_on = 0;
+ − 1251 attributes_on = 0;
444
+ − 1252 #endif
428
+ − 1253
+ − 1254 /*
+ − 1255 * Attempt to initialize the function_key_map to
+ − 1256 * some kind of sensible value
+ − 1257 */
+ − 1258
+ − 1259 term_get_fkeys (c->function_key_map, &bufptr);
+ − 1260
+ − 1261 {
+ − 1262 /* check for ANSI set-foreground and set-background strings,
+ − 1263 and assume color if so.
+ − 1264
+ − 1265 #### we should support the other (non-ANSI) ways of specifying
+ − 1266 color, too. */
+ − 1267 char foobuf[500];
+ − 1268 char *fooptr = foobuf;
+ − 1269 if ((tgetstr ("AB", &fooptr) && tgetstr ("AF", &fooptr)) ||
+ − 1270 (tgetstr ("Sf", &fooptr) && tgetstr ("Sb", &fooptr)) ||
+ − 1271 ((tgetnum ("Co") > 0) && (tgetnum ("pa") > 0)))
+ − 1272 DEVICE_CLASS (d) = Qcolor;
+ − 1273 else
+ − 1274 DEVICE_CLASS (d) = Qmono;
+ − 1275 }
+ − 1276
+ − 1277 return TTY_INIT_SUCCESS;
+ − 1278 }
+ − 1279
+ − 1280 struct fkey_table
+ − 1281 {
442
+ − 1282 const char *cap;
+ − 1283 const char *name;
428
+ − 1284 };
+ − 1285
+ − 1286 /* Termcap capability names that correspond directly to X keysyms.
+ − 1287 Some of these (marked "terminfo") aren't supplied by old-style
+ − 1288 (Berkeley) termcap entries. They're listed in X keysym order;
+ − 1289 except we put the keypad keys first, so that if they clash with
+ − 1290 other keys (as on the IBM PC keyboard) they get overridden.
+ − 1291 */
+ − 1292
+ − 1293 static struct fkey_table keys[] =
+ − 1294 {
+ − 1295 {"kh", "home"}, /* termcap */
+ − 1296 {"kl", "left"}, /* termcap */
+ − 1297 {"ku", "up"}, /* termcap */
+ − 1298 {"kr", "right"}, /* termcap */
+ − 1299 {"kd", "down"}, /* termcap */
+ − 1300 {"%8", "prior"}, /* terminfo */
+ − 1301 {"%5", "next"}, /* terminfo */
+ − 1302 {"@7", "end"}, /* terminfo */
+ − 1303 {"@1", "begin"}, /* terminfo */
+ − 1304 {"*6", "select"}, /* terminfo */
+ − 1305 {"%9", "print"}, /* terminfo */
+ − 1306 {"@4", "execute"}, /* terminfo --- actually the `command' key */
+ − 1307 /*
+ − 1308 * "insert" --- see below
+ − 1309 */
+ − 1310 {"&8", "undo"}, /* terminfo */
+ − 1311 {"%0", "redo"}, /* terminfo */
+ − 1312 {"%7", "menu"}, /* terminfo --- actually the `options' key */
+ − 1313 {"@0", "find"}, /* terminfo */
+ − 1314 {"@2", "cancel"}, /* terminfo */
+ − 1315 {"%1", "help"}, /* terminfo */
+ − 1316 /*
+ − 1317 * "break" goes here, but can't be reliably intercepted with termcap
+ − 1318 */
+ − 1319 {"&4", "reset"}, /* terminfo --- actually `restart' */
+ − 1320 /*
+ − 1321 * "system" and "user" --- no termcaps
+ − 1322 */
+ − 1323 {"kE", "clearline"}, /* terminfo */
+ − 1324 {"kA", "insertline"}, /* terminfo */
+ − 1325 {"kL", "deleteline"}, /* terminfo */
+ − 1326 {"kI", "insertchar"}, /* terminfo */
+ − 1327 {"kD", "delete"}, /* terminfo */
+ − 1328 {"kB", "backtab"}, /* terminfo */
+ − 1329 /*
+ − 1330 * "kp-backtab", "kp-space", "kp-tab" --- no termcaps
+ − 1331 */
+ − 1332 {"@8", "kp-enter"}, /* terminfo */
+ − 1333 /*
+ − 1334 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
+ − 1335 * "kp-multiply", "kp-add", "kp-separator",
+ − 1336 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
+ − 1337 * --- no termcaps for any of these.
+ − 1338 */
+ − 1339 {"K4", "kp-1"}, /* terminfo */
+ − 1340 /*
+ − 1341 * "kp-2" --- no termcap
+ − 1342 */
+ − 1343 {"K5", "kp-3"}, /* terminfo */
+ − 1344 /*
+ − 1345 * "kp-4" --- no termcap
+ − 1346 */
+ − 1347 {"K2", "kp-5"}, /* terminfo */
+ − 1348 /*
+ − 1349 * "kp-6" --- no termcap
+ − 1350 */
+ − 1351 {"K1", "kp-7"}, /* terminfo */
+ − 1352 /*
+ − 1353 * "kp-8" --- no termcap
+ − 1354 */
+ − 1355 {"K3", "kp-9"}, /* terminfo */
+ − 1356 /*
+ − 1357 * "kp-equal" --- no termcap
+ − 1358 */
+ − 1359 {"k1", "f1"},
+ − 1360 {"k2", "f2"},
+ − 1361 {"k3", "f3"},
+ − 1362 {"k4", "f4"},
+ − 1363 {"k5", "f5"},
+ − 1364 {"k6", "f6"},
+ − 1365 {"k7", "f7"},
+ − 1366 {"k8", "f8"},
+ − 1367 {"k9", "f9"},
+ − 1368 };
+ − 1369
+ − 1370 static char **term_get_fkeys_arg;
+ − 1371
+ − 1372 static Lisp_Object term_get_fkeys_1 (Lisp_Object keymap);
+ − 1373 static Lisp_Object term_get_fkeys_error (Lisp_Object err, Lisp_Object arg);
+ − 1374
+ − 1375 /* Find the escape codes sent by the function keys for Vfunction_key_map.
+ − 1376 This function scans the termcap function key sequence entries, and
+ − 1377 adds entries to Vfunction_key_map for each function key it finds. */
+ − 1378
+ − 1379 static void
+ − 1380 term_get_fkeys (Lisp_Object keymap, char **address)
+ − 1381 {
+ − 1382 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
+ − 1383 errors during the call. The only errors should be from Fdefine_key
+ − 1384 when given a key sequence containing an invalid prefix key. If the
+ − 1385 termcap defines function keys which use a prefix that is already bound
+ − 1386 to a command by the default bindings, we should silently ignore that
+ − 1387 function key specification, rather than giving the user an error and
+ − 1388 refusing to run at all on such a terminal. */
+ − 1389
+ − 1390 term_get_fkeys_arg = address;
+ − 1391
+ − 1392 condition_case_1 (Qerror,
+ − 1393 term_get_fkeys_1, keymap,
+ − 1394 term_get_fkeys_error, Qnil);
+ − 1395 }
+ − 1396
+ − 1397 static Lisp_Object
2286
+ − 1398 term_get_fkeys_error (Lisp_Object UNUSED (err), Lisp_Object arg)
428
+ − 1399 {
+ − 1400 return arg;
+ − 1401 }
+ − 1402
+ − 1403 static Lisp_Object
+ − 1404 term_get_fkeys_1 (Lisp_Object function_key_map)
+ − 1405 {
+ − 1406 int i;
+ − 1407
+ − 1408 char **address = term_get_fkeys_arg;
+ − 1409
+ − 1410 for (i = 0; i < countof (keys); i++)
+ − 1411 {
+ − 1412 char *sequence = tgetstr (keys[i].cap, address);
+ − 1413 if (sequence)
+ − 1414 Fdefine_key (function_key_map,
440
+ − 1415 build_ext_string (sequence, Qbinary),
428
+ − 1416 vector1 (intern (keys[i].name)));
+ − 1417 }
+ − 1418
+ − 1419 /* The uses of the "k0" capability are inconsistent; sometimes it
+ − 1420 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
+ − 1421 We will attempt to politely accommodate both systems by testing for
+ − 1422 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
+ − 1423 */
+ − 1424 {
442
+ − 1425 const char *k_semi = tgetstr ("k;", address);
+ − 1426 const char *k0 = tgetstr ("k0", address);
428
+ − 1427
+ − 1428 if (k_semi)
440
+ − 1429 Fdefine_key (function_key_map, build_ext_string (k_semi, Qbinary),
428
+ − 1430 vector1 (intern ("f10")));
+ − 1431
+ − 1432 if (k0)
440
+ − 1433 Fdefine_key (function_key_map, build_ext_string (k0, Qbinary),
428
+ − 1434 vector1 (intern (k_semi ? "f0" : "f10")));
+ − 1435 }
+ − 1436
+ − 1437 /* Set up cookies for numbered function keys above f10. */
+ − 1438 {
+ − 1439 char fcap[3], fkey[4];
+ − 1440
+ − 1441 fcap[0] = 'F'; fcap[2] = '\0';
+ − 1442 for (i = 11; i < 64; i++)
+ − 1443 {
+ − 1444 if (i <= 19)
+ − 1445 fcap[1] = '1' + i - 11;
+ − 1446 else if (i <= 45)
+ − 1447 fcap[1] = 'A' + i - 20;
+ − 1448 else
+ − 1449 fcap[1] = 'a' + i - 46;
+ − 1450
+ − 1451 {
+ − 1452 char *sequence = tgetstr (fcap, address);
+ − 1453 if (sequence)
+ − 1454 {
+ − 1455 sprintf (fkey, "f%d", i);
+ − 1456 Fdefine_key (function_key_map,
440
+ − 1457 build_ext_string (sequence, Qbinary),
428
+ − 1458 vector1 (intern (fkey)));
+ − 1459 }
+ − 1460 }
+ − 1461 }
+ − 1462 }
+ − 1463
+ − 1464 /*
+ − 1465 * Various mappings to try and get a better fit.
+ − 1466 */
440
+ − 1467 #define CONDITIONAL_REASSIGN(cap1, cap2, keyname) do { \
+ − 1468 if (!tgetstr (cap1, address)) \
+ − 1469 { \
+ − 1470 char *sequence = tgetstr (cap2, address); \
+ − 1471 if (sequence) \
+ − 1472 Fdefine_key (function_key_map, \
+ − 1473 build_ext_string (sequence, Qbinary), \
+ − 1474 vector1 (intern (keyname))); \
+ − 1475 } \
+ − 1476 } while (0)
428
+ − 1477
+ − 1478 /* if there's no key_next keycap, map key_npage to `next' keysym */
+ − 1479 CONDITIONAL_REASSIGN ("%5", "kN", "next");
+ − 1480 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
+ − 1481 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
+ − 1482 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
+ − 1483 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
+ − 1484
+ − 1485 /* IBM has their own non-standard dialect of terminfo.
+ − 1486 If the standard name isn't found, try the IBM name. */
+ − 1487 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
+ − 1488 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
+ − 1489 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
+ − 1490 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
+ − 1491 CONDITIONAL_REASSIGN ("@7", "kw", "end");
+ − 1492 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
+ − 1493 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
+ − 1494 CONDITIONAL_REASSIGN ("%1", "kq", "help");
+ − 1495 CONDITIONAL_REASSIGN ("*6", "kU", "select");
+ − 1496 #undef CONDITIONAL_REASSIGN
+ − 1497
+ − 1498 return Qnil;
+ − 1499 }
+ − 1500
+ − 1501
+ − 1502 /************************************************************************/
+ − 1503 /* initialization */
+ − 1504 /************************************************************************/
+ − 1505
+ − 1506 void
+ − 1507 console_type_create_redisplay_tty (void)
+ − 1508 {
+ − 1509 /* redisplay methods */
+ − 1510 CONSOLE_HAS_METHOD (tty, text_width);
+ − 1511 CONSOLE_HAS_METHOD (tty, output_display_block);
+ − 1512 CONSOLE_HAS_METHOD (tty, output_vertical_divider);
+ − 1513 CONSOLE_HAS_METHOD (tty, divider_height);
+ − 1514 CONSOLE_HAS_METHOD (tty, eol_cursor_width);
+ − 1515 CONSOLE_HAS_METHOD (tty, clear_to_window_end);
+ − 1516 CONSOLE_HAS_METHOD (tty, clear_region);
+ − 1517 CONSOLE_HAS_METHOD (tty, clear_frame);
442
+ − 1518 CONSOLE_HAS_METHOD (tty, frame_output_begin);
+ − 1519 CONSOLE_HAS_METHOD (tty, frame_output_end);
428
+ − 1520 CONSOLE_HAS_METHOD (tty, flash);
+ − 1521 CONSOLE_HAS_METHOD (tty, ring_bell);
+ − 1522 CONSOLE_HAS_METHOD (tty, set_final_cursor_coords);
+ − 1523 }