Annotation of embedaddon/readline/display.c, revision 1.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. */
        !          1640:   if (current_line == 0 && !_rl_horizontal_scroll_mode &&
        !          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: 
        !          1828:              if (_rl_horizontal_scroll_mode && ((oe-old) > (ne-new)))
        !          1829:                goto clear_rest_of_line;
        !          1830:            }
        !          1831:        }
        !          1832:       /* Otherwise, print over the existing material. */
        !          1833:       else
        !          1834:        {
        !          1835:          if (temp > 0)
        !          1836:            {
        !          1837:              /* If nfd begins at the prompt, or before the invisible
        !          1838:                 characters in the prompt, we need to adjust _rl_last_c_pos
        !          1839:                 in a multibyte locale to account for the wrap offset and
        !          1840:                 set cpos_adjusted accordingly. */
        !          1841:              _rl_output_some_chars (nfd, temp);
        !          1842:              _rl_last_c_pos += col_temp;               /* XXX */
        !          1843:              if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
        !          1844:                {
        !          1845:                  if (current_line == 0 && wrap_offset &&
        !          1846:                        displaying_prompt_first_line &&
        !          1847:                        _rl_last_c_pos > wrap_offset &&
        !          1848:                        ((nfd - new) <= prompt_last_invisible))
        !          1849:                    {
        !          1850:                      _rl_last_c_pos -= wrap_offset;
        !          1851:                      cpos_adjusted = 1;
        !          1852:                    }
        !          1853:                }
        !          1854:            }
        !          1855: clear_rest_of_line:
        !          1856:          lendiff = (oe - old) - (ne - new);
        !          1857:          if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
        !          1858:            col_lendiff = _rl_col_width (old, 0, oe - old, 1) - _rl_col_width (new, 0, ne - new, 1);
        !          1859:          else
        !          1860:            col_lendiff = lendiff;
        !          1861: 
        !          1862:          /* If we've already printed over the entire width of the screen,
        !          1863:             including the old material, then col_lendiff doesn't matter and
        !          1864:             space_to_eol will insert too many spaces.  XXX - maybe we should
        !          1865:             adjust col_lendiff based on the difference between _rl_last_c_pos
        !          1866:             and _rl_screenwidth */
        !          1867:          if (col_lendiff && ((MB_CUR_MAX == 1 || rl_byte_oriented) || (_rl_last_c_pos < _rl_screenwidth)))
        !          1868:            {     
        !          1869:              if (_rl_term_autowrap && current_line < inv_botlin)
        !          1870:                space_to_eol (col_lendiff);
        !          1871:              else
        !          1872:                _rl_clear_to_eol (col_lendiff);
        !          1873:            }
        !          1874:        }
        !          1875:     }
        !          1876: }
        !          1877: 
        !          1878: /* Tell the update routines that we have moved onto a new (empty) line. */
        !          1879: int
        !          1880: rl_on_new_line ()
        !          1881: {
        !          1882:   if (visible_line)
        !          1883:     visible_line[0] = '\0';
        !          1884: 
        !          1885:   _rl_last_c_pos = _rl_last_v_pos = 0;
        !          1886:   _rl_vis_botlin = last_lmargin = 0;
        !          1887:   if (vis_lbreaks)
        !          1888:     vis_lbreaks[0] = vis_lbreaks[1] = 0;
        !          1889:   visible_wrap_offset = 0;
        !          1890:   return 0;
        !          1891: }
        !          1892: 
        !          1893: /* Tell the update routines that we have moved onto a new line with the
        !          1894:    prompt already displayed.  Code originally from the version of readline
        !          1895:    distributed with CLISP.  rl_expand_prompt must have already been called
        !          1896:    (explicitly or implicitly).  This still doesn't work exactly right. */
        !          1897: int
        !          1898: rl_on_new_line_with_prompt ()
        !          1899: {
        !          1900:   int prompt_size, i, l, real_screenwidth, newlines;
        !          1901:   char *prompt_last_line, *lprompt;
        !          1902: 
        !          1903:   /* Initialize visible_line and invisible_line to ensure that they can hold
        !          1904:      the already-displayed prompt. */
        !          1905:   prompt_size = strlen (rl_prompt) + 1;
        !          1906:   init_line_structures (prompt_size);
        !          1907: 
        !          1908:   /* Make sure the line structures hold the already-displayed prompt for
        !          1909:      redisplay. */
        !          1910:   lprompt = local_prompt ? local_prompt : rl_prompt;
        !          1911:   strcpy (visible_line, lprompt);
        !          1912:   strcpy (invisible_line, lprompt);
        !          1913: 
        !          1914:   /* If the prompt contains newlines, take the last tail. */
        !          1915:   prompt_last_line = strrchr (rl_prompt, '\n');
        !          1916:   if (!prompt_last_line)
        !          1917:     prompt_last_line = rl_prompt;
        !          1918: 
        !          1919:   l = strlen (prompt_last_line);
        !          1920:   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
        !          1921:     _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l, 1);        /* XXX */
        !          1922:   else
        !          1923:     _rl_last_c_pos = l;
        !          1924: 
        !          1925:   /* Dissect prompt_last_line into screen lines. Note that here we have
        !          1926:      to use the real screenwidth. Readline's notion of screenwidth might be
        !          1927:      one less, see terminal.c. */
        !          1928:   real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1);
        !          1929:   _rl_last_v_pos = l / real_screenwidth;
        !          1930:   /* If the prompt length is a multiple of real_screenwidth, we don't know
        !          1931:      whether the cursor is at the end of the last line, or already at the
        !          1932:      beginning of the next line. Output a newline just to be safe. */
        !          1933:   if (l > 0 && (l % real_screenwidth) == 0)
        !          1934:     _rl_output_some_chars ("\n", 1);
        !          1935:   last_lmargin = 0;
        !          1936: 
        !          1937:   newlines = 0; i = 0;
        !          1938:   while (i <= l)
        !          1939:     {
        !          1940:       _rl_vis_botlin = newlines;
        !          1941:       vis_lbreaks[newlines++] = i;
        !          1942:       i += real_screenwidth;
        !          1943:     }
        !          1944:   vis_lbreaks[newlines] = l;
        !          1945:   visible_wrap_offset = 0;
        !          1946: 
        !          1947:   rl_display_prompt = rl_prompt;       /* XXX - make sure it's set */
        !          1948: 
        !          1949:   return 0;
        !          1950: }
        !          1951: 
        !          1952: /* Actually update the display, period. */
        !          1953: int
        !          1954: rl_forced_update_display ()
        !          1955: {
        !          1956:   register char *temp;
        !          1957: 
        !          1958:   if (visible_line)
        !          1959:     {
        !          1960:       temp = visible_line;
        !          1961:       while (*temp)
        !          1962:        *temp++ = '\0';
        !          1963:     }
        !          1964:   rl_on_new_line ();
        !          1965:   forced_display++;
        !          1966:   (*rl_redisplay_function) ();
        !          1967:   return 0;
        !          1968: }
        !          1969: 
        !          1970: /* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
        !          1971:    (Well, when we don't have multibyte characters, _rl_last_c_pos is a
        !          1972:    buffer index.)
        !          1973:    DATA is the contents of the screen line of interest; i.e., where
        !          1974:    the movement is being done. */
        !          1975: void
        !          1976: _rl_move_cursor_relative (new, data)
        !          1977:      int new;
        !          1978:      const char *data;
        !          1979: {
        !          1980:   register int i;
        !          1981:   int woff;                    /* number of invisible chars on current line */
        !          1982:   int cpos, dpos;              /* current and desired cursor positions */
        !          1983:   int adjust;
        !          1984: 
        !          1985:   woff = WRAP_OFFSET (_rl_last_v_pos, wrap_offset);
        !          1986:   cpos = _rl_last_c_pos;
        !          1987: 
        !          1988:   if (cpos == 0 && cpos == new)
        !          1989:     return;
        !          1990: 
        !          1991: #if defined (HANDLE_MULTIBYTE)
        !          1992:   /* If we have multibyte characters, NEW is indexed by the buffer point in
        !          1993:      a multibyte string, but _rl_last_c_pos is the display position.  In
        !          1994:      this case, NEW's display position is not obvious and must be
        !          1995:      calculated.  We need to account for invisible characters in this line,
        !          1996:      as long as we are past them and they are counted by _rl_col_width. */
        !          1997:   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
        !          1998:     {
        !          1999:       adjust = 1;
        !          2000:       /* Try to short-circuit common cases and eliminate a bunch of multibyte
        !          2001:         character function calls. */
        !          2002:       /* 1.  prompt string */
        !          2003:       if (new == local_prompt_len && memcmp (data, local_prompt, new) == 0)
        !          2004:        {
        !          2005:          dpos = prompt_physical_chars;
        !          2006:          cpos_adjusted = 1;
        !          2007:          adjust = 0;
        !          2008:        }
        !          2009:       /* 2.  prompt_string + line contents */
        !          2010:       else if (new > local_prompt_len && local_prompt && memcmp (data, local_prompt, local_prompt_len) == 0)
        !          2011:        {
        !          2012:          dpos = prompt_physical_chars + _rl_col_width (data, local_prompt_len, new, 1);
        !          2013:          cpos_adjusted = 1;
        !          2014:          adjust = 0;
        !          2015:        }
        !          2016:       else
        !          2017:         dpos = _rl_col_width (data, 0, new, 1);
        !          2018: 
        !          2019:       if (displaying_prompt_first_line == 0)
        !          2020:        adjust = 0;
        !          2021: 
        !          2022:       /* Use NEW when comparing against the last invisible character in the
        !          2023:         prompt string, since they're both buffer indices and DPOS is a
        !          2024:         desired display position. */
        !          2025:       if (adjust && ((new > prompt_last_invisible) ||          /* XXX - don't use woff here */
        !          2026:          (prompt_physical_chars >= _rl_screenwidth &&
        !          2027:           _rl_last_v_pos == prompt_last_screen_line &&
        !          2028:           wrap_offset >= woff && dpos >= woff &&
        !          2029:           new > (prompt_last_invisible-(_rl_screenwidth*_rl_last_v_pos)-wrap_offset))))
        !          2030:           /* XXX last comparison might need to be >= */
        !          2031:        {
        !          2032:          dpos -= woff;
        !          2033:          /* Since this will be assigned to _rl_last_c_pos at the end (more
        !          2034:             precisely, _rl_last_c_pos == dpos when this function returns),
        !          2035:             let the caller know. */
        !          2036:          cpos_adjusted = 1;
        !          2037:        }
        !          2038:     }
        !          2039:   else
        !          2040: #endif
        !          2041:     dpos = new;
        !          2042: 
        !          2043:   /* If we don't have to do anything, then return. */
        !          2044:   if (cpos == dpos)
        !          2045:     return;
        !          2046: 
        !          2047:   /* It may be faster to output a CR, and then move forwards instead
        !          2048:      of moving backwards. */
        !          2049:   /* i == current physical cursor position. */
        !          2050: #if defined (HANDLE_MULTIBYTE)
        !          2051:   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
        !          2052:     i = _rl_last_c_pos;
        !          2053:   else
        !          2054: #endif
        !          2055:   i = _rl_last_c_pos - woff;
        !          2056:   if (dpos == 0 || CR_FASTER (dpos, _rl_last_c_pos) ||
        !          2057:       (_rl_term_autowrap && i == _rl_screenwidth))
        !          2058:     {
        !          2059: #if defined (__MSDOS__)
        !          2060:       putc ('\r', rl_outstream);
        !          2061: #else
        !          2062:       tputs (_rl_term_cr, 1, _rl_output_character_function);
        !          2063: #endif /* !__MSDOS__ */
        !          2064:       cpos = _rl_last_c_pos = 0;
        !          2065:     }
        !          2066: 
        !          2067:   if (cpos < dpos)
        !          2068:     {
        !          2069:       /* Move the cursor forward.  We do it by printing the command
        !          2070:         to move the cursor forward if there is one, else print that
        !          2071:         portion of the output buffer again.  Which is cheaper? */
        !          2072: 
        !          2073:       /* The above comment is left here for posterity.  It is faster
        !          2074:         to print one character (non-control) than to print a control
        !          2075:         sequence telling the terminal to move forward one character.
        !          2076:         That kind of control is for people who don't know what the
        !          2077:         data is underneath the cursor. */
        !          2078: 
        !          2079:       /* However, we need a handle on where the current display position is
        !          2080:         in the buffer for the immediately preceding comment to be true.
        !          2081:         In multibyte locales, we don't currently have that info available.
        !          2082:         Without it, we don't know where the data we have to display begins
        !          2083:         in the buffer and we have to go back to the beginning of the screen
        !          2084:         line.  In this case, we can use the terminal sequence to move forward
        !          2085:         if it's available. */
        !          2086:       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
        !          2087:        {
        !          2088:          if (_rl_term_forward_char)
        !          2089:            {
        !          2090:              for (i = cpos; i < dpos; i++)
        !          2091:                tputs (_rl_term_forward_char, 1, _rl_output_character_function);
        !          2092:            }
        !          2093:          else
        !          2094:            {
        !          2095:              tputs (_rl_term_cr, 1, _rl_output_character_function);
        !          2096:              for (i = 0; i < new; i++)
        !          2097:                putc (data[i], rl_outstream);
        !          2098:            }
        !          2099:        }
        !          2100:       else
        !          2101:        for (i = cpos; i < new; i++)
        !          2102:          putc (data[i], rl_outstream);
        !          2103:     }
        !          2104: 
        !          2105: #if defined (HANDLE_MULTIBYTE)
        !          2106:   /* NEW points to the buffer point, but _rl_last_c_pos is the display point.
        !          2107:      The byte length of the string is probably bigger than the column width
        !          2108:      of the string, which means that if NEW == _rl_last_c_pos, then NEW's
        !          2109:      display point is less than _rl_last_c_pos. */
        !          2110: #endif
        !          2111:   else if (cpos > dpos)
        !          2112:     _rl_backspace (cpos - dpos);
        !          2113: 
        !          2114:   _rl_last_c_pos = dpos;
        !          2115: }
        !          2116: 
        !          2117: /* PWP: move the cursor up or down. */
        !          2118: void
        !          2119: _rl_move_vert (to)
        !          2120:      int to;
        !          2121: {
        !          2122:   register int delta, i;
        !          2123: 
        !          2124:   if (_rl_last_v_pos == to || to > _rl_screenheight)
        !          2125:     return;
        !          2126: 
        !          2127:   if ((delta = to - _rl_last_v_pos) > 0)
        !          2128:     {
        !          2129:       for (i = 0; i < delta; i++)
        !          2130:        putc ('\n', rl_outstream);
        !          2131: #if defined (__MSDOS__)
        !          2132:       putc ('\r', rl_outstream);
        !          2133: #else
        !          2134:       tputs (_rl_term_cr, 1, _rl_output_character_function);
        !          2135: #endif
        !          2136:       _rl_last_c_pos = 0;
        !          2137:     }
        !          2138:   else
        !          2139:     {                  /* delta < 0 */
        !          2140: #ifdef __DJGPP__
        !          2141:       int row, col;
        !          2142: 
        !          2143:       fflush (rl_outstream);
        !          2144:       ScreenGetCursor (&row, &col);
        !          2145:       ScreenSetCursor (row + delta, col);
        !          2146:       i = -delta;
        !          2147: #else
        !          2148:       if (_rl_term_up && *_rl_term_up)
        !          2149:        for (i = 0; i < -delta; i++)
        !          2150:          tputs (_rl_term_up, 1, _rl_output_character_function);
        !          2151: #endif /* !__DJGPP__ */
        !          2152:     }
        !          2153: 
        !          2154:   _rl_last_v_pos = to;         /* Now TO is here */
        !          2155: }
        !          2156: 
        !          2157: /* Physically print C on rl_outstream.  This is for functions which know
        !          2158:    how to optimize the display.  Return the number of characters output. */
        !          2159: int
        !          2160: rl_show_char (c)
        !          2161:      int c;
        !          2162: {
        !          2163:   int n = 1;
        !          2164:   if (META_CHAR (c) && (_rl_output_meta_chars == 0))
        !          2165:     {
        !          2166:       fprintf (rl_outstream, "M-");
        !          2167:       n += 2;
        !          2168:       c = UNMETA (c);
        !          2169:     }
        !          2170: 
        !          2171: #if defined (DISPLAY_TABS)
        !          2172:   if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
        !          2173: #else
        !          2174:   if (CTRL_CHAR (c) || c == RUBOUT)
        !          2175: #endif /* !DISPLAY_TABS */
        !          2176:     {
        !          2177:       fprintf (rl_outstream, "C-");
        !          2178:       n += 2;
        !          2179:       c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
        !          2180:     }
        !          2181: 
        !          2182:   putc (c, rl_outstream);
        !          2183:   fflush (rl_outstream);
        !          2184:   return n;
        !          2185: }
        !          2186: 
        !          2187: int
        !          2188: rl_character_len (c, pos)
        !          2189:      register int c, pos;
        !          2190: {
        !          2191:   unsigned char uc;
        !          2192: 
        !          2193:   uc = (unsigned char)c;
        !          2194: 
        !          2195:   if (META_CHAR (uc))
        !          2196:     return ((_rl_output_meta_chars == 0) ? 4 : 1);
        !          2197: 
        !          2198:   if (uc == '\t')
        !          2199:     {
        !          2200: #if defined (DISPLAY_TABS)
        !          2201:       return (((pos | 7) + 1) - pos);
        !          2202: #else
        !          2203:       return (2);
        !          2204: #endif /* !DISPLAY_TABS */
        !          2205:     }
        !          2206: 
        !          2207:   if (CTRL_CHAR (c) || c == RUBOUT)
        !          2208:     return (2);
        !          2209: 
        !          2210:   return ((ISPRINT (uc)) ? 1 : 2);
        !          2211: }
        !          2212: /* How to print things in the "echo-area".  The prompt is treated as a
        !          2213:    mini-modeline. */
        !          2214: static int msg_saved_prompt = 0;
        !          2215: 
        !          2216: #if defined (USE_VARARGS)
        !          2217: int
        !          2218: #if defined (PREFER_STDARG)
        !          2219: rl_message (const char *format, ...)
        !          2220: #else
        !          2221: rl_message (va_alist)
        !          2222:      va_dcl
        !          2223: #endif
        !          2224: {
        !          2225:   va_list args;
        !          2226: #if defined (PREFER_VARARGS)
        !          2227:   char *format;
        !          2228: #endif
        !          2229: #if defined (HAVE_VSNPRINTF)
        !          2230:   int bneed;
        !          2231: #endif
        !          2232: 
        !          2233: #if defined (PREFER_STDARG)
        !          2234:   va_start (args, format);
        !          2235: #else
        !          2236:   va_start (args);
        !          2237:   format = va_arg (args, char *);
        !          2238: #endif
        !          2239: 
        !          2240:   if (msg_buf == 0)
        !          2241:     msg_buf = xmalloc (msg_bufsiz = 128);
        !          2242: 
        !          2243: #if defined (HAVE_VSNPRINTF)
        !          2244:   bneed = vsnprintf (msg_buf, msg_bufsiz - 1, format, args);
        !          2245:   if (bneed >= msg_bufsiz - 1)
        !          2246:     {
        !          2247:       msg_bufsiz = bneed + 1;
        !          2248:       msg_buf = xrealloc (msg_buf, msg_bufsiz);
        !          2249:       va_end (args);
        !          2250: 
        !          2251: #if defined (PREFER_STDARG)
        !          2252:       va_start (args, format);
        !          2253: #else
        !          2254:       va_start (args);
        !          2255:       format = va_arg (args, char *);
        !          2256: #endif
        !          2257:       vsnprintf (msg_buf, msg_bufsiz - 1, format, args);
        !          2258:     }
        !          2259: #else
        !          2260:   vsprintf (msg_buf, format, args);
        !          2261:   msg_buf[msg_bufsiz - 1] = '\0';      /* overflow? */
        !          2262: #endif
        !          2263:   va_end (args);
        !          2264: 
        !          2265:   if (saved_local_prompt == 0)
        !          2266:     {
        !          2267:       rl_save_prompt ();
        !          2268:       msg_saved_prompt = 1;
        !          2269:     }
        !          2270:   else if (local_prompt != saved_local_prompt)
        !          2271:     {
        !          2272:       FREE (local_prompt);
        !          2273:       FREE (local_prompt_prefix);
        !          2274:       local_prompt = (char *)NULL;
        !          2275:     }
        !          2276:   rl_display_prompt = msg_buf;
        !          2277:   local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
        !          2278:                                         &prompt_last_invisible,
        !          2279:                                         &prompt_invis_chars_first_line,
        !          2280:                                         &prompt_physical_chars);
        !          2281:   local_prompt_prefix = (char *)NULL;
        !          2282:   local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
        !          2283:   (*rl_redisplay_function) ();
        !          2284: 
        !          2285:   return 0;
        !          2286: }
        !          2287: #else /* !USE_VARARGS */
        !          2288: int
        !          2289: rl_message (format, arg1, arg2)
        !          2290:      char *format;
        !          2291: {
        !          2292:   if (msg_buf == 0)
        !          2293:     msg_buf = xmalloc (msg_bufsiz = 128);
        !          2294: 
        !          2295:   sprintf (msg_buf, format, arg1, arg2);
        !          2296:   msg_buf[msg_bufsiz - 1] = '\0';      /* overflow? */
        !          2297: 
        !          2298:   rl_display_prompt = msg_buf;
        !          2299:   if (saved_local_prompt == 0)
        !          2300:     {
        !          2301:       rl_save_prompt ();
        !          2302:       msg_saved_prompt = 1;
        !          2303:     }
        !          2304:   else if (local_prompt != saved_local_prompt)
        !          2305:     {
        !          2306:       FREE (local_prompt);
        !          2307:       FREE (local_prompt_prefix);
        !          2308:       local_prompt = (char *)NULL;
        !          2309:     }
        !          2310:   local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
        !          2311:                                         &prompt_last_invisible,
        !          2312:                                         &prompt_invis_chars_first_line,
        !          2313:                                         &prompt_physical_chars);
        !          2314:   local_prompt_prefix = (char *)NULL;
        !          2315:   local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
        !          2316:   (*rl_redisplay_function) ();
        !          2317:       
        !          2318:   return 0;
        !          2319: }
        !          2320: #endif /* !USE_VARARGS */
        !          2321: 
        !          2322: /* How to clear things from the "echo-area". */
        !          2323: int
        !          2324: rl_clear_message ()
        !          2325: {
        !          2326:   rl_display_prompt = rl_prompt;
        !          2327:   if (msg_saved_prompt)
        !          2328:     {
        !          2329:       rl_restore_prompt ();
        !          2330:       msg_saved_prompt = 0;
        !          2331:     }
        !          2332:   (*rl_redisplay_function) ();
        !          2333:   return 0;
        !          2334: }
        !          2335: 
        !          2336: int
        !          2337: rl_reset_line_state ()
        !          2338: {
        !          2339:   rl_on_new_line ();
        !          2340: 
        !          2341:   rl_display_prompt = rl_prompt ? rl_prompt : "";
        !          2342:   forced_display = 1;
        !          2343:   return 0;
        !          2344: }
        !          2345: 
        !          2346: void
        !          2347: rl_save_prompt ()
        !          2348: {
        !          2349:   saved_local_prompt = local_prompt;
        !          2350:   saved_local_prefix = local_prompt_prefix;
        !          2351:   saved_prefix_length = prompt_prefix_length;
        !          2352:   saved_local_length = local_prompt_len;
        !          2353:   saved_last_invisible = prompt_last_invisible;
        !          2354:   saved_visible_length = prompt_visible_length;
        !          2355:   saved_invis_chars_first_line = prompt_invis_chars_first_line;
        !          2356:   saved_physical_chars = prompt_physical_chars;
        !          2357: 
        !          2358:   local_prompt = local_prompt_prefix = (char *)0;
        !          2359:   local_prompt_len = 0;
        !          2360:   prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0;
        !          2361:   prompt_invis_chars_first_line = prompt_physical_chars = 0;
        !          2362: }
        !          2363: 
        !          2364: void
        !          2365: rl_restore_prompt ()
        !          2366: {
        !          2367:   FREE (local_prompt);
        !          2368:   FREE (local_prompt_prefix);
        !          2369: 
        !          2370:   local_prompt = saved_local_prompt;
        !          2371:   local_prompt_prefix = saved_local_prefix;
        !          2372:   local_prompt_len = saved_local_length;
        !          2373:   prompt_prefix_length = saved_prefix_length;
        !          2374:   prompt_last_invisible = saved_last_invisible;
        !          2375:   prompt_visible_length = saved_visible_length;
        !          2376:   prompt_invis_chars_first_line = saved_invis_chars_first_line;
        !          2377:   prompt_physical_chars = saved_physical_chars;
        !          2378: 
        !          2379:   /* can test saved_local_prompt to see if prompt info has been saved. */
        !          2380:   saved_local_prompt = saved_local_prefix = (char *)0;
        !          2381:   saved_local_length = 0;
        !          2382:   saved_last_invisible = saved_visible_length = saved_prefix_length = 0;
        !          2383:   saved_invis_chars_first_line = saved_physical_chars = 0;
        !          2384: }
        !          2385: 
        !          2386: char *
        !          2387: _rl_make_prompt_for_search (pchar)
        !          2388:      int pchar;
        !          2389: {
        !          2390:   int len;
        !          2391:   char *pmt, *p;
        !          2392: 
        !          2393:   rl_save_prompt ();
        !          2394: 
        !          2395:   /* We've saved the prompt, and can do anything with the various prompt
        !          2396:      strings we need before they're restored.  We want the unexpanded
        !          2397:      portion of the prompt string after any final newline. */
        !          2398:   p = rl_prompt ? strrchr (rl_prompt, '\n') : 0;
        !          2399:   if (p == 0)
        !          2400:     {
        !          2401:       len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
        !          2402:       pmt = (char *)xmalloc (len + 2);
        !          2403:       if (len)
        !          2404:        strcpy (pmt, rl_prompt);
        !          2405:       pmt[len] = pchar;
        !          2406:       pmt[len+1] = '\0';
        !          2407:     }
        !          2408:   else
        !          2409:     {
        !          2410:       p++;
        !          2411:       len = strlen (p);
        !          2412:       pmt = (char *)xmalloc (len + 2);
        !          2413:       if (len)
        !          2414:        strcpy (pmt, p);
        !          2415:       pmt[len] = pchar;
        !          2416:       pmt[len+1] = '\0';
        !          2417:     }  
        !          2418: 
        !          2419:   /* will be overwritten by expand_prompt, called from rl_message */
        !          2420:   prompt_physical_chars = saved_physical_chars + 1;
        !          2421:   return pmt;
        !          2422: }
        !          2423: 
        !          2424: /* Quick redisplay hack when erasing characters at the end of the line. */
        !          2425: void
        !          2426: _rl_erase_at_end_of_line (l)
        !          2427:      int l;
        !          2428: {
        !          2429:   register int i;
        !          2430: 
        !          2431:   _rl_backspace (l);
        !          2432:   for (i = 0; i < l; i++)
        !          2433:     putc (' ', rl_outstream);
        !          2434:   _rl_backspace (l);
        !          2435:   for (i = 0; i < l; i++)
        !          2436:     visible_line[--_rl_last_c_pos] = '\0';
        !          2437:   rl_display_fixed++;
        !          2438: }
        !          2439: 
        !          2440: /* Clear to the end of the line.  COUNT is the minimum
        !          2441:    number of character spaces to clear, */
        !          2442: void
        !          2443: _rl_clear_to_eol (count)
        !          2444:      int count;
        !          2445: {
        !          2446: #ifndef __MSDOS__
        !          2447:   if (_rl_term_clreol)
        !          2448:     tputs (_rl_term_clreol, 1, _rl_output_character_function);
        !          2449:   else
        !          2450: #endif
        !          2451:     if (count)
        !          2452:       space_to_eol (count);
        !          2453: }
        !          2454: 
        !          2455: /* Clear to the end of the line using spaces.  COUNT is the minimum
        !          2456:    number of character spaces to clear, */
        !          2457: static void
        !          2458: space_to_eol (count)
        !          2459:      int count;
        !          2460: {
        !          2461:   register int i;
        !          2462: 
        !          2463:   for (i = 0; i < count; i++)
        !          2464:    putc (' ', rl_outstream);
        !          2465: 
        !          2466:   _rl_last_c_pos += count;
        !          2467: }
        !          2468: 
        !          2469: void
        !          2470: _rl_clear_screen ()
        !          2471: {
        !          2472: #ifndef __DJGPP__
        !          2473:   if (_rl_term_clrpag)
        !          2474:     tputs (_rl_term_clrpag, 1, _rl_output_character_function);
        !          2475:   else
        !          2476:     rl_crlf ();
        !          2477: #else
        !          2478:   ScreenClear ();
        !          2479:   ScreenSetCursor (0, 0);
        !          2480: #endif /* __DJGPP__ */
        !          2481: }
        !          2482: 
        !          2483: /* Insert COUNT characters from STRING to the output stream at column COL. */
        !          2484: static void
        !          2485: insert_some_chars (string, count, col)
        !          2486:      char *string;
        !          2487:      int count, col;
        !          2488: {
        !          2489:   open_some_spaces (col);
        !          2490:   _rl_output_some_chars (string, count);
        !          2491: }
        !          2492: 
        !          2493: /* Insert COL spaces, keeping the cursor at the same position.  We follow the
        !          2494:    ncurses documentation and use either im/ei with explicit spaces, or IC/ic
        !          2495:    by itself.  We assume there will either be ei or we don't need to use it. */
        !          2496: static void
        !          2497: open_some_spaces (col)
        !          2498:      int col;
        !          2499: {
        !          2500: #if !defined (__MSDOS__) && !defined (__MINGW32__)
        !          2501:   char *buffer;
        !          2502:   register int i;
        !          2503: 
        !          2504:   /* If IC is defined, then we do not have to "enter" insert mode. */
        !          2505:   if (_rl_term_IC)
        !          2506:     {
        !          2507:       buffer = tgoto (_rl_term_IC, 0, col);
        !          2508:       tputs (buffer, 1, _rl_output_character_function);
        !          2509:     }
        !          2510:   else if (_rl_term_im && *_rl_term_im)
        !          2511:     {
        !          2512:       tputs (_rl_term_im, 1, _rl_output_character_function);
        !          2513:       /* just output the desired number of spaces */
        !          2514:       for (i = col; i--; )
        !          2515:        _rl_output_character_function (' ');
        !          2516:       /* If there is a string to turn off insert mode, use it now. */
        !          2517:       if (_rl_term_ei && *_rl_term_ei)
        !          2518:        tputs (_rl_term_ei, 1, _rl_output_character_function);
        !          2519:       /* and move back the right number of spaces */
        !          2520:       _rl_backspace (col);
        !          2521:     }
        !          2522:   else if (_rl_term_ic && *_rl_term_ic)
        !          2523:     {
        !          2524:       /* If there is a special command for inserting characters, then
        !          2525:         use that first to open up the space. */
        !          2526:       for (i = col; i--; )
        !          2527:        tputs (_rl_term_ic, 1, _rl_output_character_function);
        !          2528:     }
        !          2529: #endif /* !__MSDOS__ && !__MINGW32__ */
        !          2530: }
        !          2531: 
        !          2532: /* Delete COUNT characters from the display line. */
        !          2533: static void
        !          2534: delete_chars (count)
        !          2535:      int count;
        !          2536: {
        !          2537:   if (count > _rl_screenwidth) /* XXX */
        !          2538:     return;
        !          2539: 
        !          2540: #if !defined (__MSDOS__) && !defined (__MINGW32__)
        !          2541:   if (_rl_term_DC && *_rl_term_DC)
        !          2542:     {
        !          2543:       char *buffer;
        !          2544:       buffer = tgoto (_rl_term_DC, count, count);
        !          2545:       tputs (buffer, count, _rl_output_character_function);
        !          2546:     }
        !          2547:   else
        !          2548:     {
        !          2549:       if (_rl_term_dc && *_rl_term_dc)
        !          2550:        while (count--)
        !          2551:          tputs (_rl_term_dc, 1, _rl_output_character_function);
        !          2552:     }
        !          2553: #endif /* !__MSDOS__ && !__MINGW32__ */
        !          2554: }
        !          2555: 
        !          2556: void
        !          2557: _rl_update_final ()
        !          2558: {
        !          2559:   int full_lines;
        !          2560: 
        !          2561:   full_lines = 0;
        !          2562:   /* If the cursor is the only thing on an otherwise-blank last line,
        !          2563:      compensate so we don't print an extra CRLF. */
        !          2564:   if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
        !          2565:        visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
        !          2566:     {
        !          2567:       _rl_vis_botlin--;
        !          2568:       full_lines = 1;
        !          2569:     }
        !          2570:   _rl_move_vert (_rl_vis_botlin);
        !          2571:   /* If we've wrapped lines, remove the final xterm line-wrap flag. */
        !          2572:   if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth))
        !          2573:     {
        !          2574:       char *last_line;
        !          2575: 
        !          2576:       last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]];
        !          2577:       cpos_buffer_position = -1;       /* don't know where we are in buffer */
        !          2578:       _rl_move_cursor_relative (_rl_screenwidth - 1, last_line);       /* XXX */
        !          2579:       _rl_clear_to_eol (0);
        !          2580:       putc (last_line[_rl_screenwidth - 1], rl_outstream);
        !          2581:     }
        !          2582:   _rl_vis_botlin = 0;
        !          2583:   rl_crlf ();
        !          2584:   fflush (rl_outstream);
        !          2585:   rl_display_fixed++;
        !          2586: }
        !          2587: 
        !          2588: /* Move to the start of the current line. */
        !          2589: static void
        !          2590: cr ()
        !          2591: {
        !          2592:   if (_rl_term_cr)
        !          2593:     {
        !          2594: #if defined (__MSDOS__)
        !          2595:       putc ('\r', rl_outstream);
        !          2596: #else
        !          2597:       tputs (_rl_term_cr, 1, _rl_output_character_function);
        !          2598: #endif
        !          2599:       _rl_last_c_pos = 0;
        !          2600:     }
        !          2601: }
        !          2602: 
        !          2603: /* Redraw the last line of a multi-line prompt that may possibly contain
        !          2604:    terminal escape sequences.  Called with the cursor at column 0 of the
        !          2605:    line to draw the prompt on. */
        !          2606: static void
        !          2607: redraw_prompt (t)
        !          2608:      char *t;
        !          2609: {
        !          2610:   char *oldp;
        !          2611: 
        !          2612:   oldp = rl_display_prompt;
        !          2613:   rl_save_prompt ();
        !          2614: 
        !          2615:   rl_display_prompt = t;
        !          2616:   local_prompt = expand_prompt (t, &prompt_visible_length,
        !          2617:                                   &prompt_last_invisible,
        !          2618:                                   &prompt_invis_chars_first_line,
        !          2619:                                   &prompt_physical_chars);
        !          2620:   local_prompt_prefix = (char *)NULL;
        !          2621:   local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
        !          2622: 
        !          2623:   rl_forced_update_display ();
        !          2624: 
        !          2625:   rl_display_prompt = oldp;
        !          2626:   rl_restore_prompt();
        !          2627: }
        !          2628:       
        !          2629: /* Redisplay the current line after a SIGWINCH is received. */
        !          2630: void
        !          2631: _rl_redisplay_after_sigwinch ()
        !          2632: {
        !          2633:   char *t;
        !          2634: 
        !          2635:   /* Clear the last line (assuming that the screen size change will result in
        !          2636:      either more or fewer characters on that line only) and put the cursor at
        !          2637:      column 0.  Make sure the right thing happens if we have wrapped to a new
        !          2638:      screen line. */
        !          2639:   if (_rl_term_cr)
        !          2640:     {
        !          2641:       _rl_move_vert (_rl_vis_botlin);
        !          2642: 
        !          2643: #if defined (__MSDOS__)
        !          2644:       putc ('\r', rl_outstream);
        !          2645: #else
        !          2646:       tputs (_rl_term_cr, 1, _rl_output_character_function);
        !          2647: #endif
        !          2648:       _rl_last_c_pos = 0;
        !          2649: #if defined (__MSDOS__)
        !          2650:       space_to_eol (_rl_screenwidth);
        !          2651:       putc ('\r', rl_outstream);
        !          2652: #else
        !          2653:       if (_rl_term_clreol)
        !          2654:        tputs (_rl_term_clreol, 1, _rl_output_character_function);
        !          2655:       else
        !          2656:        {
        !          2657:          space_to_eol (_rl_screenwidth);
        !          2658:          tputs (_rl_term_cr, 1, _rl_output_character_function);
        !          2659:        }
        !          2660: #endif
        !          2661:       if (_rl_last_v_pos > 0)
        !          2662:        _rl_move_vert (0);
        !          2663:     }
        !          2664:   else
        !          2665:     rl_crlf ();
        !          2666: 
        !          2667:   /* Redraw only the last line of a multi-line prompt. */
        !          2668:   t = strrchr (rl_display_prompt, '\n');
        !          2669:   if (t)
        !          2670:     redraw_prompt (++t);
        !          2671:   else
        !          2672:     rl_forced_update_display ();
        !          2673: }
        !          2674: 
        !          2675: void
        !          2676: _rl_clean_up_for_exit ()
        !          2677: {
        !          2678:   if (_rl_echoing_p)
        !          2679:     {
        !          2680:       _rl_move_vert (_rl_vis_botlin);
        !          2681:       _rl_vis_botlin = 0;
        !          2682:       fflush (rl_outstream);
        !          2683:       rl_restart_output (1, 0);
        !          2684:     }
        !          2685: }
        !          2686: 
        !          2687: void
        !          2688: _rl_erase_entire_line ()
        !          2689: {
        !          2690:   cr ();
        !          2691:   _rl_clear_to_eol (0);
        !          2692:   cr ();
        !          2693:   fflush (rl_outstream);
        !          2694: }
        !          2695: 
        !          2696: /* return the `current display line' of the cursor -- the number of lines to
        !          2697:    move up to get to the first screen line of the current readline line. */
        !          2698: int
        !          2699: _rl_current_display_line ()
        !          2700: {
        !          2701:   int ret, nleft;
        !          2702: 
        !          2703:   /* Find out whether or not there might be invisible characters in the
        !          2704:      editing buffer. */
        !          2705:   if (rl_display_prompt == rl_prompt)
        !          2706:     nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length;
        !          2707:   else
        !          2708:     nleft = _rl_last_c_pos - _rl_screenwidth;
        !          2709: 
        !          2710:   if (nleft > 0)
        !          2711:     ret = 1 + nleft / _rl_screenwidth;
        !          2712:   else
        !          2713:     ret = 0;
        !          2714: 
        !          2715:   return ret;
        !          2716: }
        !          2717: 
        !          2718: #if defined (HANDLE_MULTIBYTE)
        !          2719: /* Calculate the number of screen columns occupied by STR from START to END.
        !          2720:    In the case of multibyte characters with stateful encoding, we have to
        !          2721:    scan from the beginning of the string to take the state into account. */
        !          2722: static int
        !          2723: _rl_col_width (str, start, end, flags)
        !          2724:      const char *str;
        !          2725:      int start, end, flags;
        !          2726: {
        !          2727:   wchar_t wc;
        !          2728:   mbstate_t ps;
        !          2729:   int tmp, point, width, max;
        !          2730: 
        !          2731:   if (end <= start)
        !          2732:     return 0;
        !          2733:   if (MB_CUR_MAX == 1 || rl_byte_oriented)
        !          2734:     /* this can happen in some cases where it's inconvenient to check */
        !          2735:     return (end - start);
        !          2736: 
        !          2737:   memset (&ps, 0, sizeof (mbstate_t));
        !          2738: 
        !          2739:   point = 0;
        !          2740:   max = end;
        !          2741: 
        !          2742:   /* Try to short-circuit common cases.  The adjustment to remove wrap_offset
        !          2743:      is done by the caller. */
        !          2744:   /* 1.  prompt string */
        !          2745:   if (flags && start == 0 && end == local_prompt_len && memcmp (str, local_prompt, local_prompt_len) == 0)
        !          2746:     return (prompt_physical_chars + wrap_offset);
        !          2747:   /* 2.  prompt string + line contents */
        !          2748:   else if (flags && start == 0 && local_prompt_len > 0 && end > local_prompt_len && local_prompt && memcmp (str, local_prompt, local_prompt_len) == 0)
        !          2749:     {
        !          2750:       tmp = prompt_physical_chars + wrap_offset;
        !          2751:       /* XXX - try to call ourselves recursively with non-prompt portion */
        !          2752:       tmp += _rl_col_width (str, local_prompt_len, end, flags);
        !          2753:       return (tmp);
        !          2754:     }
        !          2755: 
        !          2756:   while (point < start)
        !          2757:     {
        !          2758:       tmp = mbrlen (str + point, max, &ps);
        !          2759:       if (MB_INVALIDCH ((size_t)tmp))
        !          2760:        {
        !          2761:          /* In this case, the bytes are invalid or too short to compose a
        !          2762:             multibyte character, so we assume that the first byte represents
        !          2763:             a single character. */
        !          2764:          point++;
        !          2765:          max--;
        !          2766: 
        !          2767:          /* Clear the state of the byte sequence, because in this case the
        !          2768:             effect of mbstate is undefined. */
        !          2769:          memset (&ps, 0, sizeof (mbstate_t));
        !          2770:        }
        !          2771:       else if (MB_NULLWCH (tmp))
        !          2772:        break;          /* Found '\0' */
        !          2773:       else
        !          2774:        {
        !          2775:          point += tmp;
        !          2776:          max -= tmp;
        !          2777:        }
        !          2778:     }
        !          2779: 
        !          2780:   /* If START is not a byte that starts a character, then POINT will be
        !          2781:      greater than START.  In this case, assume that (POINT - START) gives
        !          2782:      a byte count that is the number of columns of difference. */
        !          2783:   width = point - start;
        !          2784: 
        !          2785:   while (point < end)
        !          2786:     {
        !          2787:       tmp = mbrtowc (&wc, str + point, max, &ps);
        !          2788:       if (MB_INVALIDCH ((size_t)tmp))
        !          2789:        {
        !          2790:          /* In this case, the bytes are invalid or too short to compose a
        !          2791:             multibyte character, so we assume that the first byte represents
        !          2792:             a single character. */
        !          2793:          point++;
        !          2794:          max--;
        !          2795: 
        !          2796:          /* and assume that the byte occupies a single column. */
        !          2797:          width++;
        !          2798: 
        !          2799:          /* Clear the state of the byte sequence, because in this case the
        !          2800:             effect of mbstate is undefined. */
        !          2801:          memset (&ps, 0, sizeof (mbstate_t));
        !          2802:        }
        !          2803:       else if (MB_NULLWCH (tmp))
        !          2804:        break;                  /* Found '\0' */
        !          2805:       else
        !          2806:        {
        !          2807:          point += tmp;
        !          2808:          max -= tmp;
        !          2809:          tmp = WCWIDTH(wc);
        !          2810:          width += (tmp >= 0) ? tmp : 1;
        !          2811:        }
        !          2812:     }
        !          2813: 
        !          2814:   width += point - end;
        !          2815: 
        !          2816:   return width;
        !          2817: }
        !          2818: #endif /* HANDLE_MULTIBYTE */

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