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