mirror of
https://github.com/GnoConsortium/gno.git
synced 2024-12-21 23:29:16 +00:00
784e3de7cd
passwd, ps, purge, shutdown, stty, upper, and vi. These sources are for the versions of the utils shipped with GNO v2.0.4.
441 lines
7.7 KiB
C
441 lines
7.7 KiB
C
/*
|
|
* High level routines dealing with the output to the screen.
|
|
*/
|
|
#pragma noroot
|
|
#include "less.h"
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
|
|
#ifdef _ORCAC_
|
|
#define FAST
|
|
segment "LoadSegONE";
|
|
#endif
|
|
|
|
public int errmsgs; /* Count of messages displayed by error() */
|
|
public int need_clr;
|
|
|
|
extern int sigs;
|
|
extern int sc_width;
|
|
extern int so_s_width, so_e_width;
|
|
extern int screen_trashed;
|
|
extern int any_display;
|
|
#if __MSDOS__
|
|
extern int output_mode;
|
|
#endif
|
|
|
|
static int iprintnum(int num, int radix);
|
|
static int iprintf(char *fmt, PARG *parg);
|
|
|
|
/*
|
|
* Display the line which is in the line buffer.
|
|
*/
|
|
public void
|
|
put_line(void)
|
|
{
|
|
register int c;
|
|
register int i;
|
|
int a;
|
|
int curr_attr;
|
|
|
|
if (sigs)
|
|
{
|
|
/*
|
|
* Don't output if a signal is pending.
|
|
*/
|
|
screen_trashed = 1;
|
|
return;
|
|
}
|
|
|
|
curr_attr = NORMAL;
|
|
|
|
for (i = 0; (c = gline(i, &a)) != '\0'; i++)
|
|
{
|
|
if (a != curr_attr)
|
|
{
|
|
/*
|
|
* Changing attributes.
|
|
* Display the exit sequence for the old attribute
|
|
* and the enter sequence for the new one.
|
|
*/
|
|
switch (curr_attr)
|
|
{
|
|
case UNDERLINE: ul_exit(); break;
|
|
case BOLD: bo_exit(); break;
|
|
case BLINK: bl_exit(); break;
|
|
}
|
|
switch (a)
|
|
{
|
|
case UNDERLINE: ul_enter(); break;
|
|
case BOLD: bo_enter(); break;
|
|
case BLINK: bl_enter(); break;
|
|
}
|
|
curr_attr = a;
|
|
}
|
|
if (curr_attr == INVIS)
|
|
continue;
|
|
if (c == '\b')
|
|
putbs();
|
|
else
|
|
putchr(c);
|
|
}
|
|
}
|
|
|
|
/*static char obuf[1024];*/
|
|
static char obuf[1024];
|
|
static char *ob = obuf;
|
|
|
|
/*
|
|
* Flush buffered output.
|
|
*
|
|
* If we haven't displayed any file data yet,
|
|
* output messages on error output (file descriptor 2),
|
|
* otherwise output on standard output (file descriptor 1).
|
|
*
|
|
* This has the desirable effect of producing all
|
|
* error messages on error output if standard output
|
|
* is directed to a file. It also does the same if
|
|
* we never produce any real output; for example, if
|
|
* the input file(s) cannot be opened. If we do
|
|
* eventually produce output, code in edit() makes
|
|
* sure these messages can be seen before they are
|
|
* overwritten or scrolled away.
|
|
*/
|
|
public void
|
|
flush(void)
|
|
{
|
|
register int n;
|
|
register int fd;
|
|
|
|
#if __MSDOS__
|
|
if (output_mode == 0)
|
|
{
|
|
*ob = '\0';
|
|
cputs(obuf);
|
|
ob = obuf;
|
|
return;
|
|
}
|
|
#endif
|
|
n = ob - obuf;
|
|
if (n == 0)
|
|
return;
|
|
/* fd = (any_display) ? 1 : 2;*/
|
|
fd = (any_display) ? STDOUT_FILENO : STDERR_FILENO;
|
|
if (write(fd, obuf, n) != n)
|
|
screen_trashed = 1;
|
|
ob = obuf;
|
|
}
|
|
|
|
/*
|
|
* Output a character.
|
|
*/
|
|
#ifdef FAST
|
|
public void putchr(c)
|
|
int c;
|
|
{
|
|
static char *sz=obuf+sizeof(obuf);
|
|
char *oo;
|
|
asm {
|
|
lda ob+2
|
|
sta oo+2
|
|
lda ob
|
|
sta oo
|
|
cmp sz
|
|
bcc nofl
|
|
jsl flush
|
|
lda ob
|
|
sta oo
|
|
nofl: lda need_clr
|
|
beq noncl
|
|
stz need_clr
|
|
jsl lower_left
|
|
jsl clear_eol
|
|
noncl: lda c
|
|
cmp #10
|
|
bne notnl
|
|
lda #13
|
|
notnl: pha
|
|
lda [oo]
|
|
and #0xff00
|
|
ora 1,s
|
|
sta [oo]
|
|
pla
|
|
inc ob
|
|
}
|
|
}
|
|
#else
|
|
public void putchr(c)
|
|
int c;
|
|
{
|
|
if (ob >= &obuf[sizeof(obuf)])
|
|
flush();
|
|
if (need_clr)
|
|
{
|
|
need_clr = 0;
|
|
lower_left();
|
|
clear_eol();
|
|
}
|
|
#if __MSDOS__
|
|
if (c == '\n')
|
|
*ob++ = '\r';
|
|
#endif
|
|
#ifdef __ORCAC__
|
|
if (c == '\n')
|
|
*ob++ = '\r';
|
|
else
|
|
#endif
|
|
*ob++ = c;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Output a string.
|
|
*/
|
|
#ifdef FAST
|
|
public void putstr(s)
|
|
register char *s;
|
|
{
|
|
static char *sz=obuf+sizeof(obuf);
|
|
char *oo;
|
|
int ytmp;
|
|
|
|
asm {
|
|
stz ytmp
|
|
lda ob+2
|
|
sta oo+2
|
|
lda ob
|
|
sta oo
|
|
lp: ldy ytmp
|
|
lda [s],y
|
|
and #0xff
|
|
beq done
|
|
pha
|
|
/* jsl putchr*/
|
|
lda oo
|
|
cmp sz
|
|
bcc nofl
|
|
jsl flush
|
|
lda ob
|
|
sta oo
|
|
nofl: lda need_clr
|
|
beq noncl
|
|
stz need_clr
|
|
jsl lower_left
|
|
jsl clear_eol
|
|
noncl: lda 1,s
|
|
cmp #10
|
|
bne notnl
|
|
lda #13
|
|
notnl: pha
|
|
lda [oo]
|
|
and #0xff00
|
|
ora 1,s
|
|
sta [oo]
|
|
pla
|
|
pla
|
|
inc ob
|
|
inc oo
|
|
inc ytmp
|
|
bra lp
|
|
done:
|
|
}
|
|
}
|
|
#else
|
|
public void putstr(s)
|
|
register char *s;
|
|
{
|
|
while (*s != '\0')
|
|
putchr(*s++);
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Output an integer in a given radix.
|
|
*/
|
|
static int
|
|
iprintnum(num, radix)
|
|
int num;
|
|
int radix;
|
|
{
|
|
register char *s;
|
|
int r;
|
|
int neg;
|
|
char buf[10];
|
|
|
|
if (neg = (num < 0))
|
|
num = -num;
|
|
|
|
s = buf;
|
|
do
|
|
{
|
|
*s++ = (num % radix) + '0';
|
|
} while ((num /= radix) != 0);
|
|
|
|
if (neg)
|
|
*s++ = '-';
|
|
r = s - buf;
|
|
|
|
while (s > buf)
|
|
putchr(*--s);
|
|
return (r);
|
|
}
|
|
|
|
/*
|
|
* This function implements printf-like functionality
|
|
* using a more portable argument list mechanism than printf's.
|
|
*/
|
|
static int
|
|
iprintf(fmt, parg)
|
|
register char *fmt;
|
|
PARG *parg;
|
|
{
|
|
register char *s;
|
|
register int n;
|
|
register int col;
|
|
|
|
col = 0;
|
|
while (*fmt != '\0')
|
|
{
|
|
if (*fmt != '%')
|
|
{
|
|
putchr(*fmt++);
|
|
col++;
|
|
} else
|
|
{
|
|
++fmt;
|
|
switch (*fmt++) {
|
|
case 's':
|
|
s = parg->p_string;
|
|
parg++;
|
|
while (*s != '\0')
|
|
{
|
|
putchr(*s++);
|
|
col++;
|
|
}
|
|
break;
|
|
case 'd':
|
|
n = parg->p_int;
|
|
parg++;
|
|
col += iprintnum(n, 10);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return (col);
|
|
}
|
|
|
|
/*
|
|
* Output a message in the lower left corner of the screen
|
|
* and wait for carriage return.
|
|
*/
|
|
public void
|
|
error(fmt, parg)
|
|
char *fmt;
|
|
PARG *parg;
|
|
{
|
|
int c;
|
|
int col = 0;
|
|
static char return_to_continue[] = " (press RETURN)";
|
|
|
|
errmsgs++;
|
|
|
|
if (any_display)
|
|
{
|
|
lower_left();
|
|
clear_eol();
|
|
so_enter();
|
|
col += so_s_width;
|
|
}
|
|
|
|
col += iprintf(fmt, parg);
|
|
|
|
if (!any_display)
|
|
{
|
|
/* putchr('\n');*/
|
|
putchr('\r');
|
|
return;
|
|
}
|
|
|
|
putstr(return_to_continue);
|
|
so_exit();
|
|
col += sizeof(return_to_continue) + so_e_width;
|
|
|
|
#if ONLY_RETURN
|
|
while ((c = getchr()) != '\n' && c != '\r')
|
|
bell();
|
|
#else
|
|
c = getchr();
|
|
if (c != '\n' && c != '\r' && c != ' ' && c != READ_INTR)
|
|
ungetcc(c);
|
|
#endif
|
|
lower_left();
|
|
|
|
if (col >= sc_width)
|
|
/*
|
|
* Printing the message has probably scrolled the screen.
|
|
* {{ Unless the terminal doesn't have auto margins,
|
|
* in which case we just hammered on the right margin. }}
|
|
*/
|
|
screen_trashed = 1;
|
|
|
|
flush();
|
|
}
|
|
|
|
static char intr_to_abort[] = "... (interrupt to abort)";
|
|
|
|
/*
|
|
* Output a message in the lower left corner of the screen
|
|
* and don't wait for carriage return.
|
|
* Usually used to warn that we are beginning a potentially
|
|
* time-consuming operation.
|
|
*/
|
|
public void
|
|
ierror(fmt, parg)
|
|
char *fmt;
|
|
PARG *parg;
|
|
{
|
|
lower_left();
|
|
clear_eol();
|
|
so_enter();
|
|
(void) iprintf(fmt, parg);
|
|
putstr(intr_to_abort);
|
|
so_exit();
|
|
flush();
|
|
need_clr = 1;
|
|
}
|
|
|
|
/*
|
|
* Output a message in the lower left corner of the screen
|
|
* and return a single-character response.
|
|
*/
|
|
public int
|
|
query(fmt, parg)
|
|
char *fmt;
|
|
PARG *parg;
|
|
{
|
|
register int c;
|
|
int col = 0;
|
|
|
|
if (any_display)
|
|
{
|
|
lower_left();
|
|
clear_eol();
|
|
}
|
|
|
|
(void) iprintf(fmt, parg);
|
|
c = getchr();
|
|
|
|
if (!any_display)
|
|
{
|
|
/* putchr('\n');*/
|
|
putchr('\r');
|
|
return (c);
|
|
}
|
|
|
|
lower_left();
|
|
if (col >= sc_width)
|
|
screen_trashed = 1;
|
|
flush();
|
|
|
|
return (c);
|
|
}
|