|
|
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.