/* Copyright (c) 1979 Regents of the University of California */
* Terminal driving and line formatting routines.
* Basic motion optimizations are done here as well
* as formatting of lines (printing of control characters,
* line numbering and the like).
* The routines outchar, putchar and pline are actually
* variables, and these variables point at the current definitions
* of the routines. See the routine setflav.
* We sometimes make outchar be routines which catch the characters
* to be printed, e.g. if we want to see how long a line is.
* During open/visual, outchar and putchar will be set to
* routines in the file ex_vput.c (vputchar, vinschar, etc.).
int (*Outchar
)() = termchar
;
int (*Putchar
)() = normchar
;
int (*Pline
)() = normline
;
Putchar
= t
? listchar
: normchar
;
Pline
= t
? numbline
: normline
;
* Format c for list mode; leave things in common
* with normal print mode to be done by normchar.
if (c
< ' ' && c
!= '\n' || c
== DELETE
)
outchar('^'), c
= ctlof(c
);
* Format c for printing. Handle funnies of upper case terminals
* and crocky hazeltines which don't have ~.
else if (c
< ' ' && (c
!= '\b' || !OS
) && c
!= '\n' && c
!= '\t' || c
== DELETE
)
putchar('^'), c
= ctlof(c
);
* Print a line with a number.
* Normal line output, no numbering.
/* pdp-11 doprnt is not reentrant so can't use "printf" here
in case we are tracing */
* Given c at the beginning of a line, determine whether
* the printing of the line will erase or otherwise obliterate
* the prompt which was printed before. If it won't, do it now.
* The output buffer is initialized with a useful error
* message so we don't have to keep it in data space.
'E', 'r', 'r', 'o', 'r', ' ', 'm', 'e', 's', 's', 'a', 'g', 'e', ' ',
'f', 'i', 'l', 'e', ' ', 'n', 'o', 't', ' ',
'a', 'v', 'a', 'i', 'l', 'a', 'b', 'l', 'e', '\n', 0
static char *linp
= linb
+ 33;
* Phadnl records when we have already had a complete line ending with \n.
* If another line starts without a flush, and the terminal suggests it,
* we switch into -nl mode so that we can send lineffeeds to avoid
* Indirect to current definition of putchar.
* Termchar routine for command mode.
* Watch for possible switching to -nl mode.
* Otherwise flush into next level of buffering when
* small buffer fills or at a newline.
if (pfast
== 0 && phadnl
)
else if (linp
>= &linb
[63])
* Flush from small line buffer into output buffer.
* Work here is destroying motion into positions, and then
* letting fgoto do the optimized motion.
destline
+= destcol
/ COLUMNS
;
destcol
+= value(TABSTOP
) - destcol
% value(TABSTOP
);
destline
+= destcol
/ COLUMNS
+ 1;
if (destcol
!= 0 && destcol
% COLUMNS
== 0)
if (AM
== 0 && outcol
== COLUMNS
)
} else if (c
>= ' ' && c
!= DELETE
) {
if (XN
&& outcol
% COLUMNS
== 0)
* Sync the position of the output cursor.
* Most work here is rounding for terminal boundaries getting the
* column position implied by wraparound or the lack thereof and
* rolling up the screen to get destline on the screen.
if (destcol
> COLUMNS
- 1) {
destline
+= destcol
/ COLUMNS
;
if (outcol
> COLUMNS
- 1) {
l
= (outcol
+ 1) / COLUMNS
;
if (outline
> LINES
- 1) {
destline
-= outline
- (LINES
- 1);
if (destline
> LINES
- 1) {
if (outline
< LINES
- 1) {
if (pfast
== 0 && (!CA
|| holdcm
))
if (destline
< outline
&& !(CA
&& !holdcm
|| UP
!= NOSTR
))
tputs(tgoto(CM
, destcol
, destline
), 0, putch
);
* Tab to column col by flushing and then setting destcol.
* Move (slowly) to destination.
* Hard thing here is using home cursor on really deficient terminals.
* Otherwise just use cursor motions, hacking use of tabs and overtabbing
static int plodcnt
, plodflg
;
register int soutcol
, soutline
;
i
= (destcol
/ value(HARDTABS
)) + (destcol
% value(HARDTABS
));
j
= destcol
/ value(HARDTABS
) - outcol
/ value(HARDTABS
);
j
+= destcol
% value(HARDTABS
);
if (outcol
- destcol
<= i
&& (BS
|| BC
))
i
= j
= outcol
- destcol
;
k
= (LINES
- 1) - destline
;
i
= destcol
% value(HARDTABS
) + destcol
/ value(HARDTABS
);
if (BT && outcol > destcol && (j = (((outcol+7) & ~7) - destcol - 1) >> 3)) {
if ((k += (destcol&7)) > 4)
* If we will later need a \n which will turn into a \r\n by
* the system or the terminal, then don't bother to try to \r.
if ((NONL
|| !pfast
) && outline
< destline
)
* If the terminal will do a \r\n and there isn't room for it,
* then we can't afford a \r.
if (NC
&& outline
>= destline
)
* If it will be cheaper, or if we can't back up, then send
* a return preliminarily.
if (j
> i
+ 1 || outcol
> destcol
&& !BS
&& !BC
) {
while (outline
< destline
) {
while (outcol
> destcol
) {
if (BT && !insmode && outcol - destcol > 4+k) {
while (outline
> destline
) {
if (GT
&& !insmode
&& destcol
- outcol
> 1) {
i
= (outcol
/ value(HARDTABS
) + 1) * value(HARDTABS
);
if (destcol
- outcol
> 4 && i
< COLUMNS
&& (BC
|| BS
)) {
while (outcol
> destcol
) {
while (outcol
< destcol
) {
* move one char to the right. We don't use ND space
* because it's better to just print the char we are
* moving over. There are various exceptions, however.
* If !inopen, vtube contains garbage. If the char is
* a null or a tab we want to print a space. Other random
* chars we use space for instead, too.
fprintf(trace
, "ND: inopen=%d, i=%d, outline=%d, outcol=%d\n", inopen
, i
, outline
, outcol
);
if (!inopen
|| vtube
[outline
]==NULL
||
(i
=vtube
[outline
][outcol
]) < ' ')
* Calculate new (approximate) screen line position.
* Approximate because kill character echoes newline with
* no feedback and also because of long input lines.
* Something weird just happened and we
* lost track of whats happening out there.
* Since we cant, in general, read where we are
* we just reset to some known state.
* On cursor addressible terminals setting to unknown
* will force a cursor address soon.
if (TI
) /* otherwise it flushes anyway, and 'set tty=dumb' vomits */
putpad(TI
); /*adb change -- emit terminal initial sequence */
* Low level buffering, with the ability to drain
* buffered output without printing it.
write(1, obuf
, obp
- obuf
);
if (obp
>= &obuf
[sizeof obuf
])
* Miscellaneous routines related to output.
return (tgoto(CM
, destcol
, destline
));
* Set output through normal command mode routine.
* Printf (temporarily) in list mode.
if (ruptible
== 0 || pfast
)
tty
.sg_flags
= normf
& ~(ECHO
|XTABS
|CRMOD
);
* Prep tty for open mode.
error("Open and visual must be used interactively");
tty
.sg_flags
= (normf
&~ (ECHO
|XTABS
|CRMOD
)) | CBREAK
;
tty
.sg_flags
= (normf
&~ (ECHO
|XTABS
|CRMOD
)) | RAW
;
nttyc
.t_quitc
= nttyc
.t_startc
= nttyc
.t_stopc
= '\377';
* Stop open, restoring tty modes.
pfast
= (f
& CRMOD
) == 0;
termreset(), fgoto(), flusho();
* Into cooked mode for interruptibility.
* Restore flags to normal state f.
* Straight set of flags to state f.
register int ot
= tty
.sg_flags
;
nttyc
.t_quitc
= nttyc
.t_startc
= nttyc
.t_stopc
= '\377';
ioctl(i
, TIOCGETC
, &ottyc
);
* Bug in USG tty driver, put out a null char as a patch.
if (tty
.sg_ospeed
== B1200
)
ioctl(i
, TIOCSETN
, &tty
);
ioctl(i
, TIOCSETC
, &nttyc
);
* Print newline, or blank if in open/visual
putchar(Outchar
!= termchar
? ' ' : '\n');