/* 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(cgoto(), 0, putch
);
* Tab to column col by flushing and then setting destcol.
* Routine to decide how to do a basic motion,
* choosing between local motions and cursor addressing.
* V is vertical distance, then cost with cr.
* H is horizontal distance, then direct move cost.
if (CA
&& !holdcm
|| UP
) {
* 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
if (HO
&& (!CA
|| holdcm
)) {
i
= (destcol
>> 3) + (destcol
& 07);
if (GT
&& (j
= ((destcol
- (outcol
&~ 07)) >> 3)))
if (outcol
- destcol
<= i
&& (BS
|| BC
))
i
= j
= outcol
- destcol
;
k
= (LINES
- 1) - destline
;
if (GT
&& (!CA
|| holdcm
))
i
= (destcol
>> 3) + (destcol
& 07);
if ((!NONL
|| outline
>= destline
) && (!NC
|| outline
< destline
) &&
(outcol
- destcol
> i
+ 1 || outcol
> destcol
&& !BS
&& !BC
)) {
while (outline
< destline
) {
while (outcol
> destcol
) {
while (outline
> destline
) {
if (GT
&& destcol
- outcol
> 1) {
while ((i
= ((outcol
+ 8) &~ 7)) <= destcol
) {
if (destcol
- outcol
> 4 && (BC
|| BS
)) {
while (outcol
> destcol
) {
while (outcol
< destcol
) {
* 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.
* 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
|CRMOD
);
* Prep tty for open mode.
error("Open and visual must be used interactively");
tty
.sg_flags
= (normf
&~ (ECHO
|CRMOD
)) | RAW
;
tty
.sg_flags
= (normf
&~ (ECHO
|CRMOD
)) | CBREAK
;
* 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
;
ioctl(i
, TIOCSETN
, &tty
);
* Print newline, or blank if in open/visual
putchar(Outchar
!= termchar
? ' ' : '\n');