|
|
1.1 ! root 1: /* terminal control module for terminals described by TERMCAP ! 2: Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GNU Emacs. ! 5: ! 6: GNU Emacs is distributed in the hope that it will be useful, ! 7: but WITHOUT ANY WARRANTY. No author or distributor ! 8: accepts responsibility to anyone for the consequences of using it ! 9: or for whether it serves any particular purpose or works at all, ! 10: unless he says so in writing. Refer to the GNU Emacs General Public ! 11: License for full details. ! 12: ! 13: Everyone is granted permission to copy, modify and redistribute ! 14: GNU Emacs, but only under the conditions described in the ! 15: GNU Emacs General Public License. A copy of this license is ! 16: supposed to have been given to you along with GNU Emacs so you ! 17: can know your rights and responsibilities. It should be in a ! 18: file named COPYING. Among other things, the copyright notice ! 19: and this notice must be preserved on all copies. */ ! 20: ! 21: ! 22: #include <stdio.h> ! 23: #include <ctype.h> ! 24: #include "config.h" ! 25: #include "termhooks.h" ! 26: #include "termchar.h" ! 27: #include "termopts.h" ! 28: #include "cm.h" ! 29: ! 30: #define max(a, b) ((a) > (b) ? (a) : (b)) ! 31: #define min(a, b) ((a) < (b) ? (a) : (b)) ! 32: ! 33: #define OUTPUT(a) tputs (a, screen_height - curY, cmputc) ! 34: #define OUTPUT1(a) tputs (a, 1, cmputc) ! 35: #define OUTPUTL(a, lines) tputs (a, lines, cmputc) ! 36: #define OUTPUT_IF(a) { if (a) tputs (a, screen_height - curY, cmputc); } ! 37: #define OUTPUT1_IF(a) { if (a) tputs (a, 1, cmputc); } ! 38: ! 39: /* Terminal charateristics that higher levels want to look at. ! 40: These are all extern'd in termchar.h */ ! 41: ! 42: int screen_width; /* Number of usable columns */ ! 43: int screen_height; /* Number of lines */ ! 44: int must_write_spaces; /* Nonzero means spaces in the text ! 45: must actually be output; can't just skip ! 46: over some columns to leave them blank. */ ! 47: int min_padding_speed; /* Speed below which no padding necessary */ ! 48: ! 49: int line_ins_del_ok; /* Terminal can insert and delete lines */ ! 50: int char_ins_del_ok; /* Terminal can insert and delete chars */ ! 51: int scroll_region_ok; /* Terminal supports setting the scroll window */ ! 52: int memory_below_screen; /* Terminal remembers lines scrolled off bottom */ ! 53: int fast_clear_end_of_line; /* Terminal has a `ce' string */ ! 54: ! 55: int dont_calculate_costs; /* Nonzero means don't bother computing */ ! 56: /* various cost tables; we won't use them. */ ! 57: ! 58: /* Nonzero means no need to redraw the entire screen on resuming ! 59: a suspended Emacs. This is useful on terminals with multiple pages, ! 60: where one page is used for Emacs and another for all else. */ ! 61: int no_redraw_on_reenter; ! 62: ! 63: /* DCICcost[n] is cost of inserting N characters. ! 64: DCICcost[-n] is cost of deleting N characters. */ ! 65: ! 66: #define DCICcost (&DC_ICcost[MScreenWidth]) ! 67: int DC_ICcost[1 + 2 * MScreenWidth]; ! 68: ! 69: ! 70: /* Hook functions that you can set to snap out the functions in this file. ! 71: These are all extern'd in termhooks.h */ ! 72: ! 73: int (*topos_hook) (); ! 74: int (*raw_topos_hook) (); ! 75: ! 76: int (*clear_to_end_hook) (); ! 77: int (*clear_screen_hook) (); ! 78: int (*clear_end_of_line_hook) (); ! 79: ! 80: int (*ins_del_lines_hook) (); ! 81: ! 82: int (*change_line_highlight_hook) (); ! 83: int (*reassert_line_highlight_hook) (); ! 84: ! 85: int (*insert_chars_hook) (); ! 86: int (*write_chars_hook) (); ! 87: int (*delete_chars_hook) (); ! 88: ! 89: int (*ring_bell_hook) (); ! 90: ! 91: int (*reset_terminal_modes_hook) (); ! 92: int (*set_terminal_modes_hook) (); ! 93: int (*update_begin_hook) (); ! 94: int (*update_end_hook) (); ! 95: int (*set_terminal_window_hook) (); ! 96: ! 97: int (*read_socket_hook) (); ! 98: int (*fix_screen_hook) (); ! 99: ! 100: /* Strings, numbers and flags taken from the termcap entry. */ ! 101: ! 102: char *TS_ins_line; /* termcap "al" */ ! 103: char *TS_ins_multi_lines; /* "AL" (one parameter, # lines to insert) */ ! 104: char *TS_bell; /* "bl" */ ! 105: char *TS_clr_to_bottom; /* "cd" */ ! 106: char *TS_clr_line; /* "ce", clear to end of line */ ! 107: char *TS_clr_screen; /* "cl" */ ! 108: char *TS_set_scroll_region; /* "cs" (2 params, first line and last line) */ ! 109: char *TS_set_scroll_region_1; /* "cS" (4 params: total lines, ! 110: lines above scroll region, lines below it, ! 111: total lines again) */ ! 112: char *TS_del_char; /* "dc" */ ! 113: char *TS_del_multi_chars; /* "DC" (one parameter, # chars to delete) */ ! 114: char *TS_del_line; /* "dl" */ ! 115: char *TS_del_multi_lines; /* "DL" (one parameter, # lines to delete) */ ! 116: char *TS_delete_mode; /* "dm", enter character-delete mode */ ! 117: char *TS_end_delete_mode; /* "ed", leave character-delete mode */ ! 118: char *TS_end_insert_mode; /* "ei", leave character-insert mode */ ! 119: char *TS_ins_char; /* "ic" */ ! 120: char *TS_ins_multi_chars; /* "IC" (one parameter, # chars to insert) */ ! 121: char *TS_insert_mode; /* "im", enter character-insert mode */ ! 122: char *TS_pad_inserted_char; /* "ip". Just padding, no commands. */ ! 123: char *TS_end_keypad_mode; /* "ke" */ ! 124: char *TS_keypad_mode; /* "ks" */ ! 125: char *TS_pad_char; /* "pc", char to use as padding */ ! 126: char *TS_repeat; /* "rp" (2 params, # times to repeat ! 127: and character to be repeated) */ ! 128: char *TS_end_standout_mode; /* "se" */ ! 129: char *TS_fwd_scroll; /* "sf" */ ! 130: char *TS_standout_mode; /* "so" */ ! 131: char *TS_rev_scroll; /* "sr" */ ! 132: char *TS_end_termcap_modes; /* "te" */ ! 133: char *TS_termcap_modes; /* "ti" */ ! 134: char *TS_visible_bell; /* "vb" */ ! 135: char *TS_end_visual_mode; /* "ve" */ ! 136: char *TS_visual_mode; /* "vi" */ ! 137: char *TS_set_window; /* "wi" (4 params, start and end of window, ! 138: each as vpos and hpos) */ ! 139: ! 140: int TF_hazeltine; /* termcap hz flag. */ ! 141: int TF_insmode_motion; /* termcap mi flag: can move while in insert mode. */ ! 142: int TF_standout_motion; /* termcap mi flag: can move while in standout mode. */ ! 143: int TF_underscore; /* termcap ul flag: _ underlines if overstruck on ! 144: nonblank position. Must clear before writing _. */ ! 145: int TF_teleray; /* termcap xt flag: many weird consequences. For t1061. */ ! 146: ! 147: int TF_xs; /* Nonzero for "xs". If set together with ! 148: TN_standout_width == 0, it means don't bother ! 149: to write any end-standout cookies. */ ! 150: ! 151: int TN_standout_width; /* termcap sg number: width occupied by standout markers */ ! 152: ! 153: static int RPov; /* # chars to start a TS_repeat */ ! 154: ! 155: static int delete_in_insert_mode; /* delete mode == insert mode */ ! 156: ! 157: static int se_is_so; /* 1 if same string both enters and leaves standout mode */ ! 158: ! 159: /* internal state */ ! 160: ! 161: /* Number of chars of space used for standout marker at beginning of line, ! 162: or'd with 0100. Zero if no standout marker at all. */ ! 163: /* used iff TN_standout_width >= 0. */ ! 164: char chars_wasted[MScreenLength]; ! 165: ! 166: /* nonzero means supposed to write text in standout mode. */ ! 167: int standout_requested; ! 168: ! 169: int insert_mode; /* Nonzero when in insert mode. */ ! 170: int standout_mode; /* Nonzero when in standout mode. */ ! 171: ! 172: /* Size of window specified by higher levels. ! 173: This is the number of lines, starting from top of screen, ! 174: to participate in ins/del line operations. ! 175: Effectively it excludes the bottom ! 176: screen_height - specified_window_size ! 177: lines from those operations. */ ! 178: ! 179: int specified_window; ! 180: ! 181: char *tparam (); ! 182: ! 183: ring_bell () ! 184: { ! 185: if (ring_bell_hook) ! 186: { ! 187: (*ring_bell_hook) (); ! 188: return; ! 189: } ! 190: OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell); ! 191: } ! 192: ! 193: set_terminal_modes () ! 194: { ! 195: if (set_terminal_modes_hook) ! 196: { ! 197: (*set_terminal_modes_hook) (); ! 198: return; ! 199: } ! 200: OUTPUT_IF (TS_termcap_modes); ! 201: OUTPUT_IF (TS_visual_mode); ! 202: OUTPUT_IF (TS_keypad_mode); ! 203: losecursor (); ! 204: } ! 205: ! 206: reset_terminal_modes () ! 207: { ! 208: if (reset_terminal_modes_hook) ! 209: { ! 210: (*reset_terminal_modes_hook) (); ! 211: return; ! 212: } ! 213: if (TN_standout_width < 0) ! 214: turn_off_highlight (); ! 215: turn_off_insert (); ! 216: OUTPUT_IF (TS_end_keypad_mode); ! 217: OUTPUT_IF (TS_end_visual_mode); ! 218: OUTPUT_IF (TS_end_termcap_modes); ! 219: } ! 220: ! 221: update_begin () ! 222: { ! 223: if (update_begin_hook) ! 224: (*update_begin_hook) (); ! 225: } ! 226: ! 227: update_end () ! 228: { ! 229: if (update_end_hook) ! 230: { ! 231: (*update_end_hook) (); ! 232: return; ! 233: } ! 234: turn_off_insert (); ! 235: background_highlight (); ! 236: standout_requested = 0; ! 237: } ! 238: ! 239: set_terminal_window (size) ! 240: int size; ! 241: { ! 242: if (set_terminal_window_hook) ! 243: { ! 244: (*set_terminal_window_hook) (size); ! 245: return; ! 246: } ! 247: specified_window = size ? size : screen_height; ! 248: if (!scroll_region_ok) ! 249: return; ! 250: set_scroll_region (0, specified_window); ! 251: } ! 252: ! 253: set_scroll_region (start, stop) ! 254: int start, stop; ! 255: { ! 256: char *buf; ! 257: if (TS_set_scroll_region) ! 258: { ! 259: buf = tparam (TS_set_scroll_region, 0, 0, start, stop - 1); ! 260: } ! 261: else if (TS_set_scroll_region_1) ! 262: { ! 263: buf = tparam (TS_set_scroll_region_1, 0, 0, ! 264: screen_height, start, screen_height - stop, screen_height); ! 265: } ! 266: else ! 267: { ! 268: buf = tparam (TS_set_window, 0, 0, start, 0, stop, screen_width); ! 269: } ! 270: OUTPUT (buf); ! 271: free (buf); ! 272: losecursor (); ! 273: } ! 274: ! 275: turn_on_insert () ! 276: { ! 277: if (!insert_mode) ! 278: OUTPUT (TS_insert_mode); ! 279: insert_mode = 1; ! 280: } ! 281: ! 282: turn_off_insert () ! 283: { ! 284: if (insert_mode) ! 285: OUTPUT (TS_end_insert_mode); ! 286: insert_mode = 0; ! 287: } ! 288: ! 289: /* Handle highlighting when TN_standout_width (termcap sg) is not specified. ! 290: In these terminals, output is affected by the value of standout ! 291: mode when the output is written. ! 292: ! 293: These functions are called on all terminals, but do nothing ! 294: on terminals whose standout mode does not work that way. */ ! 295: ! 296: turn_off_highlight () ! 297: { ! 298: if (TN_standout_width < 0) ! 299: { ! 300: if (standout_mode) ! 301: OUTPUT_IF (TS_end_standout_mode); ! 302: standout_mode = 0; ! 303: } ! 304: } ! 305: ! 306: turn_on_highlight () ! 307: { ! 308: if (TN_standout_width < 0) ! 309: { ! 310: if (!standout_mode) ! 311: OUTPUT_IF (TS_standout_mode); ! 312: standout_mode = 1; ! 313: } ! 314: } ! 315: ! 316: /* Set standout mode to the state it should be in for ! 317: empty space inside windows. What this is, ! 318: depends on the user option inverse-video. */ ! 319: ! 320: background_highlight () ! 321: { ! 322: if (TN_standout_width >= 0) ! 323: return; ! 324: if (inverse_video) ! 325: turn_on_highlight (); ! 326: else ! 327: turn_off_highlight (); ! 328: } ! 329: ! 330: /* Set standout mode to the mode specified for the text to be output. */ ! 331: ! 332: static ! 333: highlight_if_desired () ! 334: { ! 335: if (TN_standout_width >= 0) ! 336: return; ! 337: if (!inverse_video == !standout_requested) ! 338: turn_off_highlight (); ! 339: else ! 340: turn_on_highlight (); ! 341: } ! 342: ! 343: /* Handle standout mode for terminals in which TN_standout_width >= 0. ! 344: On these terminals, standout is controlled by markers that ! 345: live inside the screen memory. TN_standout_width is the width ! 346: that the marker occupies in memory. Standout runs from the marker ! 347: to the end of the line on some terminals, or to the next ! 348: turn-off-standout marker (TS_end_standout_mode) string ! 349: on other terminals. */ ! 350: ! 351: /* Write a standout marker or end-standout marker at the front of the line ! 352: at vertical position vpos. */ ! 353: ! 354: write_standout_marker (flag, vpos) ! 355: int flag, vpos; ! 356: { ! 357: if (flag || (TS_end_standout_mode && !TF_teleray && !se_is_so ! 358: && !(TF_xs && TN_standout_width == 0))) ! 359: { ! 360: cmgoto (vpos, 0); ! 361: cmplus (TN_standout_width); ! 362: OUTPUT (flag ? TS_standout_mode : TS_end_standout_mode); ! 363: chars_wasted[curY] = TN_standout_width | 0100; ! 364: } ! 365: } ! 366: ! 367: /* External interface to control of standout mode. ! 368: Call this when about to modify line at position VPOS ! 369: and not change whether it is highlighted. */ ! 370: ! 371: reassert_line_highlight (highlight, vpos) ! 372: int highlight; ! 373: int vpos; ! 374: { ! 375: if (reassert_line_highlight_hook) ! 376: { ! 377: (*reassert_line_highlight_hook) (highlight, vpos); ! 378: return; ! 379: } ! 380: if (TN_standout_width < 0) ! 381: /* Handle terminals where standout takes affect at output time */ ! 382: standout_requested = highlight; ! 383: else if (chars_wasted[vpos] == 0) ! 384: /* For terminals with standout markers, write one on this line ! 385: if there isn't one already. */ ! 386: write_standout_marker (highlight, vpos); ! 387: } ! 388: ! 389: /* Call this when about to modify line at position VPOS ! 390: and change whether it is highlighted. */ ! 391: ! 392: change_line_highlight (new_highlight, vpos, first_unused_hpos) ! 393: int new_highlight, vpos, first_unused_hpos; ! 394: { ! 395: standout_requested = new_highlight; ! 396: if (change_line_highlight_hook) ! 397: { ! 398: (*change_line_highlight_hook) (new_highlight, vpos, first_unused_hpos); ! 399: return; ! 400: } ! 401: ! 402: topos (vpos, 0); ! 403: ! 404: if (TN_standout_width < 0) ! 405: background_highlight (); ! 406: /* If line starts with a marker, delete the marker */ ! 407: else if (TS_clr_line && chars_wasted[curY]) ! 408: { ! 409: turn_off_insert (); ! 410: /* On Teleray, make sure to erase the SO marker. */ ! 411: if (TF_teleray) ! 412: { ! 413: cmgoto (curY - 1, screen_width - 4); ! 414: OUTPUT ("\033S"); ! 415: curY++; /* ESC S moves to next line where the TS_standout_mode was */ ! 416: curX = 0; ! 417: } ! 418: else ! 419: cmgoto (curY, 0); /* reposition to kill standout marker */ ! 420: } ! 421: clear_end_of_line_raw (first_unused_hpos); ! 422: reassert_line_highlight (new_highlight, curY); ! 423: } ! 424: ! 425: /* Move to absolute position, specified origin 0 */ ! 426: ! 427: topos (row, col) ! 428: { ! 429: col += chars_wasted[row] & 077; ! 430: if (topos_hook) ! 431: { ! 432: (*topos_hook) (row, col); ! 433: return; ! 434: } ! 435: if (curY == row && curX == col) ! 436: return; ! 437: if (!TF_standout_motion) ! 438: background_highlight (); ! 439: if (!TF_insmode_motion) ! 440: turn_off_insert (); ! 441: cmgoto (row, col); ! 442: } ! 443: ! 444: /* Similar but don't take any account of the wasted characters. */ ! 445: ! 446: raw_topos (row, col) ! 447: { ! 448: if (raw_topos_hook) ! 449: { ! 450: (*raw_topos_hook) (row, col); ! 451: return; ! 452: } ! 453: if (curY == row && curX == col) ! 454: return; ! 455: if (!TF_standout_motion) ! 456: background_highlight (); ! 457: if (!TF_insmode_motion) ! 458: turn_off_insert (); ! 459: cmgoto (row, col); ! 460: } ! 461: ! 462: /* Erase operations */ ! 463: ! 464: /* clear from cursor to end of screen */ ! 465: clear_to_end () ! 466: { ! 467: register int i; ! 468: ! 469: if (clear_to_end_hook) ! 470: { ! 471: (*clear_to_end_hook) (); ! 472: return; ! 473: } ! 474: if (TS_clr_to_bottom) ! 475: { ! 476: background_highlight (); ! 477: OUTPUT (TS_clr_to_bottom); ! 478: bzero (chars_wasted + curY, screen_height - curY); ! 479: } ! 480: else ! 481: { ! 482: for (i = curY; i < screen_height; i++) ! 483: { ! 484: topos (i, 0); ! 485: clear_end_of_line_raw (screen_width); ! 486: } ! 487: } ! 488: } ! 489: ! 490: /* Clear entire screen */ ! 491: ! 492: clear_screen () ! 493: { ! 494: if (clear_screen_hook) ! 495: { ! 496: (*clear_screen_hook) (); ! 497: return; ! 498: } ! 499: if (TS_clr_screen) ! 500: { ! 501: background_highlight (); ! 502: OUTPUT (TS_clr_screen); ! 503: bzero (chars_wasted, screen_height); ! 504: cmat (0, 0); ! 505: } ! 506: else ! 507: { ! 508: topos (0, 0); ! 509: clear_to_end (); ! 510: } ! 511: } ! 512: ! 513: /* Clear to end of line, but do not clear any standout marker. ! 514: Assumes that the cursor is positioned at a character of real text, ! 515: which implies it cannot be before a standout marker ! 516: unless the marker has zero width. ! 517: ! 518: Note that the cursor may be moved. */ ! 519: ! 520: clear_end_of_line (first_unused_hpos) ! 521: int first_unused_hpos; ! 522: { ! 523: if (TN_standout_width == 0 && curX == 0 && chars_wasted[curY] != 0) ! 524: write_chars (" ", 1); ! 525: clear_end_of_line_raw (first_unused_hpos); ! 526: } ! 527: ! 528: /* Clear from cursor to end of line. ! 529: Assume that the line is already clear starting at column first_unused_hpos. ! 530: If the cursor is at a standout marker, erase the marker. ! 531: ! 532: Note that the cursor may be moved, on terminals lacking a `ce' string. */ ! 533: ! 534: clear_end_of_line_raw (first_unused_hpos) ! 535: int first_unused_hpos; ! 536: { ! 537: register int i; ! 538: first_unused_hpos += chars_wasted[curY] & 077; ! 539: if (clear_end_of_line_hook) ! 540: { ! 541: (*clear_end_of_line_hook) (first_unused_hpos); ! 542: return; ! 543: } ! 544: if (curX >= first_unused_hpos) ! 545: return; ! 546: /* Notice if we are erasing a magic cookie */ ! 547: if (curX == 0) ! 548: chars_wasted[curY] = 0; ! 549: background_highlight (); ! 550: if (TS_clr_line) ! 551: { ! 552: OUTPUT1 (TS_clr_line); ! 553: } ! 554: else ! 555: { /* have to do it the hard way */ ! 556: turn_off_insert (); ! 557: for (i = curX; i < first_unused_hpos; i++) ! 558: { ! 559: if (termscript) ! 560: fputc (' ', termscript); ! 561: putchar (' '); ! 562: } ! 563: cmplus (first_unused_hpos - curX); ! 564: } ! 565: } ! 566: ! 567: write_chars (start, len) ! 568: register char *start; ! 569: int len; ! 570: { ! 571: register char *p; ! 572: register int n; ! 573: register char *buf; ! 574: register int c; ! 575: char *first_check; ! 576: ! 577: if (write_chars_hook) ! 578: { ! 579: (*write_chars_hook) (start, len); ! 580: return; ! 581: } ! 582: highlight_if_desired (); ! 583: turn_off_insert (); ! 584: ! 585: /* Don't dare write in last column of bottom line, if AutoWrap, ! 586: since that would scroll the whole screen on some terminals. */ ! 587: ! 588: if (AutoWrap && curY + 1 == screen_height ! 589: && curX + len - (chars_wasted[curY] & 077) == screen_width) ! 590: len --; ! 591: ! 592: cmplus (len); ! 593: ! 594: first_check = start; ! 595: ! 596: if (RPov > len && !TF_underscore && !TF_hazeltine) ! 597: { ! 598: fwrite (start, 1, len, stdout); ! 599: if (ferror (stdout)) ! 600: clearerr (stdout); ! 601: if (termscript) ! 602: fwrite (start, 1, len, termscript); ! 603: } ! 604: else ! 605: while (--len >= 0) ! 606: { ! 607: if (RPov + 1 < len && start >= first_check && *start == start[1]) ! 608: { ! 609: p = start + 2; ! 610: ! 611: /* Now, len is number of chars left starting at p */ ! 612: while (*p++ == *start); ! 613: --p; ! 614: /* n is number of identical chars in this run */ ! 615: n = p - start; ! 616: if (n > RPov) ! 617: { ! 618: buf = tparam (TS_repeat, 0, 0, *start, n); ! 619: tputs (buf, n, cmputc); ! 620: free (buf); ! 621: start = p; ! 622: len -= n - 1; ! 623: continue; ! 624: } ! 625: else ! 626: /* If all N identical chars are too few, ! 627: don't even consider the last N-1, the last N-2,... */ ! 628: first_check = p; ! 629: } ! 630: c = *start++; ! 631: if (c == '_' && TF_underscore) ! 632: { ! 633: if (termscript) ! 634: fputc (' ', termscript); ! 635: putchar (' '); ! 636: OUTPUT (Left); ! 637: } ! 638: if (TF_hazeltine && c == '~') ! 639: c = '`'; ! 640: if (termscript) ! 641: fputc (c, termscript); ! 642: putchar (c); ! 643: } ! 644: } ! 645: ! 646: /* If start is zero, insert blanks instead of a string at start */ ! 647: ! 648: insert_chars (start, len) ! 649: register char *start; ! 650: int len; ! 651: { ! 652: register char *buf; ! 653: register int c; ! 654: ! 655: if (insert_chars_hook) ! 656: { ! 657: (*insert_chars_hook) (start, len); ! 658: return; ! 659: } ! 660: highlight_if_desired (); ! 661: ! 662: if (TS_ins_multi_chars) ! 663: { ! 664: buf = tparam (TS_ins_multi_chars, 0, 0, len); ! 665: OUTPUT1 (buf); ! 666: free (buf); ! 667: if (start) ! 668: write_chars (start, len); ! 669: return; ! 670: } ! 671: ! 672: turn_on_insert (); ! 673: cmplus (len); ! 674: ! 675: if (!TF_underscore && !TF_hazeltine && start ! 676: && TS_pad_inserted_char == 0 && TS_ins_char == 0) ! 677: { ! 678: fwrite (start, 1, len, stdout); ! 679: if (termscript) ! 680: fwrite (start, 1, len, termscript); ! 681: } ! 682: else ! 683: while (--len >= 0) ! 684: { ! 685: OUTPUT1_IF (TS_ins_char); ! 686: if (!start) ! 687: c = ' '; ! 688: else ! 689: { ! 690: c = *start++; ! 691: if (TF_hazeltine && c == '~') ! 692: c = '`'; ! 693: } ! 694: if (termscript) ! 695: fputc (c, termscript); ! 696: putchar (c); ! 697: OUTPUT1_IF (TS_pad_inserted_char); ! 698: } ! 699: } ! 700: ! 701: delete_chars (n) ! 702: register int n; ! 703: { ! 704: char *buf; ! 705: register int i; ! 706: ! 707: if (delete_chars_hook) ! 708: { ! 709: (*delete_chars_hook) (n); ! 710: return; ! 711: } ! 712: ! 713: if (delete_in_insert_mode) ! 714: { ! 715: turn_on_insert (); ! 716: } ! 717: else ! 718: { ! 719: turn_off_insert (); ! 720: OUTPUT_IF (TS_delete_mode); ! 721: } ! 722: ! 723: if (TS_del_multi_chars) ! 724: { ! 725: buf = tparam (TS_del_multi_chars, 0, 0, n); ! 726: OUTPUT1 (buf); ! 727: free (buf); ! 728: } ! 729: else ! 730: for (i = 0; i < n; i++) ! 731: OUTPUT1 (TS_del_char); ! 732: if (!delete_in_insert_mode) ! 733: OUTPUT_IF (TS_end_delete_mode); ! 734: } ! 735: ! 736: /* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */ ! 737: ! 738: ins_del_lines (vpos, n) ! 739: int vpos, n; ! 740: { ! 741: char *multi = n > 0 ? TS_ins_multi_lines : TS_del_multi_lines; ! 742: char *single = n > 0 ? TS_ins_line : TS_del_line; ! 743: char *scroll = n > 0 ? TS_rev_scroll : TS_fwd_scroll; ! 744: ! 745: register int i = n > 0 ? n : -n; ! 746: register char *buf; ! 747: char copybuf[MScreenWidth]; ! 748: ! 749: if (ins_del_lines_hook) ! 750: { ! 751: (*ins_del_lines_hook) (vpos, n); ! 752: return; ! 753: } ! 754: ! 755: /* If the lines below the insertion are being pushed ! 756: into the end of the window, this is the same as clearing; ! 757: and we know the lines are already clear, since the matching ! 758: deletion has already been done. So can ignore this. */ ! 759: /* If the lines below the deletion are blank lines coming ! 760: out of the end of the window, don't bother, ! 761: as there will be a matching inslines later that will flush them. */ ! 762: if (scroll_region_ok && vpos + i >= specified_window) ! 763: return; ! 764: if (!memory_below_screen && vpos + i >= screen_height) ! 765: return; ! 766: ! 767: if (multi) ! 768: { ! 769: raw_topos (vpos, 0); ! 770: background_highlight (); ! 771: buf = tparam (multi, 0, 0, i); ! 772: OUTPUT (buf); ! 773: free (buf); ! 774: } ! 775: else if (single) ! 776: { ! 777: raw_topos (vpos, 0); ! 778: background_highlight (); ! 779: while (--i >= 0) ! 780: OUTPUT (single); ! 781: if (TF_teleray) ! 782: curX = 0; ! 783: } ! 784: else ! 785: { ! 786: set_scroll_region (vpos, specified_window); ! 787: if (n < 0) ! 788: raw_topos (specified_window - 1, 0); ! 789: else ! 790: raw_topos (vpos, 0); ! 791: background_highlight (); ! 792: while (--i >= 0) ! 793: OUTPUTL (scroll, specified_window - vpos); ! 794: set_scroll_region (0, specified_window); ! 795: } ! 796: ! 797: if (TN_standout_width >= 0) ! 798: { ! 799: if (n < 0) ! 800: { ! 801: bcopy (&chars_wasted[curY - n], &chars_wasted[curY], screen_height - curY + n); ! 802: bzero (&chars_wasted[screen_height + n], - n); ! 803: } ! 804: else ! 805: { ! 806: bcopy (&chars_wasted[curY], ©buf[curY], screen_height - curY - n); ! 807: bcopy (©buf[curY], &chars_wasted[curY + n], screen_height - curY - n); ! 808: bzero (&chars_wasted[curY], n); ! 809: } ! 810: } ! 811: if (!scroll_region_ok && memory_below_screen && n < 0) ! 812: { ! 813: topos (screen_height + n, 0); ! 814: clear_to_end (); ! 815: } ! 816: } ! 817: ! 818: extern int cost; /* In cm.c */ ! 819: extern evalcost (); ! 820: ! 821: /* Compute cost of sending "str", in characters, ! 822: not counting any line-dependent padding. */ ! 823: string_cost (str) ! 824: char *str; ! 825: { ! 826: cost = 0; ! 827: if (str) ! 828: tputs (str, 0, evalcost); ! 829: return cost; ! 830: } ! 831: ! 832: /* Compute cost of sending "str", in characters, ! 833: counting any line-dependent padding at one line. */ ! 834: string_cost_one_line (str) ! 835: char *str; ! 836: { ! 837: cost = 0; ! 838: if (str) ! 839: tputs (str, 1, evalcost); ! 840: return cost; ! 841: } ! 842: ! 843: /* Compute per line amount of line-dependent padding, ! 844: in tenths of characters. */ ! 845: per_line_cost (str) ! 846: register char *str; ! 847: { ! 848: cost = 0; ! 849: if (str) ! 850: tputs (str, 0, evalcost); ! 851: cost = - cost; ! 852: if (str) ! 853: tputs (str, 10, evalcost); ! 854: return cost; ! 855: } ! 856: ! 857: /* ARGSUSED */ ! 858: calculate_ins_del_char_costs () ! 859: { ! 860: int ins_startup_cost, del_startup_cost; ! 861: int ins_cost_per_char, del_cost_per_char; ! 862: register int i; ! 863: register int *p; ! 864: ! 865: if (TS_ins_multi_chars) ! 866: { ! 867: ins_cost_per_char = 0; ! 868: ins_startup_cost = string_cost_one_line (TS_ins_multi_chars); ! 869: } ! 870: else if (TS_ins_char || TS_pad_inserted_char ! 871: || (TS_insert_mode && TS_end_insert_mode)) ! 872: { ! 873: ins_startup_cost = (30 * (string_cost (TS_insert_mode) + string_cost (TS_end_insert_mode))) / 100; ! 874: ins_cost_per_char = (string_cost_one_line (TS_ins_char) ! 875: + string_cost_one_line (TS_pad_inserted_char)); ! 876: } ! 877: else ! 878: { ! 879: ins_startup_cost = 9999; ! 880: ins_cost_per_char = 0; ! 881: } ! 882: ! 883: if (TS_del_multi_chars) ! 884: { ! 885: del_cost_per_char = 0; ! 886: del_startup_cost = string_cost_one_line (TS_del_multi_chars); ! 887: } ! 888: else if (TS_del_char) ! 889: { ! 890: del_startup_cost = (string_cost (TS_delete_mode) ! 891: + string_cost (TS_end_delete_mode)); ! 892: if (delete_in_insert_mode) ! 893: del_startup_cost /= 2; ! 894: del_cost_per_char = string_cost_one_line (TS_del_char); ! 895: } ! 896: else ! 897: { ! 898: del_startup_cost = 9999; ! 899: del_cost_per_char = 0; ! 900: } ! 901: ! 902: /* Delete costs are at negative offsets */ ! 903: p = &DCICcost[0]; ! 904: for (i = screen_width; --i >= 0;) ! 905: *--p = (del_startup_cost += del_cost_per_char); ! 906: ! 907: /* Doing nothing is free */ ! 908: p = &DCICcost[0]; ! 909: *p++ = 0; ! 910: ! 911: /* Insert costs are at positive offsets */ ! 912: for (i = screen_width; --i >= 0;) ! 913: *p++ = (ins_startup_cost += ins_cost_per_char); ! 914: } ! 915: ! 916: calculate_costs () ! 917: { ! 918: register char *s ! 919: = TS_set_scroll_region ? TS_set_scroll_region : TS_set_scroll_region_1; ! 920: ! 921: if (dont_calculate_costs) ! 922: return; ! 923: ! 924: if (s && (!TS_ins_line && !TS_del_line)) ! 925: CalcIDCosts (TS_rev_scroll, TS_ins_multi_lines, ! 926: TS_fwd_scroll, TS_del_multi_lines, ! 927: s, s); ! 928: else ! 929: CalcIDCosts (TS_ins_line, TS_ins_multi_lines, ! 930: TS_del_line, TS_del_multi_lines, ! 931: 0, 0); ! 932: ! 933: calculate_ins_del_char_costs (); ! 934: ! 935: /* Don't use TS_repeat if its padding is worse than sending the chars */ ! 936: if (TS_repeat && per_line_cost (TS_repeat) * baud_rate < 9000) ! 937: RPov = string_cost (TS_repeat); ! 938: else ! 939: RPov = MScreenWidth; ! 940: ! 941: cmcostinit (); /* set up cursor motion costs */ ! 942: } ! 943: ! 944: term_init (terminal_type) ! 945: char *terminal_type; ! 946: { ! 947: char *combuf; ! 948: char *fill; ! 949: char tbuf[2044]; ! 950: register char *p; ! 951: int status; ! 952: ! 953: extern char *tgetstr (); ! 954: ! 955: Wcm_clear (); ! 956: dont_calculate_costs = 0; ! 957: ! 958: status = tgetent (tbuf, terminal_type); ! 959: if (status < 0) ! 960: fatal ("Cannot open termcap database file.\n"); ! 961: if (status == 0) ! 962: fatal ("Terminal type %s is not defined.\n", terminal_type); ! 963: ! 964: #ifdef TERMINFO ! 965: combuf = (char *) malloc (2044); ! 966: #else ! 967: combuf = (char *) malloc (strlen (tbuf)); ! 968: #endif /* not TERMINFO */ ! 969: if (combuf == 0) ! 970: abort (); ! 971: fill = combuf; ! 972: ! 973: TS_ins_line = tgetstr ("al", &fill); ! 974: TS_ins_multi_lines = tgetstr ("AL", &fill); ! 975: TS_bell = tgetstr ("bl", &fill); ! 976: TS_clr_to_bottom = tgetstr ("cd", &fill); ! 977: TS_clr_line = tgetstr ("ce", &fill); ! 978: TS_clr_screen = tgetstr ("cl", &fill); ! 979: ColPosition = tgetstr ("ch", &fill); ! 980: AbsPosition = tgetstr ("cm", &fill); ! 981: CR = tgetstr ("cr", &fill); ! 982: TS_set_scroll_region = tgetstr ("cs", &fill); ! 983: TS_set_scroll_region_1 = tgetstr ("cS", &fill); ! 984: RowPosition = tgetstr ("cv", &fill); ! 985: TS_del_char = tgetstr ("dc", &fill); ! 986: TS_del_multi_chars = tgetstr ("DC", &fill); ! 987: TS_del_line = tgetstr ("dl", &fill); ! 988: TS_del_multi_lines = tgetstr ("DL", &fill); ! 989: TS_delete_mode = tgetstr ("dm", &fill); ! 990: TS_end_delete_mode = tgetstr ("ed", &fill); ! 991: TS_end_insert_mode = tgetstr ("ei", &fill); ! 992: Home = tgetstr ("ho", &fill); ! 993: TS_ins_char = tgetstr ("ic", &fill); ! 994: TS_ins_multi_chars = tgetstr ("IC", &fill); ! 995: TS_insert_mode = tgetstr ("im", &fill); ! 996: TS_pad_inserted_char = tgetstr ("ip", &fill); ! 997: TS_end_keypad_mode = tgetstr ("ke", &fill); ! 998: TS_keypad_mode = tgetstr ("ks", &fill); ! 999: LastLine = tgetstr ("ll", &fill); ! 1000: Right = tgetstr ("nd", &fill); ! 1001: Down = tgetstr ("do", &fill); ! 1002: if (!Down) ! 1003: Down = tgetstr ("nl", &fill); /* Obsolete name for "do" */ ! 1004: #ifdef VMS ! 1005: /* VMS puts a carriage return before each linefeed, ! 1006: so it is not safe to use linefeeds. */ ! 1007: if (Down && Down[0] == '\n' && Down[1] == '\0') ! 1008: Down = 0; ! 1009: #endif /* VMS */ ! 1010: if (tgetflag ("bs")) ! 1011: Left = "\b"; /* can't possibly be longer! */ ! 1012: else /* (Actually, "bs" is obsolete...) */ ! 1013: Left = tgetstr ("le", &fill); ! 1014: if (!Left) ! 1015: Left = tgetstr ("bc", &fill); /* Obsolete name for "le" */ ! 1016: TS_pad_char = tgetstr ("pc", &fill); ! 1017: TS_repeat = tgetstr ("rp", &fill); ! 1018: TS_end_standout_mode = tgetstr ("se", &fill); ! 1019: TS_fwd_scroll = tgetstr ("sf", &fill); ! 1020: TS_standout_mode = tgetstr ("so", &fill); ! 1021: TS_rev_scroll = tgetstr ("sr", &fill); ! 1022: Wcm.cm_tab = tgetstr ("ta", &fill); ! 1023: TS_end_termcap_modes = tgetstr ("te", &fill); ! 1024: TS_termcap_modes = tgetstr ("ti", &fill); ! 1025: Up = tgetstr ("up", &fill); ! 1026: TS_visible_bell = tgetstr ("vb", &fill); ! 1027: TS_end_visual_mode = tgetstr ("ve", &fill); ! 1028: TS_visual_mode = tgetstr ("vs", &fill); ! 1029: TS_set_window = tgetstr ("wi", &fill); ! 1030: ! 1031: AutoWrap = tgetflag ("am"); ! 1032: memory_below_screen = tgetflag ("db"); ! 1033: TF_hazeltine = tgetflag ("hz"); ! 1034: must_write_spaces = tgetflag ("in"); ! 1035: MetaFlag = tgetflag ("km") || tgetflag ("MT"); ! 1036: TF_insmode_motion = tgetflag ("mi"); ! 1037: TF_standout_motion = tgetflag ("ms"); ! 1038: TF_underscore = tgetflag ("ul"); ! 1039: MagicWrap = tgetflag ("xn"); ! 1040: TF_xs = tgetflag ("xs"); ! 1041: TF_teleray = tgetflag ("xt"); ! 1042: ! 1043: /* Get screen size from system, or else from termcap. */ ! 1044: get_screen_size (&screen_width, &screen_height); ! 1045: if (screen_width <= 0) ! 1046: screen_width = tgetnum ("co"); ! 1047: if (screen_height <= 0) ! 1048: screen_height = tgetnum ("li"); ! 1049: ! 1050: min_padding_speed = tgetnum ("pb"); ! 1051: TN_standout_width = tgetnum ("sg"); ! 1052: TabWidth = tgetnum ("tw"); ! 1053: ! 1054: #ifdef VMS ! 1055: /* These capabilities commonly use ^J. ! 1056: I don't know why, but sending them on VMS does not work; ! 1057: it causes following spaces to be lost, sometimes. ! 1058: For now, the simplest fix is to avoid using these capabilities ever. */ ! 1059: if (Down && Down[0] == '\n') ! 1060: Down = 0; ! 1061: #endif /* VMS */ ! 1062: ! 1063: if (!TS_bell) ! 1064: TS_bell = "\07"; ! 1065: ! 1066: if (!TS_fwd_scroll) ! 1067: TS_fwd_scroll = Down; ! 1068: ! 1069: PC = TS_pad_char ? *TS_pad_char : 0; ! 1070: ! 1071: if (TabWidth < 0) ! 1072: TabWidth = 8; ! 1073: ! 1074: /* Turned off since /etc/termcap seems to have :ta= for most terminals ! 1075: and newer termcap doc does not seem to say there is a default. ! 1076: if (!Wcm.cm_tab) ! 1077: Wcm.cm_tab = "\t"; ! 1078: */ ! 1079: ! 1080: if (TS_standout_mode == 0) ! 1081: { ! 1082: TN_standout_width = tgetnum ("ug"); ! 1083: TS_end_standout_mode = tgetstr ("ue", &fill); ! 1084: TS_standout_mode = tgetstr ("us", &fill); ! 1085: } ! 1086: ! 1087: if (TF_teleray) ! 1088: { ! 1089: Wcm.cm_tab = 0; ! 1090: /* Teleray: most programs want a space in front of TS_standout_mode, ! 1091: but Emacs can do without it (and give one extra column). */ ! 1092: TS_standout_mode = "\033RD"; ! 1093: TN_standout_width = 1; ! 1094: /* But that means we cannot rely on ^M to go to column zero! */ ! 1095: CR = 0; ! 1096: /* LF can't be trusted either -- can alter hpos */ ! 1097: /* if move at column 0 thru a line with TS_standout_mode */ ! 1098: Down = 0; ! 1099: } ! 1100: ! 1101: /* Special handling for certain terminal types known to need it */ ! 1102: ! 1103: if (!strcmp (terminal_type, "supdup")) ! 1104: { ! 1105: memory_below_screen = 1; ! 1106: Wcm.cm_losewrap = 1; ! 1107: } ! 1108: if (!strncmp (terminal_type, "c10", 3) ! 1109: || !strcmp (terminal_type, "perq")) ! 1110: { ! 1111: /* Supply a makeshift :wi string. ! 1112: This string is not valid in general since it works only ! 1113: for windows starting at the upper left corner; ! 1114: but that is all Emacs uses. ! 1115: ! 1116: This string works only if the screen is using ! 1117: the top of the video memory, because addressing is memory-relative. ! 1118: So first check the :ti string to see if that is true. ! 1119: ! 1120: It would be simpler if the :wi string could go in the termcap ! 1121: entry, but it can't because it is not fully valid. ! 1122: If it were in the termcap entry, it would confuse other programs. */ ! 1123: if (!TS_set_window) ! 1124: { ! 1125: p = TS_termcap_modes; ! 1126: while (*p && strcmp (p, "\033v ")) ! 1127: p++; ! 1128: if (*p) ! 1129: TS_set_window = "\033v%C %C %C %C "; ! 1130: } ! 1131: /* Termcap entry often fails to have :in: flag */ ! 1132: must_write_spaces = 1; ! 1133: /* :ti string typically fails to have \E^G! in it */ ! 1134: /* This limits scope of insert-char to one line. */ ! 1135: strcpy (fill, TS_termcap_modes); ! 1136: strcat (fill, "\033\007!"); ! 1137: TS_termcap_modes = fill; ! 1138: fill += strlen (fill) + 1; ! 1139: p = combuf; ! 1140: /* Change all %+ parameters to %C, to handle ! 1141: values above 96 correctly for the C100. */ ! 1142: while (p != fill) ! 1143: { ! 1144: if (p[0] == '%' && p[1] == '+') ! 1145: p[1] = 'C'; ! 1146: p++; ! 1147: } ! 1148: } ! 1149: ! 1150: screen_height = min (screen_height, MScreenLength); ! 1151: screen_width = min (screen_width, MScreenWidth); ! 1152: ! 1153: ScreenRows = screen_height; ! 1154: ScreenCols = screen_width; ! 1155: specified_window = screen_height; ! 1156: ! 1157: if (Wcm_init ()) /* can't do cursor motion */ ! 1158: #ifdef VMS ! 1159: fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\ ! 1160: It lacks the ability to position the cursor.\n\ ! 1161: If that is not the actual type of terminal you have, use either the\n\ ! 1162: DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\ ! 1163: or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.\n", ! 1164: terminal_type); ! 1165: #else ! 1166: fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\ ! 1167: It lacks the ability to position the cursor.\n\ ! 1168: If that is not the actual type of terminal you have,\n\ ! 1169: use the C-shell command `setenv TERM ...' to specify the correct type.\n\ ! 1170: It may be necessary to do `unsetenv TERMCAP' as well.\n", ! 1171: terminal_type); ! 1172: #endif ! 1173: ! 1174: delete_in_insert_mode ! 1175: = TS_delete_mode && TS_insert_mode ! 1176: && !strcmp (TS_delete_mode, TS_insert_mode); ! 1177: ! 1178: se_is_so = TS_standout_mode && TS_end_standout_mode ! 1179: && !strcmp (TS_standout_mode, TS_end_standout_mode); ! 1180: ! 1181: /* Remove width of standout marker from usable width of line */ ! 1182: if (TN_standout_width > 0) ! 1183: screen_width -= TN_standout_width; ! 1184: ! 1185: UseTabs = tabs_safe_p () && TabWidth == 8; ! 1186: ! 1187: scroll_region_ok = TS_set_window || TS_set_scroll_region ! 1188: || TS_set_scroll_region_1; ! 1189: ! 1190: line_ins_del_ok = (((TS_ins_line || TS_ins_multi_lines) ! 1191: && (TS_del_line || TS_del_multi_lines)) ! 1192: || (scroll_region_ok ! 1193: && TS_fwd_scroll ! 1194: && TS_rev_scroll)); ! 1195: ! 1196: char_ins_del_ok = ((TS_ins_char || TS_insert_mode || ! 1197: TS_pad_inserted_char || TS_ins_multi_chars) ! 1198: && (TS_del_char || TS_del_multi_chars)); ! 1199: ! 1200: fast_clear_end_of_line = TS_clr_line != 0; ! 1201: ! 1202: init_baud_rate (); ! 1203: if (read_socket_hook) /* Baudrate is somewhat */ ! 1204: /* meaningless in this case */ ! 1205: baud_rate = 9600; ! 1206: ! 1207: calculate_costs (); ! 1208: } ! 1209: ! 1210: /* VARARGS 1 */ ! 1211: fatal (str, arg1, arg2) ! 1212: { ! 1213: fprintf (stderr, "emacs: "); ! 1214: fprintf (stderr, str, arg1, arg2); ! 1215: fflush (stderr); ! 1216: exit (1); ! 1217: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.