Back to index

tetex-bin  3.0
Defines | Functions
lib_mvcur.c File Reference
#include <curses.priv.h>
#include <term.h>
#include <ctype.h>

Go to the source code of this file.

Defines

#define COMPUTE_OVERHEAD   1 /* I use a 90MHz Pentium @ 9.6Kbps */
#define LONG_DIST   (8 - COMPUTE_OVERHEAD)
#define NOT_LOCAL(fy, fx, ty, tx)
#define WANT_CHAR(y, x)   SP->_newscr->_line[y].text[x] /* desired state */
#define BAUDRATE   cur_term->_baudrate /* bits per second */
#define OPT_SIZE   512
#define CostOf(cap, affcnt)   _nc_msec_cost(cap,affcnt);
#define NormalizedCost(cap, affcnt)   normalized_cost(cap,affcnt);
#define NEXTTAB(fr)   (fr + init_tabs - (fr % init_tabs))
#define LASTTAB(fr)   ((fr > 0) ? ((fr - 1) / init_tabs) * init_tabs : -1)
#define NullResult   _nc_str_null(&result, sizeof(buffer))
#define InitResult   _nc_str_init(&result, buffer, sizeof(buffer))

Functions

static int normalized_cost (const char *const cap, int affcnt)
 _nc_msec_cost (const char *const cap, int affcnt)
static void reset_scroll_region (void)
 _nc_mvcur_resume (void)
 _nc_mvcur_init (void)
 _nc_mvcur_wrap (void)
static int repeated_append (string_desc *target, int total, int num, int repeat, const char *src)
static int relative_move (string_desc *target, int from_y, int from_x, int to_y, int to_x, bool ovw)
static int onscreen_mvcur (int yold, int xold, int ynew, int xnew, bool ovw)
 mvcur (int yold, int xold, int ynew, int xnew)

Define Documentation

#define BAUDRATE   cur_term->_baudrate /* bits per second */

Definition at line 160 of file lib_mvcur.c.

#define COMPUTE_OVERHEAD   1 /* I use a 90MHz Pentium @ 9.6Kbps */

Definition at line 94 of file lib_mvcur.c.

#define CostOf (   cap,
  affcnt 
)    _nc_msec_cost(cap,affcnt);

Definition at line 202 of file lib_mvcur.c.

#define InitResult   _nc_str_init(&result, buffer, sizeof(buffer))
#define LASTTAB (   fr)    ((fr > 0) ? ((fr - 1) / init_tabs) * init_tabs : -1)

Definition at line 477 of file lib_mvcur.c.

#define LONG_DIST   (8 - COMPUTE_OVERHEAD)

Definition at line 102 of file lib_mvcur.c.

#define NEXTTAB (   fr)    (fr + init_tabs - (fr % init_tabs))

Definition at line 471 of file lib_mvcur.c.

#define NormalizedCost (   cap,
  affcnt 
)    normalized_cost(cap,affcnt);

Definition at line 203 of file lib_mvcur.c.

#define NOT_LOCAL (   fy,
  fx,
  ty,
  tx 
)
Value:
((tx > LONG_DIST) \
               && (tx < screen_columns - 1 - LONG_DIST) \
               && (abs(ty-fy) + abs(tx-fx) > LONG_DIST))

Definition at line 111 of file lib_mvcur.c.

#define NullResult   _nc_str_null(&result, sizeof(buffer))
#define OPT_SIZE   512

Definition at line 169 of file lib_mvcur.c.

#define WANT_CHAR (   y,
  x 
)    SP->_newscr->_line[y].text[x] /* desired state */

Definition at line 159 of file lib_mvcur.c.


Function Documentation

_nc_msec_cost ( const char *const  cap,
int  affcnt 
)

Definition at line 208 of file lib_mvcur.c.

