4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
31 /* Copyright (c) 1981 Regents of the University of California */
33 #pragma ident "%Z%%M% %I% %E% SMI"
40 * Deal with the screen, clearing, cursor positioning, putting characters
41 * into the screen image, and deleting characters.
42 * Really hard stuff here is utilizing insert character operations
43 * on intelligent terminals which differs widely from terminal to terminal.
51 tfixnl(), fprintf(trace
, "------\nvclear, clear_screen '%s'\n", clear_screen
);
53 tputs(clear_screen
, lines
, putch
);
59 vclrbyte(vtube0
, WCOLS
* (WECHO
- ZERO
+ 1));
66 vclrbyte(wchar_t *cp
, int i
)
76 * Clear a physical display line, high level.
79 vclrlin(int l
, line
*tp
)
83 if ((hold
& HOLDAT
) == 0)
84 putchar(tp
> dol
? ((UPPERCASE
|| tilde_glitch
) ? '^' : '~') : '@');
85 if (state
== HARDOPEN
)
91 * Clear to the end of the current physical line
101 fprintf(trace
, "vclreol(), destcol %d, ateopr() %d\n", destcol
, ateopr());
103 if (destcol
== WCOLS
)
105 destline
+= destcol
/ WCOLS
;
107 if (destline
< 0 || destline
> WECHO
)
108 error(gettext("Internal error: vclreol"));
110 tp
= vtube
[destline
] + destcol
;
112 if (insert_null_glitch
&& *tp
|| !ateopr()) {
121 while (i
> 0 && (j
= *tp
& (QUOTE
|TRIM
))) {
122 if (j
!= ' ' && (j
& QUOTE
) == 0) {
124 (void) vputchar(' ');
131 * Clear the echo line.
132 * If didphys then its been cleared physically (as
133 * a side effect of a clear to end of display, e.g.)
134 * so just do it logically.
135 * If work here is being held off, just remember, in
136 * heldech, if work needs to be done, don't do anything.
145 fprintf(trace
, "vclrech(%d), Peekkey %d, hold %o\n", didphys
, Peekkey
, hold
);
149 if (hold
& HOLDECH
) {
153 if (!didphys
&& (clr_eos
|| clr_eol
)) {
156 * If display is retained below, then MUST use clr_eos or
157 * clr_eol since we don't really know whats out there.
158 * Vigoto might decide (incorrectly) to do nothing.
163 * This is tricky. If clr_eos is as cheap we
164 * should use it, so we don't have extra junk
165 * floating around in memory below. But if
166 * clr_eol costs less we should use it. The real
167 * reason here is that clr_eos is incredibly
168 * expensive on the HP 2626 (1/2 second or more)
169 * which makes ^D scroll really slow. But the
170 * 2621 has a bug that shows up if we use clr_eol
171 * instead of clr_eos, so we make sure the costs
172 * are equal so it will prefer clr_eol.
179 if (teleray_glitch
) {
180 /* This code basically handles the t1061
181 * where positioning at (0, 0) won't work
182 * because the terminal won't let you put
183 * the cursor on it's magic cookie.
185 * Should probably be ceol_standout_glitch
187 * new glitch, but right now t1061 is the
188 * only terminal with teleray_glitch.
191 vputp(delete_line
, 1);
201 vclrbyte(vtube
[WECHO
], WCOLS
);
206 * Fix the echo area for use, setting
207 * the state variable splitw so we wont rollup
208 * when we move the cursor there.
215 if (state
!= VISUAL
&& state
!= CRTOPEN
) {
219 vgoto(WECHO
, 0); flusho();
223 * Put the cursor ``before'' cp.
226 vcursbef(unsigned char *cp
)
230 vgotoCL(value(vi_NUMBER
) << 3);
232 vgotoCL(lcolumn(cp
)-1);
236 * Put the cursor ``at'' cp.
239 vcursat(unsigned char *cp
)
242 if (cp
<= linebuf
&& linebuf
[0] == 0)
243 vgotoCL(value(vi_NUMBER
) << 3);
245 vgotoCL(lcolumn(cp
));
249 * Put the cursor ``after'' cp.
252 vcursaft(unsigned char *cp
)
255 vgotoCL(lcolumn(nextchr(cp
)));
259 * Fix the cursor to be positioned in the correct place
260 * to accept a command.
270 * Compute the column position implied by the cursor at ``nc'',
271 * and move the cursor there.
274 vsetcurs(unsigned char *nc
)
286 * Move the cursor invisibly, i.e. only remember to do it.
297 * Move the cursor to the position implied by any previous
298 * vigoto (or low level hacking with destcol/destline as in readecho).
304 vgoto(destline
, destcol
);
308 * Goto column x of the current line.
317 vgoto(LINE(vcline
), x
);
321 * Invisible goto column x of current line.
330 vigoto(LINE(vcline
), x
);
334 * Show the current mode in the right hand part of the echo line,
335 * then return the cursor to where it is now.
338 vshowmode(unsigned char *msg
)
340 int savecol
, saveline
, savesplit
;
345 if (!value(vi_SHOWMODE
))
347 /* Don't alter mode message for macros (arrow keys) or yank/put */
350 savecol
= outcol
; saveline
= outline
; savesplit
= splitw
;
351 splitw
= 1; /* To avoid scrolling */
352 vigoto(WECHO
, WCOLS
-20);
357 length
= mbtowc(&wchar
, (char *)p
, MULTI_BYTE_MAX
);
360 * This should never happen, but
361 * if 'msg' doesn't make a valid string,
362 * treat this case as the same as the
366 * Going back to command mode - clear the message.
371 (void) vputchar(wchar
);
377 * Going back to command mode - clear the message.
382 FLAGS(WECHO
) |= VDIRT
;
383 vgoto(saveline
, savecol
);
388 * Move cursor to line y, column x, handling wraparound and scrolling.
398 * Fold the possibly too large value of x.
405 error("Internal error: vgoto");
407 if (outcol
>= WCOLS
) {
408 if (auto_right_margin
) {
409 outline
+= outcol
/ WCOLS
;
416 * In a hardcopy or glass crt open, print the stuff
417 * implied by a motion, or backspace.
419 if (state
== HARDOPEN
|| state
== ONEOPEN
) {
421 error(gettext("Line too long for open"));
422 if (x
+ 1 < outcol
- x
|| (outcol
> x
&& !cursor_left
))
423 destcol
= 0, fgoto();
424 tp
= vtube
[WBOT
] + outcol
;
428 unsigned char multic
[MULTI_BYTE_MAX
];
432 length
= wctomb((char *)multic
, c
);
437 (!over_strike
|| erase_overstrike
)
440 if ((col
= wcwidth(c
)) < 0)
446 vputp(cursor_left
, 0);
449 destcol
= outcol
= x
;
455 * If the destination position implies a scroll, do it.
458 if (destline
> WBOT
&& (!splitw
|| destline
> WECHO
)) {
464 * If there really is a motion involved, do it.
465 * The check here is an optimization based on profiling.
468 if ((destline
- outline
) * WCOLS
!= destcol
- outcol
) {
469 if (!move_insert_mode
)
476 * This is the hardest code in the editor, and deals with insert modes
477 * on different kinds of intelligent terminals. The complexity is due
478 * to the cross product of three factors:
480 * 1. Lines may display as more than one segment on the screen.
481 * 2. There are 2 kinds of intelligent terminal insert modes.
482 * 3. Tabs squash when you insert characters in front of them,
483 * in a way in which current intelligent terminals don't handle.
485 * The two kinds of terminals are typified by the DM2500 or HP2645 for
486 * one and the CONCEPT-100 or the FOX for the other.
488 * The first (HP2645) kind has an insert mode where the characters
489 * fall off the end of the line and the screen is shifted rigidly
490 * no matter how the display came about.
492 * The second (CONCEPT-100) kind comes from terminals which are designed
493 * for forms editing and which distinguish between blanks and ``spaces''
494 * on the screen, spaces being like blank, but never having had
495 * and data typed into that screen position (since, e.g. a clear operation
496 * like clear screen). On these terminals, when you insert a character,
497 * the characters from where you are to the end of the screen shift
498 * over till a ``space'' is found, and the null character there gets
502 * The code here considers the line as consisting of several parts
503 * the first part is the ``doomed'' part, i.e. a part of the line
504 * which is being typed over. Next comes some text up to the first
505 * following tab. The tab is the next segment of the line, and finally
506 * text after the tab.
508 * We have to consider each of these segments and the effect of the
509 * insertion of a character on them. On terminals like HP2645's we
510 * must simulate a multi-line insert mode using the primitive one
511 * line insert mode. If we are inserting in front of a tab, we have
512 * to either delete characters from the tab or insert white space
513 * (when the tab reaches a new spot where it gets larger) before we
514 * insert the new character.
516 * On a terminal like a CONCEPT our strategy is to make all
517 * blanks be displayed, while trying to keep the screen having ``spaces''
518 * for portions of tabs. In this way the terminal hardware does some
519 * of the hacking for compression of tabs, although this tends to
520 * disappear as you work on the line and spaces change into blanks.
522 * There are a number of boundary conditions (like typing just before
523 * the first following tab) where we can avoid a lot of work. Most
524 * of them have to be dealt with explicitly because performance is
525 * much, much worse if we don't.
527 * A final thing which is hacked here is two flavors of insert mode.
528 * Datamedia's do this by an insert mode which you enter and leave
529 * and by having normal motion character operate differently in this
530 * mode, notably by having a newline insert a line on the screen in
531 * this mode. This generally means it is unsafe to move around
532 * the screen ignoring the fact that we are in this mode.
533 * This is possible on some terminals, and wins big (e.g. HP), so
534 * we encode this as a ``can move in insert capability'' mi,
535 * and terminals which have it can do insert mode with much less
536 * work when tabs are present following the cursor on the current line.
540 * Routine to expand a tab, calling the normal Outchar routine
541 * to put out each implied character. Note that we call outchar
542 * with a QUOTE. We use QUOTE internally to represent a position
543 * which is part of the expansion of a tab.
548 int i
= tabcol(destcol
, value(vi_TABSTOP
)) - destcol
;
556 * Variables for insert mode.
558 int linend
; /* The column position of end of line */
559 int tabstart
; /* Column of start of first following tab */
560 int tabend
; /* Column of end of following tabs */
561 int tabsize
; /* Size of the following tabs */
562 int tabslack
; /* Number of ``spaces'' in following tabs */
563 int inssiz
; /* Number of characters to be inserted */
564 int inscol
; /* Column where insertion is taking place */
565 int shft
; /* Amount tab expansion shifted rest of line */
566 int slakused
; /* This much of tabslack will be used up */
569 * This routine MUST be called before insert mode is run,
570 * and brings all segments of the current line to the top
571 * of the screen image buffer so it is easier for us to
578 wchar_t *cp
= vtube0
;
580 for (i
= 0; i
< DEPTH(vcline
); i
++) {
581 vmaktop(LINE(vcline
) + i
, cp
);
587 vmaktop(int p
, wchar_t *cp
)
590 wchar_t temp
[TUBECOLS
];
592 if (p
< 0 || vtube
[p
] == cp
)
594 for (i
= ZERO
; i
<= WECHO
; i
++)
595 if (vtube
[i
] == cp
) {
596 copy(temp
, vtube
[i
], WCOLS
* sizeof(wchar_t));
597 copy(vtube
[i
], vtube
[p
], WCOLS
* sizeof(wchar_t));
598 copy(vtube
[p
], temp
, WCOLS
* sizeof(wchar_t));
603 error(gettext("Line too long"));
607 * Insert character c at current cursor position.
608 * Multi-character inserts occur only as a result
609 * of expansion of tabs (i.e. inssize == 1 except
610 * for tabs or multibyte characters)
611 * and code assumes this in several place
612 * to make life simpler.
620 if ((!enter_insert_mode
|| !exit_insert_mode
) && ((hold
& HOLDQIK
) || !value(vi_REDRAW
) || value(vi_SLOWOPEN
))) {
622 * Don't want to try to use terminal
623 * insert mode, or to try to fake it.
624 * Just put the character out; the screen
625 * will probably be wrong but we will fix it later.
632 if (DEPTH(vcline
) * WCOLS
+ !value(vi_REDRAW
) >
633 (destline
- LINE(vcline
)) * WCOLS
+ destcol
)
636 * The next line is about to be clobbered
637 * make space for another segment of this line
638 * (on an intelligent terminal) or just remember
639 * that next line was clobbered (on a dumb one
640 * if we don't care to redraw the tail.
645 int i2
= LINE(vcline
) + DEPTH(vcline
);
646 if (i2
< LINE(vcline
+ 1) || i2
> WBOT
)
649 vinslin(i2
, 1, vcline
);
658 * Compute the number of positions in the line image of the
659 * current line. This is done from the physical image
660 * since that is faster. Note that we have no memory
661 * from insertion to insertion so that routines which use
662 * us don't have to worry about moving the cursor around.
668 * Search backwards for a non-null character
669 * from the end of the displayed line.
671 i
= WCOLS
* DEPTH(vcline
);
682 * We insert at a position based on the physical location
683 * of the output cursor.
685 inscol
= destcol
+ (destline
- LINE(vcline
)) * WCOLS
;
688 * Characters inserted from a tab must be
689 * remembered as being part of a tab, but we can't
690 * use QUOTE here since we really need to print blanks.
691 * QUOTE|' ' is the representation of this.
693 inssiz
= tabcol(inscol
, value(vi_TABSTOP
)) - inscol
;
696 if ((inssiz
= wcwidth(c
)) < 0)
701 * If the text to be inserted is less than the number
702 * of doomed positions, then we don't need insert mode,
703 * rather we can just typeover.
705 if (inssiz
<= doomed
) {
707 if (inscol
!= linend
)
720 * Have to really do some insertion, thus
721 * stake out the bounds of the first following
722 * group of tabs, computing starting position,
723 * ending position, and the number of ``spaces'' therein
724 * so we can tell how much it will squish.
726 tp
= vtube0
+ inscol
;
727 for (i
= inscol
; i
< linend
; i
++)
732 tabstart
= tabend
= i
;
734 while (tabend
< linend
) {
736 if ((wchar
& QUOTE
) == 0)
738 if ((wchar
& TRIM
) == 0)
743 tabsize
= tabend
- tabstart
;
746 * For HP's and DM's, e.g. tabslack has no meaning.
748 if (!insert_null_glitch
)
752 fprintf(trace
, "inscol %d, inssiz %d, tabstart %d, ",
753 inscol
, inssiz
, tabstart
);
754 fprintf(trace
, "tabend %d, tabslack %d, linend %d\n",
755 tabend
, tabslack
, linend
);
760 * The real work begins.
766 * There are tabs on this line.
767 * If they need to expand, then the rest of the line
768 * will have to be shifted over. In this case,
769 * we will need to make sure there are no ``spaces''
770 * in the rest of the line (on e.g. CONCEPT-100)
771 * and then grab another segment on the screen if this
772 * line is now deeper. We then do the shift
773 * implied by the insertion.
775 if (inssiz
>= doomed
+ tabcol(tabstart
, value(vi_TABSTOP
)) - tabstart
) {
776 if (insert_null_glitch
)
778 vneedpos(value(vi_TABSTOP
));
781 } else if (inssiz
> doomed
)
783 * No tabs, but line may still get deeper.
785 vneedpos(inssiz
- doomed
);
787 * Now put in the inserted characters.
792 * Now put the cursor in its final resting place.
794 destline
= LINE(vcline
);
795 destcol
= inscol
+ inssiz
;
801 * Rigidify the rest of the line after the first
802 * group of following tabs, typing blanks over ``spaces''.
808 wchar_t *tp
= vtube0
+ tabend
;
810 for (col
= tabend
; col
< linend
; col
++)
811 if ((*tp
++ & TRIM
) == 0) {
814 (void) vputchar(' ' | QUOTE
);
819 * We need cnt more positions on this line.
820 * Open up new space on the screen (this may in fact be a
823 * On a dumb terminal we may infact redisplay the rest of the
824 * screen here brute force to keep it pretty.
829 int d
= DEPTH(vcline
);
830 int rmdr
= d
* WCOLS
- linend
;
831 if (cnt
<= rmdr
- insert_null_glitch
)
840 int d
= DEPTH(vcline
);
843 e
= LINE(vcline
) + DEPTH(vcline
);
844 if (e
< LINE(vcline
+ 1)) {
851 e
= vglitchup(vcline
, d
);
852 vigoto(e
, 0); vclreol();
854 int (*Ooutchar
)() = Outchar
;
868 * Do the shift of the next tabstop implied by
869 * insertion so it expands.
877 wchar_t *tp
= vtube0
;
879 short oldhold
= hold
;
881 shft
= value(vi_TABSTOP
);
883 if (!enter_insert_mode
&& !exit_insert_mode
) {
885 * Dumb terminals are easy, we just have
886 * to retype the text.
888 vigotoCL(tabend
+ shft
);
890 for (i
= tabend
; i
< linend
; i
++)
891 if((wchar
= *up
++) != FILLER
)
892 (void) vputchar(wchar
);
893 } else if (insert_null_glitch
) {
895 * CONCEPT-like terminals do most of the work for us,
896 * we don't have to muck with simulation of multi-line
897 * insert mode. Some of the shifting may come for free
898 * also if the tabs don't have enough slack to take up
899 * all the inserted characters.
902 slakused
= inssiz
- doomed
;
903 if (slakused
> tabslack
) {
904 i
-= slakused
- tabslack
;
905 slakused
-= tabslack
;
907 if (i
> 0 && tabend
!= linend
) {
912 (void) vputchar(' ' | QUOTE
);
917 * HP and Datamedia type terminals have to have multi-line
918 * insert faked. Hack each segment after where we are
919 * (going backwards to where we are.) We then can
920 * hack the segment where the end of the first following
923 for (j
= DEPTH(vcline
) - 1; j
> (tabend
+ shft
) / WCOLS
; j
--) {
926 up
= tp
+ j
* WCOLS
- shft
;
932 (void) vputchar(wchar
);
939 i
= shft
- (inssiz
- doomed
);
941 tabslack
= inssiz
- doomed
;
945 (void) vputchar(' ');
950 * Now do the data moving in the internal screen
951 * image which is common to all three cases.
960 if (insert_null_glitch
&& tshft
) {
970 * Now do the insert of the characters (finally).
979 short oldhold
= hold
;
982 if (tabsize
&& (enter_insert_mode
&& exit_insert_mode
) && inssiz
- doomed
> tabslack
)
984 * There is a tab out there which will be affected
985 * by the insertion since there aren't enough doomed
986 * characters to take up all the insertion and we do
987 * have insert mode capability.
989 if (inscol
+ doomed
== tabstart
) {
991 * The end of the doomed characters sits right at the
992 * start of the tabs, then we don't need to use insert
993 * mode; unless the tab has already been expanded
994 * in which case we MUST use insert mode.
1000 * The last really special case to handle is case
1001 * where the tab is just sitting there and doesn't
1002 * have enough slack to let the insertion take
1003 * place without shifting the rest of the line
1004 * over. In this case we have to go out and
1005 * delete some characters of the tab before we start
1006 * or the answer will be wrong, as the rest of the
1007 * line will have been shifted. This code means
1008 * that terminals with only insert character (no
1009 * delete character) won't work correctly.
1011 i
= inssiz
- doomed
- tabslack
- slakused
;
1012 i
%= value(vi_TABSTOP
);
1016 for (i
= inssiz
- doomed
- tabslack
; i
> 0; i
--)
1017 vputp(delete_character
, DEPTH(vcline
));
1023 * Now put out the characters of the actual insertion.
1027 for (i
= inssiz
; i
> 0; i
--) {
1033 else if (enter_insert_mode
&& exit_insert_mode
) {
1038 if((c
& QUOTE
) == 0)
1042 if (!enter_insert_mode
|| !exit_insert_mode
) {
1044 * We are a dumb terminal; brute force update
1045 * the rest of the line; this is very much an n^^2 process,
1046 * and totally unreasonable at low speed.
1048 * You asked for it, you get it.
1051 tp
= vtube0
+ inscol
+ doomed
;
1052 for (i
= inscol
+ doomed
; i
< tabstart
; i
++) {
1054 (void) vputchar(*tp
);
1058 vigotoCL(tabstart
+ inssiz
- doomed
);
1059 for (i
= tabsize
- (inssiz
- doomed
) + shft
; i
> 0; i
--)
1060 (void) vputchar(' ' | QUOTE
);
1062 if (!insert_null_glitch
) {
1064 * On terminals without multi-line
1065 * insert in the hardware, we must go fix the segments
1066 * between the inserted text and the following
1067 * tabs, if they are on different lines.
1072 for (j
= (inscol
+ inssiz
- 1) / WCOLS
+ 1;
1073 j
<= (tabstart
+ inssiz
- doomed
- 1) / WCOLS
; j
++) {
1075 i
= inssiz
- doomed
;
1076 up
= tp
+ j
* WCOLS
- i
;
1080 if((wchar
= *up
++) != FILLER
)
1081 (void) vputchar(wchar
);
1082 } while (--i
&& *up
);
1086 * On terminals with multi line inserts,
1087 * life is simpler, just reflect eating of
1090 tp
= vtube0
+ tabend
;
1091 for (i
= tabsize
- (inssiz
- doomed
); i
>= 0; i
--) {
1092 if ((*--tp
& (QUOTE
|TRIM
)) == QUOTE
) {
1094 if (tabslack
>= slakused
)
1101 * Blank out the shifted positions to be tab positions.
1104 tp
= vtube0
+ tabend
+ shft
;
1105 for (i
= tabsize
- (inssiz
- doomed
) + shft
; i
> 0; i
--)
1106 if ((*--tp
& QUOTE
) == 0)
1112 * Finally, complete the screen image update
1113 * to reflect the insertion.
1116 tp
= vtube0
+ tabstart
; up
= tp
+ inssiz
- doomed
;
1117 for (i
= tabstart
; i
> inscol
+ doomed
; i
--)
1119 for (i
= inssiz
; i
> 0; i
--)
1120 if((c
& QUOTE
) == 0) {
1121 int width
= wcwidth(c
);
1137 * Go into ``delete mode''. If the
1138 * sequence which goes into delete mode
1139 * is the same as that which goes into insert
1140 * mode, then we are in delete mode already.
1147 if (eq(enter_delete_mode
, enter_insert_mode
))
1151 vputp(enter_delete_mode
, 0);
1155 * If we are coming out of delete mode, but
1156 * delete and insert mode end with the same sequence,
1157 * it wins to pretend we are now in insert mode,
1158 * since we will likely want to be there again soon
1159 * if we just moved over to delete space from part of
1166 if (eq(enter_delete_mode
, enter_insert_mode
)) {
1170 vputp(exit_delete_mode
, 0);
1174 * In and out of insert mode.
1175 * Note that the code here demands that there be
1176 * a string for insert mode (the null string) even
1177 * if the terminal does all insertions a single character
1178 * at a time, since it branches based on whether enter_insert_mode is null.
1185 vputp(enter_insert_mode
, 0);
1194 vputp(exit_insert_mode
, 0);
1200 * Put the character c on the screen at the current cursor position.
1201 * This routine handles wraparound and scrolling and understands not
1202 * to roll when splitw is set, i.e. we are working in the echo area.
1203 * There is a bunch of hacking here dealing with the difference between
1204 * QUOTE, QUOTE|' ', and ' ' for CONCEPT-100 like terminals, and also
1205 * code to deal with terminals which overstrike, including CRT's where
1206 * you can erase overstrikes with some work. CRT's which do underlining
1207 * implicitly which has to be erased (like CONCEPTS) are also handled.
1212 unsigned char multic
[MULTI_BYTE_MAX
];
1214 int d
, length
, length2
, bytelength
;
1216 short oldhold
= hold
;
1227 if ((length
= wcwidth(c
)) < 0)
1229 /* Fix problem of >79 chars on echo line. */
1230 if (destcol
>= WCOLS
-1 && splitw
&& destline
== WECHO
)
1232 if (destcol
>= WCOLS
) {
1233 destline
+= destcol
/ WCOLS
;
1236 if (destline
> WBOT
&& (!splitw
|| destline
> WECHO
))
1239 error(gettext("Line too long to fit on screen"));
1240 if(destcol
+ length
- 1 >= WCOLS
) {
1241 /* print out split multibyte character using '>' */
1245 (void) vputchar('>');
1249 (void) vputchar(mc_filler
);
1251 for (length
= WCOLS
- destcol
; length
; length
--)
1252 (void) vputchar(mc_filler
);
1254 if ((length
= wcwidth(c
)) < 0)
1258 #endif /* PRESUNEUC */
1262 tp
= vtube
[destline
] + destcol
;
1271 * We can get away without printing a space in a number
1272 * of cases, but not always. We get away with doing nothing
1273 * if we are not in insert mode, and not on a CONCEPT-100
1274 * like terminal, and either not in hardcopy open or in hardcopy
1275 * open on a terminal with no overstriking, provided,
1276 * in all cases, that nothing has ever been displayed
1277 * at this position. Ugh.
1279 if (!insmode
&& !insert_null_glitch
&& (state
!= HARDOPEN
|| over_strike
) && (*tp
&TRIM
) == 0) {
1289 * When in insert mode, tabs have to expand
1290 * to real, printed blanks.
1299 if ((hold
& HOLDPUPD
) == 0)
1305 * A ``space'' ontop of a part of a tab.
1318 * Now get away with doing nothing if the characters
1319 * are the same, provided we are not in insert mode
1320 * and if we are in hardopen, that the terminal has overstrike.
1323 if (rewrite
== _OFF
&& d
== (c
& TRIM
) && !insmode
&& (state
!= HARDOPEN
|| over_strike
)) {
1325 if (rewrite
== _OFF
&& d
== (c
& TRIM
) && !insmode
&&
1326 (state
!= HARDOPEN
|| over_strike
) && !multibyte
) {
1327 #endif /* PRESUNEUC */
1328 if ((hold
& HOLDPUPD
) == 0) {
1340 * Backwards looking optimization.
1341 * The low level cursor motion routines will use
1342 * a cursor motion right sequence to step 1 character
1343 * right. On, e.g., a DM3025A this is 2 characters
1344 * and printing is noticeably slower at 300 baud.
1345 * Since the low level routines are not allowed to use
1346 * spaces for positioning, we discover the common
1347 * case of a single space here and force a space
1350 if (destcol
== outcol
+ 1 && tp
[-1] == ' ' && outline
== destline
) {
1356 * This is an inline expansion a call to vcsync() dictated
1357 * by high frequency in a profile.
1359 if (outcol
!= destcol
|| outline
!= destline
)
1360 vgoto(destline
, destcol
);
1363 * Deal with terminals which have overstrike.
1364 * We handle erasing general overstrikes, erasing
1365 * underlines on terminals (such as CONCEPTS) which
1366 * do underlining correctly automatically (e.g. on nroff
1367 * output), and remembering, in hardcopy mode,
1368 * that we have overstruct something.
1370 if (!insmode
&& d
&& d
!= ' ' && d
!= (c
& TRIM
)) {
1371 if (erase_overstrike
&& (over_strike
|| transparent_underline
&& (c
== '_' || d
== '_'))) {
1373 outcol
++, destcol
++;
1380 * Unless we are just bashing characters around for
1381 * inner working of insert mode, update the display.
1383 if ((hold
& HOLDPUPD
) == 0) {
1386 /* put in filler characters */
1393 * In insert mode, put out the insert_character sequence, padded
1394 * based on the depth of the current line.
1395 * A terminal which had no real insert mode, rather
1396 * opening a character position at a time could do this.
1397 * Actually should use depth to end of current line
1398 * but this rarely matters.
1401 vputp(insert_character
, DEPTH(vcline
));
1403 bytelength
= wctomb((char *)multic
, c
);
1409 * In insert mode, insert_padding is a post insert pad.
1412 vputp(insert_padding
, DEPTH(vcline
));
1417 * CONCEPT braindamage in early models: after a wraparound
1418 * the next newline is eaten. It's hungry so we just
1419 * feed it now rather than worrying about it.
1420 * Fixed to use return linefeed to work right
1421 * on vt100/tab132 as well as concept.
1423 if (eat_newline_glitch
&& outcol
% WCOLS
== 0) {
1432 * Delete display positions stcol through endcol.
1433 * Amount of use of special terminal features here is limited.
1436 physdc(int stcol
, int endcol
)
1441 int nc
= endcol
- stcol
;
1445 tfixnl(), fprintf(trace
, "physdc(%d, %d)\n", stcol
, endcol
);
1447 if (!delete_character
|| nc
<= 0)
1449 if (insert_null_glitch
) {
1451 * CONCEPT-100 like terminal.
1452 * If there are any ``spaces'' in the material to be
1453 * deleted, then this is too hard, just retype.
1456 up
= vtube0
+ stcol
;
1459 if ((*up
++ & (QUOTE
|TRIM
)) == QUOTE
)
1464 if (*up
== 0 || (*up
++ & QUOTE
) == QUOTE
)
1470 * HP like delete mode.
1471 * Compute how much text we are moving over by deleting.
1472 * If it appears to be faster to just retype
1473 * the line, do nothing and that will be done later.
1474 * We are assuming 2 output characters per deleted
1475 * characters and that clear to end of line is available.
1478 if (i
!= endcol
/ WCOLS
)
1483 up
= vtube
[i
]; tp
= up
+ endcol
; tpe
= up
+ WCOLS
;
1484 while (tp
< tpe
&& *tp
)
1486 if (tp
- (up
+ stcol
) < 2 * nc
)
1492 * Go into delete mode and do the actual delete.
1493 * Padding is on delete_character itself.
1496 for (i
= nc
; i
> 0; i
--)
1497 vputp(delete_character
, DEPTH(vcline
));
1498 vputp(exit_delete_mode
, 0);
1502 * With CONCEPT like terminals, characters are pulled left
1503 * from first following null. HP like terminals shift rest of
1504 * this (single physical) line rigidly.
1506 if (insert_null_glitch
) {
1507 up
= vtube0
+ stcol
;
1508 tp
= vtube0
+ endcol
;
1510 if ((i
& (QUOTE
|TRIM
)) == QUOTE
)
1518 copy(up
+ stcol
, up
+ endcol
, (WCOLS
- endcol
) * sizeof(wchar_t));
1519 vclrbyte(tpe
- nc
, nc
);
1527 if (trubble
|| techoin
)
1528 fprintf(trace
, "\n");
1529 trubble
= 0, techoin
= 0;
1539 fprintf(trace
, "vcnt = %d, vcline = %d, vliny = ", vcnt
, vcline
);
1540 for (i
= 0; i
<= vcnt
; i
++) {
1541 fprintf(trace
, "%d", LINE(i
));
1542 if (FLAGS(i
) & VDIRT
)
1543 fprintf(trace
, "*");
1545 fprintf(trace
, "<%d>", DEPTH(i
));
1547 fprintf(trace
, " ");
1549 fprintf(trace
, "\n");
1553 int c
; /* char --> int */
1559 fprintf(trace
, "$");
1560 else if (c
& QUOTE
) /* for 3B (no sign extension) */
1561 fprintf(trace
, "~%c", ctlof(c
&TRIM
));
1562 else if (c
< ' ' || c
== DELETE
)
1563 fprintf(trace
, "^%c", ctlof(c
));
1565 fprintf(trace
, "%c", c
);
1570 * Put a character with possible tracing.