version 1.4, 2000/03/03 19:31:27 |
version 1.5, 2000/04/13 06:12:17 |
|
|
* this as a reasonable way to allow for widly varying and ever changing |
* this as a reasonable way to allow for widly varying and ever changing |
* varieties of terminal types. This should be used where practical. |
* varieties of terminal types. This should be used where practical. |
*/ |
*/ |
/* Known problems: |
/* |
* If you have a terminal with no clear to end of screen and |
* Known problems: If you have a terminal with no clear to end of screen and |
* memory of lines below the ones visible on the screen, display |
* memory of lines below the ones visible on the screen, display will be |
* will be wrong in some cases. I doubt that any such terminal |
* wrong in some cases. I doubt that any such terminal was ever made, but I |
* was ever made, but I thought everyone with delete line would |
* thought everyone with delete line would have clear to end of screen too... |
* have clear to end of screen too... |
|
* |
* |
* Code for terminals without clear to end of screen and/or clear |
* Code for terminals without clear to end of screen and/or clear to end of line |
* to end of line has not been extensivly tested. |
* has not been extensivly tested. |
* |
* |
* Cost calculations are very rough. Costs of insert/delete line |
* Cost calculations are very rough. Costs of insert/delete line may be far |
* may be far from the truth. This is accentuated by display.c |
* from the truth. This is accentuated by display.c not knowing about |
* not knowing about multi-line insert/delete. |
* multi-line insert/delete. |
* |
* |
* Using scrolling region vs insert/delete line should probably |
* Using scrolling region vs insert/delete line should probably be based on cost |
* be based on cost rather than the assuption that scrolling |
* rather than the assuption that scrolling region operations look better. |
* region operations look better. |
|
*/ |
*/ |
#include "def.h" |
#include "def.h" |
|
|
#include <curses.h> |
|
#include <term.h> |
#include <term.h> |
|
|
extern int ttrow; |
extern int ttrow; |
extern int ttcol; |
extern int ttcol; |
extern int tttop; |
extern int tttop; |
extern int ttbot; |
extern int ttbot; |
extern int tthue; |
extern int tthue; |
|
|
extern int ttputc(); |
extern int ttputc(); |
|
|
int tceeol; /* Costs are set later */ |
int tceeol; /* Costs are set later */ |
int tcinsl; |
int tcinsl; |
int tcdell; |
int tcdell; |
|
|
static int insdel; /* Do we have both insert & delete line? */ |
static int insdel; /* Do we have both insert & delete line? */ |
static char * scroll_fwd; /* How to scroll forward. */ |
static char *scroll_fwd; /* How to scroll forward. */ |
|
|
#ifdef NO_RESIZE |
#ifdef NO_RESIZE |
static setttysize(); |
static setttysize(); |
#endif |
#endif |
|
|
/* |
/* |
* Initialize the terminal when the editor |
* Initialize the terminal when the editor |
* gets started up. |
* gets started up. |
*/ |
*/ |
ttinit() { |
VOID |
char *tv_stype; |
ttinit() |
char *t, *p; |
{ |
|
char *tv_stype; |
|
char *t, *p; |
#ifndef gettermtype /* (avoid declaration if #define) */ |
#ifndef gettermtype /* (avoid declaration if #define) */ |
char *gettermtype(); /* system dependent function to determin terminal type */ |
char *gettermtype(); /* system dependent function to |
|
* determin terminal type */ |
#endif |
#endif |
|
|
if ((tv_stype = gettermtype()) == NULL) |
if ((tv_stype = gettermtype()) == NULL) |
panic("Could not determine terminal type"); |
panic("Could not determine terminal type"); |
if (setupterm(tv_stype, 1, NULL) == ERR) { |
if (setupterm(tv_stype, 1, NULL)) { |
(void) asprintf(&p, "Unknown terminal type: %s", tv_stype); |
(void) asprintf(&p, "Unknown terminal type: %s", tv_stype); |
panic(p); |
panic(p); |
} |
} |
|
|
scroll_fwd = scroll_forward; |
scroll_fwd = scroll_forward; |
if (!scroll_fwd || !*scroll_fwd) { |
if (!scroll_fwd || !*scroll_fwd) { |
/* this is what GNU Emacs does */ |
/* this is what GNU Emacs does */ |
|
|
if (!scroll_fwd || !*scroll_fwd) |
if (!scroll_fwd || !*scroll_fwd) |
scroll_fwd = "\n"; |
scroll_fwd = "\n"; |
} |
} |
|
|
if (!cursor_address || !cursor_up) |
if (!cursor_address || !cursor_up) |
panic("This terminal is to stupid to run mg"); |
panic("This terminal is to stupid to run mg"); |
ttresize(); /* set nrow & ncol */ |
ttresize(); /* set nrow & ncol */ |
|
|
if (!clr_eol) |
if (!clr_eol) |
tceeol = ncol; |
tceeol = ncol; |
|
|
|
|
/* Estimate cost of inserting a line */ |
/* Estimate cost of inserting a line */ |
if (change_scroll_region && scroll_reverse) |
if (change_scroll_region && scroll_reverse) |
tcinsl = charcost(change_scroll_region)*2 + |
tcinsl = charcost(change_scroll_region) * 2 + |
charcost(scroll_reverse); |
charcost(scroll_reverse); |
else if (parm_insert_line) |
else if (parm_insert_line) |
tcinsl = charcost(parm_insert_line); |
tcinsl = charcost(parm_insert_line); |
else if (insert_line) |
else if (insert_line) |
|
|
|
|
/* Estimate cost of deleting a line */ |
/* Estimate cost of deleting a line */ |
if (change_scroll_region) |
if (change_scroll_region) |
tcdell = charcost(change_scroll_region)*2 + |
tcdell = charcost(change_scroll_region) * 2 + |
charcost(scroll_fwd); |
charcost(scroll_fwd); |
else if (parm_delete_line) |
else if (parm_delete_line) |
tcdell = charcost(parm_delete_line); |
tcdell = charcost(parm_delete_line); |
else if (delete_line) |
else if (delete_line) |
tcdell = charcost(delete_line); |
tcdell = charcost(delete_line); |
else |
else |
tcdell = NROW * NCOL; /* make this cost high enough */ |
tcdell = NROW * NCOL; /* make this cost high enough */ |
|
|
/* Flag to indicate that we can both insert and delete lines */ |
/* Flag to indicate that we can both insert and delete lines */ |
insdel = (insert_line || parm_insert_line) && (delete_line || parm_delete_line); |
insdel = (insert_line || parm_insert_line) && (delete_line || parm_delete_line); |
|
|
if (enter_ca_mode) |
if (enter_ca_mode) |
putpad(enter_ca_mode, 1); /* init the term */ |
putpad(enter_ca_mode, 1); /* enter application mode */ |
|
|
setttysize(); |
setttysize(); |
} |
} |
|
|
* Re-initialize the terminal when the editor is resumed. |
* Re-initialize the terminal when the editor is resumed. |
* The keypad_xmit doesn't really belong here but... |
* The keypad_xmit doesn't really belong here but... |
*/ |
*/ |
ttreinit() { |
VOID |
|
ttreinit() |
|
{ |
if (enter_ca_mode) |
if (enter_ca_mode) |
putpad(enter_ca_mode, 1); /* enter application mode */ |
putpad(enter_ca_mode, 1); /* enter application mode */ |
if (keypad_xmit) |
if (keypad_xmit) |
|
|
* query the display for the increment, and put it |
* query the display for the increment, and put it |
* back to what it was. |
* back to what it was. |
*/ |
*/ |
tttidy() { |
VOID |
|
tttidy() |
|
{ |
|
|
/* set the term back to normal mode */ |
|
if (exit_ca_mode) |
|
putpad(exit_ca_mode, 1); |
|
#ifdef XKEYS |
#ifdef XKEYS |
ttykeymaptidy(); |
ttykeymaptidy(); |
#endif |
#endif |
|
/* set the term back to normal mode */ |
|
if (exit_ca_mode) |
|
putpad(exit_ca_mode, 1); |
} |
} |
|
|
/* |
/* |
|
|
* have left the cursor in the right |
* have left the cursor in the right |
* location last time! |
* location last time! |
*/ |
*/ |
ttmove(row, col) { |
VOID |
char *tgoto(); |
ttmove(row, col) |
|
{ |
|
char *tgoto(); |
|
|
if (ttrow != row || ttcol !=col) { |
if (ttrow != row || ttcol != col) { |
putpad(tgoto(cursor_address, col, row), 1); |
putpad(tgoto(cursor_address, col, row), 1); |
ttrow = row; |
ttrow = row; |
ttcol = col; |
ttcol = col; |
} |
} |
} |
} |
|
|
/* |
/* |
* Erase to end of line. |
* Erase to end of line. |
*/ |
*/ |
tteeol() { |
VOID |
|
tteeol() |
|
{ |
|
|
if (clr_eol) |
if (clr_eol) |
putpad(clr_eol, 1); |
putpad(clr_eol, 1); |
else { |
else { |
int i = ncol - ttcol; |
int i = ncol - ttcol; |
while (i--) |
while (i--) |
ttputc(' '); |
ttputc(' '); |
ttrow = ttcol = HUGE; |
ttrow = ttcol = HUGE; |
|
|
/* |
/* |
* Erase to end of page. |
* Erase to end of page. |
*/ |
*/ |
tteeop() { |
VOID |
int line; |
tteeop() |
|
{ |
|
int line; |
|
|
if (clr_eos) |
if (clr_eos) |
putpad(clr_eos, nrow - ttrow); |
putpad(clr_eos, nrow - ttrow); |
|
|
/* |
/* |
* Make a noise. |
* Make a noise. |
*/ |
*/ |
ttbeep() { |
VOID |
|
ttbeep() |
|
{ |
putpad(bell, 1); |
putpad(bell, 1); |
ttflush(); |
ttflush(); |
} |
} |
|
|
* If no scrolling region, use a set |
* If no scrolling region, use a set |
* of insert and delete line sequences |
* of insert and delete line sequences |
*/ |
*/ |
ttinsl(row, bot, nchunk) { |
VOID |
int i, nl; |
ttinsl(row, bot, nchunk) |
|
{ |
|
int i, nl; |
|
|
if (row == bot) { /* Case of one line insert is */ |
if (row == bot) { /* Case of one line insert is */ |
ttmove(row, 0); /* special */ |
ttmove(row, 0); /* special */ |
tteeol(); |
tteeol(); |
return; |
return; |
} |
} |
if (change_scroll_region && scroll_reverse) { |
if (change_scroll_region && scroll_reverse) { |
/* Use scroll region and back index */ |
/* Use scroll region and back index */ |
nl = bot - row; |
nl = bot - row; |
ttwindow(row,bot); |
ttwindow(row, bot); |
ttmove(row, 0); |
ttmove(row, 0); |
while (nchunk--) |
while (nchunk--) |
putpad(scroll_reverse, nl); |
putpad(scroll_reverse, nl); |
ttnowindow(); |
ttnowindow(); |
return; |
return; |
} else if (insdel) { |
} else if (insdel) { |
ttmove(1+bot-nchunk, 0); |
ttmove(1 + bot - nchunk, 0); |
nl = nrow - ttrow; |
nl = nrow - ttrow; |
if (parm_delete_line) |
if (parm_delete_line) |
putpad(tgoto(parm_delete_line, 0, nchunk), nl); |
putpad(tgoto(parm_delete_line, 0, nchunk), nl); |
else |
else |
/* For all lines in the chunk */ |
/* For all lines in the chunk */ |
for (i=0; i<nchunk; i++) |
for (i = 0; i < nchunk; i++) |
putpad(delete_line, nl); |
putpad(delete_line, nl); |
ttmove(row, 0); |
ttmove(row, 0); |
nl = nrow - ttrow; /* ttmove() changes ttrow */ |
nl = nrow - ttrow; /* ttmove() changes ttrow */ |
|
|
putpad(tgoto(parm_insert_line, 0, nchunk), nl); |
putpad(tgoto(parm_insert_line, 0, nchunk), nl); |
else |
else |
/* For all lines in the chunk */ |
/* For all lines in the chunk */ |
for (i=0; i<nchunk; i++) |
for (i = 0; i < nchunk; i++) |
putpad(insert_line, nl); |
putpad(insert_line, nl); |
ttrow = HUGE; |
ttrow = HUGE; |
ttcol = HUGE; |
ttcol = HUGE; |
|
|
* lines. The presence of the echo area makes a |
* lines. The presence of the echo area makes a |
* boundry condition go away. |
* boundry condition go away. |
*/ |
*/ |
|
VOID |
ttdell(row, bot, nchunk) |
ttdell(row, bot, nchunk) |
{ |
{ |
int i, nl; |
int i, nl; |
|
|
if (row == bot) { /* One line special case */ |
if (row == bot) { /* One line special case */ |
ttmove(row, 0); |
ttmove(row, 0); |
tteeol(); |
tteeol(); |
return; |
return; |
} |
} |
if (change_scroll_region) { /* scrolling region */ |
if (change_scroll_region) { /* scrolling region */ |
nl = bot - row; |
nl = bot - row; |
ttwindow(row, bot); |
ttwindow(row, bot); |
ttmove(bot, 0); |
ttmove(bot, 0); |
while (nchunk--) |
while (nchunk--) |
putpad(scroll_fwd, nl); |
putpad(scroll_fwd, nl); |
ttnowindow(); |
ttnowindow(); |
} |
} else if (insdel) { |
else if (insdel) { |
ttmove(row, 0); /* Else use insert/delete line */ |
ttmove(row, 0); /* Else use insert/delete line */ |
|
nl = nrow - ttrow; |
nl = nrow - ttrow; |
if (parm_delete_line) |
if (parm_delete_line) |
putpad(tgoto(parm_delete_line, 0, nchunk), nl); |
putpad(tgoto(parm_delete_line, 0, nchunk), nl); |
else |
else |
/* For all lines in the chunk */ |
/* For all lines in the chunk */ |
for (i=0; i<nchunk; i++) |
for (i = 0; i < nchunk; i++) |
putpad(delete_line, nl); |
putpad(delete_line, nl); |
ttmove(1+bot-nchunk,0); |
ttmove(1 + bot - nchunk, 0); |
nl = nrow - ttrow; /* ttmove() changes ttrow */ |
nl = nrow - ttrow; /* ttmove() changes ttrow */ |
if (parm_insert_line) |
if (parm_insert_line) |
putpad(tgoto(parm_insert_line, 0, nchunk), nl); |
putpad(tgoto(parm_insert_line, 0, nchunk), nl); |
else |
else |
/* For all lines in the chunk */ |
/* For all lines in the chunk */ |
for (i=0; i<nchunk; i++) |
for (i = 0; i < nchunk; i++) |
putpad(insert_line, nl); |
putpad(insert_line, nl); |
ttrow = HUGE; |
ttrow = HUGE; |
ttcol = HUGE; |
ttcol = HUGE; |
|
|
* moves the cursor). |
* moves the cursor). |
* |
* |
*/ |
*/ |
|
VOID |
ttwindow(top, bot) |
ttwindow(top, bot) |
{ |
{ |
if (change_scroll_region && (tttop != top || ttbot != bot)) { |
if (change_scroll_region && (tttop != top || ttbot != bot)) { |
putpad(tgoto(change_scroll_region, bot, top), nrow - ttrow); |
putpad(tgoto(change_scroll_region, bot, top), nrow - ttrow); |
ttrow = HUGE; /* Unknown. */ |
ttrow = HUGE; /* Unknown. */ |
ttcol = HUGE; |
ttcol = HUGE; |
tttop = top; /* Remember region. */ |
tttop = top; /* Remember region. */ |
ttbot = bot; |
ttbot = bot; |
} |
} |
} |
} |
|
|
* This behavior seems to work right on systems |
* This behavior seems to work right on systems |
* where you can set your terminal size. |
* where you can set your terminal size. |
*/ |
*/ |
|
VOID |
ttnowindow() |
ttnowindow() |
{ |
{ |
if (change_scroll_region) { |
if (change_scroll_region) { |
putpad(tgoto(change_scroll_region, |
putpad(tgoto(change_scroll_region, |
(nrow > lines ? nrow : lines) - 1, 0), nrow - ttrow); |
(nrow > lines ? nrow : lines) - 1, 0), nrow - ttrow); |
ttrow = HUGE; /* Unknown. */ |
ttrow = HUGE; /* Unknown. */ |
ttcol = HUGE; |
ttcol = HUGE; |
tttop = HUGE; /* No scroll region. */ |
tttop = HUGE; /* No scroll region. */ |
ttbot = HUGE; |
ttbot = HUGE; |
} |
} |
} |
} |
|
|
* line by line basis, so don't bother sending |
* line by line basis, so don't bother sending |
* out the color shift. |
* out the color shift. |
*/ |
*/ |
|
VOID |
ttcolor(color) |
ttcolor(color) |
int color; |
int color; |
{ |
{ |
|
|
if (color != tthue) { |
if (color != tthue) { |
if (color == CTEXT) /* Normal video. */ |
if (color == CTEXT) /* Normal video. */ |
putpad(exit_standout_mode, 1); |
putpad(exit_standout_mode, 1); |
else if (color == CMODE) /* Reverse video. */ |
else if (color == CMODE) /* Reverse video. */ |
putpad(enter_standout_mode, 1); |
putpad(enter_standout_mode, 1); |
tthue = color; /* Save the color. */ |
tthue = color; /* Save the color. */ |
} |
} |
} |
} |
|
|
|
|
* with a screen NROW by NCOL. Look in "window.c" to |
* with a screen NROW by NCOL. Look in "window.c" to |
* see how the caller deals with a change. |
* see how the caller deals with a change. |
*/ |
*/ |
ttresize() { |
VOID |
|
ttresize() |
|
{ |
|
|
setttysize(); /* found in "ttyio.c", */ |
setttysize(); /* found in "ttyio.c", */ |
/* ask OS for tty size */ |
/* ask OS for tty size */ |
if (nrow < 1) /* Check limits. */ |
if (nrow < 1) /* Check limits. */ |
nrow = 1; |
nrow = 1; |
else if (nrow > NROW) |
else if (nrow > NROW) |
nrow = NROW; |
nrow = NROW; |
|
|
} |
} |
|
|
#ifdef NO_RESIZE |
#ifdef NO_RESIZE |
static setttysize() { |
static |
|
setttysize() |
|
{ |
nrow = lines; |
nrow = lines; |
ncol = columns; |
ncol = columns; |
} |
} |
#endif |
#endif |
|
|
static int cci; |
static int cci; |
|
|
/*ARGSUSED*/ |
/* ARGSUSED */ |
static int /* fake char output for charcost() */ |
static int /* fake char output for charcost() */ |
fakec(c) |
fakec(c) |
char c; |
char c; |
{ |
{ |
cci++; |
cci++; |
} |
} |
|
|
/* calculate the cost of doing string s */ |
/* calculate the cost of doing string s */ |
charcost (s) char *s; { |
charcost(s) |
|
char *s; |
|
{ |
cci = 0; |
cci = 0; |
|
|
tputs(s, nrow, fakec); |
tputs(s, nrow, fakec); |