home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 5 Edit
/
05-Edit.zip
/
most423.zip
/
display.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-03-05
|
17KB
|
674 lines
#include <stdio.h>
#ifndef sequent
#include <stdlib.h>
#endif
#ifdef unix
#ifndef sequent
# include <unistd.h>
#endif
#endif
#include "externs.h"
#include "buffer.h"
#include "display.h"
#include "sysdep.h"
int SCREEN_WIDTH = 80;
#ifdef __EMX__
int SCREEN_HEIGHT = 25;
int SCREEN_ROWS = 24; /* height - 1 */
#else
int SCREEN_HEIGHT = 24;
int SCREEN_ROWS = 23; /* height - 1 */
#endif
int Term_Cannot_Insert = 0;
/* 1 if terminal lacks the ability to do into insert mode or into delete
mode. Currently controlled by S-Lang but later perhaps termcap. */
int Term_Cannot_Scroll = 0;
char *INS_MODE_STR; /* = "\033[4h"; */ /* ins mode (im) */
char *EINS_MODE_STR; /* = "\033[4l"; */ /* end ins mode (ei) */
char *SCROLL_R_STR; /* = "\033[%d;%dr"; */ /* scroll region */
char *CLS_STR; /* = "\033[2J\033[H"; */ /* cl termcap STR for ansi terminals */
char *DEL_EOL_STR; /* = "\033[K"; */ /* ce */
char *DEL_CHAR_STR; /* = "\033[P"; */ /* dc */
char *DEL_N_LINES_STR; /* = "\033[%dM"; */ /* DL */
char *ADD_N_LINES_STR; /* = "\033[%dL"; */ /* AL */
char *REV_SCROLL_STR;
char *TT_BOLD_STR; /* = "\033[1m"; */ /* md */
char *TT_NORM_STR; /* = "\033[0m"; */ /* me */
char *TT_ULIN_STR; /* = "\033[4m"; */ /* us */
char *TT_REVV_STR; /* = "\033[7m"; */ /* mr */
char *CURS_F_STR; /* = "\033[%dC"; */ /* RI termcap string */
static int LEN_CURS_F_STR = 5;
/* cm string has %i%d since termcap numbers columns from 0 */
/* char *CURS_POS_STR = "\033[%d;%df"; ansi-- hor and vert pos */
char *CURS_POS_STR; /* = "\033[%i%d;%dH";*/ /* cm termcap string */
int Output_Rate = 0; /* number of chars to output in 1 second */
/* scrolling region */
static int Scroll_r1 = 0, Scroll_r2 = 23;
static int Cursor_r;
static void tt_write(char *str, int n)
{
/* static unsigned long last_time;
static int total;
unsigned long now;
*/
if (str == NULL) return;
/* total += n; */
write(fileno(stdout), str, n);
/* if ((Output_Rate > 20) && (total > Output_Rate))
{
total = 0;
if ((now = sys_time()) - last_time <= 1)
{
sleep((unsigned) 1);
}
last_time = now;
}
*/
}
void send_string_to_term(char *str)
{
if (str == NULL) return;
tt_write(str, strlen(str));
}
void tt_putchar(char ch)
{
#if !defined(VMS) && !HAS_TERMIOS
write(fileno(stdout), &ch, 1);
if (ch == '\n') ch = '\r';
else return;
#endif
write(fileno(stdout), &ch, 1);
}
/* this is supposed to be fast--- also handles
termcap: %d, &i, %., %+, %r strings as well as terminfo stuff */
int tt_sprintf(char *buf, char *fmt, int x, int y)
{
register unsigned char *f = (unsigned char *) fmt, *b, ch;
int offset = 0, tinfo = 0;
int stack[10];
int i = 0, z;
stack[0] = y; stack[1] = x; i = 2;
b = (unsigned char *) buf;
if (fmt != NULL) while ((ch = *f++) != 0)
{
if (ch != '%') *b++ = ch;
else
{
ch = *f++;
if (ch == 'p')
{
tinfo = 1;
ch = *f++;
if (ch == '1') stack[i++] = x; else stack[i++] = y;
}
else if (ch == '\'') /* 'x' */
{
stack[i++] = *f++;
f++;
}
else if ((ch == 'd') || (ch == 2) || (ch == 3))
{
z = stack[--i];
z += offset;
if (z >= 100)
{
*b++ = z / 100 + '0';
z = z % 100;
goto ten;
}
else if (ch == 3)
{
*b++ = '0';
ch = '2';
}
if (z >= 10)
{
ten:
*b++ = z / 10 + '0';
z = z % 10;
}
else if (ch == 2) *b++ = '0';
*b++ = z + '0';
}
else if (ch == 'i')
{
offset = 1;
}
else if (ch == '+')
{
if (tinfo)
{
z = stack[--i];
stack[i-1] += z;
}
else
{
ch = *f++;
if ((unsigned char) ch == 128) ch = 0;
ch = ch + (unsigned char) stack[--i];
if (ch == '\n') ch++;
*b++ = ch;
}
}
else if (ch == 'r')
{
stack[0] = x;
stack[1] = y;
}
else if ((ch == '.') || (ch == 'c'))
{
ch = (unsigned char) stack[--i];
if (ch == '\n') ch++;
*b++ = ch;
}
else *b++ = ch;
}
}
*b = 0;
return((int) (b - (unsigned char *) buf));
}
void tt_printf(char *fmt, int x, int y)
{
char buf[256];
int n;
n = tt_sprintf(buf, fmt, x, y);
tt_write(buf, n);
}
void curs_bol()
{
tt_putchar('\r');
}
void set_scroll_region(int r1, int r2)
{
Scroll_r1 = r1 - 1;
Scroll_r2 = r2 - 1;
tt_printf(SCROLL_R_STR,Scroll_r1, Scroll_r2);
}
void reset_scroll_region()
{
set_scroll_region(1, SCREEN_HEIGHT);
}
/* the goto_rc function moves to row relative to scrolling region */
void goto_rc(int r, int c)
{
Cursor_r = r - 1 + Scroll_r1;
tt_printf(CURS_POS_STR, Cursor_r,c - 1);
}
void begin_insert()
{
send_string_to_term(INS_MODE_STR);
}
void end_insert()
{
send_string_to_term(EINS_MODE_STR);
}
void tt_delete_char()
{
send_string_to_term(DEL_CHAR_STR);
}
void tt_erase_line()
{
curs_bol();
send_string_to_term(DEL_EOL_STR);
}
void tt_delete_nlines(int n)
{
int r1, curs;
if (!n) return;
if (DEL_N_LINES_STR != NULL) tt_printf(DEL_N_LINES_STR,n, 0);
else
/* get a new terminal */
{
r1 = Scroll_r1 + 1;
curs = Cursor_r + 1;
set_scroll_region(curs, Scroll_r2 + 1);
goto_rc(Scroll_r2 - Scroll_r1 + 1, 1);
while (n--) tt_putchar('\n');
set_scroll_region(r1, Scroll_r2 + 1);
goto_rc(curs, 1);
}
}
void cls()
{
send_string_to_term(CLS_STR);
}
void reverse_index(int n)
{
if (!n) return;
if (ADD_N_LINES_STR != NULL) tt_printf(ADD_N_LINES_STR,n, 0);
else
{
while(n--) send_string_to_term(REV_SCROLL_STR);
}
}
void beep()
{
tt_putchar('\007');
}
void tt_del_eol()
{
send_string_to_term(DEL_EOL_STR);
}
void tt_reverse_video()
{
send_string_to_term(TT_REVV_STR);
}
void tt_normal_video()
{
send_string_to_term(TT_NORM_STR);
}
void narrow_width()
{
send_string_to_term("\033[?3l");
}
void wide_width()
{
send_string_to_term("\033[?3h");
}
void smart_puts(char *neww,char *oldd, int row, int spc)
{
char out[250], curs[20], *mark;
register char *p, ch, ch1;
register char *neew = neww, *old = oldd;
int ii,max_len,i, curs_set = 0, curs_len = 0;
char *new_save;
i = 0;
ii = 0;
*curs = 0;
max_len = LEN_CURS_F_STR;
/* many times we are scrolling and line to compare is blank. Treat this
case special */
if (spc == 0)
{
p = neew;
while(*p == ' ') p++;
if (*p == 0) return;
goto_rc(row, p - neew + 1);
old = out;
ch1 = ' ';
while (1)
{
while (ch = *p++, (ch1 != ch) && ch) *old++ = ch;
mark = old;
if (!ch) break;
*old++ = ch1;
while(ch = *p++, (ch == ch1) && ch) *old++ = ch;
if (old - mark > max_len)
{
*mark = 0;
send_string_to_term(out);
if (ch == 0) return;
if (mark != out) goto_rc(row, p - neew);
old = out;
}
if (!ch) break;
p--;
}
*old = 0;
send_string_to_term(out);
return;
}
/* while they match, go on */
/* Note that neew - new_save is then column of character */
new_save = neew + 1;
while (((ch = *neew++) == *old++) && ch);
i += neew - new_save;
if (!ch)
/* we are at the end of the new, so delete eond of old line */
{
if ((ch1 = *(old - 1)) == ' ')
{
while (*old++ == ch1);
ch1 = *(old - 1);
}
if (ch1 == 0) return;
goto_rc(row, i + 1);
tt_del_eol();
return;
}
if (i)
{
curs_len = tt_sprintf(curs, CURS_POS_STR, row - 1, i);
curs_set = 1;
}
while(1)
{
ch1 = 0;
p = out;
*p++ = ch;
while (ch1 = *old++, ch = *neew++, (ch != ch1) && ch) *p++ = ch;
mark = p;
*p++ = ch;
if (ch) while (ch = *neew++, ch1 = *old++, (ch == ch1) && ch)
{
*p++ = ch;
}
*p = 0;
i = p - mark;
if (i > max_len)
{
*mark = 0;
if (*curs)
{
tt_write(curs, curs_len);
*curs = 0;
}
if (!curs_set)
{
goto_rc(row, 1);
curs_set = 1;
}
send_string_to_term(out);
if (!ch)
{
if (ch1)
{
old--; ch = ' ';
while (ch1 = *old++, (ch1 == ch));
}
if (ch1 == 0) return;
if (curs_set && (CURS_F_STR != NULL)) tt_printf(CURS_F_STR, i, 0);
else
{
tt_printf(CURS_POS_STR, row - 1, neew - new_save);
curs_set = 1;
}
tt_del_eol();
return;
}
if (i)
{
if (curs_set && (CURS_F_STR != NULL)) curs_len = tt_sprintf(curs, CURS_F_STR, i, 0);
else
{
curs_len = tt_sprintf(curs, CURS_POS_STR, row - 1, neew - new_save);
curs_set = 1;
}
}
}
else
{
if (*curs)
{
tt_write(curs, curs_len);
*curs = 0;
}
if (!curs_set)
{
goto_rc(row, 1);
curs_set = 1;
}
send_string_to_term(out);
if (!ch)
{
if (ch1 == ' ')
{
while (*old++ == ch1);
ch1 = *(old - 1);
}
if (ch1) tt_del_eol();
return;
}
}
}
}
/* termcap stuff */
static int vt100_like = 0;
#ifdef unix
extern char *tgetstr(char *, char **);
extern int tgetent(char *, char *);
extern int tgetnum(char *);
static char tbuf[1024];
static char *Null_String = "";
static char *my_tgetstr(char *what, char **p)
{
register char *w, *w1;
char *wsave;
what = tgetstr(what, p);
if (what != NULL)
{
/* lose pad info --- with today's technology, term is a loser if
it is really needed */
while ((*what == '.') ||
((*what >= '0') && (*what <= '9'))) what++;
if (*what == '*') what++;
/* lose terminfo padding--- looks like $<...> */
w = what;
while (*w) if ((*w++ == '$') && (*w == '<'))
{
w1 = w - 1;
while (*w && (*w != '>')) w++;
if (*w == 0) break;
w++;
wsave = w1;
while ((*w1++ = *w++) != 0);
w = wsave;
}
if (*what == 0) what = NULL;
}
return(what);
}
extern char *getenv();
static char tstr_buf[512];
void get_terminfo()
{
char *t, *term, ch;
char *p = tstr_buf;
#ifdef TIOCSTI
(void) signal(SIGWINCH,resize_display);
#endif
if (NULL == (term = getenv("TERM")))
{
exit_error("TERM environment variable needs set.");
}
if (1 != tgetent(tbuf, term)) exit_error("Unknown terminal.");
if ((SCREEN_WIDTH = tgetnum("co")) <= 0) SCREEN_WIDTH = 80;
#ifdef __EMX__
if ((SCREEN_HEIGHT = tgetnum("li")) <= 0) SCREEN_HEIGHT = 25;
#else
if ((SCREEN_HEIGHT = tgetnum("li")) <= 0) SCREEN_HEIGHT = 24;
#endif
SCREEN_ROWS = SCREEN_HEIGHT - 1;
t = term;
if (strcmp(t, "vt52") && (*t++ == 'v') && (*t++ == 't')
&& (ch = *t, (ch >= '1') && (ch <= '9')))
{
vt100_like = 1;
/* make up for DEC'S braindead termcaps (probably most other unix too) */
if ((ch >= 2) || !strcmp(t, "102"))
{
set_term_vtxxx(0);
return;
}
}
if ((NULL == (CLS_STR = my_tgetstr("cl", &p)))
|| (NULL == (CURS_POS_STR = my_tgetstr("cm", &p))))
{
exit_error("Terminal not powerful enough for MOST.");
}
if ((NULL == (INS_MODE_STR = my_tgetstr("im", &p)))
|| ( NULL == (EINS_MODE_STR = my_tgetstr("ei", &p)))
|| ( NULL == (DEL_CHAR_STR = my_tgetstr("dc", &p))))
Term_Cannot_Insert = 1;
REV_SCROLL_STR = my_tgetstr("sr", &p);
DEL_N_LINES_STR = my_tgetstr("DL", &p);
ADD_N_LINES_STR = my_tgetstr("AL", &p);
SCROLL_R_STR = my_tgetstr("cs", &p);
if ((SCROLL_R_STR == NULL)
|| (((NULL == DEL_N_LINES_STR) || (NULL == ADD_N_LINES_STR))
&& (NULL == REV_SCROLL_STR)))
Term_Cannot_Scroll = 1;
#ifdef __linux__
if (!strcmp(term, "console")) Term_Cannot_Scroll = 1;
#endif
DEL_EOL_STR = my_tgetstr("ce", &p);
/* so, se */
if (NULL == (TT_REVV_STR = my_tgetstr("mr", &p))) TT_REVV_STR = Null_String;
if (NULL == (TT_BOLD_STR = my_tgetstr("md", &p))) TT_BOLD_STR = Null_String;
if (NULL == (TT_NORM_STR = my_tgetstr("me", &p))) TT_NORM_STR = Null_String;
if (NULL == (TT_ULIN_STR = my_tgetstr("us", &p))) TT_ULIN_STR = Null_String;
if (NULL != (CURS_F_STR = my_tgetstr("RI", &p)))
{
LEN_CURS_F_STR = strlen(CURS_F_STR);
}
else LEN_CURS_F_STR = strlen(CURS_POS_STR);
get_term_dimensions(&SCREEN_WIDTH, &SCREEN_HEIGHT);
SCREEN_ROWS = SCREEN_HEIGHT - 1;
}
#endif
/* specific to vtxxx only */
void enable_cursor_keys()
{
if (vt100_like) send_string_to_term("\033=\033[?1l");
}
/* This sets term for vt102 terminals it parameter vt100 is 0. If vt100
is non-zero, set terminal appropriate for a only vt100
(no add line capability). */
void set_term_vtxxx(int is_vt100)
{
vt100_like = 1;
SCROLL_R_STR = "\033[%i%d;%dr";
CLS_STR = "\033[2J\033[H";
TT_REVV_STR = "\033[7m";
TT_NORM_STR = "\033[m";
TT_BOLD_STR = "\033[1m";
TT_ULIN_STR = "\033[4m";
DEL_EOL_STR = "\033[K";
REV_SCROLL_STR = "\033M";
CURS_F_STR = "\033[%dC";
CURS_POS_STR = "\033[%i%d;%dH";
if (!is_vt100)
{
DEL_N_LINES_STR = "\033[%dM";
INS_MODE_STR = "\033[4h";
EINS_MODE_STR = "\033[4l";
DEL_CHAR_STR = "\033[P";
ADD_N_LINES_STR = "\033[%dL";
}
else
{
DEL_N_LINES_STR = NULL;
INS_MODE_STR = NULL;
EINS_MODE_STR = NULL;
DEL_CHAR_STR = NULL;
ADD_N_LINES_STR = NULL;
}
get_term_dimensions(&SCREEN_WIDTH, &SCREEN_HEIGHT);
SCREEN_ROWS = SCREEN_HEIGHT - 1;
Term_Cannot_Insert = 0;
enable_cursor_keys();
}
#ifndef VMS
/* This routine may be problematic when there are more windows than
the new screen size can support. Until I think of what to do,
I have not touched this routine. */
#ifdef TIOCSTI
void resize_display()
{
char c;
get_term_dimensions(&SCREEN_WIDTH, &SCREEN_HEIGHT);
SCREEN_ROWS = SCREEN_HEIGHT - 1;
c = 'R'; /* force a redraw of screen */
ioctl(0,TIOCSTI,&c);
#ifdef TIOCSTI
(void) signal(SIGWINCH,resize_display);
#endif
}
#endif
#endif