{
    if (cap == 0)
       return (INFINITY);
    else {
       const char *cp;
       float cum_cost = 0.0;

       for (cp = cap; *cp; cp++) {
           /* extract padding, either mandatory or required */
           if (cp[0] == '$' && cp[1] == '<' && strchr(cp, '>')) {
              float number = 0.0;

              for (cp += 2; *cp != '>'; cp++) {
                  if (isdigit(UChar(*cp)))
                     number = number * 10 + (*cp - '0');
                  else if (*cp == '*')
                     number *= affcnt;
                  else if (*cp == '.' && (*++cp != '>') && isdigit(UChar(*cp)))
                     number += (*cp - '0') / 10.0;
              }

#if NCURSES_NO_PADDING
              if (!(SP->_no_padding))
#endif
                  cum_cost += number * 10;
           } else
              cum_cost += SP->_char_padding;
       }

       return ((int) cum_cost);
    }
}

Here is the caller graph for this function:

Definition at line 294 of file lib_mvcur.c.

{
    if (isatty(fileno(SP->_ofp)))
       SP->_char_padding = ((BAUDBYTE * 1000 * 10)
                          / (BAUDRATE > 0 ? BAUDRATE : 9600));
    else
       SP->_char_padding = 1;      /* must be nonzero */
    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 = CostOf(carriage_return, 0);
    SP->_home_cost = CostOf(cursor_home, 0);
    SP->_ll_cost = CostOf(cursor_to_ll, 0);
#if USE_HARD_TABS
    SP->_ht_cost = CostOf(tab, 0);
    SP->_cbt_cost = CostOf(back_tab, 0);
#endif /* USE_HARD_TABS */
    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);

    SP->_smir_cost = CostOf(enter_insert_mode, 0);
    SP->_rmir_cost = CostOf(exit_insert_mode, 0);
    SP->_ip_cost = 0;
    if (insert_padding) {
       SP->_ip_cost = CostOf(insert_padding, 0);
    }

    /*
     * Assumption: if the terminal has memory_relative addressing, the
     * initialization strings or smcup will set single-page mode so we
     * can treat it like absolute screen addressing.  This seems to be true
     * for all cursor_mem_address terminal types in the terminfo database.
     */
    SP->_address_cursor = cursor_address ? cursor_address : cursor_mem_address;

    /*
     * Parametrized local-motion strings.  This static cost computation
     * depends on the following assumptions:
     *
     * (1) They never have * padding.  In the entire master terminfo database
     *     as of March 1995, only the obsolete Zenith Z-100 pc violates this.
     *     (Proportional padding is found mainly in insert, delete and scroll
     *     capabilities).
     *
     * (2) The average case of cup has two two-digit parameters.  Strictly,
     *     the average case for a 24 * 80 screen has ((10*10*(1 + 1)) +
     *     (14*10*(1 + 2)) + (10*70*(2 + 1)) + (14*70*4)) / (24*80) = 3.458
     *     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/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
     *     (strictly, (((10 * 1) + (14 * 2)) / 24) = 1.5833).
     *
     * All these averages depend on the assumption that all parameter values
     * are equally probable.
     */
    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);

    /*
     * If this is a bce-terminal, we want to bias the choice so we use clr_eol
     * rather than spaces at the end of a line.
     */
    if (back_color_erase)
       SP->_el_cost = 0;

    /* 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);
    SP->_cuf_ch_cost = NormalizedCost(tparm(parm_right_cursor, 23), 1);
    SP->_inline_cost = min(SP->_cup_ch_cost,
                        min(SP->_hpa_ch_cost,
                            SP->_cuf_ch_cost));

    /*
     * If save_cursor is used within enter_ca_mode, we should not use it for
     * scrolling optimization, since the corresponding restore_cursor is not
     * nested on the various terminals (vt100, xterm, etc.) which use this
     * feature.
     */
    if (save_cursor != 0
       && enter_ca_mode != 0
       && strstr(enter_ca_mode, save_cursor) != 0) {
       T(("...suppressed sc/rc capability due to conflict with smcup/rmcup"));
       save_cursor = 0;
       restore_cursor = 0;
    }

    /*
     * 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();
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 264 of file lib_mvcur.c.

{
    /* 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();
    SP->_cursrow = SP->_curscol = -1;

    /* restore cursor shape */
    if (SP->_cursor != -1) {
       int cursor = SP->_cursor;
       SP->_cursor = -1;
       curs_set(cursor);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 416 of file lib_mvcur.c.

{
    /* leave cursor at screen bottom */
    mvcur(-1, -1, screen_lines - 1, 0);

    /* set cursor to normal mode */
    if (SP->_cursor != -1)
       curs_set(1);

    if (exit_ca_mode) {
       TPUTS_TRACE("exit_ca_mode");
       putp(exit_ca_mode);
    }
    /*
     * Reset terminal's tab counter.  There's a long-time bug that
     * if you exit a "curses" program such as vi or more, tab
     * forward, and then backspace, the cursor doesn't go to the
     * right place.  The problem is that the kernel counts the
     * escape sequences that reset things as column positions.
     * Utter a \r to reset this invisibly.
     */
    _nc_outch('\r');
}

Here is the call graph for this function:

Here is the caller graph for this function:

mvcur ( int  yold,
int  xold,
int  ynew,
int  xnew 
)

Definition at line 847 of file lib_mvcur.c.

{
    attr_t oldattr;
    int code;

    TR(TRACE_CALLS | TRACE_MOVE, (T_CALLED("mvcur(%d,%d,%d,%d)"),
                              yold, xold, ynew, xnew));

    if (SP == 0) {
       code = ERR;
    } else if (yold == ynew && xold == xnew) {
       code = OK;
    } else {

       /*
        * Most work here is rounding for terminal boundaries getting the
        * column position implied by wraparound or the lack thereof and
        * rolling up the screen to get ynew on the screen.
        */
       if (xnew >= screen_columns) {
           ynew += xnew / screen_columns;
           xnew %= screen_columns;
       }

       /*
        * Force restore even if msgr is on when we're in an alternate
        * character set -- these have a strong tendency to screw up the CR &
        * LF used for local character motions!
        */
       oldattr = SP->_current_attr;
       if ((oldattr & A_ALTCHARSET)
           || (oldattr && !move_standout_mode)) {
           TR(TRACE_CHARPUT, ("turning off (%#lx) %s before move",
                            oldattr, _traceattr(oldattr)));
           (void) vidattr(A_NORMAL);
       }

       if (xold >= screen_columns) {
           int l;

           if (SP->_nl) {
              l = (xold + 1) / screen_columns;
              yold += l;
              if (yold >= screen_lines)
                  l -= (yold - screen_lines - 1);

              if (l > 0) {
                  if (carriage_return) {
                     TPUTS_TRACE("carriage_return");
                     putp(carriage_return);
                  } else
                     _nc_outch('\r');
                  xold = 0;

                  while (l > 0) {
                     if (newline) {
                         TPUTS_TRACE("newline");
                         putp(newline);
                     } else
                         _nc_outch('\n');
                     l--;
                  }
              }
           } else {
              /*
               * If caller set nonl(), we cannot really use newlines to
               * position to the next row.
               */
              xold = -1;
              yold = -1;
           }
       }

       if (yold > screen_lines - 1)
           yold = screen_lines - 1;
       if (ynew > screen_lines - 1)
           ynew = screen_lines - 1;

       /* destination location is on screen now */
       code = onscreen_mvcur(yold, xold, ynew, xnew, TRUE);

       /*
        * Restore attributes if we disabled them before moving.
        */
       if (oldattr != SP->_current_attr) {
           TR(TRACE_CHARPUT, ("turning on (%#lx) %s after move",
                            oldattr, _traceattr(oldattr)));
           (void) vidattr(oldattr);
       }
    }
    returnCode(code);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int normalized_cost ( const char *const  cap,
int  affcnt 
) [static]

Definition at line 244 of file lib_mvcur.c.

{
    int cost = _nc_msec_cost(cap, affcnt);
    if (cost != INFINITY)
       cost = (cost + SP->_char_padding - 1) / SP->_char_padding;
    return cost;
}

Here is the call graph for this function:

static int onscreen_mvcur ( int  yold,
int  xold,
int  ynew,
int  xnew,
bool  ovw 
) [inline, static]

Definition at line 698 of file lib_mvcur.c.

{
    string_desc result;
    char buffer[OPT_SIZE];
    int tactic = 0, newcost, usecost = INFINITY;
    int t5_cr_cost;

#if defined(MAIN) || defined(NCURSES_TEST)
    struct timeval before, after;

    gettimeofday(&before, NULL);
#endif /* MAIN */

#define NullResult _nc_str_null(&result, sizeof(buffer))
#define InitResult _nc_str_init(&result, buffer, sizeof(buffer))

    /* tactic #0: use direct cursor addressing */
    if (_nc_safe_strcpy(InitResult, tparm(SP->_address_cursor, ynew, xnew))) {
       tactic = 0;
       usecost = SP->_cup_cost;

#if defined(TRACE) || defined(NCURSES_TEST)
       if (!(_nc_optimize_enable & OPTIMIZE_MVCUR))
           goto nonlocal;
#endif /* TRACE */

       /*
        * We may be able to tell in advance that the full optimization
        * will probably not be worth its overhead.  Also, don't try to
        * use local movement if the current attribute is anything but
        * A_NORMAL...there are just too many ways this can screw up
        * (like, say, local-movement \n getting mapped to some obscure
        * character because A_ALTCHARSET is on).
        */
       if (yold == -1 || xold == -1 || NOT_LOCAL(yold, xold, ynew, xnew)) {
#if defined(MAIN) || defined(NCURSES_TEST)
           if (!profiling) {
              (void) fputs("nonlocal\n", stderr);
              goto nonlocal;       /* always run the optimizer if profiling */
           }
#else
           goto nonlocal;
#endif /* MAIN */
       }
    }
#ifndef NO_OPTIMIZE
    /* tactic #1: use local movement */
    if (yold != -1 && xold != -1
       && ((newcost = relative_move(NullResult, yold, xold, ynew, xnew,
                                 ovw)) != INFINITY)
       && newcost < usecost) {
       tactic = 1;
       usecost = newcost;
    }

    /* tactic #2: use carriage-return + local movement */
    if (yold != -1 && carriage_return
       && ((newcost = relative_move(NullResult, yold, 0, ynew, xnew, ovw))
           != INFINITY)
       && SP->_cr_cost + newcost < usecost) {
       tactic = 2;
       usecost = SP->_cr_cost + newcost;
    }

    /* tactic #3: use home-cursor + local movement */
    if (cursor_home
       && ((newcost = relative_move(NullResult, 0, 0, ynew, xnew, ovw)) != INFINITY)
       && SP->_home_cost + newcost < usecost) {
       tactic = 3;
       usecost = SP->_home_cost + newcost;
    }

    /* tactic #4: use home-down + local movement */
    if (cursor_to_ll
       && ((newcost = relative_move(NullResult, screen_lines - 1, 0, ynew,
                                 xnew, ovw)) != INFINITY)
       && SP->_ll_cost + newcost < usecost) {
       tactic = 4;
       usecost = SP->_ll_cost + newcost;
    }

    /*
     * tactic #5: use left margin for wrap to right-hand side,
     * unless strange wrap behavior indicated by xenl might hose us.
     */
    t5_cr_cost = (xold > 0 ? SP->_cr_cost : 0);
    if (auto_left_margin && !eat_newline_glitch
       && yold > 0 && cursor_left
       && ((newcost = relative_move(NullResult, yold - 1, screen_columns -
                                 1, ynew, xnew, ovw)) != INFINITY)
       && t5_cr_cost + SP->_cub1_cost + newcost < usecost) {
       tactic = 5;
       usecost = t5_cr_cost + SP->_cub1_cost + newcost;
    }

    /*
     * These cases are ordered by estimated relative frequency.
     */
    if (tactic)
       InitResult;
    switch (tactic) {
    case 1:
       (void) relative_move(&result, yold, xold, ynew, xnew, ovw);
       break;
    case 2:
       (void) _nc_safe_strcpy(&result, carriage_return);
       (void) relative_move(&result, yold, 0, ynew, xnew, ovw);
       break;
    case 3:
       (void) _nc_safe_strcpy(&result, cursor_home);
       (void) relative_move(&result, 0, 0, ynew, xnew, ovw);
       break;
    case 4:
       (void) _nc_safe_strcpy(&result, cursor_to_ll);
       (void) relative_move(&result, screen_lines - 1, 0, ynew, xnew, ovw);
       break;
    case 5:
       if (xold > 0)
           (void) _nc_safe_strcat(&result, carriage_return);
       (void) _nc_safe_strcat(&result, cursor_left);
       (void) relative_move(&result, yold - 1, screen_columns - 1, ynew,
                          xnew, ovw);
       break;
    }
#endif /* !NO_OPTIMIZE */

  nonlocal:
#if defined(MAIN) || defined(NCURSES_TEST)
    gettimeofday(&after, NULL);
    diff = after.tv_usec - before.tv_usec
       + (after.tv_sec - before.tv_sec) * 1000000;
    if (!profiling)
       (void) fprintf(stderr,
                     "onscreen: %d microsec, %f 28.8Kbps char-equivalents\n",
                     (int) diff, diff / 288);
#endif /* MAIN */

    if (usecost != INFINITY) {
       TPUTS_TRACE("mvcur");
       tputs(buffer, 1, _nc_outch);
       SP->_cursrow = ynew;
       SP->_curscol = xnew;
       return (OK);
    } else
       return (ERR);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int relative_move ( string_desc target,
int  from_y,
int  from_x,
int  to_y,
int  to_x,
bool  ovw 
) [static]

Definition at line 480 of file lib_mvcur.c.

{
    string_desc save;
    int n, vcost = 0, hcost = 0;

    (void) _nc_str_copy(&save, target);

    if (to_y != from_y) {
       vcost = INFINITY;

       if (row_address != 0
           && _nc_safe_strcat(target, tparm(row_address, to_y))) {
           vcost = SP->_vpa_cost;
       }

       if (to_y > from_y) {
           n = (to_y - from_y);

           if (parm_down_cursor
              && SP->_cud_cost < vcost
              && _nc_safe_strcat(_nc_str_copy(target, &save),
                               tparm(parm_down_cursor, n))) {
              vcost = SP->_cud_cost;
           }

           if (cursor_down
              && (*cursor_down != '\n' || SP->_nl)
              && (n * SP->_cud1_cost < vcost)) {
              vcost = repeated_append(_nc_str_copy(target, &save), 0,
                                   SP->_cud1_cost, n, cursor_down);
           }
       } else {             /* (to_y < from_y) */
           n = (from_y - to_y);

           if (parm_up_cursor
              && SP->_cuu_cost < vcost
              && _nc_safe_strcat(_nc_str_copy(target, &save),
                               tparm(parm_up_cursor, n))) {
              vcost = SP->_cuu_cost;
           }

           if (cursor_up && (n * SP->_cuu1_cost < vcost)) {
              vcost = repeated_append(_nc_str_copy(target, &save), 0,
                                   SP->_cuu1_cost, n, cursor_up);
           }
       }

       if (vcost == INFINITY)
           return (INFINITY);
    }

    save = *target;

    if (to_x != from_x) {
       char str[OPT_SIZE];
       string_desc check;

       hcost = INFINITY;

       if (column_address
           && _nc_safe_strcat(_nc_str_copy(target, &save),
                            tparm(column_address, to_x))) {
           hcost = SP->_hpa_cost;
       }

       if (to_x > from_x) {
           n = to_x - from_x;

           if (parm_right_cursor
              && SP->_cuf_cost < hcost
              && _nc_safe_strcat(_nc_str_copy(target, &save),
                               tparm(parm_right_cursor, n))) {
              hcost = SP->_cuf_cost;
           }

           if (cursor_right) {
              int lhcost = 0;

              (void) _nc_str_init(&check, str, sizeof(str));

#if USE_HARD_TABS
              /* use hard tabs, if we have them, to do as much as possible */
              if (init_tabs > 0 && tab) {
                  int nxt, fr;

                  for (fr = from_x; (nxt = NEXTTAB(fr)) <= to_x; fr = nxt) {
                     lhcost = repeated_append(&check, lhcost,
                                           SP->_ht_cost, 1, tab);
                     if (lhcost == INFINITY)
                         break;
                  }

                  n = to_x - fr;
                  from_x = fr;
              }
#endif /* USE_HARD_TABS */

              if (n <= 0 || n >= (int) check.s_size)
                  ovw = FALSE;
#if BSD_TPUTS
              /*
               * If we're allowing BSD-style padding in tputs, don't generate
               * a string with a leading digit.  Otherwise, that will be
               * interpreted as a padding value rather than sent to the
               * screen.
               */
              if (ovw
                  && n > 0
                  && n < (int) check.s_size
                  && vcost == 0
                  && str[0] == '\0') {
                  int wanted = CharOf(WANT_CHAR(to_y, from_x));
                  if (is8bits(wanted) && isdigit(wanted))
                     ovw = FALSE;
              }
#endif
              /*
               * 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
               * is true between the time a hardware scroll has been done
               * and the time the structure WANT_CHAR would access has been
               * updated.
               */
              if (ovw) {
                  int i;

                  for (i = 0; i < n; i++) {
                     NCURSES_CH_T ch = WANT_CHAR(to_y, from_x + i);
                     if (AttrOf(ch) != SP->_current_attr
#if USE_WIDEC_SUPPORT
                         || !Charable(ch)
#endif
                         ) {
                         ovw = FALSE;
                         break;
                     }
                  }
              }
              if (ovw) {
                  int i;

                  for (i = 0; i < n; i++)
                     *check.s_tail++ = CharOf(WANT_CHAR(to_y, from_x + i));
                  *check.s_tail = '\0';
                  check.s_size -= n;
                  lhcost += n * SP->_char_padding;
              } else {
                  lhcost = repeated_append(&check, lhcost, SP->_cuf1_cost,
                                        n, cursor_right);
              }

              if (lhcost < hcost
                  && _nc_safe_strcat(_nc_str_copy(target, &save), str)) {
                  hcost = lhcost;
              }
           }
       } else {             /* (to_x < from_x) */
           n = from_x - to_x;

           if (parm_left_cursor
              && SP->_cub_cost < hcost
              && _nc_safe_strcat(_nc_str_copy(target, &save),
                               tparm(parm_left_cursor, n))) {
              hcost = SP->_cub_cost;
           }

           if (cursor_left) {
              int lhcost = 0;

              (void) _nc_str_init(&check, str, sizeof(str));

#if USE_HARD_TABS
              if (init_tabs > 0 && back_tab) {
                  int nxt, fr;

                  for (fr = from_x; (nxt = LASTTAB(fr)) >= to_x; fr = nxt) {
                     lhcost = repeated_append(&check, lhcost,
                                           SP->_cbt_cost, 1, back_tab);
                     if (lhcost == INFINITY)
                         break;
                  }

                  n = fr - to_x;
              }
#endif /* USE_HARD_TABS */

              lhcost = repeated_append(&check, lhcost, SP->_cub1_cost, n, cursor_left);

              if (lhcost < hcost
                  && _nc_safe_strcat(_nc_str_copy(target, &save), str)) {
                  hcost = lhcost;
              }
           }
       }

       if (hcost == INFINITY)
           return (INFINITY);
    }

    return (vcost + hcost);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int repeated_append ( string_desc target,
int  total,
int  num,
int  repeat,
const char *  src 
) [inline, static]

Definition at line 451 of file lib_mvcur.c.

{
    size_t need = repeat * strlen(src);

    if (need < target->s_size) {
       while (repeat-- > 0) {
           if (_nc_safe_strcat(target, src)) {
              total += num;
           } else {
              total = INFINITY;
              break;
           }
       }
    } else {
       total = INFINITY;
    }
    return total;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void reset_scroll_region ( void  ) [static]

Definition at line 254 of file lib_mvcur.c.

{
    if (change_scroll_region) {
       TPUTS_TRACE("change_scroll_region");
       putp(tparm(change_scroll_region, 0, screen_lines - 1));
    }
}

Here is the call graph for this function:

Here is the caller graph for this function: