diff options
Diffstat (limited to 'lib/libcurses/lib_mvcur.c')
-rw-r--r-- | lib/libcurses/lib_mvcur.c | 563 |
1 files changed, 312 insertions, 251 deletions
diff --git a/lib/libcurses/lib_mvcur.c b/lib/libcurses/lib_mvcur.c index 2281faf238c..a03a17338c7 100644 --- a/lib/libcurses/lib_mvcur.c +++ b/lib/libcurses/lib_mvcur.c @@ -27,13 +27,15 @@ ** ** void _nc_mvcur_init(void), mvcur_wrap(void) ** +** void _nc_mvcur_resume(void) +** ** int mvcur(int old_y, int old_x, int new_y, int new_x) ** ** void _nc_mvcur_wrap(void) ** ** int _nc_mvcur_scrolln(int n, int top, int bot, int maxy) ** -** Comparisons with older movement optimizers: +** Comparisons with older movement optimizers: ** SVr3 curses mvcur() can't use cursor_to_ll or auto_left_margin. ** 4.4BSD curses can't use cuu/cud/cuf/cub/hpa/vpa/tab/cbt for local ** motions. It doesn't use tactics based on auto_left_margin. Weirdly @@ -54,7 +56,7 @@ ** cuf, cub, cuu1, cud1, cuf1, cub1. It may be that one or more are wrong. ** ** Note: you should expect this code to look like a resource hog in a profile. -** That's because it does a lot of I/O, through the tputs() calls. The I/O +** That's because it does a lot of I/O, through the tputs() calls. The I/O ** cost swamps the computation overhead (and as machines get faster, this ** will become even more true). Comments in the test exerciser at the end ** go into detail about tuning and how you can gauge the optimizer's @@ -128,6 +130,8 @@ * int _cuu_cost; // cost of (parm_cursor_up) * int _hpa_cost; // cost of (column_address) * int _vpa_cost; // cost of (row_address) + * int _ech_cost; // cost of (erase_chars) + * int _rep_cost; // cost of (repeat_char) * * The TABS_OK switch controls whether it is reliable to use tab/backtabs * for local motions. On many systems, it's not, due to uncertainties about @@ -135,11 +139,14 @@ * have parm_right_cursor, tab motions don't win you a lot anyhow. */ -#include "curses.priv.h" -#include "term.h" +#include <curses.priv.h> +#include <term.h> +#include <ctype.h> + +MODULE_ID("Id: lib_mvcur.c,v 1.37 1997/05/03 22:15:26 Peter.Wemm Exp $") + +#define STRLEN(s) (s != 0) ? strlen(s) : 0 -#define NLMAPPING SP->_nl /* nl() on? */ -#define RAWFLAG SP->_raw /* raw() on? */ #define CURRENT_ATTR SP->_current_attr /* current phys attribute */ #define CURRENT_ROW SP->_cursrow /* phys cursor row */ #define CURRENT_COLUMN SP->_curscol /* phys cursor column */ @@ -147,14 +154,6 @@ #define WANT_CHAR(y, x) SP->_newscr->_line[y].text[x] /* desired state */ #define BAUDRATE SP->_baudrate /* bits per second */ -#include <string.h> -#include <ctype.h> -#include <stdlib.h> - -#ifdef TRACE -bool no_optimize; /* suppress optimization */ -#endif /* TRACE */ - #ifdef MAIN #include <sys/time.h> @@ -164,13 +163,10 @@ static float diff; #define OPT_SIZE 512 -static char *address_cursor; -static int carriage_return_length; -static int cursor_home_length; -static int cursor_to_ll_length; - static void save_curs(void); static void restore_curs(void); +static int cost_of(const char *const cap, int affcnt); +static int normalized_cost(const char *const cap, int affcnt); /**************************************************************************** * @@ -178,17 +174,41 @@ static void restore_curs(void); * ****************************************************************************/ -#define INFINITY 1000000 /* too high to use */ +#ifdef TRACE +static int +trace_cost_of(const char *capname, const char *cap, int affcnt) +{ + int result = cost_of(cap,affcnt); + TR(TRACE_CHARPUT|TRACE_MOVE, ("CostOf %s %d", capname, result)); + return result; +} +#define CostOf(cap,affcnt) trace_cost_of(#cap,cap,affcnt); -static int cost(char *cap, int affcnt) +static int +trace_normalized_cost(const char *capname, const char *cap, int affcnt) +{ + int result = normalized_cost(cap,affcnt); + TR(TRACE_CHARPUT|TRACE_MOVE, ("NormalizedCost %s %d", capname, result)); + return result; +} +#define NormalizedCost(cap,affcnt) trace_normalized_cost(#cap,cap,affcnt); + +#else + +#define CostOf(cap,affcnt) cost_of(cap,affcnt); +#define NormalizedCost(cap,affcnt) normalized_cost(cap,affcnt); + +#endif + +static int cost_of(const char *const cap, int affcnt) /* compute the cost of a given operation */ { - if (cap == (char *)NULL) + if (cap == 0) return(INFINITY); else { - char *cp; - float cum_cost = 0; + const char *cp; + float cum_cost = 0; for (cp = cap; *cp; cp++) { @@ -217,29 +237,73 @@ static int cost(char *cap, int affcnt) } } -void _nc_mvcur_init(SCREEN *sp) +static int normalized_cost(const char *const cap, int affcnt) +/* compute the effective character-count for an operation (round up) */ +{ + int cost = cost_of(cap, affcnt); + if (cost != INFINITY) + cost = (cost + SP->_char_padding - 1) / SP->_char_padding; + return cost; +} + +static void reset_scroll_region(void) +/* Set the scroll-region to a known state (the default) */ +{ + if (change_scroll_region) + { + /* change_scroll_region may trash the cursor location */ + save_curs(); + TPUTS_TRACE("change_scroll_region"); + putp(tparm(change_scroll_region, 0, screen_lines - 1)); + restore_curs(); + } +} + +void _nc_mvcur_resume(void) +/* what to do at initialization time and after each shellout */ +{ + /* initialize screen for cursor access */ + if (enter_ca_mode) + { + TPUTS_TRACE("enter_ca_mode"); + putp(enter_ca_mode); + } + + /* + * Doing this here rather than in _nc_mvcur_wrap() ensures that + * ncurses programs will see a reset scroll region even if a + * program that messed with it died ungracefully. + * + * This also undoes the effects of terminal init strings that assume + * they know the screen size. This is useful when you're running + * a vt100 emulation through xterm. + */ + reset_scroll_region(); +} + +void _nc_mvcur_init(void) /* initialize the cost structure */ { /* * 9 = 7 bits + 1 parity + 1 stop. */ - if (BAUDRATE != 0) - SP->_char_padding = (9 * 1000 * 10) / BAUDRATE; - else - SP->_char_padding = 9 * 1000 * 10 / 9600; /* use some default if baudrate == 0 */ + SP->_char_padding = (9 * 1000 * 10) / (BAUDRATE > 0 ? BAUDRATE : 9600); + if (SP->_char_padding <= 0) + SP->_char_padding = 1; /* must be nonzero */ + TR(TRACE_CHARPUT|TRACE_MOVE, ("char_padding %d msecs", SP->_char_padding)); /* non-parameterized local-motion strings */ - SP->_cr_cost = cost(carriage_return, 0); - SP->_home_cost = cost(cursor_home, 0); - SP->_ll_cost = cost(cursor_to_ll, 0); + SP->_cr_cost = CostOf(carriage_return, 0); + SP->_home_cost = CostOf(cursor_home, 0); + SP->_ll_cost = CostOf(cursor_to_ll, 0); #ifdef TABS_OK - SP->_ht_cost = cost(tab, 0); - SP->_cbt_cost = cost(back_tab, 0); + SP->_ht_cost = CostOf(tab, 0); + SP->_cbt_cost = CostOf(back_tab, 0); #endif /* TABS_OK */ - SP->_cub1_cost = cost(cursor_left, 0); - SP->_cuf1_cost = cost(cursor_right, 0); - SP->_cud1_cost = cost(cursor_down, 0); - SP->_cuu1_cost = cost(cursor_up, 0); + SP->_cub1_cost = CostOf(cursor_left, 0); + SP->_cuf1_cost = CostOf(cursor_right, 0); + SP->_cud1_cost = CostOf(cursor_down, 0); + SP->_cuu1_cost = CostOf(cursor_up, 0); /* * Assumption: if the terminal has memory_relative addressing, the @@ -247,7 +311,7 @@ void _nc_mvcur_init(SCREEN *sp) * can treat it like absolute screen addressing. This seems to be true * for all cursor_mem_address terminal types in the terminfo database. */ - address_cursor = cursor_address ? cursor_address : cursor_mem_address; + SP->_address_cursor = cursor_address ? cursor_address : cursor_mem_address; /* * Parametrized local-motion strings. This static cost computation @@ -264,7 +328,7 @@ void _nc_mvcur_init(SCREEN *sp) * digits of parameters. On a 25x80 screen the average is 3.6197. * On larger screens the value gets much closer to 4. * - * (3) The average case of cub/cuf/hpa has 2 digits of parameters + * (3) The average case of cub/cuf/hpa/ech/rep has 2 digits of parameters * (strictly, (((10 * 1) + (70 * 2)) / 80) = 1.8750). * * (4) The average case of cud/cuu/vpa has 2 digits of parameters @@ -273,39 +337,47 @@ void _nc_mvcur_init(SCREEN *sp) * All these averages depend on the assumption that all parameter values * are equally probable. */ - SP->_cup_cost = cost(tparm(address_cursor, 23, 23), 1); - SP->_cub_cost = cost(tparm(parm_left_cursor, 23), 1); - SP->_cuf_cost = cost(tparm(parm_right_cursor, 23), 1); - SP->_cud_cost = cost(tparm(parm_down_cursor, 23), 1); - SP->_cuu_cost = cost(tparm(parm_up_cursor, 23), 1); - SP->_hpa_cost = cost(tparm(column_address, 23), 1); - SP->_vpa_cost = cost(tparm(row_address, 23), 1); - - /* initialize screen for cursor access */ - if (enter_ca_mode) - { - TPUTS_TRACE("enter_ca_mode"); - putp(enter_ca_mode); - } + SP->_cup_cost = CostOf(tparm(SP->_address_cursor, 23, 23), 1); + SP->_cub_cost = CostOf(tparm(parm_left_cursor, 23), 1); + SP->_cuf_cost = CostOf(tparm(parm_right_cursor, 23), 1); + SP->_cud_cost = CostOf(tparm(parm_down_cursor, 23), 1); + SP->_cuu_cost = CostOf(tparm(parm_up_cursor, 23), 1); + SP->_hpa_cost = CostOf(tparm(column_address, 23), 1); + SP->_vpa_cost = CostOf(tparm(row_address, 23), 1); + + /* non-parameterized screen-update strings */ + SP->_ed_cost = NormalizedCost(clr_eos, 1); + SP->_el_cost = NormalizedCost(clr_eol, 1); + SP->_el1_cost = NormalizedCost(clr_bol, 1); + SP->_dch1_cost = NormalizedCost(delete_character, 1); + SP->_ich1_cost = NormalizedCost(insert_character, 1); + + /* parameterized screen-update strings */ + SP->_dch_cost = NormalizedCost(tparm(parm_dch, 23), 1); + SP->_ich_cost = NormalizedCost(tparm(parm_ich, 23), 1); + SP->_ech_cost = NormalizedCost(tparm(erase_chars, 23), 1); + SP->_rep_cost = NormalizedCost(tparm(repeat_char, ' ', 23), 1); + + SP->_cup_ch_cost = NormalizedCost(tparm(SP->_address_cursor, 23, 23), 1); + SP->_hpa_ch_cost = NormalizedCost(tparm(column_address, 23), 1); /* pre-compute some capability lengths */ - carriage_return_length = carriage_return ? strlen(carriage_return) : 0; - cursor_home_length = cursor_home ? strlen(cursor_home) : 0; - cursor_to_ll_length = cursor_to_ll ? strlen(cursor_to_ll) : 0; + SP->_carriage_return_length = STRLEN(carriage_return); + SP->_cursor_home_length = STRLEN(cursor_home); + SP->_cursor_to_ll_length = STRLEN(cursor_to_ll); + + /* + * A different, possibly better way to arrange this would be to set + * SP->_endwin = TRUE at window initialization time and let this be + * called by doupdate's return-from-shellout code. + */ + _nc_mvcur_resume(); } void _nc_mvcur_wrap(void) /* wrap up cursor-addressing mode */ { - /* change_scroll_region may trash the cursor location */ - save_curs(); - if (change_scroll_region) - { - TPUTS_TRACE("change_scroll_region"); - putp(tparm(change_scroll_region, 0, screen_lines - 1)); - } - restore_curs(); - + reset_scroll_region(); if (exit_ca_mode) { TPUTS_TRACE("exit_ca_mode"); @@ -322,14 +394,12 @@ void _nc_mvcur_wrap(void) /* * Perform repeated-append, returning cost */ -static __inline int -repeated_append (int total, int num, int repeat, char *dst, char *src) +static inline int +repeated_append (int total, int num, int repeat, char *dst, const char *src) { register size_t src_len = strlen(src); - register size_t dst_len = 0; + register size_t dst_len = STRLEN(dst); - if (dst) - dst_len = strlen(dst); if ((dst_len + repeat * src_len) < OPT_SIZE-1) { total += (num * repeat); if (dst) { @@ -356,7 +426,6 @@ relative_move(char *result, int from_y,int from_x,int to_y,int to_x, bool ovw) /* move via local motions (cuu/cuu1/cud/cud1/cub1/cub/cuf1/cuf/vpa/hpa) */ { int n, vcost = 0, hcost = 0; - bool used_lf = FALSE; if (result) result[0] = '\0'; @@ -387,8 +456,6 @@ relative_move(char *result, int from_y,int from_x,int to_y,int to_x, bool ovw) { if (result) result[0] = '\0'; - if (cursor_down[0] == '\n') - used_lf = TRUE; vcost = repeated_append(vcost, SP->_cud1_cost, n, result, cursor_down); } } @@ -415,13 +482,6 @@ relative_move(char *result, int from_y,int from_x,int to_y,int to_x, bool ovw) return(INFINITY); } - /* - * It may be that we're using a cud1 capability of \n with the - * side-effect of taking the cursor to column 0. Deal with this. - */ - if (used_lf && NLMAPPING && !RAWFLAG) - from_x = 0; - if (result) result += strlen(result); @@ -473,11 +533,11 @@ relative_move(char *result, int from_y,int from_x,int to_y,int to_x, bool ovw) } #endif /* TABS_OK */ -#if defined(REAL_ATTR) && defined(WANT_CHAR) && 0 +#if defined(REAL_ATTR) && defined(WANT_CHAR) /* * If we have no attribute changes, overwrite is cheaper. * Note: must suppress this by passing in ovw = FALSE whenever - * WANT_CHAR would return invalid data. In particular, this + * WANT_CHAR would return invalid data. In particular, this * is true between the time a hardware scroll has been done * and the time the structure WANT_CHAR would access has been * updated. @@ -582,7 +642,7 @@ relative_move(char *result, int from_y,int from_x,int to_y,int to_x, bool ovw) * the simpler method below. */ -static __inline int +static inline int onscreen_mvcur(int yold,int xold,int ynew,int xnew, bool ovw) /* onscreen move from (yold, xold) to (ynew, xnew) */ { @@ -596,16 +656,16 @@ onscreen_mvcur(int yold,int xold,int ynew,int xnew, bool ovw) #endif /* MAIN */ /* tactic #0: use direct cursor addressing */ - sp = tparm(address_cursor, ynew, xnew); + sp = tparm(SP->_address_cursor, ynew, xnew); if (sp) { tactic = 0; (void) strcpy(use, sp); usecost = SP->_cup_cost; -#ifdef TRACE - if (no_optimize) - xold = yold = -1; +#if defined(TRACE) || defined(NCURSES_TEST) + if (!(_nc_optimize_enable & OPTIMIZE_MVCUR)) + goto nonlocal; #endif /* TRACE */ /* @@ -616,7 +676,7 @@ onscreen_mvcur(int yold,int xold,int ynew,int xnew, bool ovw) * (like, say, local-movement \n getting mapped to some obscure * character because A_ALTCHARSET is on). */ - if (yold == -1 || xold == -1 || + if (yold == -1 || xold == -1 || REAL_ATTR != A_NORMAL || NOT_LOCAL(yold, xold, ynew, xnew)) { #ifdef MAIN @@ -664,7 +724,7 @@ onscreen_mvcur(int yold,int xold,int ynew,int xnew, bool ovw) /* tactic #4: use home-down + local movement */ if (cursor_to_ll - && ((newcost=relative_move(NULL, screen_lines-1, 0, ynew, xnew, ovw)) != INFINITY) + && ((newcost=relative_move(NULL, screen_lines-1, 0, ynew, xnew, ovw)) != INFINITY) && SP->_ll_cost + newcost < usecost) { tactic = 4; @@ -694,19 +754,19 @@ onscreen_mvcur(int yold,int xold,int ynew,int xnew, bool ovw) else if (tactic == 2) { (void) strcpy(use, carriage_return); - (void) relative_move(use + carriage_return_length, + (void) relative_move(use + SP->_carriage_return_length, yold,0,ynew,xnew, ovw); } else if (tactic == 3) { (void) strcpy(use, cursor_home); - (void) relative_move(use + cursor_home_length, + (void) relative_move(use + SP->_cursor_home_length, 0, 0, ynew, xnew, ovw); } else if (tactic == 4) { (void) strcpy(use, cursor_to_ll); - (void) relative_move(use + cursor_to_ll_length, + (void) relative_move(use + SP->_cursor_to_ll_length, screen_lines-1, 0, ynew, xnew, ovw); } else /* if (tactic == 5) */ @@ -766,48 +826,42 @@ int mvcur(int yold, int xold, int ynew, int xnew) l = (xold + 1) / screen_columns; yold += l; - xold %= screen_columns; - if (!auto_right_margin) - { - while (l > 0) { + if (yold >= screen_lines) + l -= (yold - screen_lines - 1); + + while (l > 0) { if (newline) { - TPUTS_TRACE("newline"); - tputs(newline, 0, _nc_outch); + TPUTS_TRACE("newline"); + tputs(newline, 0, _nc_outch); } else - putchar('\n'); + putchar('\n'); l--; - } - xold = 0; - } - if (yold > screen_lines - 1) - { - ynew -= yold - (screen_lines - 1); - yold = screen_lines - 1; + if (xold > 0) + { + if (carriage_return) + { + TPUTS_TRACE("carriage_return"); + tputs(carriage_return, 0, _nc_outch); + } + else + putchar('\r'); + xold = 0; + } } } -#ifdef CURSES_OVERRUN /* not used, it takes us out of sync with curscr */ - /* - * The destination line is offscreen. Try to scroll the screen to - * bring it onscreen. Note: this is not a documented feature of the - * API. It's here for compatibility with archaic curses code, a - * feature no one seems to have actually used in a long time. - */ - if (ynew >= screen_lines) - { - if (mvcur_scrolln((ynew - (screen_lines - 1)), 0, screen_lines - 1, screen_lines - 1) == OK) - ynew = screen_lines - 1; - else - return(ERR); - } -#endif /* CURSES_OVERRUN */ + if (yold > screen_lines - 1) + yold = screen_lines - 1; + if (ynew > screen_lines - 1) + ynew = screen_lines - 1; /* destination location is on screen now */ return(onscreen_mvcur(yold, xold, ynew, xnew, TRUE)); } + /**************************************************************************** * * Cursor save_restore @@ -847,15 +901,11 @@ static void restore_curs(void) * ****************************************************************************/ -int _nc_mvcur_scrolln(int n, int top, int bot, int maxy) +static int DoTheScrolling(int n, int top, int bot, int maxy) /* scroll region from top to bot by n lines */ { int i; - TR(TRACE_MOVE, ("mvcur_scrolln(%d, %d, %d, %d)", n, top, bot, maxy)); - - save_curs(); - /* * This code was adapted from Keith Bostic's hardware scrolling * support for 4.4BSD curses. I (esr) translated it to use terminfo @@ -874,32 +924,22 @@ int _nc_mvcur_scrolln(int n, int top, int bot, int maxy) * BSD curses. BSD curses preferred pairs of il/dl operations * over scrolls, allegedly because il/dl looked faster. We, on * the other hand, prefer scrolls because (a) they're just as fast - * on modern terminals and (b) using them avoids bouncing an + * on many terminals and (b) using them avoids bouncing an * unchanged bottom section of the screen up and down, which is * visually nasty. */ if (n > 0) { /* - * Do explicit clear to end of region if it's possible that the - * terminal might hold on to stuff we push off the end. + * Explicitly clear if stuff pushed off top of region might + * be saved by the terminal. */ - if (non_dest_scroll_region || (memory_below && bot == maxy)) - { - if (bot == maxy && clr_eos) - { - mvcur(-1, -1, lines - n, 0); - TPUTS_TRACE("clr_eos"); - tputs(clr_eos, n, _nc_outch); - } - else if (clr_eol) + if (non_dest_scroll_region || (memory_above && top == 0)) { + for (i = 0; i < n; i++) { - for (i = 0; i < n; i++) - { - mvcur(-1, -1, lines - n + i, 0); - TPUTS_TRACE("clr_eol"); - tputs(clr_eol, n, _nc_outch); - } + mvcur(-1, -1, i, 0); + TPUTS_TRACE("clr_eol"); + tputs(clr_eol, n, _nc_outch); } } @@ -907,47 +947,32 @@ int _nc_mvcur_scrolln(int n, int top, int bot, int maxy) { TPUTS_TRACE("change_scroll_region"); tputs(tparm(change_scroll_region, top, bot), 0, _nc_outch); + onscreen_mvcur(-1, -1, bot, 0, TRUE); + if (parm_index != NULL) { TPUTS_TRACE("parm_index"); tputs(tparm(parm_index, n, 0), n, _nc_outch); } else + { for (i = 0; i < n; i++) { TPUTS_TRACE("scroll_forward"); tputs(scroll_forward, 0, _nc_outch); } + } TPUTS_TRACE("change_scroll_region"); tputs(tparm(change_scroll_region, 0, maxy), 0, _nc_outch); - restore_curs(); - return(OK); } - - /* Scroll up the block. */ - if (parm_index && top == 0) + else if (parm_index && top == 0 && bot == maxy) { onscreen_mvcur(oy, ox, bot, 0, TRUE); TPUTS_TRACE("parm_index"); tputs(tparm(parm_index, n, 0), n, _nc_outch); } - else if (parm_delete_line) - { - onscreen_mvcur(oy, ox, top, 0, TRUE); - TPUTS_TRACE("parm_delete_line"); - tputs(tparm(parm_delete_line, n, 0), n, _nc_outch); - } - else if (delete_line) - { - onscreen_mvcur(oy, ox, top, 0, TRUE); - for (i = 0; i < n; i++) - { - TPUTS_TRACE("parm_index"); - tputs(delete_line, 0, _nc_outch); - } - } - else if (scroll_forward && top == 0) + else if (scroll_forward && top == 0 && bot == maxy) { onscreen_mvcur(oy, ox, bot, 0, TRUE); for (i = 0; i < n; i++) @@ -956,116 +981,167 @@ int _nc_mvcur_scrolln(int n, int top, int bot, int maxy) tputs(scroll_forward, 0, _nc_outch); } } - else - return(ERR); - - /* Push down the bottom region. */ - if (parm_insert_line) - { - onscreen_mvcur(top, 0, bot - n + 1, 0, FALSE); - TPUTS_TRACE("parm_insert_line"); - tputs(tparm(parm_insert_line, n, 0), n, _nc_outch); - } - else if (insert_line) + else if (_nc_idlok + && (parm_delete_line || delete_line) + && (parm_insert_line || insert_line)) { + onscreen_mvcur(oy, ox, top, 0, TRUE); + + if (parm_delete_line) + { + TPUTS_TRACE("parm_delete_line"); + tputs(tparm(parm_delete_line, n, 0), n, _nc_outch); + } + else + { + for (i = 0; i < n; i++) + { + TPUTS_TRACE("parm_index"); + tputs(delete_line, 0, _nc_outch); + } + } + onscreen_mvcur(top, 0, bot - n + 1, 0, FALSE); - for (i = 0; i < n; i++) + + /* Push down the bottom region. */ + if (parm_insert_line) { - TPUTS_TRACE("insert_line"); - tputs(insert_line, 0, _nc_outch); + TPUTS_TRACE("parm_insert_line"); + tputs(tparm(parm_insert_line, n, 0), n, _nc_outch); + } + else + { + for (i = 0; i < n; i++) + { + TPUTS_TRACE("insert_line"); + tputs(insert_line, 0, _nc_outch); + } } } else return(ERR); - restore_curs(); } else /* (n < 0) */ { /* - * Explicitly clear if stuff pushed off top of region might - * be saved by the terminal. + * Do explicit clear to end of region if it's possible that the + * terminal might hold on to stuff we push off the end. */ - if (non_dest_scroll_region || (memory_above && top == 0)) - for (i = 0; i < n; i++) + if (non_dest_scroll_region || (memory_below && bot == maxy)) + { + if (bot == maxy && clr_eos) { - mvcur(-1, -1, i, 0); - TPUTS_TRACE("clr_eol"); - tputs(clr_eol, n, _nc_outch); + mvcur(-1, -1, lines + n, 0); + TPUTS_TRACE("clr_eos"); + tputs(clr_eos, n, _nc_outch); + } + else if (clr_eol) + { + for (i = 0; i < -n; i++) + { + mvcur(-1, -1, lines + n + i, 0); + TPUTS_TRACE("clr_eol"); + tputs(clr_eol, n, _nc_outch); + } } + } if (change_scroll_region && (scroll_reverse || parm_rindex)) { TPUTS_TRACE("change_scroll_region"); tputs(tparm(change_scroll_region, top, bot), 0, _nc_outch); + onscreen_mvcur(-1, -1, top, 0, TRUE); + if (parm_rindex) { TPUTS_TRACE("parm_rindex"); tputs(tparm(parm_rindex, -n, 0), -n, _nc_outch); } else + { for (i = n; i < 0; i++) { TPUTS_TRACE("scroll_reverse"); tputs(scroll_reverse, 0, _nc_outch); } + } TPUTS_TRACE("change_scroll_region"); tputs(tparm(change_scroll_region, 0, maxy), 0, _nc_outch); - restore_curs(); - return(OK); } - - /* Preserve the bottom lines. */ - onscreen_mvcur(oy, ox, bot + n + 1, 0, TRUE); - if (parm_rindex && bot == maxy) + else if (parm_rindex && top == 0 && bot == maxy) { + onscreen_mvcur(oy, ox, bot + n + 1, 0, TRUE); + TPUTS_TRACE("parm_rindex"); tputs(tparm(parm_rindex, -n, 0), -n, _nc_outch); } - else if (parm_delete_line) + else if (scroll_reverse && top == 0 && bot == maxy) { - TPUTS_TRACE("parm_delete_line"); - tputs(tparm(parm_delete_line, -n, 0), -n, _nc_outch); - } - else if (delete_line) - for (i = n; i < 0; i++) - { - TPUTS_TRACE("delete_line"); - tputs(delete_line, 0, _nc_outch); - } - else if (scroll_reverse && bot == maxy) + onscreen_mvcur(-1, -1, 0, 0, TRUE); for (i = n; i < 0; i++) { TPUTS_TRACE("scroll_reverse"); tputs(scroll_reverse, 0, _nc_outch); } - else - return(ERR); - - /* Scroll the block down. */ - if (parm_insert_line) - { - onscreen_mvcur(bot + n + 1, 0, top, 0, FALSE); - TPUTS_TRACE("parm_insert_line"); - tputs(tparm(parm_insert_line, -n, 0), -n, _nc_outch); } - else if (insert_line) + else if (_nc_idlok + && (parm_delete_line || delete_line) + && (parm_insert_line || insert_line)) { + onscreen_mvcur(oy, ox, bot + n + 1, 0, TRUE); + + if (parm_delete_line) + { + TPUTS_TRACE("parm_delete_line"); + tputs(tparm(parm_delete_line, -n, 0), -n, _nc_outch); + } + else + { + for (i = n; i < 0; i++) + { + TPUTS_TRACE("delete_line"); + tputs(delete_line, 0, _nc_outch); + } + } + onscreen_mvcur(bot + n + 1, 0, top, 0, FALSE); - for (i = n; i < 0; i++) + + /* Scroll the block down. */ + if (parm_insert_line) { - TPUTS_TRACE("insert_line"); - tputs(insert_line, 0, _nc_outch); + TPUTS_TRACE("parm_insert_line"); + tputs(tparm(parm_insert_line, -n, 0), -n, _nc_outch); + } + else + { + for (i = n; i < 0; i++) + { + TPUTS_TRACE("insert_line"); + tputs(insert_line, 0, _nc_outch); + } } } else return(ERR); - restore_curs(); } return(OK); } +int _nc_mvcur_scrolln(int n, int top, int bot, int maxy) +/* scroll region from top to bot by n lines */ +{ + int code; + + TR(TRACE_MOVE, ("mvcur_scrolln(%d, %d, %d, %d)", n, top, bot, maxy)); + + save_curs(); + code = DoTheScrolling(n, top, bot, maxy); + restore_curs(); + return(code); +} + #ifdef MAIN /**************************************************************************** * @@ -1073,13 +1149,8 @@ int _nc_mvcur_scrolln(int n, int top, int bot, int maxy) * ****************************************************************************/ -#if HAVE_UNISTD_H -#include <unistd.h> -#endif -#include <string.h> -#include <stdlib.h> -#include "tic.h" -#include "dump_entry.h" +#include <tic.h> +#include <dump_entry.h> char *_nc_progname = "mvcur"; @@ -1125,12 +1196,13 @@ static int roll(int n) int main(int argc, char *argv[]) { - (void) strncpy(tname, getenv("TERM"), sizeof tname-1); + (void) strncpy(tname, getenv("TERM"), sizeof(tname) - 1); + tname[sizeof(tname) - 1] = '\0'; load_term(); - _nc_setupscreen(lines, columns); + _nc_setupscreen(lines, columns, stdout); baudrate(); - _nc_mvcur_init(SP); + _nc_mvcur_init(); #if HAVE_SETVBUF || HAVE_SETBUFFER /* * Undo the effects of our optimization hack, otherwise our interactive @@ -1164,8 +1236,6 @@ int main(int argc, char *argv[]) (void) printf("r[eload] -- reload terminal info for %s\n", getenv("TERM")); (void) puts("l[oad] <term> -- load terminal info for type <term>"); -(void) puts("nl -- assume NL -> CR/LF when computing (default)"); -(void) puts("nonl -- don't assume NL -> CR/LF when computing"); (void) puts("d[elete] <cap> -- delete named capability"); (void) puts("i[nspect] -- display terminal capabilities"); (void) puts("c[ost] -- dump cursor-optimization cost table"); @@ -1201,23 +1271,14 @@ int main(int argc, char *argv[]) } else if (buf[0] == 'r') { - (void) strncpy(tname, getenv("TERM"), sizeof tname-1); + (void) strncpy(tname, getenv("TERM"), sizeof(tname) - 1); + tname[sizeof(tname) - 1] = '\0'; load_term(); } else if (sscanf(buf, "l %s", tname) == 1) { load_term(); } - else if (strncmp(buf, "nl", 2) == 0) - { - NLMAPPING = TRUE; - (void) puts("NL -> CR/LF will be assumed."); - } - else if (strncmp(buf, "nonl", 4) == 0) - { - NLMAPPING = FALSE; - (void) puts("NL -> CR/LF will not be assumed."); - } else if (sscanf(buf, "d %s", capname) == 1) { struct name_table_entry const *np = _nc_find_entry(capname, @@ -1257,18 +1318,18 @@ int main(int argc, char *argv[]) } else if (buf[0] == 'o') { - if (no_optimize) + if (_nc_optime_enable & OPTIMIZE_MVCUR) { - no_optimize = FALSE; - (void) puts("Optimization is now on."); + _nc_optimize_enable &=~ OPTIMIZE_MVCUR; + (void) puts("Optimization is now off."); } else { - no_optimize = TRUE; - (void) puts("Optimization is now off."); + _nc_optimize_enable |= OPTIMIZE_MVCUR; + (void) puts("Optimization is now on."); } } - /* + /* * You can use the `t' test to profile and tune the movement * optimizer. Use iteration values in three digits or more. * At above 5000 iterations the profile timing averages are stable @@ -1297,7 +1358,7 @@ int main(int argc, char *argv[]) xmits = 0; for (i = 0; i < n; i++) { - /* + /* * This does a move test between two random locations, * Random moves probably short-change the optimizer, * which will work better on the short moves probably @@ -1326,13 +1387,13 @@ int main(int argc, char *argv[]) */ perchar = cumtime / n; - (void) printf("%d moves (%ld chars) in %d msec, %f msec each:\n", + (void) printf("%d moves (%ld chars) in %d msec, %f msec each:\n", n, xmits, (int)cumtime, perchar); for (i = 0; speeds[i]; i++) { /* - * Total estimated time for the moves, computation and + * Total estimated time for the moves, computation and * transmission both. Transmission time is an estimate * assuming 9 bits/char, 8 bits + 1 stop bit. */ |