BSD 2 development
[unix-history] / .ref-BSD-1 / ex-1.1 / ex_put.c
#include "ex.h"
#include "ex_tty.h"
/*
* Ex - a text editor
* Bill Joy UCB June 1977
*/
STATIC char line[66] "Error message file not available\n/usr/lib/ex1.1strings";
STATIC char *linp line + 33;
extern char *erpath line + 33;
extern char pfast;
STATIC char phadnl;
termchar(c)
char c;
{
if (pfast == 0 && phadnl)
pstart();
if (c == '\n')
phadnl = 1;
else if (linp >= &line[63])
flush1();
*linp++ = c;
if (c == '\n' && pfast == 0) {
fgoto();
flush1();
}
}
flush()
{
flush1();
flush2();
}
flush1()
{
register char *lp, *cp;
register c;
*linp = 0;
lp = line;
while (*lp)
switch (c = *lp++) {
case '\r':
destline =+ destcol / COLUMNS;
destcol = 0;
continue;
case '\013':
destline--;
continue;
case '\b':
if (value(PRINTALL))
goto printit;
if (destcol)
destcol--;
continue;
case '\032':
if (CLEAR) {
putS(CLEAR);
outcol = 0;
outline = 0;
destcol = 0;
destline = 0;
}
continue;
case ' ':
if (value(PRINTALL))
goto printit;
destcol++;
continue;
case '\t':
if (value(PRINTALL))
goto printit;
destcol =+ 8;
destcol =& ~7;
continue;
case '\n':
destline =+ destcol / COLUMNS + 1;
if (destcol != 0 && destcol % COLUMNS == 0)
destline--;
destcol = 0;
continue;
default:
printit:
fgoto();
for (;;) {
if (AM == 0 && outcol == COLUMNS)
fgoto();
c =& 0177;
putch(c);
if (c == '\b') {
outcol--;
destcol--;
} else if (c >= ' ' && c != 0177) {
outcol++;
destcol++;
}
c = *lp++;
if (c <= ' ')
break;
}
--lp;
continue;
}
linp = line;
}
putS(cp)
char *cp;
{
if (cp == NIL)
return;
while (*cp)
putch(*cp++);
}
flush2()
{
fgoto();
flusho();
pstop();
}
/*
* Goto destline, destcol from outline, outcol.
* We must be cognizant of the capabilities of the terminal
* and (if its a crt) the possibly finite size of its screen.
* The following capability variables are considered:
*
* NOCR if true, can't CR
* BS if true, can BS
* CA if true, can cursor address
* NDSPACE non-destructive space sequence (cursor right)
* UPLINE up line sequence (reverse line-feed)
* AM if true, terminal has automatic return at right margin
*/
fgoto()
{
register int l, c;
/*
* Adjust the destination column to be
* non-virtual by performing line folding.
*/
if (destcol > COLUMNS - 1) {
destline =+ destcol / COLUMNS;
destcol =% COLUMNS;
}
if (outcol > COLUMNS - 1) {
l = (outcol + 1) / COLUMNS;
outline =+ l;
outcol =% COLUMNS;
if (AM == 0) {
/*
* Software automatic margins
*/
while (l > 0) {
putch('\n');
if (pfast)
putch('\r');
l--;
}
outcol = 0;
}
/*
* Outline has to be a real line...
* rounding outline and destline down corresponds
* to "rolling" the screen up.
*/
if (outline > LINES - 1) {
destline =- outline - (LINES - 1);
outline = LINES - 1;
}
}
/*
* If destination line is off the screen
* provide an appropriate "on screen" target,
* call ourselves recursively to get it,
* and then roll the screen up.
*/
if (destline > LINES - 1) {
l = destline;
destline = LINES - 1;
if (outline < LINES - 1) {
c = destcol;
if (pfast == 0 && !CA)
destcol = 0;
fgoto();
destcol = c;
}
while (l > LINES - 1) {
putch('\n');
l--;
if (pfast == 0)
outcol = 0;
}
}
if (destline < outline && !(CA || UPLINE))
/*
* If can't CA or UPLINE
* we have no hope of reducing outline.
*/
destline = outline;
/*
* Try to do the move with very local cursor motions,
* perhaps using a carriage return to move to
* the left margin.
*/
if (motion())
return;
if (CA && !value(PRINTALL)) {
putS(cgoto());
outline = destline;
outcol = destcol;
} else
plod();
}
setcol(col)
int col;
{
register int del;
flush1();
del = col - outcol;
destcol = col;
if (destcol < 0)
destcol = 0;
/* off the line may not work on 3a here */
fgoto();
/*
* ADM3A special - fix tabs
*/
if (TTY == 'ca' && (del <= -4 || del >= 4)) {
del =- 3;
del =& 07;
if (del < 0)
del =+ 8;
while (del > 0) {
/*
* A tip of the hatlo hat here too!
*/
putch('\033');
putch('x');
del--;
}
}
flush();
}
/*
* v is vertical distance, then cost with cr
* h is horizontal distance, then direct move cost
*/
motion()
{
register int v, h, c;
if (!BS)
return (0);
v = destline - outline;
if (v < 0)
if (CA || UPLINE)
v = -v;
else
destline = outline;
h = destcol;
if (!v || pfast) {
h =- outcol;
if (h < 0)
h = -h;
}
h =+ v;
if (pfast || !NOCR) {
if (outcol)
v++;
v =+ destcol;
} else
v = 5;
if (v >= 4 && h >= 4)
return (0);
plod();
return (1);
}
plod()
{
register int i;
while (outline < destline) {
outline++;
putch('\n');
if (NOCR || pfast == 0)
outcol = 0;
}
if (!NOCR && (outcol - destcol > destcol + 1 || outcol > destcol && !BS)) {
putch('\r');
outcol = 0;
}
while (outcol > destcol) {
outcol--;
putch('\b');
}
while (outline > destline) {
outline--;
putS(UPLINE);
}
if (!CA && PT)
while ((i = ((outcol + 8) &~ 7)) < destcol) {
putch('\t');
outcol = i;
}
while (outcol < destcol) {
if (inopen) {
if (!NDSPACE) {
/*
* What a feat of engineering!
* A terminal with cursor addressibility
* but no cursor move 1 char right sequence!
*/
putS(cgoto());
outcol = destcol;
return;
}
putS(NDSPACE);
} else
putch(' ');
outcol++;
}
}
partinp()
{
putch('\n');
noteinp();
}
noteinp()
{
outline++;
if (outline > LINES - 1)
outline = LINES - 1;
destline = outline;
destcol = outcol = 0;
}
notech(i)
int i;
{
outcol =+ i;
destcol =+ i;
}
#define ECHO 010
#define CRLF 020
pstart()
{
if (NOCR || !value(OPTIMIZE) || value(PRINTALL))
return;
if (ruptible == 0)
return;
fgoto();
flusho();
if (pfast)
return;
pfast = 1;
gTTY(1);
normtty = 1;
normf = tty[2];
tty[2] =& ~(ECHO|CRLF);
sTTY(1);
}
pstop()
{
phadnl = 0;
linp = line;
draino();
normal();
if (pfast != 1)
return;
pfast = 0;
}
termreset()
{
destcol = 0;
destline = LINES - 1;
if (!value(PRINTALL))
if (CA) {
outcol = -20;
outline = -20;
} else {
outcol = destcol;
outline = destline;
}
}
draino()
{
obuf.fildes = 1;
obuf.nunused = 0;
obuf.xfree = 0;
}
ostart()
{
if (!intty)
error("Open and visual must be used interactively");
gTTY(1);
normtty = 1;
normf = tty[2];
tty[2] = (tty[2] &~ (ECHO|CRLF)) | RAW;
sTTY(1);
pfast = 2;
}
ostop()
{
pfast = 0;
normal();
termreset();
}
flusho()
{
fflush(&obuf);
}
putnl()
{
putchar('\n');
}
gTTY(i)
{
gtty(i, tty);
}
sTTY(i)
{
stty(i, tty);
}
putch(c)
{
putc(c, &obuf);
}