Annotation of embedaddon/readline/display.c, revision 1.1.1.1.2.1

1.1       misho       1: /* display.c -- readline redisplay facility. */
                      2: 
                      3: /* Copyright (C) 1987-2013 Free Software Foundation, Inc.
                      4: 
                      5:    This file is part of the GNU Readline Library (Readline), a library    
                      6:    for reading lines of text with interactive input and history editing.
                      7: 
                      8:    Readline is free software: you can redistribute it and/or modify
                      9:    it under the terms of the GNU General Public License as published by
                     10:    the Free Software Foundation, either version 3 of the License, or
                     11:    (at your option) any later version.
                     12: 
                     13:    Readline is distributed in the hope that it will be useful,
                     14:    but WITHOUT ANY WARRANTY; without even the implied warranty of
                     15:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     16:    GNU General Public License for more details.
                     17: 
                     18:    You should have received a copy of the GNU General Public License
                     19:    along with Readline.  If not, see <http://www.gnu.org/licenses/>.
                     20: */
                     21: 
                     22: #define READLINE_LIBRARY
                     23: 
                     24: #if defined (HAVE_CONFIG_H)
                     25: #  include <config.h>
                     26: #endif
                     27: 
                     28: #include <sys/types.h>
                     29: 
                     30: #if defined (HAVE_UNISTD_H)
                     31: #  include <unistd.h>
                     32: #endif /* HAVE_UNISTD_H */
                     33: 
                     34: #include "posixstat.h"
                     35: 
                     36: #if defined (HAVE_STDLIB_H)
                     37: #  include <stdlib.h>
                     38: #else
                     39: #  include "ansi_stdlib.h"
                     40: #endif /* HAVE_STDLIB_H */
                     41: 
                     42: #include <stdio.h>
                     43: 
                     44: #ifdef __MSDOS__
                     45: #  include <pc.h>
                     46: #endif
                     47: 
                     48: /* System-specific feature definitions and include files. */
                     49: #include "rldefs.h"
                     50: #include "rlmbutil.h"
                     51: 
                     52: /* Termcap library stuff. */
                     53: #include "tcap.h"
                     54: 
                     55: /* Some standard library routines. */
                     56: #include "readline.h"
                     57: #include "history.h"
                     58: 
                     59: #include "rlprivate.h"
                     60: #include "xmalloc.h"
                     61: 
                     62: #if !defined (strchr) && !defined (__STDC__)
                     63: extern char *strchr (), *strrchr ();
                     64: #endif /* !strchr && !__STDC__ */
                     65: 
                     66: static void update_line PARAMS((char *, char *, int, int, int, int));
                     67: static void space_to_eol PARAMS((int));
                     68: static void delete_chars PARAMS((int));
                     69: static void insert_some_chars PARAMS((char *, int, int));
                     70: static void open_some_spaces PARAMS((int));
                     71: static void cr PARAMS((void));
                     72: 
                     73: /* State of visible and invisible lines. */
                     74: struct line_state
                     75:   {
                     76:     char *line;
                     77:     int *lbreaks;
                     78:     int lbsize;
                     79: #if defined (HANDLE_MULTIBYTE)
                     80:     int *wrapped_line;
                     81:     int wbsize;
                     82: #endif
                     83:   };
                     84: 
                     85: /* The line display buffers.  One is the line currently displayed on
                     86:    the screen.  The other is the line about to be displayed. */
                     87: static struct line_state line_state_array[2];
                     88: static struct line_state *line_state_visible = &line_state_array[0];
                     89: static struct line_state *line_state_invisible = &line_state_array[1];
                     90: static int line_structures_initialized = 0;
                     91: 
                     92: /* Backwards-compatible names. */
                     93: #define inv_lbreaks    (line_state_invisible->lbreaks)
                     94: #define inv_lbsize     (line_state_invisible->lbsize)
                     95: #define vis_lbreaks    (line_state_visible->lbreaks)
                     96: #define vis_lbsize     (line_state_visible->lbsize)
                     97: 
                     98: #define visible_line   (line_state_visible->line)
                     99: #define invisible_line (line_state_invisible->line)
                    100: 
                    101: #if defined (HANDLE_MULTIBYTE)
                    102: static int _rl_col_width PARAMS((const char *, int, int, int));
                    103: #else
                    104: #  define _rl_col_width(l, s, e, f)    (((e) <= (s)) ? 0 : (e) - (s))
                    105: #endif
                    106: 
                    107: /* Heuristic used to decide whether it is faster to move from CUR to NEW
                    108:    by backing up or outputting a carriage return and moving forward.  CUR
                    109:    and NEW are either both buffer positions or absolute screen positions. */
                    110: #define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new)))
                    111: 
                    112: /* _rl_last_c_pos is an absolute cursor position in multibyte locales and a
                    113:    buffer index in others.  This macro is used when deciding whether the
                    114:    current cursor position is in the middle of a prompt string containing
                    115:    invisible characters.  XXX - might need to take `modmark' into account. */
                    116: #define PROMPT_ENDING_INDEX \
                    117:   ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) ? prompt_physical_chars : prompt_last_invisible+1)
                    118:   
                    119: 
                    120: /* **************************************************************** */
                    121: /*                                                                 */
                    122: /*                     Display stuff                               */
                    123: /*                                                                 */
                    124: /* **************************************************************** */
                    125: 
                    126: /* This is the stuff that is hard for me.  I never seem to write good
                    127:    display routines in C.  Let's see how I do this time. */
                    128: 
                    129: /* (PWP) Well... Good for a simple line updater, but totally ignores
                    130:    the problems of input lines longer than the screen width.
                    131: 
                    132:    update_line and the code that calls it makes a multiple line,
                    133:    automatically wrapping line update.  Careful attention needs
                    134:    to be paid to the vertical position variables. */
                    135: 
                    136: /* Keep two buffers; one which reflects the current contents of the
                    137:    screen, and the other to draw what we think the new contents should
                    138:    be.  Then compare the buffers, and make whatever changes to the
                    139:    screen itself that we should.  Finally, make the buffer that we
                    140:    just drew into be the one which reflects the current contents of the
                    141:    screen, and place the cursor where it belongs.
                    142: 
                    143:    Commands that want to can fix the display themselves, and then let
                    144:    this function know that the display has been fixed by setting the
                    145:    RL_DISPLAY_FIXED variable.  This is good for efficiency. */
                    146: 
                    147: /* Application-specific redisplay function. */
                    148: rl_voidfunc_t *rl_redisplay_function = rl_redisplay;
                    149: 
                    150: /* Global variables declared here. */
                    151: /* What YOU turn on when you have handled all redisplay yourself. */
                    152: int rl_display_fixed = 0;
                    153: 
                    154: int _rl_suppress_redisplay = 0;
                    155: int _rl_want_redisplay = 0;
                    156: 
                    157: /* The stuff that gets printed out before the actual text of the line.
                    158:    This is usually pointing to rl_prompt. */
                    159: char *rl_display_prompt = (char *)NULL;
                    160: 
                    161: /* Pseudo-global variables declared here. */
                    162: 
                    163: /* The visible cursor position.  If you print some text, adjust this. */
                    164: /* NOTE: _rl_last_c_pos is used as a buffer index when not in a locale
                    165:    supporting multibyte characters, and an absolute cursor position when
                    166:    in such a locale.  This is an artifact of the donated multibyte support.
                    167:    Care must be taken when modifying its value. */
                    168: int _rl_last_c_pos = 0;
                    169: int _rl_last_v_pos = 0;
                    170: 
                    171: static int cpos_adjusted;
                    172: static int cpos_buffer_position;
                    173: static int displaying_prompt_first_line;
                    174: static int prompt_multibyte_chars;
                    175: 
                    176: /* Number of lines currently on screen minus 1. */
                    177: int _rl_vis_botlin = 0;
                    178: 
                    179: /* Variables used only in this file. */
                    180: /* The last left edge of text that was displayed.  This is used when
                    181:    doing horizontal scrolling.  It shifts in thirds of a screenwidth. */
                    182: static int last_lmargin;
                    183: 
                    184: /* A buffer for `modeline' messages. */
                    185: static char *msg_buf = 0;
                    186: static int msg_bufsiz = 0;
                    187: 
                    188: /* Non-zero forces the redisplay even if we thought it was unnecessary. */
                    189: static int forced_display;
                    190: 
                    191: /* Default and initial buffer size.  Can grow. */
                    192: static int line_size = 1024;
                    193: 
                    194: /* Variables to keep track of the expanded prompt string, which may
                    195:    include invisible characters. */
                    196: 
                    197: static char *local_prompt, *local_prompt_prefix;
                    198: static int local_prompt_len;
                    199: static int prompt_visible_length, prompt_prefix_length;
                    200: 
                    201: /* The number of invisible characters in the line currently being
                    202:    displayed on the screen. */
                    203: static int visible_wrap_offset;
                    204: 
                    205: /* The number of invisible characters in the prompt string.  Static so it
                    206:    can be shared between rl_redisplay and update_line */
                    207: static int wrap_offset;
                    208: 
                    209: /* The index of the last invisible character in the prompt string. */
                    210: static int prompt_last_invisible;
                    211: 
                    212: /* The length (buffer offset) of the first line of the last (possibly
                    213:    multi-line) buffer displayed on the screen. */
                    214: static int visible_first_line_len;
                    215: 
                    216: /* Number of invisible characters on the first physical line of the prompt.
                    217:    Only valid when the number of physical characters in the prompt exceeds
                    218:    (or is equal to) _rl_screenwidth. */
                    219: static int prompt_invis_chars_first_line;
                    220: 
                    221: static int prompt_last_screen_line;
                    222: 
                    223: static int prompt_physical_chars;
                    224: 
                    225: /* set to a non-zero value by rl_redisplay if we are marking modified history
                    226:    lines and the current line is so marked. */
                    227: static int modmark;
                    228: 
                    229: /* Variables to save and restore prompt and display information. */
                    230: 
                    231: /* These are getting numerous enough that it's time to create a struct. */
                    232: 
                    233: static char *saved_local_prompt;
                    234: static char *saved_local_prefix;
                    235: static int saved_last_invisible;
                    236: static int saved_visible_length;
                    237: static int saved_prefix_length;
                    238: static int saved_local_length;
                    239: static int saved_invis_chars_first_line;
                    240: static int saved_physical_chars;
                    241: 
                    242: /* Return a character indicating the editing mode, for use in the prompt. */
                    243: static int
                    244: prompt_modechar ()
                    245: {
                    246:   if (rl_editing_mode == emacs_mode)
                    247:     return '@';
                    248:   else if (_rl_keymap == vi_insertion_keymap)
                    249:     return '+';                /* vi insert mode */
                    250:   else
                    251:     return ':';                /* vi command mode */
                    252: }
                    253: 
                    254: /* Expand the prompt string S and return the number of visible
                    255:    characters in *LP, if LP is not null.  This is currently more-or-less
                    256:    a placeholder for expansion.  LIP, if non-null is a place to store the
                    257:    index of the last invisible character in the returned string. NIFLP,
                    258:    if non-zero, is a place to store the number of invisible characters in
                    259:    the first prompt line.  The previous are used as byte counts -- indexes
                    260:    into a character buffer. */
                    261: 
                    262: /* Current implementation:
                    263:        \001 (^A) start non-visible characters
                    264:        \002 (^B) end non-visible characters
                    265:    all characters except \001 and \002 (following a \001) are copied to
                    266:    the returned string; all characters except those between \001 and
                    267:    \002 are assumed to be `visible'. */        
                    268: 
                    269: static char *
                    270: expand_prompt (pmt, lp, lip, niflp, vlp)
                    271:      char *pmt;
                    272:      int *lp, *lip, *niflp, *vlp;
                    273: {
                    274:   char *r, *ret, *p, *igstart;
                    275:   int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars;
                    276: 
                    277:   /* Short-circuit if we can. */
                    278:   if ((MB_CUR_MAX <= 1 || rl_byte_oriented) && strchr (pmt, RL_PROMPT_START_IGNORE) == 0)
                    279:     {
                    280:       if (pmt == rl_prompt && _rl_show_mode_in_prompt)
                    281:         {
                    282:           l = strlen (pmt);
                    283:           r = (char *)xmalloc (l + 2);
                    284:           r[0] = prompt_modechar ();
                    285:           strcpy (r + 1, pmt);
                    286:         }
                    287:       else
                    288:        r = savestring (pmt);
                    289: 
                    290:       if (lp)
                    291:        *lp = strlen (r);
                    292:       if (lip)
                    293:        *lip = 0;
                    294:       if (niflp)
                    295:        *niflp = 0;
                    296:       if (vlp)
                    297:        *vlp = lp ? *lp : strlen (r);
                    298:       return r;
                    299:     }
                    300: 
                    301:   l = strlen (pmt);
                    302:   r = ret = (char *)xmalloc (l + 2);
                    303: 
                    304:   rl = physchars = 0;  /* move up here so mode show can set them */
                    305:   if (pmt == rl_prompt && _rl_show_mode_in_prompt)
                    306:     {
                    307:       *r++ = prompt_modechar ();
                    308:       rl = physchars = 1;
                    309:     }
                    310: 
                    311:   invfl = 0;   /* invisible chars in first line of prompt */
                    312:   invflset = 0;        /* we only want to set invfl once */
                    313: 
                    314:   igstart = 0;
                    315:   for (ignoring = last = ninvis = 0, p = pmt; p && *p; p++)
                    316:     {
                    317:       /* This code strips the invisible character string markers
                    318:         RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
                    319:       if (ignoring == 0 && *p == RL_PROMPT_START_IGNORE)               /* XXX - check ignoring? */
                    320:        {
                    321:          ignoring = 1;
                    322:          igstart = p;
                    323:          continue;
                    324:        }
                    325:       else if (ignoring && *p == RL_PROMPT_END_IGNORE)
                    326:        {
                    327:          ignoring = 0;
                    328:          if (p != (igstart + 1))
                    329:            last = r - ret - 1;
                    330:          continue;
                    331:        }
                    332:       else
                    333:        {
                    334: #if defined (HANDLE_MULTIBYTE)
                    335:          if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                    336:            {
                    337:              pind = p - pmt;
                    338:              ind = _rl_find_next_mbchar (pmt, pind, 1, MB_FIND_NONZERO);
                    339:              l = ind - pind;
                    340:              while (l--)
                    341:                *r++ = *p++;
                    342:              if (!ignoring)
                    343:                {
                    344:                  /* rl ends up being assigned to prompt_visible_length,
                    345:                     which is the number of characters in the buffer that
                    346:                     contribute to characters on the screen, which might
                    347:                     not be the same as the number of physical characters
                    348:                     on the screen in the presence of multibyte characters */
                    349:                  rl += ind - pind;
                    350:                  physchars += _rl_col_width (pmt, pind, ind, 0);
                    351:                }
                    352:              else
                    353:                ninvis += ind - pind;
                    354:              p--;                      /* compensate for later increment */
                    355:            }
                    356:          else
                    357: #endif
                    358:            {
                    359:              *r++ = *p;
                    360:              if (!ignoring)
                    361:                {
                    362:                  rl++;                 /* visible length byte counter */
                    363:                  physchars++;
                    364:                }
                    365:              else
                    366:                ninvis++;               /* invisible chars byte counter */
                    367:            }
                    368: 
                    369:          if (invflset == 0 && rl >= _rl_screenwidth)
                    370:            {
                    371:              invfl = ninvis;
                    372:              invflset = 1;
                    373:            }
                    374:        }
                    375:     }
                    376: 
                    377:   if (rl < _rl_screenwidth)
                    378:     invfl = ninvis;
                    379: 
                    380:   *r = '\0';
                    381:   if (lp)
                    382:     *lp = rl;
                    383:   if (lip)
                    384:     *lip = last;
                    385:   if (niflp)
                    386:     *niflp = invfl;
                    387:   if  (vlp)
                    388:     *vlp = physchars;
                    389:   return ret;
                    390: }
                    391: 
                    392: /* Just strip out RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE from
                    393:    PMT and return the rest of PMT. */
                    394: char *
                    395: _rl_strip_prompt (pmt)
                    396:      char *pmt;
                    397: {
                    398:   char *ret;
                    399: 
                    400:   ret = expand_prompt (pmt, (int *)NULL, (int *)NULL, (int *)NULL, (int *)NULL);
                    401:   return ret;
                    402: }
                    403: 
                    404: void
                    405: _rl_reset_prompt ()
                    406: {
                    407:   rl_visible_prompt_length = rl_expand_prompt (rl_prompt);
                    408: }
                    409: 
                    410: /*
                    411:  * Expand the prompt string into the various display components, if
                    412:  * necessary.
                    413:  *
                    414:  * local_prompt = expanded last line of string in rl_display_prompt
                    415:  *               (portion after the final newline)
                    416:  * local_prompt_prefix = portion before last newline of rl_display_prompt,
                    417:  *                      expanded via expand_prompt
                    418:  * prompt_visible_length = number of visible characters in local_prompt
                    419:  * prompt_prefix_length = number of visible characters in local_prompt_prefix
                    420:  *
                    421:  * This function is called once per call to readline().  It may also be
                    422:  * called arbitrarily to expand the primary prompt.
                    423:  *
                    424:  * The return value is the number of visible characters on the last line
                    425:  * of the (possibly multi-line) prompt.
                    426:  */
                    427: int
                    428: rl_expand_prompt (prompt)
                    429:      char *prompt;
                    430: {
                    431:   char *p, *t;
                    432:   int c;
                    433: 
                    434:   /* Clear out any saved values. */
                    435:   FREE (local_prompt);
                    436:   FREE (local_prompt_prefix);
                    437: 
                    438:   local_prompt = local_prompt_prefix = (char *)0;
                    439:   local_prompt_len = 0;
                    440:   prompt_last_invisible = prompt_invis_chars_first_line = 0;
                    441:   prompt_visible_length = prompt_physical_chars = 0;
                    442: 
                    443:   if (prompt == 0 || *prompt == 0)
                    444:     return (0);
                    445: 
                    446:   p = strrchr (prompt, '\n');
                    447:   if (!p)
                    448:     {
                    449:       /* The prompt is only one logical line, though it might wrap. */
                    450:       local_prompt = expand_prompt (prompt, &prompt_visible_length,
                    451:                                            &prompt_last_invisible,
                    452:                                            &prompt_invis_chars_first_line,
                    453:                                            &prompt_physical_chars);
                    454:       local_prompt_prefix = (char *)0;
                    455:       local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
                    456:       return (prompt_visible_length);
                    457:     }
                    458:   else
                    459:     {
                    460:       /* The prompt spans multiple lines. */
                    461:       t = ++p;
                    462:       local_prompt = expand_prompt (p, &prompt_visible_length,
                    463:                                       &prompt_last_invisible,
                    464:                                       &prompt_invis_chars_first_line,
                    465:                                       &prompt_physical_chars);
                    466:       c = *t; *t = '\0';
                    467:       /* The portion of the prompt string up to and including the
                    468:         final newline is now null-terminated. */
                    469:       local_prompt_prefix = expand_prompt (prompt, &prompt_prefix_length,
                    470:                                                   (int *)NULL,
                    471:                                                   (int *)NULL,
                    472:                                                   (int *)NULL);
                    473:       *t = c;
                    474:       local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
                    475:       return (prompt_prefix_length);
                    476:     }
                    477: }
                    478: 
                    479: /* Initialize the VISIBLE_LINE and INVISIBLE_LINE arrays, and their associated
                    480:    arrays of line break markers.  MINSIZE is the minimum size of VISIBLE_LINE
                    481:    and INVISIBLE_LINE; if it is greater than LINE_SIZE, LINE_SIZE is
                    482:    increased.  If the lines have already been allocated, this ensures that
                    483:    they can hold at least MINSIZE characters. */
                    484: static void
                    485: init_line_structures (minsize)
                    486:       int minsize;
                    487: {
                    488:   register int n;
                    489: 
                    490:   if (invisible_line == 0)     /* initialize it */
                    491:     {
                    492:       if (line_size < minsize)
                    493:        line_size = minsize;
                    494:       visible_line = (char *)xmalloc (line_size);
                    495:       invisible_line = (char *)xmalloc (line_size);
                    496:     }
                    497:   else if (line_size < minsize)        /* ensure it can hold MINSIZE chars */
                    498:     {
                    499:       line_size *= 2;
                    500:       if (line_size < minsize)
                    501:        line_size = minsize;
                    502:       visible_line = (char *)xrealloc (visible_line, line_size);
                    503:       invisible_line = (char *)xrealloc (invisible_line, line_size);
                    504:     }
                    505: 
                    506:   for (n = minsize; n < line_size; n++)
                    507:     {
                    508:       visible_line[n] = 0;
                    509:       invisible_line[n] = 1;
                    510:     }
                    511: 
                    512:   if (vis_lbreaks == 0)
                    513:     {
                    514:       /* should be enough. */
                    515:       inv_lbsize = vis_lbsize = 256;
                    516: 
                    517: #if defined (HANDLE_MULTIBYTE)
                    518:       line_state_visible->wbsize = vis_lbsize;
                    519:       line_state_visible->wrapped_line = (int *)xmalloc (line_state_visible->wbsize * sizeof (int));
                    520: 
                    521:       line_state_invisible->wbsize = inv_lbsize;
                    522:       line_state_invisible->wrapped_line = (int *)xmalloc (line_state_invisible->wbsize * sizeof (int));
                    523: #endif
                    524: 
                    525:       inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int));
                    526:       vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int));
                    527:       inv_lbreaks[0] = vis_lbreaks[0] = 0;
                    528:     }
                    529: 
                    530:   line_structures_initialized = 1;
                    531: }
                    532:   
                    533: /* Basic redisplay algorithm. */
                    534: void
                    535: rl_redisplay ()
                    536: {
                    537:   register int in, out, c, linenum, cursor_linenum;
                    538:   register char *line;
                    539:   int inv_botlin, lb_botlin, lb_linenum, o_cpos;
                    540:   int newlines, lpos, temp, n0, num, prompt_lines_estimate;
                    541:   char *prompt_this_line;
                    542: #if defined (HANDLE_MULTIBYTE)
                    543:   wchar_t wc;
                    544:   size_t wc_bytes;
                    545:   int wc_width;
                    546:   mbstate_t ps;
                    547:   int _rl_wrapped_multicolumn = 0;
                    548: #endif
                    549: 
                    550:   if (_rl_echoing_p == 0)
                    551:     return;
                    552: 
                    553:   /* Block keyboard interrupts because this function manipulates global
                    554:      data structures. */
                    555:   _rl_block_sigint ();  
                    556:   RL_SETSTATE (RL_STATE_REDISPLAYING);
                    557: 
                    558:   if (!rl_display_prompt)
                    559:     rl_display_prompt = "";
                    560: 
                    561:   if (line_structures_initialized == 0)
                    562:     {
                    563:       init_line_structures (0);
                    564:       rl_on_new_line ();
                    565:     }
                    566: 
                    567:   /* Draw the line into the buffer. */
                    568:   cpos_buffer_position = -1;
                    569: 
                    570:   prompt_multibyte_chars = prompt_visible_length - prompt_physical_chars;
                    571: 
                    572:   line = invisible_line;
                    573:   out = inv_botlin = 0;
                    574: 
                    575:   /* Mark the line as modified or not.  We only do this for history
                    576:      lines. */
                    577:   modmark = 0;
                    578:   if (_rl_mark_modified_lines && current_history () && rl_undo_list)
                    579:     {
                    580:       line[out++] = '*';
                    581:       line[out] = '\0';
                    582:       modmark = 1;
                    583:     }
                    584: 
                    585:   /* If someone thought that the redisplay was handled, but the currently
                    586:      visible line has a different modification state than the one about
                    587:      to become visible, then correct the caller's misconception. */
                    588:   if (visible_line[0] != invisible_line[0])
                    589:     rl_display_fixed = 0;
                    590: 
                    591:   /* If the prompt to be displayed is the `primary' readline prompt (the
                    592:      one passed to readline()), use the values we have already expanded.
                    593:      If not, use what's already in rl_display_prompt.  WRAP_OFFSET is the
                    594:      number of non-visible characters in the prompt string. */
                    595:   if (rl_display_prompt == rl_prompt || local_prompt)
                    596:     {
                    597:       if (local_prompt_prefix && forced_display)
                    598:        _rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix));
                    599: 
                    600:       if (local_prompt_len > 0)
                    601:        {
                    602:          temp = local_prompt_len + out + 2;
                    603:          if (temp >= line_size)
                    604:            {
                    605:              line_size = (temp + 1024) - (temp % 1024);
                    606:              visible_line = (char *)xrealloc (visible_line, line_size);
                    607:              line = invisible_line = (char *)xrealloc (invisible_line, line_size);
                    608:            }
                    609:          strncpy (line + out, local_prompt, local_prompt_len);
                    610:          out += local_prompt_len;
                    611:        }
                    612:       line[out] = '\0';
                    613:       wrap_offset = local_prompt_len - prompt_visible_length;
                    614:     }
                    615:   else
                    616:     {
                    617:       int pmtlen;
                    618:       prompt_this_line = strrchr (rl_display_prompt, '\n');
                    619:       if (!prompt_this_line)
                    620:        prompt_this_line = rl_display_prompt;
                    621:       else
                    622:        {
                    623:          prompt_this_line++;
                    624:          pmtlen = prompt_this_line - rl_display_prompt;        /* temp var */
                    625:          if (forced_display)
                    626:            {
                    627:              _rl_output_some_chars (rl_display_prompt, pmtlen);
                    628:              /* Make sure we are at column zero even after a newline,
                    629:                 regardless of the state of terminal output processing. */
                    630:              if (pmtlen < 2 || prompt_this_line[-2] != '\r')
                    631:                cr ();
                    632:            }
                    633:        }
                    634: 
                    635:       prompt_physical_chars = pmtlen = strlen (prompt_this_line);
                    636:       temp = pmtlen + out + 2;
                    637:       if (temp >= line_size)
                    638:        {
                    639:          line_size = (temp + 1024) - (temp % 1024);
                    640:          visible_line = (char *)xrealloc (visible_line, line_size);
                    641:          line = invisible_line = (char *)xrealloc (invisible_line, line_size);
                    642:        }
                    643:       strncpy (line + out,  prompt_this_line, pmtlen);
                    644:       out += pmtlen;
                    645:       line[out] = '\0';
                    646:       wrap_offset = prompt_invis_chars_first_line = 0;
                    647:     }
                    648: 
                    649: #define CHECK_INV_LBREAKS() \
                    650:       do { \
                    651:        if (newlines >= (inv_lbsize - 2)) \
                    652:          { \
                    653:            inv_lbsize *= 2; \
                    654:            inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
                    655:          } \
                    656:       } while (0)
                    657: 
                    658: #if defined (HANDLE_MULTIBYTE)   
                    659: #define CHECK_LPOS() \
                    660:       do { \
                    661:        lpos++; \
                    662:        if (lpos >= _rl_screenwidth) \
                    663:          { \
                    664:            if (newlines >= (inv_lbsize - 2)) \
                    665:              { \
                    666:                inv_lbsize *= 2; \
                    667:                inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
                    668:              } \
                    669:            inv_lbreaks[++newlines] = out; \
                    670:            if (newlines >= (line_state_invisible->wbsize - 1)) \
                    671:              { \
                    672:                line_state_invisible->wbsize *= 2; \
                    673:                line_state_invisible->wrapped_line = (int *)xrealloc (line_state_invisible->wrapped_line, line_state_invisible->wbsize * sizeof(int)); \
                    674:              } \
                    675:            line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn; \
                    676:            lpos = 0; \
                    677:          } \
                    678:       } while (0)
                    679: #else
                    680: #define CHECK_LPOS() \
                    681:       do { \
                    682:        lpos++; \
                    683:        if (lpos >= _rl_screenwidth) \
                    684:          { \
                    685:            if (newlines >= (inv_lbsize - 2)) \
                    686:              { \
                    687:                inv_lbsize *= 2; \
                    688:                inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
                    689:              } \
                    690:            inv_lbreaks[++newlines] = out; \
                    691:            lpos = 0; \
                    692:          } \
                    693:       } while (0)
                    694: #endif
                    695: 
                    696:   /* inv_lbreaks[i] is where line i starts in the buffer. */
                    697:   inv_lbreaks[newlines = 0] = 0;
                    698:   lpos = prompt_physical_chars + modmark;
                    699: 
                    700: #if defined (HANDLE_MULTIBYTE)
                    701:   memset (line_state_invisible->wrapped_line, 0, line_state_invisible->wbsize * sizeof (int));
                    702:   num = 0;
                    703: #endif
                    704: 
                    705:   /* prompt_invis_chars_first_line is the number of invisible characters in
                    706:      the first physical line of the prompt.
                    707:      wrap_offset - prompt_invis_chars_first_line is the number of invis
                    708:      chars on the second (or, more generally, last) line. */
                    709: 
                    710:   /* This is zero-based, used to set the newlines */
                    711:   prompt_lines_estimate = lpos / _rl_screenwidth;
                    712: 
                    713:   /* what if lpos is already >= _rl_screenwidth before we start drawing the
                    714:      contents of the command line? */
                    715:   while (lpos >= _rl_screenwidth)
                    716:     {
                    717:       int z;
                    718:       /* fix from Darin Johnson <darin@acuson.com> for prompt string with
                    719:          invisible characters that is longer than the screen width.  The
                    720:          prompt_invis_chars_first_line variable could be made into an array
                    721:          saying how many invisible characters there are per line, but that's
                    722:          probably too much work for the benefit gained.  How many people have
                    723:          prompts that exceed two physical lines?
                    724:          Additional logic fix from Edward Catmur <ed@catmur.co.uk> */
                    725: #if defined (HANDLE_MULTIBYTE)
                    726:       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0)
                    727:        {
                    728:          n0 = num;
                    729:           temp = local_prompt_len;
                    730:           while (num < temp)
                    731:            {
                    732:              z = _rl_col_width  (local_prompt, n0, num, 1);
                    733:              if (z > _rl_screenwidth)
                    734:                {
                    735:                  num = _rl_find_prev_mbchar (local_prompt, num, MB_FIND_ANY);
                    736:                  break;
                    737:                }
                    738:              else if (z == _rl_screenwidth)
                    739:                break;
                    740:              num++;
                    741:            }
                    742:           temp = num;
                    743:        }
                    744:       else
                    745: #endif /* !HANDLE_MULTIBYTE */
                    746:        temp = ((newlines + 1) * _rl_screenwidth);
                    747: 
                    748:       /* Now account for invisible characters in the current line. */
                    749:       /* XXX - this assumes that the invisible characters may be split, but only
                    750:         between the first and the last lines. */
                    751:       temp += (newlines == 0) ? prompt_invis_chars_first_line
                    752:                              : ((newlines == prompt_lines_estimate) ? wrap_offset : prompt_invis_chars_first_line);
                    753: 
                    754:       inv_lbreaks[++newlines] = temp;
                    755: #if defined (HANDLE_MULTIBYTE)
                    756:       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0)
                    757:        lpos -= _rl_col_width (local_prompt, n0, num, 1);
                    758:       else
                    759: #endif
                    760:        lpos -= _rl_screenwidth;
                    761:     }
                    762: 
                    763:   prompt_last_screen_line = newlines;
                    764: 
                    765:   /* Draw the rest of the line (after the prompt) into invisible_line, keeping
                    766:      track of where the cursor is (cpos_buffer_position), the number of the line containing
                    767:      the cursor (lb_linenum), the last line number (lb_botlin and inv_botlin).
                    768:      It maintains an array of line breaks for display (inv_lbreaks).
                    769:      This handles expanding tabs for display and displaying meta characters. */
                    770:   lb_linenum = 0;
                    771: #if defined (HANDLE_MULTIBYTE)
                    772:   in = 0;
                    773:   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                    774:     {
                    775:       memset (&ps, 0, sizeof (mbstate_t));
                    776:       /* XXX - what if wc_bytes ends up <= 0? check for MB_INVALIDCH */
                    777:       wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps);
                    778:     }
                    779:   else
                    780:     wc_bytes = 1;
                    781:   while (in < rl_end)
                    782: #else
                    783:   for (in = 0; in < rl_end; in++)
                    784: #endif
                    785:     {
                    786:       c = (unsigned char)rl_line_buffer[in];
                    787: 
                    788: #if defined (HANDLE_MULTIBYTE)
                    789:       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                    790:        {
                    791:          if (MB_INVALIDCH (wc_bytes))
                    792:            {
                    793:              /* Byte sequence is invalid or shortened.  Assume that the
                    794:                 first byte represents a character. */
                    795:              wc_bytes = 1;
                    796:              /* Assume that a character occupies a single column. */
                    797:              wc_width = 1;
                    798:              memset (&ps, 0, sizeof (mbstate_t));
                    799:            }
                    800:          else if (MB_NULLWCH (wc_bytes))
                    801:            break;                      /* Found '\0' */
                    802:          else
                    803:            {
                    804:              temp = WCWIDTH (wc);
                    805:              wc_width = (temp >= 0) ? temp : 1;
                    806:            }
                    807:        }
                    808: #endif
                    809: 
                    810:       if (out + 8 >= line_size)                /* XXX - 8 for \t */
                    811:        {
                    812:          line_size *= 2;
                    813:          visible_line = (char *)xrealloc (visible_line, line_size);
                    814:          invisible_line = (char *)xrealloc (invisible_line, line_size);
                    815:          line = invisible_line;
                    816:        }
                    817: 
                    818:       if (in == rl_point)
                    819:        {
                    820:          cpos_buffer_position = out;
                    821:          lb_linenum = newlines;
                    822:        }
                    823: 
                    824: #if defined (HANDLE_MULTIBYTE)
                    825:       if (META_CHAR (c) && _rl_output_meta_chars == 0) /* XXX - clean up */
                    826: #else
                    827:       if (META_CHAR (c))
                    828: #endif
                    829:        {
                    830:          if (_rl_output_meta_chars == 0)
                    831:            {
                    832:              sprintf (line + out, "\\%o", c);
                    833: 
                    834:              if (lpos + 4 >= _rl_screenwidth)
                    835:                {
                    836:                  temp = _rl_screenwidth - lpos;
                    837:                  CHECK_INV_LBREAKS ();
                    838:                  inv_lbreaks[++newlines] = out + temp;
                    839:                  lpos = 4 - temp;
                    840:                }
                    841:              else
                    842:                lpos += 4;
                    843: 
                    844:              out += 4;
                    845:            }
                    846:          else
                    847:            {
                    848:              line[out++] = c;
                    849:              CHECK_LPOS();
                    850:            }
                    851:        }
                    852: #if defined (DISPLAY_TABS)
                    853:       else if (c == '\t')
                    854:        {
                    855:          register int newout;
                    856: 
                    857: #if 0
                    858:          newout = (out | (int)7) + 1;
                    859: #else
                    860:          newout = out + 8 - lpos % 8;
                    861: #endif
                    862:          temp = newout - out;
                    863:          if (lpos + temp >= _rl_screenwidth)
                    864:            {
                    865:              register int temp2;
                    866:              temp2 = _rl_screenwidth - lpos;
                    867:              CHECK_INV_LBREAKS ();
                    868:              inv_lbreaks[++newlines] = out + temp2;
                    869:              lpos = temp - temp2;
                    870:              while (out < newout)
                    871:                line[out++] = ' ';
                    872:            }
                    873:          else
                    874:            {
                    875:              while (out < newout)
                    876:                line[out++] = ' ';
                    877:              lpos += temp;
                    878:            }
                    879:        }
                    880: #endif
                    881:       else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
                    882:        {
                    883:          line[out++] = '\0';   /* XXX - sentinel */
                    884:          CHECK_INV_LBREAKS ();
                    885:          inv_lbreaks[++newlines] = out;
                    886:          lpos = 0;
                    887:        }
                    888:       else if (CTRL_CHAR (c) || c == RUBOUT)
                    889:        {
                    890:          line[out++] = '^';
                    891:          CHECK_LPOS();
                    892:          line[out++] = CTRL_CHAR (c) ? UNCTRL (c) : '?';
                    893:          CHECK_LPOS();
                    894:        }
                    895:       else
                    896:        {
                    897: #if defined (HANDLE_MULTIBYTE)
                    898:          if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                    899:            {
                    900:              register int i;
                    901: 
                    902:              _rl_wrapped_multicolumn = 0;
                    903: 
                    904:              if (_rl_screenwidth < lpos + wc_width)
                    905:                for (i = lpos; i < _rl_screenwidth; i++)
                    906:                  {
                    907:                    /* The space will be removed in update_line() */
                    908:                    line[out++] = ' ';
                    909:                    _rl_wrapped_multicolumn++;
                    910:                    CHECK_LPOS();
                    911:                  }
                    912:              if (in == rl_point)
                    913:                {
                    914:                  cpos_buffer_position = out;
                    915:                  lb_linenum = newlines;
                    916:                }
                    917:              for (i = in; i < in+wc_bytes; i++)
                    918:                line[out++] = rl_line_buffer[i];
                    919:              for (i = 0; i < wc_width; i++)
                    920:                CHECK_LPOS();
                    921:            }
                    922:          else
                    923:            {
                    924:              line[out++] = c;
                    925:              CHECK_LPOS();
                    926:            }
                    927: #else
                    928:          line[out++] = c;
                    929:          CHECK_LPOS();
                    930: #endif
                    931:        }
                    932: 
                    933: #if defined (HANDLE_MULTIBYTE)
                    934:       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                    935:        {
                    936:          in += wc_bytes;
                    937:          /* XXX - what if wc_bytes ends up <= 0? check for MB_INVALIDCH */
                    938:          wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps);
                    939:        }
                    940:       else
                    941:         in++;
                    942: #endif
                    943: 
                    944:     }
                    945:   line[out] = '\0';
                    946:   if (cpos_buffer_position < 0)
                    947:     {
                    948:       cpos_buffer_position = out;
                    949:       lb_linenum = newlines;
                    950:     }
                    951: 
                    952:   inv_botlin = lb_botlin = newlines;
                    953:   CHECK_INV_LBREAKS ();
                    954:   inv_lbreaks[newlines+1] = out;
                    955:   cursor_linenum = lb_linenum;
                    956: 
                    957:   /* CPOS_BUFFER_POSITION == position in buffer where cursor should be placed.
                    958:      CURSOR_LINENUM == line number where the cursor should be placed. */
                    959: 
                    960:   /* PWP: now is when things get a bit hairy.  The visible and invisible
                    961:      line buffers are really multiple lines, which would wrap every
                    962:      (screenwidth - 1) characters.  Go through each in turn, finding
                    963:      the changed region and updating it.  The line order is top to bottom. */
                    964: 
                    965:   /* If we can move the cursor up and down, then use multiple lines,
                    966:      otherwise, let long lines display in a single terminal line, and
                    967:      horizontally scroll it. */
                    968:   displaying_prompt_first_line = 1;
                    969:   if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
                    970:     {
                    971:       int nleft, pos, changed_screen_line, tx;
                    972: 
                    973:       if (!rl_display_fixed || forced_display)
                    974:        {
                    975:          forced_display = 0;
                    976: 
                    977:          /* If we have more than a screenful of material to display, then
                    978:             only display a screenful.  We should display the last screen,
                    979:             not the first.  */
                    980:          if (out >= _rl_screenchars)
                    981:            {
                    982:              if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                    983:                out = _rl_find_prev_mbchar (line, _rl_screenchars, MB_FIND_ANY);
                    984:              else
                    985:                out = _rl_screenchars - 1;
                    986:            }
                    987: 
                    988:          /* The first line is at character position 0 in the buffer.  The
                    989:             second and subsequent lines start at inv_lbreaks[N], offset by
                    990:             OFFSET (which has already been calculated above).  */
                    991: 
                    992: #define INVIS_FIRST()  (prompt_physical_chars > _rl_screenwidth ? prompt_invis_chars_first_line : wrap_offset)
                    993: #define WRAP_OFFSET(line, offset)  ((line == 0) \
                    994:                                        ? (offset ? INVIS_FIRST() : 0) \
                    995:                                        : ((line == prompt_last_screen_line) ? wrap_offset-prompt_invis_chars_first_line : 0))
                    996: #define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
                    997: #define VIS_LLEN(l)    ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
                    998: #define INV_LLEN(l)    (inv_lbreaks[l+1] - inv_lbreaks[l])
                    999: #define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
                   1000: #define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
                   1001: #define INV_LINE(line) (invisible_line + inv_lbreaks[line])
                   1002: 
                   1003: #define OLD_CPOS_IN_PROMPT() (cpos_adjusted == 0 && \
                   1004:                        _rl_last_c_pos != o_cpos && \
                   1005:                        _rl_last_c_pos > wrap_offset && \
                   1006:                        o_cpos < prompt_last_invisible)
                   1007: 
                   1008:          /* For each line in the buffer, do the updating display. */
                   1009:          for (linenum = 0; linenum <= inv_botlin; linenum++)
                   1010:            {
                   1011:              /* This can lead us astray if we execute a program that changes
                   1012:                 the locale from a non-multibyte to a multibyte one. */
                   1013:              o_cpos = _rl_last_c_pos;
                   1014:              cpos_adjusted = 0;
                   1015:              update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum,
                   1016:                           VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin);
                   1017: 
                   1018:              /* update_line potentially changes _rl_last_c_pos, but doesn't
                   1019:                 take invisible characters into account, since _rl_last_c_pos
                   1020:                 is an absolute cursor position in a multibyte locale.  See
                   1021:                 if compensating here is the right thing, or if we have to
                   1022:                 change update_line itself.  There are several cases in which
                   1023:                 update_line adjusts _rl_last_c_pos itself (so it can pass
                   1024:                 _rl_move_cursor_relative accurate values); it communicates
                   1025:                 this back by setting cpos_adjusted.  If we assume that
                   1026:                 _rl_last_c_pos is correct (an absolute cursor position) each
                   1027:                 time update_line is called, then we can assume in our
                   1028:                 calculations that o_cpos does not need to be adjusted by
                   1029:                 wrap_offset. */
                   1030:              if (linenum == 0 && (MB_CUR_MAX > 1 && rl_byte_oriented == 0) && OLD_CPOS_IN_PROMPT())
                   1031:                _rl_last_c_pos -= prompt_invis_chars_first_line;        /* XXX - was wrap_offset */
                   1032:              else if (linenum == prompt_last_screen_line && prompt_physical_chars > _rl_screenwidth &&
                   1033:                        (MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
                   1034:                        cpos_adjusted == 0 &&
                   1035:                        _rl_last_c_pos != o_cpos &&
                   1036:                        _rl_last_c_pos > (prompt_last_invisible - _rl_screenwidth - prompt_invis_chars_first_line))
                   1037:                _rl_last_c_pos -= (wrap_offset-prompt_invis_chars_first_line);
                   1038:                  
                   1039:              /* If this is the line with the prompt, we might need to
                   1040:                 compensate for invisible characters in the new line. Do
                   1041:                 this only if there is not more than one new line (which
                   1042:                 implies that we completely overwrite the old visible line)
                   1043:                 and the new line is shorter than the old.  Make sure we are
                   1044:                 at the end of the new line before clearing. */
                   1045:              if (linenum == 0 &&
                   1046:                  inv_botlin == 0 && _rl_last_c_pos == out &&
                   1047:                  (wrap_offset > visible_wrap_offset) &&
                   1048:                  (_rl_last_c_pos < visible_first_line_len))
                   1049:                {
                   1050:                  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   1051:                    nleft = _rl_screenwidth - _rl_last_c_pos;
                   1052:                  else
                   1053:                    nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos;
                   1054:                  if (nleft)
                   1055:                    _rl_clear_to_eol (nleft);
                   1056:                }
                   1057: #if 0
                   1058:              /* This segment is intended to handle the case where the prompt
                   1059:                 has invisible characters on the second line and the new line
                   1060:                 to be displayed needs to clear the rest of the old characters
                   1061:                 out (e.g., when printing the i-search prompt).  In general,
                   1062:                 the case of the new line being shorter than the old.
                   1063:                 Incomplete */
                   1064:              else if (linenum == prompt_last_screen_line &&
                   1065:                       prompt_physical_chars > _rl_screenwidth &&
                   1066:                       wrap_offset != prompt_invis_chars_first_line &&
                   1067:                       _rl_last_c_pos == out &&
                   1068: #endif
                   1069: 
                   1070: 
                   1071:              /* Since the new first line is now visible, save its length. */
                   1072:              if (linenum == 0)
                   1073:                visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset;
                   1074:            }
                   1075: 
                   1076:          /* We may have deleted some lines.  If so, clear the left over
                   1077:             blank ones at the bottom out. */
                   1078:          if (_rl_vis_botlin > inv_botlin)
                   1079:            {
                   1080:              char *tt;
                   1081:              for (; linenum <= _rl_vis_botlin; linenum++)
                   1082:                {
                   1083:                  tt = VIS_CHARS (linenum);
                   1084:                  _rl_move_vert (linenum);
                   1085:                  _rl_move_cursor_relative (0, tt);
                   1086:                  _rl_clear_to_eol
                   1087:                    ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth);
                   1088:                }
                   1089:            }
                   1090:          _rl_vis_botlin = inv_botlin;
                   1091: 
                   1092:          /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
                   1093:             different screen line during this redisplay. */
                   1094:          changed_screen_line = _rl_last_v_pos != cursor_linenum;
                   1095:          if (changed_screen_line)
                   1096:            {
                   1097:              _rl_move_vert (cursor_linenum);
                   1098:              /* If we moved up to the line with the prompt using _rl_term_up,
                   1099:                 the physical cursor position on the screen stays the same,
                   1100:                 but the buffer position needs to be adjusted to account
                   1101:                 for invisible characters. */
                   1102:              if ((MB_CUR_MAX == 1 || rl_byte_oriented) && cursor_linenum == 0 && wrap_offset)
                   1103:                _rl_last_c_pos += wrap_offset;
                   1104:            }
                   1105: 
                   1106:          /* We have to reprint the prompt if it contains invisible
                   1107:             characters, since it's not generally OK to just reprint
                   1108:             the characters from the current cursor position.  But we
                   1109:             only need to reprint it if the cursor is before the last
                   1110:             invisible character in the prompt string. */
                   1111:          nleft = prompt_visible_length + wrap_offset;
                   1112:          if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
                   1113: #if 0
                   1114:              _rl_last_c_pos <= PROMPT_ENDING_INDEX && local_prompt)
                   1115: #else
                   1116:              _rl_last_c_pos < PROMPT_ENDING_INDEX && local_prompt)
                   1117: #endif
                   1118:            {
                   1119: #if defined (__MSDOS__)
                   1120:              putc ('\r', rl_outstream);
                   1121: #else
                   1122:              if (_rl_term_cr)
                   1123:                tputs (_rl_term_cr, 1, _rl_output_character_function);
                   1124: #endif
                   1125:              if (modmark)
                   1126:                _rl_output_some_chars ("*", 1);
                   1127: 
                   1128:              _rl_output_some_chars (local_prompt, nleft);
                   1129:              if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   1130:                _rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft, 1) - wrap_offset + modmark;
                   1131:              else
                   1132:                _rl_last_c_pos = nleft + modmark;
                   1133:            }
                   1134: 
                   1135:          /* Where on that line?  And where does that line start
                   1136:             in the buffer? */
                   1137:          pos = inv_lbreaks[cursor_linenum];
                   1138:          /* nleft == number of characters in the line buffer between the
                   1139:             start of the line and the desired cursor position. */
                   1140:          nleft = cpos_buffer_position - pos;
                   1141: 
                   1142:          /* NLEFT is now a number of characters in a buffer.  When in a
                   1143:             multibyte locale, however, _rl_last_c_pos is an absolute cursor
                   1144:             position that doesn't take invisible characters in the prompt
                   1145:             into account.  We use a fudge factor to compensate. */
                   1146: 
                   1147:          /* Since _rl_backspace() doesn't know about invisible characters in the
                   1148:             prompt, and there's no good way to tell it, we compensate for
                   1149:             those characters here and call _rl_backspace() directly. */
                   1150:          if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
                   1151:            {
                   1152:              /* TX == new physical cursor position in multibyte locale. */
                   1153:              if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   1154:                tx = _rl_col_width (&visible_line[pos], 0, nleft, 1) - visible_wrap_offset;
                   1155:              else
                   1156:                tx = nleft;
                   1157:              if (tx >= 0 && _rl_last_c_pos > tx)
                   1158:                {
                   1159:                  _rl_backspace (_rl_last_c_pos - tx);  /* XXX */
                   1160:                  _rl_last_c_pos = tx;
                   1161:                }
                   1162:            }
                   1163: 
                   1164:          /* We need to note that in a multibyte locale we are dealing with
                   1165:             _rl_last_c_pos as an absolute cursor position, but moving to a
                   1166:             point specified by a buffer position (NLEFT) that doesn't take
                   1167:             invisible characters into account. */
                   1168:          if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   1169:            _rl_move_cursor_relative (nleft, &invisible_line[pos]);
                   1170:          else if (nleft != _rl_last_c_pos)
                   1171:            _rl_move_cursor_relative (nleft, &invisible_line[pos]);
                   1172:        }
                   1173:     }
                   1174:   else                         /* Do horizontal scrolling. */
                   1175:     {
                   1176: #define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
                   1177:       int lmargin, ndisp, nleft, phys_c_pos, t;
                   1178: 
                   1179:       /* Always at top line. */
                   1180:       _rl_last_v_pos = 0;
                   1181: 
                   1182:       /* Compute where in the buffer the displayed line should start.  This
                   1183:         will be LMARGIN. */
                   1184: 
                   1185:       /* The number of characters that will be displayed before the cursor. */
                   1186:       ndisp = cpos_buffer_position - wrap_offset;
                   1187:       nleft  = prompt_visible_length + wrap_offset;
                   1188:       /* Where the new cursor position will be on the screen.  This can be
                   1189:         longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
                   1190:       phys_c_pos = cpos_buffer_position - (last_lmargin ? last_lmargin : wrap_offset);
                   1191:       t = _rl_screenwidth / 3;
                   1192: 
                   1193:       /* If the number of characters had already exceeded the screenwidth,
                   1194:         last_lmargin will be > 0. */
                   1195: 
                   1196:       /* If the number of characters to be displayed is more than the screen
                   1197:         width, compute the starting offset so that the cursor is about
                   1198:         two-thirds of the way across the screen. */
                   1199:       if (phys_c_pos > _rl_screenwidth - 2)
                   1200:        {
                   1201:          lmargin = cpos_buffer_position - (2 * t);
                   1202:          if (lmargin < 0)
                   1203:            lmargin = 0;
                   1204:          /* If the left margin would be in the middle of a prompt with
                   1205:             invisible characters, don't display the prompt at all. */
                   1206:          if (wrap_offset && lmargin > 0 && lmargin < nleft)
                   1207:            lmargin = nleft;
                   1208:        }
                   1209:       else if (ndisp < _rl_screenwidth - 2)            /* XXX - was -1 */
                   1210:        lmargin = 0;
                   1211:       else if (phys_c_pos < 1)
                   1212:        {
                   1213:          /* If we are moving back towards the beginning of the line and
                   1214:             the last margin is no longer correct, compute a new one. */
                   1215:          lmargin = ((cpos_buffer_position - 1) / t) * t;       /* XXX */
                   1216:          if (wrap_offset && lmargin > 0 && lmargin < nleft)
                   1217:            lmargin = nleft;
                   1218:        }
                   1219:       else
                   1220:        lmargin = last_lmargin;
                   1221: 
                   1222:       displaying_prompt_first_line = lmargin < nleft;
                   1223: 
                   1224:       /* If the first character on the screen isn't the first character
                   1225:         in the display line, indicate this with a special character. */
                   1226:       if (lmargin > 0)
                   1227:        line[lmargin] = '<';
                   1228: 
                   1229:       /* If SCREENWIDTH characters starting at LMARGIN do not encompass
                   1230:         the whole line, indicate that with a special character at the
                   1231:         right edge of the screen.  If LMARGIN is 0, we need to take the
                   1232:         wrap offset into account. */
                   1233:       t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth;
                   1234:       if (t < out)
                   1235:        line[t - 1] = '>';
                   1236: 
                   1237:       if (rl_display_fixed == 0 || forced_display || lmargin != last_lmargin)
                   1238:        {
                   1239:          forced_display = 0;
                   1240:          o_cpos = _rl_last_c_pos;
                   1241:          cpos_adjusted = 0;
                   1242:          update_line (&visible_line[last_lmargin],
                   1243:                       &invisible_line[lmargin],
                   1244:                       0,
                   1245:                       _rl_screenwidth + visible_wrap_offset,
                   1246:                       _rl_screenwidth + (lmargin ? 0 : wrap_offset),
                   1247:                       0);
                   1248: 
                   1249:          if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
                   1250:                displaying_prompt_first_line && OLD_CPOS_IN_PROMPT())
                   1251:            _rl_last_c_pos -= prompt_invis_chars_first_line;    /* XXX - was wrap_offset */
                   1252: 
                   1253:          /* If the visible new line is shorter than the old, but the number
                   1254:             of invisible characters is greater, and we are at the end of
                   1255:             the new line, we need to clear to eol. */
                   1256:          t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
                   1257:          if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
                   1258:              (_rl_last_c_pos == out) && displaying_prompt_first_line &&
                   1259:              t < visible_first_line_len)
                   1260:            {
                   1261:              nleft = _rl_screenwidth - t;
                   1262:              _rl_clear_to_eol (nleft);
                   1263:            }
                   1264:          visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
                   1265:          if (visible_first_line_len > _rl_screenwidth)
                   1266:            visible_first_line_len = _rl_screenwidth;
                   1267: 
                   1268:          _rl_move_cursor_relative (cpos_buffer_position - lmargin, &invisible_line[lmargin]);
                   1269:          last_lmargin = lmargin;
                   1270:        }
                   1271:     }
                   1272:   fflush (rl_outstream);
                   1273: 
                   1274:   /* Swap visible and non-visible lines. */
                   1275:   {
                   1276:     struct line_state *vtemp = line_state_visible;
                   1277: 
                   1278:     line_state_visible = line_state_invisible;
                   1279:     line_state_invisible = vtemp;
                   1280: 
                   1281:     rl_display_fixed = 0;
                   1282:     /* If we are displaying on a single line, and last_lmargin is > 0, we
                   1283:        are not displaying any invisible characters, so set visible_wrap_offset
                   1284:        to 0. */
                   1285:     if (_rl_horizontal_scroll_mode && last_lmargin)
                   1286:       visible_wrap_offset = 0;
                   1287:     else
                   1288:       visible_wrap_offset = wrap_offset;
                   1289:   }
                   1290: 
                   1291:   RL_UNSETSTATE (RL_STATE_REDISPLAYING);
                   1292:   _rl_release_sigint ();
                   1293: }
                   1294: 
                   1295: /* PWP: update_line() is based on finding the middle difference of each
                   1296:    line on the screen; vis:
                   1297: 
                   1298:                             /old first difference
                   1299:        /beginning of line   |        /old last same       /old EOL
                   1300:        v                    v        v             v
                   1301: old:   eddie> Oh, my little gruntle-buggy is to me, as lurgid as
                   1302: new:   eddie> Oh, my little buggy says to me, as lurgid as
                   1303:        ^                    ^  ^                          ^
                   1304:        \beginning of line   |  \new last same     \new end of line
                   1305:                             \new first difference
                   1306: 
                   1307:    All are character pointers for the sake of speed.  Special cases for
                   1308:    no differences, as well as for end of line additions must be handled.
                   1309: 
                   1310:    Could be made even smarter, but this works well enough */
                   1311: static void
                   1312: update_line (old, new, current_line, omax, nmax, inv_botlin)
                   1313:      register char *old, *new;
                   1314:      int current_line, omax, nmax, inv_botlin;
                   1315: {
                   1316:   register char *ofd, *ols, *oe, *nfd, *nls, *ne;
                   1317:   int temp, lendiff, wsatend, od, nd, twidth, o_cpos;
                   1318:   int current_invis_chars;
                   1319:   int col_lendiff, col_temp;
                   1320:   int bytes_to_insert;
                   1321: #if defined (HANDLE_MULTIBYTE)
                   1322:   mbstate_t ps_new, ps_old;
                   1323:   int new_offset, old_offset;
                   1324: #endif
                   1325: 
                   1326:   /* If we're at the right edge of a terminal that supports xn, we're
                   1327:      ready to wrap around, so do so.  This fixes problems with knowing
                   1328:      the exact cursor position and cut-and-paste with certain terminal
                   1329:      emulators.  In this calculation, TEMP is the physical screen
                   1330:      position of the cursor. */
                   1331:   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   1332:     temp = _rl_last_c_pos;
                   1333:   else
                   1334:     temp = _rl_last_c_pos - WRAP_OFFSET (_rl_last_v_pos, visible_wrap_offset);
                   1335:   if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
                   1336:        && _rl_last_v_pos == current_line - 1)
                   1337:     {
                   1338: #if defined (HANDLE_MULTIBYTE)
                   1339:       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   1340:        {
                   1341:          wchar_t wc;
                   1342:          mbstate_t ps;
                   1343:          int tempwidth, bytes;
                   1344:          size_t ret;
                   1345: 
                   1346:          /* This fixes only double-column characters, but if the wrapped
                   1347:             character consumes more than three columns, spaces will be
                   1348:             inserted in the string buffer. */
                   1349:          if (current_line < line_state_visible->wbsize && line_state_visible->wrapped_line[current_line] > 0)
                   1350:            _rl_clear_to_eol (line_state_visible->wrapped_line[current_line]);
                   1351: 
                   1352:          memset (&ps, 0, sizeof (mbstate_t));
                   1353:          ret = mbrtowc (&wc, new, MB_CUR_MAX, &ps);
                   1354:          if (MB_INVALIDCH (ret))
                   1355:            {
                   1356:              tempwidth = 1;
                   1357:              ret = 1;
                   1358:            }
                   1359:          else if (MB_NULLWCH (ret))
                   1360:            tempwidth = 0;
                   1361:          else
                   1362:            tempwidth = WCWIDTH (wc);
                   1363: 
                   1364:          if (tempwidth > 0)
                   1365:            {
                   1366:              int count, i;
                   1367:              bytes = ret;
                   1368:              for (count = 0; count < bytes; count++)
                   1369:                putc (new[count], rl_outstream);
                   1370:              _rl_last_c_pos = tempwidth;
                   1371:              _rl_last_v_pos++;
                   1372:              memset (&ps, 0, sizeof (mbstate_t));
                   1373:              ret = mbrtowc (&wc, old, MB_CUR_MAX, &ps);
                   1374:              if (ret != 0 && bytes != 0)
                   1375:                {
                   1376:                  if (MB_INVALIDCH (ret))
                   1377:                    ret = 1;
                   1378:                  memmove (old+bytes, old+ret, strlen (old+ret));
                   1379:                  memcpy (old, new, bytes);
                   1380:                  /* Fix up indices if we copy data from one line to another */
                   1381:                  omax += bytes - ret;
                   1382:                  for (i = current_line+1; i <= inv_botlin+1; i++)
                   1383:                    vis_lbreaks[i] += bytes - ret;
                   1384:                }
                   1385:            }
                   1386:          else
                   1387:            {
                   1388:              putc (' ', rl_outstream);
                   1389:              _rl_last_c_pos = 1;
                   1390:              _rl_last_v_pos++;
                   1391:              if (old[0] && new[0])
                   1392:                old[0] = new[0];
                   1393:            }
                   1394:        }
                   1395:       else
                   1396: #endif
                   1397:        {
                   1398:          if (new[0])
                   1399:            putc (new[0], rl_outstream);
                   1400:          else
                   1401:            putc (' ', rl_outstream);
                   1402:          _rl_last_c_pos = 1;
                   1403:          _rl_last_v_pos++;
                   1404:          if (old[0] && new[0])
                   1405:            old[0] = new[0];
                   1406:        }
                   1407:     }
                   1408: 
                   1409:       
                   1410:   /* Find first difference. */
                   1411: #if defined (HANDLE_MULTIBYTE)
                   1412:   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   1413:     {
                   1414:       /* See if the old line is a subset of the new line, so that the
                   1415:         only change is adding characters. */
                   1416:       temp = (omax < nmax) ? omax : nmax;
                   1417:       if (memcmp (old, new, temp) == 0)                /* adding at the end */
                   1418:        {
                   1419:          new_offset = old_offset = temp;
                   1420:          ofd = old + temp;
                   1421:          nfd = new + temp;
                   1422:        }
                   1423:       else
                   1424:        {      
                   1425:          memset (&ps_new, 0, sizeof(mbstate_t));
                   1426:          memset (&ps_old, 0, sizeof(mbstate_t));
                   1427: 
                   1428:          if (omax == nmax && STREQN (new, old, omax))
                   1429:            {
                   1430:              old_offset = omax;
                   1431:              new_offset = nmax;
                   1432:              ofd = old + omax;
                   1433:              nfd = new + nmax;
                   1434:            }
                   1435:          else
                   1436:            {
                   1437:              new_offset = old_offset = 0;
                   1438:              for (ofd = old, nfd = new;
                   1439:                    (ofd - old < omax) && *ofd &&
                   1440:                    _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new); )
                   1441:                {
                   1442:                  old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY);
                   1443:                  new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY);
                   1444: 
                   1445:                  ofd = old + old_offset;
                   1446:                  nfd = new + new_offset;
                   1447:                }
                   1448:            }
                   1449:        }
                   1450:     }
                   1451:   else
                   1452: #endif
                   1453:   for (ofd = old, nfd = new;
                   1454:        (ofd - old < omax) && *ofd && (*ofd == *nfd);
                   1455:        ofd++, nfd++)
                   1456:     ;
                   1457: 
                   1458:   /* Move to the end of the screen line.  ND and OD are used to keep track
                   1459:      of the distance between ne and new and oe and old, respectively, to
                   1460:      move a subtraction out of each loop. */
                   1461:   for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
                   1462:   for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
                   1463: 
                   1464:   /* If no difference, continue to next line. */
                   1465:   if (ofd == oe && nfd == ne)
                   1466:     return;
                   1467: 
                   1468: #if defined (HANDLE_MULTIBYTE)
                   1469:   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0 && _rl_utf8locale)
                   1470:     {
                   1471:       wchar_t wc;
                   1472:       mbstate_t ps = { 0 };
                   1473:       int t;
                   1474: 
                   1475:       /* If the first character in the difference is a zero-width character,
                   1476:         assume it's a combining character and back one up so the two base
                   1477:         characters no longer compare equivalently. */
                   1478:       t = mbrtowc (&wc, ofd, MB_CUR_MAX, &ps);
                   1479:       if (t > 0 && UNICODE_COMBINING_CHAR (wc) && WCWIDTH (wc) == 0)
                   1480:        {
                   1481:          old_offset = _rl_find_prev_mbchar (old, ofd - old, MB_FIND_ANY);
                   1482:          new_offset = _rl_find_prev_mbchar (new, nfd - new, MB_FIND_ANY);
                   1483:          ofd = old + old_offset;       /* equal by definition */
                   1484:          nfd = new + new_offset;
                   1485:        }
                   1486:     }
                   1487: #endif
                   1488: 
                   1489:   wsatend = 1;                 /* flag for trailing whitespace */
                   1490: 
                   1491: #if defined (HANDLE_MULTIBYTE)
                   1492:   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   1493:     {
                   1494:       ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY);
                   1495:       nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY);
                   1496: 
                   1497:       while ((ols > ofd) && (nls > nfd))
                   1498:        {
                   1499:          memset (&ps_old, 0, sizeof (mbstate_t));
                   1500:          memset (&ps_new, 0, sizeof (mbstate_t));
                   1501: 
                   1502: #if 0
                   1503:          /* On advice from jir@yamato.ibm.com */
                   1504:          _rl_adjust_point (old, ols - old, &ps_old);
                   1505:          _rl_adjust_point (new, nls - new, &ps_new);
                   1506: #endif
                   1507: 
                   1508:          if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0)
                   1509:            break;
                   1510: 
                   1511:          if (*ols == ' ')
                   1512:            wsatend = 0;
                   1513: 
                   1514:          ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY);
                   1515:          nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY);
                   1516:        }
                   1517:     }
                   1518:   else
                   1519:     {
                   1520: #endif /* HANDLE_MULTIBYTE */
                   1521:   ols = oe - 1;                        /* find last same */
                   1522:   nls = ne - 1;
                   1523:   while ((ols > ofd) && (nls > nfd) && (*ols == *nls))
                   1524:     {
                   1525:       if (*ols != ' ')
                   1526:        wsatend = 0;
                   1527:       ols--;
                   1528:       nls--;
                   1529:     }
                   1530: #if defined (HANDLE_MULTIBYTE)
                   1531:     }
                   1532: #endif
                   1533: 
                   1534:   if (wsatend)
                   1535:     {
                   1536:       ols = oe;
                   1537:       nls = ne;
                   1538:     }
                   1539: #if defined (HANDLE_MULTIBYTE)
                   1540:   /* This may not work for stateful encoding, but who cares?  To handle
                   1541:      stateful encoding properly, we have to scan each string from the
                   1542:      beginning and compare. */
                   1543:   else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0)
                   1544: #else
                   1545:   else if (*ols != *nls)
                   1546: #endif
                   1547:     {
                   1548:       if (*ols)                        /* don't step past the NUL */
                   1549:        {
                   1550:          if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   1551:            ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY);
                   1552:          else
                   1553:            ols++;
                   1554:        }
                   1555:       if (*nls)
                   1556:        {
                   1557:          if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   1558:            nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY);
                   1559:          else
                   1560:            nls++;
                   1561:        }
                   1562:     }
                   1563: 
                   1564:   /* count of invisible characters in the current invisible line. */
                   1565:   current_invis_chars = W_OFFSET (current_line, wrap_offset);
                   1566:   if (_rl_last_v_pos != current_line)
                   1567:     {
                   1568:       _rl_move_vert (current_line);
                   1569:       if ((MB_CUR_MAX == 1 || rl_byte_oriented) && current_line == 0 && visible_wrap_offset)
                   1570:        _rl_last_c_pos += visible_wrap_offset;
                   1571:     }
                   1572: 
                   1573:   /* If this is the first line and there are invisible characters in the
                   1574:      prompt string, and the prompt string has not changed, and the current
                   1575:      cursor position is before the last invisible character in the prompt,
                   1576:      and the index of the character to move to is past the end of the prompt
                   1577:      string, then redraw the entire prompt string.  We can only do this
                   1578:      reliably if the terminal supports a `cr' capability.
                   1579: 
                   1580:      This is not an efficiency hack -- there is a problem with redrawing
                   1581:      portions of the prompt string if they contain terminal escape
                   1582:      sequences (like drawing the `unbold' sequence without a corresponding
                   1583:      `bold') that manifests itself on certain terminals. */
                   1584: 
                   1585:   lendiff = local_prompt_len;
                   1586:   od = ofd - old;      /* index of first difference in visible line */
                   1587:   if (current_line == 0 && !_rl_horizontal_scroll_mode &&
                   1588:       _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 &&
                   1589:       od >= lendiff && _rl_last_c_pos < PROMPT_ENDING_INDEX)
                   1590:     {
                   1591: #if defined (__MSDOS__)
                   1592:       putc ('\r', rl_outstream);
                   1593: #else
                   1594:       tputs (_rl_term_cr, 1, _rl_output_character_function);
                   1595: #endif
                   1596:       if (modmark)
                   1597:        _rl_output_some_chars ("*", 1);
                   1598:       _rl_output_some_chars (local_prompt, lendiff);
                   1599:       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   1600:        {
                   1601:          /* We take wrap_offset into account here so we can pass correct
                   1602:             information to _rl_move_cursor_relative. */
                   1603:          _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff, 1) - wrap_offset + modmark;
                   1604:          cpos_adjusted = 1;
                   1605:        }
                   1606:       else
                   1607:        _rl_last_c_pos = lendiff + modmark;
                   1608:     }
                   1609: 
                   1610:   o_cpos = _rl_last_c_pos;
                   1611: 
                   1612:   /* When this function returns, _rl_last_c_pos is correct, and an absolute
                   1613:      cursor position in multibyte mode, but a buffer index when not in a
                   1614:      multibyte locale. */
                   1615:   _rl_move_cursor_relative (od, old);
                   1616: 
                   1617: #if defined (HANDLE_MULTIBYTE)
                   1618:   /* We need to indicate that the cursor position is correct in the presence of
                   1619:      invisible characters in the prompt string.  Let's see if setting this when
                   1620:      we make sure we're at the end of the drawn prompt string works. */
                   1621:   if (current_line == 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0 &&
                   1622:       (_rl_last_c_pos > 0 || o_cpos > 0) &&
                   1623:       _rl_last_c_pos == prompt_physical_chars)
                   1624:     cpos_adjusted = 1;
                   1625: #endif
                   1626: 
                   1627:   /* if (len (new) > len (old))
                   1628:      lendiff == difference in buffer (bytes)
                   1629:      col_lendiff == difference on screen (columns)
                   1630:      When not using multibyte characters, these are equal */
                   1631:   lendiff = (nls - nfd) - (ols - ofd);
                   1632:   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   1633:     col_lendiff = _rl_col_width (new, nfd - new, nls - new, 1) - _rl_col_width (old, ofd - old, ols - old, 1);
                   1634:   else
                   1635:     col_lendiff = lendiff;
                   1636: 
                   1637:   /* If we are changing the number of invisible characters in a line, and
                   1638:      the spot of first difference is before the end of the invisible chars,
                   1639:      lendiff needs to be adjusted. */
1.1.1.1.2.1! misho    1640:   if (current_line == 0 && /* !_rl_horizontal_scroll_mode && */
1.1       misho    1641:       current_invis_chars != visible_wrap_offset)
                   1642:     {
                   1643:       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   1644:        {
                   1645:          lendiff += visible_wrap_offset - current_invis_chars;
                   1646:          col_lendiff += visible_wrap_offset - current_invis_chars;
                   1647:        }
                   1648:       else
                   1649:        {
                   1650:          lendiff += visible_wrap_offset - current_invis_chars;
                   1651:          col_lendiff = lendiff;
                   1652:        }
                   1653:     }
                   1654: 
                   1655:   /* We use temp as a count of the number of bytes from the first difference
                   1656:      to the end of the new line.  col_temp is the corresponding number of
                   1657:      screen columns.  A `dumb' update moves to the spot of first difference
                   1658:      and writes TEMP bytes. */
                   1659:   /* Insert (diff (len (old), len (new)) ch. */
                   1660:   temp = ne - nfd;
                   1661:   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   1662:     col_temp = _rl_col_width (new, nfd - new, ne - new, 1);
                   1663:   else
                   1664:     col_temp = temp;
                   1665: 
                   1666:   /* how many bytes from the new line buffer to write to the display */
                   1667:   bytes_to_insert = nls - nfd;
                   1668: 
                   1669:   /* col_lendiff > 0 if we are adding characters to the line */
                   1670:   if (col_lendiff > 0) /* XXX - was lendiff */
                   1671:     {
                   1672:       /* Non-zero if we're increasing the number of lines. */
                   1673:       int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
                   1674:       /* If col_lendiff is > 0, implying that the new string takes up more
                   1675:         screen real estate than the old, but lendiff is < 0, meaning that it
                   1676:         takes fewer bytes, we need to just output the characters starting
                   1677:         from the first difference.  These will overwrite what is on the
                   1678:         display, so there's no reason to do a smart update.  This can really
                   1679:         only happen in a multibyte environment. */
                   1680:       if (lendiff < 0)
                   1681:        {
                   1682:          _rl_output_some_chars (nfd, temp);
                   1683:          _rl_last_c_pos += col_temp;   /* XXX - was _rl_col_width (nfd, 0, temp, 1); */
                   1684:          /* If nfd begins before any invisible characters in the prompt,
                   1685:             adjust _rl_last_c_pos to account for wrap_offset and set
                   1686:             cpos_adjusted to let the caller know. */
                   1687:          if (current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
                   1688:            {
                   1689:              _rl_last_c_pos -= wrap_offset;
                   1690:              cpos_adjusted = 1;
                   1691:            }
                   1692:          return;
                   1693:        }
                   1694:       /* Sometimes it is cheaper to print the characters rather than
                   1695:         use the terminal's capabilities.  If we're growing the number
                   1696:         of lines, make sure we actually cause the new line to wrap
                   1697:         around on auto-wrapping terminals. */
                   1698:       else if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
                   1699:        {
                   1700:          /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
                   1701:             _rl_horizontal_scroll_mode == 1, inserting the characters with
                   1702:             _rl_term_IC or _rl_term_ic will screw up the screen because of the
                   1703:             invisible characters.  We need to just draw them. */
                   1704:          /* The same thing happens if we're trying to draw before the last
                   1705:             invisible character in the prompt string or we're increasing the
                   1706:             number of invisible characters in the line and we're not drawing
                   1707:             the entire prompt string. */
                   1708:          if (*ols && ((_rl_horizontal_scroll_mode &&
                   1709:                        _rl_last_c_pos == 0 &&
                   1710:                        lendiff > prompt_visible_length &&
                   1711:                        current_invis_chars > 0) == 0) &&
                   1712:                      (((MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
                   1713:                        current_line == 0 && wrap_offset &&
                   1714:                        ((nfd - new) <= prompt_last_invisible) &&
                   1715:                        (col_lendiff < prompt_visible_length)) == 0) &&
                   1716:                      (visible_wrap_offset >= current_invis_chars))
                   1717:            {
                   1718:              open_some_spaces (col_lendiff);
                   1719:              _rl_output_some_chars (nfd, bytes_to_insert);
                   1720:              if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   1721:                _rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
                   1722:              else
                   1723:                _rl_last_c_pos += bytes_to_insert;
                   1724:            }
                   1725:          else if ((MB_CUR_MAX == 1 || rl_byte_oriented != 0) && *ols == 0 && lendiff > 0)
                   1726:            {
                   1727:              /* At the end of a line the characters do not have to
                   1728:                 be "inserted".  They can just be placed on the screen. */
                   1729:              _rl_output_some_chars (nfd, temp);
                   1730:              _rl_last_c_pos += col_temp;
                   1731:              return;
                   1732:            }
                   1733:          else  /* just write from first difference to end of new line */
                   1734:            {
                   1735:              _rl_output_some_chars (nfd, temp);
                   1736:              _rl_last_c_pos += col_temp;
                   1737:              /* If nfd begins before the last invisible character in the
                   1738:                 prompt, adjust _rl_last_c_pos to account for wrap_offset
                   1739:                 and set cpos_adjusted to let the caller know. */
                   1740:              if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
                   1741:                {
                   1742:                  _rl_last_c_pos -= wrap_offset;
                   1743:                  cpos_adjusted = 1;
                   1744:                }
                   1745:              return;
                   1746:            }
                   1747: 
                   1748:          if (bytes_to_insert > lendiff)
                   1749:            {
                   1750:              /* If nfd begins before the last invisible character in the
                   1751:                 prompt, adjust _rl_last_c_pos to account for wrap_offset
                   1752:                 and set cpos_adjusted to let the caller know. */
                   1753:              if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
                   1754:                {
                   1755:                  _rl_last_c_pos -= wrap_offset;
                   1756:                  cpos_adjusted = 1;
                   1757:                }
                   1758:            }
                   1759:        }
                   1760:       else
                   1761:        {
                   1762:          /* cannot insert chars, write to EOL */
                   1763:          _rl_output_some_chars (nfd, temp);
                   1764:          _rl_last_c_pos += col_temp;
                   1765:          /* If we're in a multibyte locale and were before the last invisible
                   1766:             char in the current line (which implies we just output some invisible
                   1767:             characters) we need to adjust _rl_last_c_pos, since it represents
                   1768:             a physical character position. */
                   1769:          if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
                   1770:                current_line == prompt_last_screen_line && wrap_offset &&
                   1771:                displaying_prompt_first_line &&
                   1772:                wrap_offset != prompt_invis_chars_first_line &&
                   1773:                ((nfd-new) < (prompt_last_invisible-(current_line*_rl_screenwidth))))
                   1774:            {
                   1775:              _rl_last_c_pos -= wrap_offset - prompt_invis_chars_first_line;
                   1776:              cpos_adjusted = 1;
                   1777:            }
                   1778:        }
                   1779:     }
                   1780:   else                         /* Delete characters from line. */
                   1781:     {
                   1782:       /* If possible and inexpensive to use terminal deletion, then do so. */
                   1783:       if (_rl_term_dc && (2 * col_temp) >= -col_lendiff)
                   1784:        {
                   1785:          /* If all we're doing is erasing the invisible characters in the
                   1786:             prompt string, don't bother.  It screws up the assumptions
                   1787:             about what's on the screen. */
                   1788:          if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
                   1789:              displaying_prompt_first_line &&
                   1790:              -lendiff == visible_wrap_offset)
                   1791:            col_lendiff = 0;
                   1792: 
                   1793:          /* If we have moved lmargin and we're shrinking the line, we've
                   1794:             already moved the cursor to the first character of the new line,
                   1795:             so deleting -col_lendiff characters will mess up the cursor
                   1796:             position calculation */
                   1797:          if (_rl_horizontal_scroll_mode && displaying_prompt_first_line == 0 &&
                   1798:                col_lendiff && _rl_last_c_pos < -col_lendiff)
                   1799:            col_lendiff = 0;
                   1800: 
                   1801:          if (col_lendiff)
                   1802:            delete_chars (-col_lendiff); /* delete (diff) characters */
                   1803: 
                   1804:          /* Copy (new) chars to screen from first diff to last match,
                   1805:             overwriting what is there. */
                   1806:          if (bytes_to_insert > 0)
                   1807:            {
                   1808:              /* If nfd begins at the prompt, or before the invisible
                   1809:                 characters in the prompt, we need to adjust _rl_last_c_pos
                   1810:                 in a multibyte locale to account for the wrap offset and
                   1811:                 set cpos_adjusted accordingly. */
                   1812:              _rl_output_some_chars (nfd, bytes_to_insert);
                   1813:              if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   1814:                {
                   1815:                  _rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
                   1816:                  if (current_line == 0 && wrap_offset &&
                   1817:                        displaying_prompt_first_line &&
                   1818:                        _rl_last_c_pos > wrap_offset &&
                   1819:                        ((nfd - new) <= prompt_last_invisible))
                   1820:                    {
                   1821:                      _rl_last_c_pos -= wrap_offset;
                   1822:                      cpos_adjusted = 1;
                   1823:                    }
                   1824:                }
                   1825:              else
                   1826:                _rl_last_c_pos += bytes_to_insert;
                   1827: 
1.1.1.1.2.1! misho    1828:              /* XXX - we only want to do this if we are at the end of the line
        !          1829:                 so we move there with _rl_move_cursor_relative */
1.1       misho    1830:              if (_rl_horizontal_scroll_mode && ((oe-old) > (ne-new)))
1.1.1.1.2.1! misho    1831:                {
        !          1832:                  _rl_move_cursor_relative (ne-new, new);
        !          1833:                  goto clear_rest_of_line;
        !          1834:                }
1.1       misho    1835:            }
                   1836:        }
                   1837:       /* Otherwise, print over the existing material. */
                   1838:       else
                   1839:        {
                   1840:          if (temp > 0)
                   1841:            {
                   1842:              /* If nfd begins at the prompt, or before the invisible
                   1843:                 characters in the prompt, we need to adjust _rl_last_c_pos
                   1844:                 in a multibyte locale to account for the wrap offset and
                   1845:                 set cpos_adjusted accordingly. */
                   1846:              _rl_output_some_chars (nfd, temp);
                   1847:              _rl_last_c_pos += col_temp;               /* XXX */
                   1848:              if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   1849:                {
                   1850:                  if (current_line == 0 && wrap_offset &&
                   1851:                        displaying_prompt_first_line &&
                   1852:                        _rl_last_c_pos > wrap_offset &&
                   1853:                        ((nfd - new) <= prompt_last_invisible))
                   1854:                    {
                   1855:                      _rl_last_c_pos -= wrap_offset;
                   1856:                      cpos_adjusted = 1;
                   1857:                    }
                   1858:                }
                   1859:            }
                   1860: clear_rest_of_line:
                   1861:          lendiff = (oe - old) - (ne - new);
                   1862:          if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   1863:            col_lendiff = _rl_col_width (old, 0, oe - old, 1) - _rl_col_width (new, 0, ne - new, 1);
                   1864:          else
                   1865:            col_lendiff = lendiff;
                   1866: 
                   1867:          /* If we've already printed over the entire width of the screen,
                   1868:             including the old material, then col_lendiff doesn't matter and
                   1869:             space_to_eol will insert too many spaces.  XXX - maybe we should
                   1870:             adjust col_lendiff based on the difference between _rl_last_c_pos
                   1871:             and _rl_screenwidth */
                   1872:          if (col_lendiff && ((MB_CUR_MAX == 1 || rl_byte_oriented) || (_rl_last_c_pos < _rl_screenwidth)))
                   1873:            {     
                   1874:              if (_rl_term_autowrap && current_line < inv_botlin)
                   1875:                space_to_eol (col_lendiff);
                   1876:              else
                   1877:                _rl_clear_to_eol (col_lendiff);
                   1878:            }
                   1879:        }
                   1880:     }
                   1881: }
                   1882: 
                   1883: /* Tell the update routines that we have moved onto a new (empty) line. */
                   1884: int
                   1885: rl_on_new_line ()
                   1886: {
                   1887:   if (visible_line)
                   1888:     visible_line[0] = '\0';
                   1889: 
                   1890:   _rl_last_c_pos = _rl_last_v_pos = 0;
                   1891:   _rl_vis_botlin = last_lmargin = 0;
                   1892:   if (vis_lbreaks)
                   1893:     vis_lbreaks[0] = vis_lbreaks[1] = 0;
                   1894:   visible_wrap_offset = 0;
                   1895:   return 0;
                   1896: }
                   1897: 
                   1898: /* Tell the update routines that we have moved onto a new line with the
                   1899:    prompt already displayed.  Code originally from the version of readline
                   1900:    distributed with CLISP.  rl_expand_prompt must have already been called
                   1901:    (explicitly or implicitly).  This still doesn't work exactly right. */
                   1902: int
                   1903: rl_on_new_line_with_prompt ()
                   1904: {
                   1905:   int prompt_size, i, l, real_screenwidth, newlines;
                   1906:   char *prompt_last_line, *lprompt;
                   1907: 
                   1908:   /* Initialize visible_line and invisible_line to ensure that they can hold
                   1909:      the already-displayed prompt. */
                   1910:   prompt_size = strlen (rl_prompt) + 1;
                   1911:   init_line_structures (prompt_size);
                   1912: 
                   1913:   /* Make sure the line structures hold the already-displayed prompt for
                   1914:      redisplay. */
                   1915:   lprompt = local_prompt ? local_prompt : rl_prompt;
                   1916:   strcpy (visible_line, lprompt);
                   1917:   strcpy (invisible_line, lprompt);
                   1918: 
                   1919:   /* If the prompt contains newlines, take the last tail. */
                   1920:   prompt_last_line = strrchr (rl_prompt, '\n');
                   1921:   if (!prompt_last_line)
                   1922:     prompt_last_line = rl_prompt;
                   1923: 
                   1924:   l = strlen (prompt_last_line);
                   1925:   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   1926:     _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l, 1);        /* XXX */
                   1927:   else
                   1928:     _rl_last_c_pos = l;
                   1929: 
                   1930:   /* Dissect prompt_last_line into screen lines. Note that here we have
                   1931:      to use the real screenwidth. Readline's notion of screenwidth might be
                   1932:      one less, see terminal.c. */
                   1933:   real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1);
                   1934:   _rl_last_v_pos = l / real_screenwidth;
                   1935:   /* If the prompt length is a multiple of real_screenwidth, we don't know
                   1936:      whether the cursor is at the end of the last line, or already at the
                   1937:      beginning of the next line. Output a newline just to be safe. */
                   1938:   if (l > 0 && (l % real_screenwidth) == 0)
                   1939:     _rl_output_some_chars ("\n", 1);
                   1940:   last_lmargin = 0;
                   1941: 
                   1942:   newlines = 0; i = 0;
                   1943:   while (i <= l)
                   1944:     {
                   1945:       _rl_vis_botlin = newlines;
                   1946:       vis_lbreaks[newlines++] = i;
                   1947:       i += real_screenwidth;
                   1948:     }
                   1949:   vis_lbreaks[newlines] = l;
                   1950:   visible_wrap_offset = 0;
                   1951: 
                   1952:   rl_display_prompt = rl_prompt;       /* XXX - make sure it's set */
                   1953: 
                   1954:   return 0;
                   1955: }
                   1956: 
                   1957: /* Actually update the display, period. */
                   1958: int
                   1959: rl_forced_update_display ()
                   1960: {
                   1961:   register char *temp;
                   1962: 
                   1963:   if (visible_line)
                   1964:     {
                   1965:       temp = visible_line;
                   1966:       while (*temp)
                   1967:        *temp++ = '\0';
                   1968:     }
                   1969:   rl_on_new_line ();
                   1970:   forced_display++;
                   1971:   (*rl_redisplay_function) ();
                   1972:   return 0;
                   1973: }
                   1974: 
                   1975: /* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
                   1976:    (Well, when we don't have multibyte characters, _rl_last_c_pos is a
                   1977:    buffer index.)
                   1978:    DATA is the contents of the screen line of interest; i.e., where
                   1979:    the movement is being done. */
                   1980: void
                   1981: _rl_move_cursor_relative (new, data)
                   1982:      int new;
                   1983:      const char *data;
                   1984: {
                   1985:   register int i;
                   1986:   int woff;                    /* number of invisible chars on current line */
                   1987:   int cpos, dpos;              /* current and desired cursor positions */
                   1988:   int adjust;
                   1989: 
                   1990:   woff = WRAP_OFFSET (_rl_last_v_pos, wrap_offset);
                   1991:   cpos = _rl_last_c_pos;
                   1992: 
                   1993:   if (cpos == 0 && cpos == new)
                   1994:     return;
                   1995: 
                   1996: #if defined (HANDLE_MULTIBYTE)
                   1997:   /* If we have multibyte characters, NEW is indexed by the buffer point in
                   1998:      a multibyte string, but _rl_last_c_pos is the display position.  In
                   1999:      this case, NEW's display position is not obvious and must be
                   2000:      calculated.  We need to account for invisible characters in this line,
                   2001:      as long as we are past them and they are counted by _rl_col_width. */
                   2002:   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   2003:     {
                   2004:       adjust = 1;
                   2005:       /* Try to short-circuit common cases and eliminate a bunch of multibyte
                   2006:         character function calls. */
                   2007:       /* 1.  prompt string */
                   2008:       if (new == local_prompt_len && memcmp (data, local_prompt, new) == 0)
                   2009:        {
                   2010:          dpos = prompt_physical_chars;
                   2011:          cpos_adjusted = 1;
                   2012:          adjust = 0;
                   2013:        }
                   2014:       /* 2.  prompt_string + line contents */
                   2015:       else if (new > local_prompt_len && local_prompt && memcmp (data, local_prompt, local_prompt_len) == 0)
                   2016:        {
                   2017:          dpos = prompt_physical_chars + _rl_col_width (data, local_prompt_len, new, 1);
                   2018:          cpos_adjusted = 1;
                   2019:          adjust = 0;
                   2020:        }
                   2021:       else
                   2022:         dpos = _rl_col_width (data, 0, new, 1);
                   2023: 
                   2024:       if (displaying_prompt_first_line == 0)
                   2025:        adjust = 0;
                   2026: 
                   2027:       /* Use NEW when comparing against the last invisible character in the
                   2028:         prompt string, since they're both buffer indices and DPOS is a
                   2029:         desired display position. */
                   2030:       if (adjust && ((new > prompt_last_invisible) ||          /* XXX - don't use woff here */
                   2031:          (prompt_physical_chars >= _rl_screenwidth &&
                   2032:           _rl_last_v_pos == prompt_last_screen_line &&
                   2033:           wrap_offset >= woff && dpos >= woff &&
                   2034:           new > (prompt_last_invisible-(_rl_screenwidth*_rl_last_v_pos)-wrap_offset))))
                   2035:           /* XXX last comparison might need to be >= */
                   2036:        {
                   2037:          dpos -= woff;
                   2038:          /* Since this will be assigned to _rl_last_c_pos at the end (more
                   2039:             precisely, _rl_last_c_pos == dpos when this function returns),
                   2040:             let the caller know. */
                   2041:          cpos_adjusted = 1;
                   2042:        }
                   2043:     }
                   2044:   else
                   2045: #endif
                   2046:     dpos = new;
                   2047: 
                   2048:   /* If we don't have to do anything, then return. */
                   2049:   if (cpos == dpos)
                   2050:     return;
                   2051: 
                   2052:   /* It may be faster to output a CR, and then move forwards instead
                   2053:      of moving backwards. */
                   2054:   /* i == current physical cursor position. */
                   2055: #if defined (HANDLE_MULTIBYTE)
                   2056:   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   2057:     i = _rl_last_c_pos;
                   2058:   else
                   2059: #endif
                   2060:   i = _rl_last_c_pos - woff;
                   2061:   if (dpos == 0 || CR_FASTER (dpos, _rl_last_c_pos) ||
                   2062:       (_rl_term_autowrap && i == _rl_screenwidth))
                   2063:     {
                   2064: #if defined (__MSDOS__)
                   2065:       putc ('\r', rl_outstream);
                   2066: #else
                   2067:       tputs (_rl_term_cr, 1, _rl_output_character_function);
                   2068: #endif /* !__MSDOS__ */
                   2069:       cpos = _rl_last_c_pos = 0;
                   2070:     }
                   2071: 
                   2072:   if (cpos < dpos)
                   2073:     {
                   2074:       /* Move the cursor forward.  We do it by printing the command
                   2075:         to move the cursor forward if there is one, else print that
                   2076:         portion of the output buffer again.  Which is cheaper? */
                   2077: 
                   2078:       /* The above comment is left here for posterity.  It is faster
                   2079:         to print one character (non-control) than to print a control
                   2080:         sequence telling the terminal to move forward one character.
                   2081:         That kind of control is for people who don't know what the
                   2082:         data is underneath the cursor. */
                   2083: 
                   2084:       /* However, we need a handle on where the current display position is
                   2085:         in the buffer for the immediately preceding comment to be true.
                   2086:         In multibyte locales, we don't currently have that info available.
                   2087:         Without it, we don't know where the data we have to display begins
                   2088:         in the buffer and we have to go back to the beginning of the screen
                   2089:         line.  In this case, we can use the terminal sequence to move forward
                   2090:         if it's available. */
                   2091:       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   2092:        {
                   2093:          if (_rl_term_forward_char)
                   2094:            {
                   2095:              for (i = cpos; i < dpos; i++)
                   2096:                tputs (_rl_term_forward_char, 1, _rl_output_character_function);
                   2097:            }
                   2098:          else
                   2099:            {
                   2100:              tputs (_rl_term_cr, 1, _rl_output_character_function);
                   2101:              for (i = 0; i < new; i++)
                   2102:                putc (data[i], rl_outstream);
                   2103:            }
                   2104:        }
                   2105:       else
                   2106:        for (i = cpos; i < new; i++)
                   2107:          putc (data[i], rl_outstream);
                   2108:     }
                   2109: 
                   2110: #if defined (HANDLE_MULTIBYTE)
                   2111:   /* NEW points to the buffer point, but _rl_last_c_pos is the display point.
                   2112:      The byte length of the string is probably bigger than the column width
                   2113:      of the string, which means that if NEW == _rl_last_c_pos, then NEW's
                   2114:      display point is less than _rl_last_c_pos. */
                   2115: #endif
                   2116:   else if (cpos > dpos)
                   2117:     _rl_backspace (cpos - dpos);
                   2118: 
                   2119:   _rl_last_c_pos = dpos;
                   2120: }
                   2121: 
                   2122: /* PWP: move the cursor up or down. */
                   2123: void
                   2124: _rl_move_vert (to)
                   2125:      int to;
                   2126: {
                   2127:   register int delta, i;
                   2128: 
                   2129:   if (_rl_last_v_pos == to || to > _rl_screenheight)
                   2130:     return;
                   2131: 
                   2132:   if ((delta = to - _rl_last_v_pos) > 0)
                   2133:     {
                   2134:       for (i = 0; i < delta; i++)
                   2135:        putc ('\n', rl_outstream);
                   2136: #if defined (__MSDOS__)
                   2137:       putc ('\r', rl_outstream);
                   2138: #else
                   2139:       tputs (_rl_term_cr, 1, _rl_output_character_function);
                   2140: #endif
                   2141:       _rl_last_c_pos = 0;
                   2142:     }
                   2143:   else
                   2144:     {                  /* delta < 0 */
                   2145: #ifdef __DJGPP__
                   2146:       int row, col;
                   2147: 
                   2148:       fflush (rl_outstream);
                   2149:       ScreenGetCursor (&row, &col);
                   2150:       ScreenSetCursor (row + delta, col);
                   2151:       i = -delta;
                   2152: #else
                   2153:       if (_rl_term_up && *_rl_term_up)
                   2154:        for (i = 0; i < -delta; i++)
                   2155:          tputs (_rl_term_up, 1, _rl_output_character_function);
                   2156: #endif /* !__DJGPP__ */
                   2157:     }
                   2158: 
                   2159:   _rl_last_v_pos = to;         /* Now TO is here */
                   2160: }
                   2161: 
                   2162: /* Physically print C on rl_outstream.  This is for functions which know
                   2163:    how to optimize the display.  Return the number of characters output. */
                   2164: int
                   2165: rl_show_char (c)
                   2166:      int c;
                   2167: {
                   2168:   int n = 1;
                   2169:   if (META_CHAR (c) && (_rl_output_meta_chars == 0))
                   2170:     {
                   2171:       fprintf (rl_outstream, "M-");
                   2172:       n += 2;
                   2173:       c = UNMETA (c);
                   2174:     }
                   2175: 
                   2176: #if defined (DISPLAY_TABS)
                   2177:   if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
                   2178: #else
                   2179:   if (CTRL_CHAR (c) || c == RUBOUT)
                   2180: #endif /* !DISPLAY_TABS */
                   2181:     {
                   2182:       fprintf (rl_outstream, "C-");
                   2183:       n += 2;
                   2184:       c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
                   2185:     }
                   2186: 
                   2187:   putc (c, rl_outstream);
                   2188:   fflush (rl_outstream);
                   2189:   return n;
                   2190: }
                   2191: 
                   2192: int
                   2193: rl_character_len (c, pos)
                   2194:      register int c, pos;
                   2195: {
                   2196:   unsigned char uc;
                   2197: 
                   2198:   uc = (unsigned char)c;
                   2199: 
                   2200:   if (META_CHAR (uc))
                   2201:     return ((_rl_output_meta_chars == 0) ? 4 : 1);
                   2202: 
                   2203:   if (uc == '\t')
                   2204:     {
                   2205: #if defined (DISPLAY_TABS)
                   2206:       return (((pos | 7) + 1) - pos);
                   2207: #else
                   2208:       return (2);
                   2209: #endif /* !DISPLAY_TABS */
                   2210:     }
                   2211: 
                   2212:   if (CTRL_CHAR (c) || c == RUBOUT)
                   2213:     return (2);
                   2214: 
                   2215:   return ((ISPRINT (uc)) ? 1 : 2);
                   2216: }
                   2217: /* How to print things in the "echo-area".  The prompt is treated as a
                   2218:    mini-modeline. */
                   2219: static int msg_saved_prompt = 0;
                   2220: 
                   2221: #if defined (USE_VARARGS)
                   2222: int
                   2223: #if defined (PREFER_STDARG)
                   2224: rl_message (const char *format, ...)
                   2225: #else
                   2226: rl_message (va_alist)
                   2227:      va_dcl
                   2228: #endif
                   2229: {
                   2230:   va_list args;
                   2231: #if defined (PREFER_VARARGS)
                   2232:   char *format;
                   2233: #endif
                   2234: #if defined (HAVE_VSNPRINTF)
                   2235:   int bneed;
                   2236: #endif
                   2237: 
                   2238: #if defined (PREFER_STDARG)
                   2239:   va_start (args, format);
                   2240: #else
                   2241:   va_start (args);
                   2242:   format = va_arg (args, char *);
                   2243: #endif
                   2244: 
                   2245:   if (msg_buf == 0)
                   2246:     msg_buf = xmalloc (msg_bufsiz = 128);
                   2247: 
                   2248: #if defined (HAVE_VSNPRINTF)
                   2249:   bneed = vsnprintf (msg_buf, msg_bufsiz - 1, format, args);
                   2250:   if (bneed >= msg_bufsiz - 1)
                   2251:     {
                   2252:       msg_bufsiz = bneed + 1;
                   2253:       msg_buf = xrealloc (msg_buf, msg_bufsiz);
                   2254:       va_end (args);
                   2255: 
                   2256: #if defined (PREFER_STDARG)
                   2257:       va_start (args, format);
                   2258: #else
                   2259:       va_start (args);
                   2260:       format = va_arg (args, char *);
                   2261: #endif
                   2262:       vsnprintf (msg_buf, msg_bufsiz - 1, format, args);
                   2263:     }
                   2264: #else
                   2265:   vsprintf (msg_buf, format, args);
                   2266:   msg_buf[msg_bufsiz - 1] = '\0';      /* overflow? */
                   2267: #endif
                   2268:   va_end (args);
                   2269: 
                   2270:   if (saved_local_prompt == 0)
                   2271:     {
                   2272:       rl_save_prompt ();
                   2273:       msg_saved_prompt = 1;
                   2274:     }
                   2275:   else if (local_prompt != saved_local_prompt)
                   2276:     {
                   2277:       FREE (local_prompt);
                   2278:       FREE (local_prompt_prefix);
                   2279:       local_prompt = (char *)NULL;
                   2280:     }
                   2281:   rl_display_prompt = msg_buf;
                   2282:   local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
                   2283:                                         &prompt_last_invisible,
                   2284:                                         &prompt_invis_chars_first_line,
                   2285:                                         &prompt_physical_chars);
                   2286:   local_prompt_prefix = (char *)NULL;
                   2287:   local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
                   2288:   (*rl_redisplay_function) ();
                   2289: 
                   2290:   return 0;
                   2291: }
                   2292: #else /* !USE_VARARGS */
                   2293: int
                   2294: rl_message (format, arg1, arg2)
                   2295:      char *format;
                   2296: {
                   2297:   if (msg_buf == 0)
                   2298:     msg_buf = xmalloc (msg_bufsiz = 128);
                   2299: 
                   2300:   sprintf (msg_buf, format, arg1, arg2);
                   2301:   msg_buf[msg_bufsiz - 1] = '\0';      /* overflow? */
                   2302: 
                   2303:   rl_display_prompt = msg_buf;
                   2304:   if (saved_local_prompt == 0)
                   2305:     {
                   2306:       rl_save_prompt ();
                   2307:       msg_saved_prompt = 1;
                   2308:     }
                   2309:   else if (local_prompt != saved_local_prompt)
                   2310:     {
                   2311:       FREE (local_prompt);
                   2312:       FREE (local_prompt_prefix);
                   2313:       local_prompt = (char *)NULL;
                   2314:     }
                   2315:   local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
                   2316:                                         &prompt_last_invisible,
                   2317:                                         &prompt_invis_chars_first_line,
                   2318:                                         &prompt_physical_chars);
                   2319:   local_prompt_prefix = (char *)NULL;
                   2320:   local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
                   2321:   (*rl_redisplay_function) ();
                   2322:       
                   2323:   return 0;
                   2324: }
                   2325: #endif /* !USE_VARARGS */
                   2326: 
                   2327: /* How to clear things from the "echo-area". */
                   2328: int
                   2329: rl_clear_message ()
                   2330: {
                   2331:   rl_display_prompt = rl_prompt;
                   2332:   if (msg_saved_prompt)
                   2333:     {
                   2334:       rl_restore_prompt ();
                   2335:       msg_saved_prompt = 0;
                   2336:     }
                   2337:   (*rl_redisplay_function) ();
                   2338:   return 0;
                   2339: }
                   2340: 
                   2341: int
                   2342: rl_reset_line_state ()
                   2343: {
                   2344:   rl_on_new_line ();
                   2345: 
                   2346:   rl_display_prompt = rl_prompt ? rl_prompt : "";
                   2347:   forced_display = 1;
                   2348:   return 0;
                   2349: }
                   2350: 
                   2351: void
                   2352: rl_save_prompt ()
                   2353: {
                   2354:   saved_local_prompt = local_prompt;
                   2355:   saved_local_prefix = local_prompt_prefix;
                   2356:   saved_prefix_length = prompt_prefix_length;
                   2357:   saved_local_length = local_prompt_len;
                   2358:   saved_last_invisible = prompt_last_invisible;
                   2359:   saved_visible_length = prompt_visible_length;
                   2360:   saved_invis_chars_first_line = prompt_invis_chars_first_line;
                   2361:   saved_physical_chars = prompt_physical_chars;
                   2362: 
                   2363:   local_prompt = local_prompt_prefix = (char *)0;
                   2364:   local_prompt_len = 0;
                   2365:   prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0;
                   2366:   prompt_invis_chars_first_line = prompt_physical_chars = 0;
                   2367: }
                   2368: 
                   2369: void
                   2370: rl_restore_prompt ()
                   2371: {
                   2372:   FREE (local_prompt);
                   2373:   FREE (local_prompt_prefix);
                   2374: 
                   2375:   local_prompt = saved_local_prompt;
                   2376:   local_prompt_prefix = saved_local_prefix;
                   2377:   local_prompt_len = saved_local_length;
                   2378:   prompt_prefix_length = saved_prefix_length;
                   2379:   prompt_last_invisible = saved_last_invisible;
                   2380:   prompt_visible_length = saved_visible_length;
                   2381:   prompt_invis_chars_first_line = saved_invis_chars_first_line;
                   2382:   prompt_physical_chars = saved_physical_chars;
                   2383: 
                   2384:   /* can test saved_local_prompt to see if prompt info has been saved. */
                   2385:   saved_local_prompt = saved_local_prefix = (char *)0;
                   2386:   saved_local_length = 0;
                   2387:   saved_last_invisible = saved_visible_length = saved_prefix_length = 0;
                   2388:   saved_invis_chars_first_line = saved_physical_chars = 0;
                   2389: }
                   2390: 
                   2391: char *
                   2392: _rl_make_prompt_for_search (pchar)
                   2393:      int pchar;
                   2394: {
                   2395:   int len;
                   2396:   char *pmt, *p;
                   2397: 
                   2398:   rl_save_prompt ();
                   2399: 
                   2400:   /* We've saved the prompt, and can do anything with the various prompt
                   2401:      strings we need before they're restored.  We want the unexpanded
                   2402:      portion of the prompt string after any final newline. */
                   2403:   p = rl_prompt ? strrchr (rl_prompt, '\n') : 0;
                   2404:   if (p == 0)
                   2405:     {
                   2406:       len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
                   2407:       pmt = (char *)xmalloc (len + 2);
                   2408:       if (len)
                   2409:        strcpy (pmt, rl_prompt);
                   2410:       pmt[len] = pchar;
                   2411:       pmt[len+1] = '\0';
                   2412:     }
                   2413:   else
                   2414:     {
                   2415:       p++;
                   2416:       len = strlen (p);
                   2417:       pmt = (char *)xmalloc (len + 2);
                   2418:       if (len)
                   2419:        strcpy (pmt, p);
                   2420:       pmt[len] = pchar;
                   2421:       pmt[len+1] = '\0';
                   2422:     }  
                   2423: 
                   2424:   /* will be overwritten by expand_prompt, called from rl_message */
                   2425:   prompt_physical_chars = saved_physical_chars + 1;
                   2426:   return pmt;
                   2427: }
                   2428: 
                   2429: /* Quick redisplay hack when erasing characters at the end of the line. */
                   2430: void
                   2431: _rl_erase_at_end_of_line (l)
                   2432:      int l;
                   2433: {
                   2434:   register int i;
                   2435: 
                   2436:   _rl_backspace (l);
                   2437:   for (i = 0; i < l; i++)
                   2438:     putc (' ', rl_outstream);
                   2439:   _rl_backspace (l);
                   2440:   for (i = 0; i < l; i++)
                   2441:     visible_line[--_rl_last_c_pos] = '\0';
                   2442:   rl_display_fixed++;
                   2443: }
                   2444: 
                   2445: /* Clear to the end of the line.  COUNT is the minimum
                   2446:    number of character spaces to clear, */
                   2447: void
                   2448: _rl_clear_to_eol (count)
                   2449:      int count;
                   2450: {
                   2451: #ifndef __MSDOS__
                   2452:   if (_rl_term_clreol)
                   2453:     tputs (_rl_term_clreol, 1, _rl_output_character_function);
                   2454:   else
                   2455: #endif
                   2456:     if (count)
                   2457:       space_to_eol (count);
                   2458: }
                   2459: 
                   2460: /* Clear to the end of the line using spaces.  COUNT is the minimum
                   2461:    number of character spaces to clear, */
                   2462: static void
                   2463: space_to_eol (count)
                   2464:      int count;
                   2465: {
                   2466:   register int i;
                   2467: 
                   2468:   for (i = 0; i < count; i++)
                   2469:    putc (' ', rl_outstream);
                   2470: 
                   2471:   _rl_last_c_pos += count;
                   2472: }
                   2473: 
                   2474: void
                   2475: _rl_clear_screen ()
                   2476: {
                   2477: #ifndef __DJGPP__
                   2478:   if (_rl_term_clrpag)
                   2479:     tputs (_rl_term_clrpag, 1, _rl_output_character_function);
                   2480:   else
                   2481:     rl_crlf ();
                   2482: #else
                   2483:   ScreenClear ();
                   2484:   ScreenSetCursor (0, 0);
                   2485: #endif /* __DJGPP__ */
                   2486: }
                   2487: 
                   2488: /* Insert COUNT characters from STRING to the output stream at column COL. */
                   2489: static void
                   2490: insert_some_chars (string, count, col)
                   2491:      char *string;
                   2492:      int count, col;
                   2493: {
                   2494:   open_some_spaces (col);
                   2495:   _rl_output_some_chars (string, count);
                   2496: }
                   2497: 
                   2498: /* Insert COL spaces, keeping the cursor at the same position.  We follow the
                   2499:    ncurses documentation and use either im/ei with explicit spaces, or IC/ic
                   2500:    by itself.  We assume there will either be ei or we don't need to use it. */
                   2501: static void
                   2502: open_some_spaces (col)
                   2503:      int col;
                   2504: {
                   2505: #if !defined (__MSDOS__) && !defined (__MINGW32__)
                   2506:   char *buffer;
                   2507:   register int i;
                   2508: 
                   2509:   /* If IC is defined, then we do not have to "enter" insert mode. */
                   2510:   if (_rl_term_IC)
                   2511:     {
                   2512:       buffer = tgoto (_rl_term_IC, 0, col);
                   2513:       tputs (buffer, 1, _rl_output_character_function);
                   2514:     }
                   2515:   else if (_rl_term_im && *_rl_term_im)
                   2516:     {
                   2517:       tputs (_rl_term_im, 1, _rl_output_character_function);
                   2518:       /* just output the desired number of spaces */
                   2519:       for (i = col; i--; )
                   2520:        _rl_output_character_function (' ');
                   2521:       /* If there is a string to turn off insert mode, use it now. */
                   2522:       if (_rl_term_ei && *_rl_term_ei)
                   2523:        tputs (_rl_term_ei, 1, _rl_output_character_function);
                   2524:       /* and move back the right number of spaces */
                   2525:       _rl_backspace (col);
                   2526:     }
                   2527:   else if (_rl_term_ic && *_rl_term_ic)
                   2528:     {
                   2529:       /* If there is a special command for inserting characters, then
                   2530:         use that first to open up the space. */
                   2531:       for (i = col; i--; )
                   2532:        tputs (_rl_term_ic, 1, _rl_output_character_function);
                   2533:     }
                   2534: #endif /* !__MSDOS__ && !__MINGW32__ */
                   2535: }
                   2536: 
                   2537: /* Delete COUNT characters from the display line. */
                   2538: static void
                   2539: delete_chars (count)
                   2540:      int count;
                   2541: {
                   2542:   if (count > _rl_screenwidth) /* XXX */
                   2543:     return;
                   2544: 
                   2545: #if !defined (__MSDOS__) && !defined (__MINGW32__)
                   2546:   if (_rl_term_DC && *_rl_term_DC)
                   2547:     {
                   2548:       char *buffer;
                   2549:       buffer = tgoto (_rl_term_DC, count, count);
                   2550:       tputs (buffer, count, _rl_output_character_function);
                   2551:     }
                   2552:   else
                   2553:     {
                   2554:       if (_rl_term_dc && *_rl_term_dc)
                   2555:        while (count--)
                   2556:          tputs (_rl_term_dc, 1, _rl_output_character_function);
                   2557:     }
                   2558: #endif /* !__MSDOS__ && !__MINGW32__ */
                   2559: }
                   2560: 
                   2561: void
                   2562: _rl_update_final ()
                   2563: {
                   2564:   int full_lines;
                   2565: 
                   2566:   full_lines = 0;
                   2567:   /* If the cursor is the only thing on an otherwise-blank last line,
                   2568:      compensate so we don't print an extra CRLF. */
                   2569:   if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
                   2570:        visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
                   2571:     {
                   2572:       _rl_vis_botlin--;
                   2573:       full_lines = 1;
                   2574:     }
                   2575:   _rl_move_vert (_rl_vis_botlin);
                   2576:   /* If we've wrapped lines, remove the final xterm line-wrap flag. */
                   2577:   if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth))
                   2578:     {
                   2579:       char *last_line;
                   2580: 
                   2581:       last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]];
                   2582:       cpos_buffer_position = -1;       /* don't know where we are in buffer */
                   2583:       _rl_move_cursor_relative (_rl_screenwidth - 1, last_line);       /* XXX */
                   2584:       _rl_clear_to_eol (0);
                   2585:       putc (last_line[_rl_screenwidth - 1], rl_outstream);
                   2586:     }
                   2587:   _rl_vis_botlin = 0;
                   2588:   rl_crlf ();
                   2589:   fflush (rl_outstream);
                   2590:   rl_display_fixed++;
                   2591: }
                   2592: 
                   2593: /* Move to the start of the current line. */
                   2594: static void
                   2595: cr ()
                   2596: {
                   2597:   if (_rl_term_cr)
                   2598:     {
                   2599: #if defined (__MSDOS__)
                   2600:       putc ('\r', rl_outstream);
                   2601: #else
                   2602:       tputs (_rl_term_cr, 1, _rl_output_character_function);
                   2603: #endif
                   2604:       _rl_last_c_pos = 0;
                   2605:     }
                   2606: }
                   2607: 
                   2608: /* Redraw the last line of a multi-line prompt that may possibly contain
                   2609:    terminal escape sequences.  Called with the cursor at column 0 of the
                   2610:    line to draw the prompt on. */
                   2611: static void
                   2612: redraw_prompt (t)
                   2613:      char *t;
                   2614: {
                   2615:   char *oldp;
                   2616: 
                   2617:   oldp = rl_display_prompt;
                   2618:   rl_save_prompt ();
                   2619: 
                   2620:   rl_display_prompt = t;
                   2621:   local_prompt = expand_prompt (t, &prompt_visible_length,
                   2622:                                   &prompt_last_invisible,
                   2623:                                   &prompt_invis_chars_first_line,
                   2624:                                   &prompt_physical_chars);
                   2625:   local_prompt_prefix = (char *)NULL;
                   2626:   local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
                   2627: 
                   2628:   rl_forced_update_display ();
                   2629: 
                   2630:   rl_display_prompt = oldp;
                   2631:   rl_restore_prompt();
                   2632: }
                   2633:       
                   2634: /* Redisplay the current line after a SIGWINCH is received. */
                   2635: void
                   2636: _rl_redisplay_after_sigwinch ()
                   2637: {
                   2638:   char *t;
                   2639: 
                   2640:   /* Clear the last line (assuming that the screen size change will result in
                   2641:      either more or fewer characters on that line only) and put the cursor at
                   2642:      column 0.  Make sure the right thing happens if we have wrapped to a new
                   2643:      screen line. */
                   2644:   if (_rl_term_cr)
                   2645:     {
                   2646:       _rl_move_vert (_rl_vis_botlin);
                   2647: 
                   2648: #if defined (__MSDOS__)
                   2649:       putc ('\r', rl_outstream);
                   2650: #else
                   2651:       tputs (_rl_term_cr, 1, _rl_output_character_function);
                   2652: #endif
                   2653:       _rl_last_c_pos = 0;
                   2654: #if defined (__MSDOS__)
                   2655:       space_to_eol (_rl_screenwidth);
                   2656:       putc ('\r', rl_outstream);
                   2657: #else
                   2658:       if (_rl_term_clreol)
                   2659:        tputs (_rl_term_clreol, 1, _rl_output_character_function);
                   2660:       else
                   2661:        {
                   2662:          space_to_eol (_rl_screenwidth);
                   2663:          tputs (_rl_term_cr, 1, _rl_output_character_function);
                   2664:        }
                   2665: #endif
                   2666:       if (_rl_last_v_pos > 0)
                   2667:        _rl_move_vert (0);
                   2668:     }
                   2669:   else
                   2670:     rl_crlf ();
                   2671: 
                   2672:   /* Redraw only the last line of a multi-line prompt. */
                   2673:   t = strrchr (rl_display_prompt, '\n');
                   2674:   if (t)
                   2675:     redraw_prompt (++t);
                   2676:   else
                   2677:     rl_forced_update_display ();
                   2678: }
                   2679: 
                   2680: void
                   2681: _rl_clean_up_for_exit ()
                   2682: {
                   2683:   if (_rl_echoing_p)
                   2684:     {
1.1.1.1.2.1! misho    2685:       if (_rl_vis_botlin > 0)  /* minor optimization plus bug fix */
        !          2686:        _rl_move_vert (_rl_vis_botlin);
1.1       misho    2687:       _rl_vis_botlin = 0;
                   2688:       fflush (rl_outstream);
                   2689:       rl_restart_output (1, 0);
                   2690:     }
                   2691: }
                   2692: 
                   2693: void
                   2694: _rl_erase_entire_line ()
                   2695: {
                   2696:   cr ();
                   2697:   _rl_clear_to_eol (0);
                   2698:   cr ();
                   2699:   fflush (rl_outstream);
                   2700: }
                   2701: 
                   2702: /* return the `current display line' of the cursor -- the number of lines to
                   2703:    move up to get to the first screen line of the current readline line. */
                   2704: int
                   2705: _rl_current_display_line ()
                   2706: {
                   2707:   int ret, nleft;
                   2708: 
                   2709:   /* Find out whether or not there might be invisible characters in the
                   2710:      editing buffer. */
                   2711:   if (rl_display_prompt == rl_prompt)
                   2712:     nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length;
                   2713:   else
                   2714:     nleft = _rl_last_c_pos - _rl_screenwidth;
                   2715: 
                   2716:   if (nleft > 0)
                   2717:     ret = 1 + nleft / _rl_screenwidth;
                   2718:   else
                   2719:     ret = 0;
                   2720: 
                   2721:   return ret;
                   2722: }
                   2723: 
                   2724: #if defined (HANDLE_MULTIBYTE)
                   2725: /* Calculate the number of screen columns occupied by STR from START to END.
                   2726:    In the case of multibyte characters with stateful encoding, we have to
                   2727:    scan from the beginning of the string to take the state into account. */
                   2728: static int
                   2729: _rl_col_width (str, start, end, flags)
                   2730:      const char *str;
                   2731:      int start, end, flags;
                   2732: {
                   2733:   wchar_t wc;
                   2734:   mbstate_t ps;
                   2735:   int tmp, point, width, max;
                   2736: 
                   2737:   if (end <= start)
                   2738:     return 0;
                   2739:   if (MB_CUR_MAX == 1 || rl_byte_oriented)
                   2740:     /* this can happen in some cases where it's inconvenient to check */
                   2741:     return (end - start);
                   2742: 
                   2743:   memset (&ps, 0, sizeof (mbstate_t));
                   2744: 
                   2745:   point = 0;
                   2746:   max = end;
                   2747: 
                   2748:   /* Try to short-circuit common cases.  The adjustment to remove wrap_offset
                   2749:      is done by the caller. */
                   2750:   /* 1.  prompt string */
                   2751:   if (flags && start == 0 && end == local_prompt_len && memcmp (str, local_prompt, local_prompt_len) == 0)
                   2752:     return (prompt_physical_chars + wrap_offset);
                   2753:   /* 2.  prompt string + line contents */
                   2754:   else if (flags && start == 0 && local_prompt_len > 0 && end > local_prompt_len && local_prompt && memcmp (str, local_prompt, local_prompt_len) == 0)
                   2755:     {
                   2756:       tmp = prompt_physical_chars + wrap_offset;
                   2757:       /* XXX - try to call ourselves recursively with non-prompt portion */
                   2758:       tmp += _rl_col_width (str, local_prompt_len, end, flags);
                   2759:       return (tmp);
                   2760:     }
                   2761: 
                   2762:   while (point < start)
                   2763:     {
                   2764:       tmp = mbrlen (str + point, max, &ps);
                   2765:       if (MB_INVALIDCH ((size_t)tmp))
                   2766:        {
                   2767:          /* In this case, the bytes are invalid or too short to compose a
                   2768:             multibyte character, so we assume that the first byte represents
                   2769:             a single character. */
                   2770:          point++;
                   2771:          max--;
                   2772: 
                   2773:          /* Clear the state of the byte sequence, because in this case the
                   2774:             effect of mbstate is undefined. */
                   2775:          memset (&ps, 0, sizeof (mbstate_t));
                   2776:        }
                   2777:       else if (MB_NULLWCH (tmp))
                   2778:        break;          /* Found '\0' */
                   2779:       else
                   2780:        {
                   2781:          point += tmp;
                   2782:          max -= tmp;
                   2783:        }
                   2784:     }
                   2785: 
                   2786:   /* If START is not a byte that starts a character, then POINT will be
                   2787:      greater than START.  In this case, assume that (POINT - START) gives
                   2788:      a byte count that is the number of columns of difference. */
                   2789:   width = point - start;
                   2790: 
                   2791:   while (point < end)
                   2792:     {
                   2793:       tmp = mbrtowc (&wc, str + point, max, &ps);
                   2794:       if (MB_INVALIDCH ((size_t)tmp))
                   2795:        {
                   2796:          /* In this case, the bytes are invalid or too short to compose a
                   2797:             multibyte character, so we assume that the first byte represents
                   2798:             a single character. */
                   2799:          point++;
                   2800:          max--;
                   2801: 
                   2802:          /* and assume that the byte occupies a single column. */
                   2803:          width++;
                   2804: 
                   2805:          /* Clear the state of the byte sequence, because in this case the
                   2806:             effect of mbstate is undefined. */
                   2807:          memset (&ps, 0, sizeof (mbstate_t));
                   2808:        }
                   2809:       else if (MB_NULLWCH (tmp))
                   2810:        break;                  /* Found '\0' */
                   2811:       else
                   2812:        {
                   2813:          point += tmp;
                   2814:          max -= tmp;
                   2815:          tmp = WCWIDTH(wc);
                   2816:          width += (tmp >= 0) ? tmp : 1;
                   2817:        }
                   2818:     }
                   2819: 
                   2820:   width += point - end;
                   2821: 
                   2822:   return width;
                   2823: }
                   2824: #endif /* HANDLE_MULTIBYTE */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>