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], &copybuf[curY], screen_height - curY - n);
 788:       bcopy (&copybuf[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: }

Defined functions

background_highlight defined in line 311; used 10 times
calculate_costs defined in line 896; used 2 times
calculate_ins_del_char_costs defined in line 839; used 1 times
change_line_highlight defined in line 382; used 1 times
clear_end_of_line_raw defined in line 524; used 3 times
clear_screen defined in line 482; used 1 times
clear_to_end defined in line 455; used 2 times
delete_chars defined in line 682; used 3 times
fatal defined in line 1158; used 2 times
highlight_if_desired defined in line 323; used 2 times
insert_chars defined in line 629; used 2 times
per_line_cost defined in line 826; used 3 times
raw_topos defined in line 436; used 4 times
reassert_line_highlight defined in line 361; used 3 times
reset_terminal_modes defined in line 195; used 1 times
ring_bell defined in line 172; used 1 times
set_scroll_region defined in line 242; used 3 times
string_cost defined in line 804; used 9 times
string_cost_one_line defined in line 815; used 5 times
term_init defined in line 924; used 1 times
topos defined in line 417; used 14 times
turn_off_highlight defined in line 287; used 3 times
turn_off_insert defined in line 273; used 8 times
turn_on_highlight defined in line 297; used 2 times
turn_on_insert defined in line 266; used 2 times
update_begin defined in line 210; used 1 times
update_end defined in line 216; used 1 times
write_chars defined in line 557; used 10 times
write_standout_marker defined in line 345; used 1 times

Defined variables

DC_ICcost defined in line 62; used 2 times
RPov defined in line 144; used 5 times
TF_hazeltine defined in line 135; used 5 times
TF_insmode_motion defined in line 136; used 3 times
TF_standout_motion defined in line 137; used 3 times
TF_teleray defined in line 140; used 5 times
TF_underscore defined in line 138; used 4 times
TN_standout_width defined in line 142; used 16 times
TS_bell defined in line 99; used 4 times
TS_clr_line defined in line 101; used 5 times
TS_clr_screen defined in line 102; used 3 times
TS_clr_to_bottom defined in line 100; used 3 times
TS_del_char defined in line 107; used 5 times
TS_del_line defined in line 109; used 5 times
TS_del_multi_chars defined in line 108; used 7 times
TS_del_multi_lines defined in line 110; used 5 times
TS_delete_mode defined in line 111; used 5 times
TS_end_delete_mode defined in line 112; used 3 times
TS_end_insert_mode defined in line 113; used 4 times
TS_end_keypad_mode defined in line 118; used 2 times
TS_end_standout_mode defined in line 123; used 7 times
TS_end_termcap_modes defined in line 127; used 2 times
TS_end_visual_mode defined in line 130; used 2 times
TS_fwd_scroll defined in line 124; used 6 times
TS_ins_char defined in line 114; used 6 times
TS_ins_line defined in line 97; used 5 times
TS_ins_multi_chars defined in line 115; used 7 times
TS_ins_multi_lines defined in line 98; used 5 times
TS_insert_mode defined in line 116; used 6 times
TS_keypad_mode defined in line 119; used 2 times
TS_pad_char defined in line 120; used 3 times
TS_pad_inserted_char defined in line 117; used 5 times
TS_repeat defined in line 121; used 6 times
TS_rev_scroll defined in line 126; used 4 times
TS_set_scroll_region defined in line 103; used 7 times
TS_set_scroll_region_1 defined in line 104; used 6 times
TS_set_window defined in line 132; used 6 times
TS_standout_mode defined in line 125; used 8 times
TS_termcap_modes defined in line 128; used 5 times
TS_visible_bell defined in line 129; used 3 times
TS_visual_mode defined in line 131; used 2 times
char_ins_del_ok defined in line 50; used 2 times
chars_wasted defined in line 155; used 15 times
delete_in_insert_mode defined in line 146; used 4 times
dont_calculate_costs defined in line 55; used 3 times
fast_clear_end_of_line defined in line 53; used 2 times
insert_mode defined in line 160; used 4 times
line_ins_del_ok defined in line 49; used 2 times
memory_below_screen defined in line 52; used 5 times
min_padding_speed defined in line 47; used 2 times
must_write_spaces defined in line 44; used 3 times
screen_height defined in line 43; used 52 times
scroll_region_ok defined in line 51; used 6 times
se_is_so defined in line 148; used 2 times
specified_window defined in line 170; used 8 times
standout_mode defined in line 161; used 4 times
standout_requested defined in line 158; used 4 times

Defined macros

DCICcost defined in line 61; used 2 times
OUTPUT defined in line 33; used 11 times
OUTPUT1 defined in line 34; used 4 times
OUTPUT1_IF defined in line 37; used 2 times
OUTPUTL defined in line 35; used 1 times
OUTPUT_IF defined in line 36; used 10 times
max defined in line 30; never used
min defined in line 31; used 2 times
Last modified: 1986-03-11
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4234
Valid CSS Valid XHTML 1.0 Strict