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

1.1       misho       1: /* display.c -- readline redisplay facility. */
                      2: 
1.1.1.3 ! misho       3: /* Copyright (C) 1987-2020 Free Software Foundation, Inc.
1.1       misho       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: 
1.1.1.3 ! misho      66: static void putc_face PARAMS((int, int, char *));
        !            67: static void puts_face PARAMS((const char *, const char *, int));
        !            68: static void norm_face PARAMS((char *, int));
        !            69: 
        !            70: static void update_line PARAMS((char *, char *, char *, char *, int, int, int, int));
1.1       misho      71: static void space_to_eol PARAMS((int));
                     72: static void delete_chars PARAMS((int));
                     73: static void insert_some_chars PARAMS((char *, int, int));
                     74: static void open_some_spaces PARAMS((int));
                     75: static void cr PARAMS((void));
1.1.1.3 ! misho      76: static void redraw_prompt PARAMS((char *));
        !            77: static void _rl_move_cursor_relative PARAMS((int, const char *, const char *));
        !            78: 
        !            79: /* Values for FLAGS */
        !            80: #define PMT_MULTILINE  0x01
        !            81: 
        !            82: static char *expand_prompt PARAMS((char *, int, int *, int *, int *, int *));
        !            83: 
        !            84: #define DEFAULT_LINE_BUFFER_SIZE       1024
1.1       misho      85: 
                     86: /* State of visible and invisible lines. */
                     87: struct line_state
                     88:   {
                     89:     char *line;
1.1.1.3 ! misho      90:     char *lface;
1.1       misho      91:     int *lbreaks;
                     92:     int lbsize;
                     93: #if defined (HANDLE_MULTIBYTE)
                     94:     int wbsize;
1.1.1.3 ! misho      95:     int *wrapped_line;
1.1       misho      96: #endif
                     97:   };
                     98: 
                     99: /* The line display buffers.  One is the line currently displayed on
                    100:    the screen.  The other is the line about to be displayed. */
                    101: static struct line_state line_state_array[2];
                    102: static struct line_state *line_state_visible = &line_state_array[0];
                    103: static struct line_state *line_state_invisible = &line_state_array[1];
                    104: static int line_structures_initialized = 0;
                    105: 
                    106: /* Backwards-compatible names. */
                    107: #define inv_lbreaks    (line_state_invisible->lbreaks)
                    108: #define inv_lbsize     (line_state_invisible->lbsize)
                    109: #define vis_lbreaks    (line_state_visible->lbreaks)
                    110: #define vis_lbsize     (line_state_visible->lbsize)
                    111: 
                    112: #define visible_line   (line_state_visible->line)
1.1.1.3 ! misho     113: #define vis_face       (line_state_visible->lface)
1.1       misho     114: #define invisible_line (line_state_invisible->line)
1.1.1.3 ! misho     115: #define inv_face       (line_state_invisible->lface)
1.1       misho     116: 
                    117: #if defined (HANDLE_MULTIBYTE)
                    118: static int _rl_col_width PARAMS((const char *, int, int, int));
                    119: #else
                    120: #  define _rl_col_width(l, s, e, f)    (((e) <= (s)) ? 0 : (e) - (s))
                    121: #endif
                    122: 
                    123: /* Heuristic used to decide whether it is faster to move from CUR to NEW
                    124:    by backing up or outputting a carriage return and moving forward.  CUR
                    125:    and NEW are either both buffer positions or absolute screen positions. */
                    126: #define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new)))
                    127: 
                    128: /* _rl_last_c_pos is an absolute cursor position in multibyte locales and a
                    129:    buffer index in others.  This macro is used when deciding whether the
                    130:    current cursor position is in the middle of a prompt string containing
                    131:    invisible characters.  XXX - might need to take `modmark' into account. */
1.1.1.3 ! misho     132: /* XXX - only valid when tested against _rl_last_c_pos; buffer indices need
        !           133:    to use prompt_last_invisible directly. */
1.1       misho     134: #define PROMPT_ENDING_INDEX \
                    135:   ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) ? prompt_physical_chars : prompt_last_invisible+1)
                    136: 
1.1.1.3 ! misho     137: #define FACE_NORMAL    '0'
        !           138: #define FACE_STANDOUT  '1'
        !           139: #define FACE_INVALID   ((char)1)
        !           140:   
1.1       misho     141: /* **************************************************************** */
                    142: /*                                                                 */
                    143: /*                     Display stuff                               */
                    144: /*                                                                 */
                    145: /* **************************************************************** */
                    146: 
                    147: /* This is the stuff that is hard for me.  I never seem to write good
                    148:    display routines in C.  Let's see how I do this time. */
                    149: 
                    150: /* (PWP) Well... Good for a simple line updater, but totally ignores
                    151:    the problems of input lines longer than the screen width.
                    152: 
                    153:    update_line and the code that calls it makes a multiple line,
                    154:    automatically wrapping line update.  Careful attention needs
                    155:    to be paid to the vertical position variables. */
                    156: 
                    157: /* Keep two buffers; one which reflects the current contents of the
                    158:    screen, and the other to draw what we think the new contents should
                    159:    be.  Then compare the buffers, and make whatever changes to the
                    160:    screen itself that we should.  Finally, make the buffer that we
                    161:    just drew into be the one which reflects the current contents of the
                    162:    screen, and place the cursor where it belongs.
                    163: 
                    164:    Commands that want to can fix the display themselves, and then let
                    165:    this function know that the display has been fixed by setting the
                    166:    RL_DISPLAY_FIXED variable.  This is good for efficiency. */
                    167: 
                    168: /* Application-specific redisplay function. */
                    169: rl_voidfunc_t *rl_redisplay_function = rl_redisplay;
                    170: 
                    171: /* Global variables declared here. */
                    172: /* What YOU turn on when you have handled all redisplay yourself. */
                    173: int rl_display_fixed = 0;
                    174: 
                    175: /* The stuff that gets printed out before the actual text of the line.
                    176:    This is usually pointing to rl_prompt. */
                    177: char *rl_display_prompt = (char *)NULL;
                    178: 
1.1.1.3 ! misho     179: /* Variables used to include the editing mode in the prompt. */
        !           180: char *_rl_emacs_mode_str;
        !           181: int _rl_emacs_modestr_len;
        !           182: 
        !           183: char *_rl_vi_ins_mode_str;
        !           184: int _rl_vi_ins_modestr_len;
        !           185: 
        !           186: char *_rl_vi_cmd_mode_str;
        !           187: int _rl_vi_cmd_modestr_len;
        !           188: 
1.1       misho     189: /* Pseudo-global variables declared here. */
                    190: 
1.1.1.3 ! misho     191: /* Hints for other parts of readline to give to the display engine. */
        !           192: int _rl_suppress_redisplay = 0;
        !           193: int _rl_want_redisplay = 0;
        !           194: 
1.1       misho     195: /* The visible cursor position.  If you print some text, adjust this. */
                    196: /* NOTE: _rl_last_c_pos is used as a buffer index when not in a locale
                    197:    supporting multibyte characters, and an absolute cursor position when
                    198:    in such a locale.  This is an artifact of the donated multibyte support.
                    199:    Care must be taken when modifying its value. */
                    200: int _rl_last_c_pos = 0;
                    201: int _rl_last_v_pos = 0;
                    202: 
1.1.1.3 ! misho     203: /* Number of physical lines consumed by the current line buffer currently
        !           204:   on screen minus 1. */
        !           205: int _rl_vis_botlin = 0;
        !           206: 
        !           207: static int _rl_quick_redisplay = 0;
        !           208: 
        !           209: /* This is a hint update_line gives to rl_redisplay that it has adjusted the
        !           210:    value of _rl_last_c_pos *and* taken the presence of any invisible chars in
        !           211:    the prompt into account.  rl_redisplay notes this and does not do the
        !           212:    adjustment itself. */
1.1       misho     213: static int cpos_adjusted;
1.1.1.3 ! misho     214: 
        !           215: /* The index into the line buffer corresponding to the cursor position */
1.1       misho     216: static int cpos_buffer_position;
1.1.1.3 ! misho     217: 
        !           218: /* A flag to note when we're displaying the first line of the prompt */
1.1       misho     219: static int displaying_prompt_first_line;
1.1.1.3 ! misho     220: /* The number of multibyte characters in the prompt, if any */
1.1       misho     221: static int prompt_multibyte_chars;
                    222: 
1.1.1.3 ! misho     223: static int _rl_inv_botlin = 0;
1.1       misho     224: 
                    225: /* Variables used only in this file. */
                    226: /* The last left edge of text that was displayed.  This is used when
                    227:    doing horizontal scrolling.  It shifts in thirds of a screenwidth. */
                    228: static int last_lmargin;
                    229: 
                    230: /* A buffer for `modeline' messages. */
                    231: static char *msg_buf = 0;
                    232: static int msg_bufsiz = 0;
                    233: 
                    234: /* Non-zero forces the redisplay even if we thought it was unnecessary. */
                    235: static int forced_display;
                    236: 
                    237: /* Default and initial buffer size.  Can grow. */
1.1.1.3 ! misho     238: static int line_size  = 0;
        !           239: 
        !           240: /* Set to a non-zero value if horizontal scrolling has been enabled
        !           241:    automatically because the terminal was resized to height 1. */
        !           242: static int horizontal_scrolling_autoset = 0;   /* explicit initialization */
1.1       misho     243: 
                    244: /* Variables to keep track of the expanded prompt string, which may
                    245:    include invisible characters. */
                    246: 
                    247: static char *local_prompt, *local_prompt_prefix;
                    248: static int local_prompt_len;
1.1.1.3 ! misho     249: static int prompt_prefix_length;
        !           250: /* Number of chars in the buffer that contribute to visible chars on the screen.
        !           251:    This might be different from the number of physical chars in the presence
        !           252:    of multibyte characters */
        !           253: static int prompt_visible_length;
1.1       misho     254: 
                    255: /* The number of invisible characters in the line currently being
                    256:    displayed on the screen. */
                    257: static int visible_wrap_offset;
                    258: 
                    259: /* The number of invisible characters in the prompt string.  Static so it
                    260:    can be shared between rl_redisplay and update_line */
                    261: static int wrap_offset;
                    262: 
                    263: /* The index of the last invisible character in the prompt string. */
                    264: static int prompt_last_invisible;
                    265: 
                    266: /* The length (buffer offset) of the first line of the last (possibly
                    267:    multi-line) buffer displayed on the screen. */
                    268: static int visible_first_line_len;
                    269: 
                    270: /* Number of invisible characters on the first physical line of the prompt.
                    271:    Only valid when the number of physical characters in the prompt exceeds
                    272:    (or is equal to) _rl_screenwidth. */
                    273: static int prompt_invis_chars_first_line;
                    274: 
                    275: static int prompt_last_screen_line;
                    276: 
                    277: static int prompt_physical_chars;
                    278: 
1.1.1.3 ! misho     279: /* An array of indexes into the prompt string where we will break physical
        !           280:    screen lines.  It's easier to compute in expand_prompt and use later in
        !           281:    rl_redisplay instead of having rl_redisplay try to guess about invisible
        !           282:    characters in the prompt or use heuristics about where they are. */
        !           283: static int *local_prompt_newlines;
        !           284: 
1.1       misho     285: /* set to a non-zero value by rl_redisplay if we are marking modified history
                    286:    lines and the current line is so marked. */
                    287: static int modmark;
                    288: 
1.1.1.3 ! misho     289: static int line_totbytes;
        !           290: 
1.1       misho     291: /* Variables to save and restore prompt and display information. */
                    292: 
                    293: /* These are getting numerous enough that it's time to create a struct. */
                    294: 
                    295: static char *saved_local_prompt;
                    296: static char *saved_local_prefix;
1.1.1.3 ! misho     297: static int *saved_local_prompt_newlines;
        !           298: 
1.1       misho     299: static int saved_last_invisible;
                    300: static int saved_visible_length;
                    301: static int saved_prefix_length;
                    302: static int saved_local_length;
                    303: static int saved_invis_chars_first_line;
                    304: static int saved_physical_chars;
                    305: 
1.1.1.3 ! misho     306: /* Return a string indicating the editing mode, for use in the prompt. */
        !           307: 
        !           308: static char *
        !           309: prompt_modestr (int *lenp)
1.1       misho     310: {
                    311:   if (rl_editing_mode == emacs_mode)
1.1.1.3 ! misho     312:     {
        !           313:       if (lenp)
        !           314:        *lenp = _rl_emacs_mode_str ? _rl_emacs_modestr_len : RL_EMACS_MODESTR_DEFLEN;
        !           315:       return _rl_emacs_mode_str ? _rl_emacs_mode_str : RL_EMACS_MODESTR_DEFAULT;
        !           316:     }
1.1       misho     317:   else if (_rl_keymap == vi_insertion_keymap)
1.1.1.3 ! misho     318:     {
        !           319:       if (lenp)
        !           320:        *lenp = _rl_vi_ins_mode_str ? _rl_vi_ins_modestr_len : RL_VI_INS_MODESTR_DEFLEN;
        !           321:       return _rl_vi_ins_mode_str ? _rl_vi_ins_mode_str : RL_VI_INS_MODESTR_DEFAULT;            /* vi insert mode */
        !           322:     }
1.1       misho     323:   else
1.1.1.3 ! misho     324:     {
        !           325:       if (lenp)
        !           326:        *lenp = _rl_vi_cmd_mode_str ? _rl_vi_cmd_modestr_len : RL_VI_CMD_MODESTR_DEFLEN;
        !           327:       return _rl_vi_cmd_mode_str ? _rl_vi_cmd_mode_str : RL_VI_CMD_MODESTR_DEFAULT;            /* vi command mode */
        !           328:     }
1.1       misho     329: }
                    330: 
                    331: /* Expand the prompt string S and return the number of visible
                    332:    characters in *LP, if LP is not null.  This is currently more-or-less
                    333:    a placeholder for expansion.  LIP, if non-null is a place to store the
                    334:    index of the last invisible character in the returned string. NIFLP,
                    335:    if non-zero, is a place to store the number of invisible characters in
                    336:    the first prompt line.  The previous are used as byte counts -- indexes
1.1.1.3 ! misho     337:    into a character buffer.  *VLP gets the number of physical characters in
        !           338:    the expanded prompt (visible length) */
1.1       misho     339: 
                    340: /* Current implementation:
                    341:        \001 (^A) start non-visible characters
                    342:        \002 (^B) end non-visible characters
                    343:    all characters except \001 and \002 (following a \001) are copied to
                    344:    the returned string; all characters except those between \001 and
                    345:    \002 are assumed to be `visible'. */        
                    346: 
1.1.1.3 ! misho     347: /* Possible values for FLAGS:
        !           348:        PMT_MULTILINE   caller indicates that this is part of a multiline prompt
        !           349: */
        !           350: 
        !           351: /* This approximates the number of lines the prompt will take when displayed */
        !           352: #define APPROX_DIV(n, d)       (((n) < (d)) ? 1 : ((n) / (d)) + 1)
        !           353: 
1.1       misho     354: static char *
1.1.1.3 ! misho     355: expand_prompt (char *pmt, int flags, int *lp, int *lip, int *niflp, int *vlp)
1.1       misho     356: {
1.1.1.3 ! misho     357:   char *r, *ret, *p, *igstart, *nprompt, *ms;
1.1       misho     358:   int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars;
1.1.1.3 ! misho     359:   int mlen, newlines, newlines_guess, bound;
        !           360:   int mb_cur_max;
1.1       misho     361: 
1.1.1.3 ! misho     362:   /* We only expand the mode string for the last line of a multiline prompt
        !           363:      (a prompt with embedded newlines). */
        !           364:   ms = (((pmt == rl_prompt) ^ (flags & PMT_MULTILINE)) && _rl_show_mode_in_prompt) ? prompt_modestr (&mlen) : 0;
        !           365:   if (ms)
1.1       misho     366:     {
1.1.1.3 ! misho     367:       l = strlen (pmt);
        !           368:       nprompt = (char *)xmalloc (l + mlen + 1);
        !           369:       memcpy (nprompt, ms, mlen);
        !           370:       strcpy (nprompt + mlen, pmt);
1.1       misho     371:     }
1.1.1.3 ! misho     372:   else
        !           373:     nprompt = pmt;
1.1       misho     374: 
1.1.1.3 ! misho     375:   mb_cur_max = MB_CUR_MAX;
1.1       misho     376: 
1.1.1.3 ! misho     377:   if (_rl_screenwidth == 0)
        !           378:     _rl_get_screen_size (0, 0);        /* avoid division by zero */
        !           379: 
        !           380:   /* Short-circuit if we can.  We can do this if we are treating the prompt as
        !           381:      a sequence of bytes and there are no invisible characters in the prompt
        !           382:      to deal with. Since we populate local_prompt_newlines, we have to run
        !           383:      through the rest of the function if this prompt looks like it's going to
        !           384:      be longer than one screen line. */
        !           385:   if ((mb_cur_max <= 1 || rl_byte_oriented) && strchr (nprompt, RL_PROMPT_START_IGNORE) == 0)
1.1       misho     386:     {
1.1.1.3 ! misho     387:       l = strlen (nprompt);
        !           388:       if (l < (_rl_screenwidth > 0 ? _rl_screenwidth : 80))
        !           389:         {
        !           390:          r = (nprompt == pmt) ? savestring (pmt) : nprompt;
        !           391:          if (lp)
        !           392:            *lp = l;
        !           393:          if (lip)
        !           394:            *lip = 0;
        !           395:          if (niflp)
        !           396:            *niflp = 0;
        !           397:          if (vlp)
        !           398:            *vlp = l;
        !           399: 
        !           400:          local_prompt_newlines = (int *) xrealloc (local_prompt_newlines, sizeof (int) * 2);
        !           401:          local_prompt_newlines[0] = 0;
        !           402:          local_prompt_newlines[1] = -1;
        !           403: 
        !           404:          return r;
        !           405:         }
1.1       misho     406:     }
                    407: 
1.1.1.3 ! misho     408:   l = strlen (nprompt);                        /* XXX */
        !           409:   r = ret = (char *)xmalloc (l + 1);
        !           410: 
        !           411:   /* Guess at how many screen lines the prompt will take to size the array that
        !           412:      keeps track of where the line wraps happen */
        !           413:   newlines_guess = (_rl_screenwidth > 0) ? APPROX_DIV(l,  _rl_screenwidth) : APPROX_DIV(l, 80);
        !           414:   local_prompt_newlines = (int *) xrealloc (local_prompt_newlines, sizeof (int) * (newlines_guess + 1));
        !           415:   local_prompt_newlines[newlines = 0] = 0;
        !           416:   for (rl = 1; rl <= newlines_guess; rl++)
        !           417:     local_prompt_newlines[rl] = -1;
        !           418: 
        !           419:   rl = physchars = 0;  /* mode string now part of nprompt */
        !           420:   invfl = 0;           /* invisible chars in first line of prompt */
        !           421:   invflset = 0;                /* we only want to set invfl once */
        !           422:   igstart = 0;         /* we're not ignoring any characters yet */
1.1       misho     423: 
1.1.1.3 ! misho     424:   for (ignoring = last = ninvis = 0, p = nprompt; p && *p; p++)
1.1       misho     425:     {
                    426:       /* This code strips the invisible character string markers
                    427:         RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
                    428:       if (ignoring == 0 && *p == RL_PROMPT_START_IGNORE)               /* XXX - check ignoring? */
                    429:        {
                    430:          ignoring = 1;
                    431:          igstart = p;
                    432:          continue;
                    433:        }
                    434:       else if (ignoring && *p == RL_PROMPT_END_IGNORE)
                    435:        {
                    436:          ignoring = 0;
                    437:          if (p != (igstart + 1))
                    438:            last = r - ret - 1;
                    439:          continue;
                    440:        }
                    441:       else
                    442:        {
                    443: #if defined (HANDLE_MULTIBYTE)
1.1.1.3 ! misho     444:          if (mb_cur_max > 1 && rl_byte_oriented == 0)
1.1       misho     445:            {
1.1.1.3 ! misho     446:              pind = p - nprompt;
        !           447:              ind = _rl_find_next_mbchar (nprompt, pind, 1, MB_FIND_NONZERO);
1.1       misho     448:              l = ind - pind;
                    449:              while (l--)
                    450:                *r++ = *p++;
                    451:              if (!ignoring)
                    452:                {
                    453:                  /* rl ends up being assigned to prompt_visible_length,
                    454:                     which is the number of characters in the buffer that
                    455:                     contribute to characters on the screen, which might
                    456:                     not be the same as the number of physical characters
                    457:                     on the screen in the presence of multibyte characters */
                    458:                  rl += ind - pind;
1.1.1.3 ! misho     459:                  physchars += _rl_col_width (nprompt, pind, ind, 0);
1.1       misho     460:                }
                    461:              else
                    462:                ninvis += ind - pind;
                    463:              p--;                      /* compensate for later increment */
                    464:            }
                    465:          else
                    466: #endif
                    467:            {
                    468:              *r++ = *p;
                    469:              if (!ignoring)
                    470:                {
                    471:                  rl++;                 /* visible length byte counter */
                    472:                  physchars++;
                    473:                }
                    474:              else
                    475:                ninvis++;               /* invisible chars byte counter */
                    476:            }
                    477: 
1.1.1.3 ! misho     478:          if (invflset == 0 && physchars >= _rl_screenwidth)
1.1       misho     479:            {
                    480:              invfl = ninvis;
                    481:              invflset = 1;
                    482:            }
1.1.1.3 ! misho     483: 
        !           484:          if (physchars >= (bound = (newlines + 1) * _rl_screenwidth) && local_prompt_newlines[newlines+1] == -1)
        !           485:            {
        !           486:              int new;
        !           487:              if (physchars > bound)            /* should rarely happen */
        !           488:                {
        !           489: #if defined (HANDLE_MULTIBYTE)
        !           490:                  *r = '\0';    /* need null-termination for strlen */
        !           491:                  if (mb_cur_max > 1 && rl_byte_oriented == 0)
        !           492:                    new = _rl_find_prev_mbchar (ret, r - ret, MB_FIND_ANY);
        !           493:                  else
        !           494: #endif
        !           495:                    new = r - ret - (physchars - bound);        /* XXX */
        !           496:                }
        !           497:              else
        !           498:                new = r - ret;
        !           499:              local_prompt_newlines[++newlines] = new;
        !           500:            }
1.1       misho     501:        }
                    502:     }
                    503: 
                    504:   if (rl < _rl_screenwidth)
                    505:     invfl = ninvis;
                    506: 
                    507:   *r = '\0';
                    508:   if (lp)
                    509:     *lp = rl;
                    510:   if (lip)
                    511:     *lip = last;
                    512:   if (niflp)
                    513:     *niflp = invfl;
                    514:   if  (vlp)
                    515:     *vlp = physchars;
1.1.1.3 ! misho     516: 
        !           517:   if (nprompt != pmt)
        !           518:     free (nprompt);
        !           519: 
1.1       misho     520:   return ret;
                    521: }
                    522: 
                    523: /* Just strip out RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE from
                    524:    PMT and return the rest of PMT. */
                    525: char *
1.1.1.3 ! misho     526: _rl_strip_prompt (char *pmt)
1.1       misho     527: {
                    528:   char *ret;
                    529: 
1.1.1.3 ! misho     530:   ret = expand_prompt (pmt, 0, (int *)NULL, (int *)NULL, (int *)NULL, (int *)NULL);
1.1       misho     531:   return ret;
                    532: }
                    533: 
                    534: void
1.1.1.3 ! misho     535: _rl_reset_prompt (void)
1.1       misho     536: {
                    537:   rl_visible_prompt_length = rl_expand_prompt (rl_prompt);
                    538: }
                    539: 
                    540: /*
                    541:  * Expand the prompt string into the various display components, if
                    542:  * necessary.
                    543:  *
                    544:  * local_prompt = expanded last line of string in rl_display_prompt
                    545:  *               (portion after the final newline)
                    546:  * local_prompt_prefix = portion before last newline of rl_display_prompt,
                    547:  *                      expanded via expand_prompt
                    548:  * prompt_visible_length = number of visible characters in local_prompt
                    549:  * prompt_prefix_length = number of visible characters in local_prompt_prefix
                    550:  *
1.1.1.3 ! misho     551:  * It also tries to keep track of the number of invisible characters in the
        !           552:  * prompt string, and where they are.
        !           553:  *
1.1       misho     554:  * This function is called once per call to readline().  It may also be
                    555:  * called arbitrarily to expand the primary prompt.
                    556:  *
                    557:  * The return value is the number of visible characters on the last line
1.1.1.3 ! misho     558:  * of the (possibly multi-line) prompt.  In this case, multi-line means
        !           559:  * there are embedded newlines in the prompt string itself, not that the
        !           560:  * number of physical characters exceeds the screen width and the prompt
        !           561:  * wraps.
1.1       misho     562:  */
                    563: int
1.1.1.3 ! misho     564: rl_expand_prompt (char *prompt)
1.1       misho     565: {
                    566:   char *p, *t;
                    567:   int c;
                    568: 
                    569:   /* Clear out any saved values. */
                    570:   FREE (local_prompt);
                    571:   FREE (local_prompt_prefix);
                    572: 
                    573:   local_prompt = local_prompt_prefix = (char *)0;
                    574:   local_prompt_len = 0;
                    575:   prompt_last_invisible = prompt_invis_chars_first_line = 0;
                    576:   prompt_visible_length = prompt_physical_chars = 0;
                    577: 
                    578:   if (prompt == 0 || *prompt == 0)
                    579:     return (0);
                    580: 
                    581:   p = strrchr (prompt, '\n');
1.1.1.3 ! misho     582:   if (p == 0)
1.1       misho     583:     {
                    584:       /* The prompt is only one logical line, though it might wrap. */
1.1.1.3 ! misho     585:       local_prompt = expand_prompt (prompt, 0, &prompt_visible_length,
        !           586:                                               &prompt_last_invisible,
        !           587:                                               &prompt_invis_chars_first_line,
        !           588:                                               &prompt_physical_chars);
1.1       misho     589:       local_prompt_prefix = (char *)0;
                    590:       local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
                    591:       return (prompt_visible_length);
                    592:     }
                    593:   else
                    594:     {
                    595:       /* The prompt spans multiple lines. */
                    596:       t = ++p;
                    597:       c = *t; *t = '\0';
                    598:       /* The portion of the prompt string up to and including the
                    599:         final newline is now null-terminated. */
1.1.1.3 ! misho     600:       local_prompt_prefix = expand_prompt (prompt, PMT_MULTILINE,
        !           601:                                                   &prompt_prefix_length,
1.1       misho     602:                                                   (int *)NULL,
                    603:                                                   (int *)NULL,
                    604:                                                   (int *)NULL);
                    605:       *t = c;
1.1.1.3 ! misho     606: 
        !           607:       local_prompt = expand_prompt (p, PMT_MULTILINE,
        !           608:                                       &prompt_visible_length,
        !           609:                                       &prompt_last_invisible,
        !           610:                                       &prompt_invis_chars_first_line,
        !           611:                                       &prompt_physical_chars);
1.1       misho     612:       local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
                    613:       return (prompt_prefix_length);
                    614:     }
                    615: }
                    616: 
1.1.1.3 ! misho     617: /* Allocate the various line structures, making sure they can hold MINSIZE
        !           618:    bytes. If the existing line size can accommodate MINSIZE bytes, don't do
        !           619:    anything. */
        !           620: static void
        !           621: realloc_line (int minsize)
        !           622: {
        !           623:   int minimum_size;
        !           624:   int newsize, delta;
        !           625: 
        !           626:   minimum_size = DEFAULT_LINE_BUFFER_SIZE;
        !           627:   if (minsize < minimum_size)
        !           628:     minsize = minimum_size;
        !           629:   if (minsize <= _rl_screenwidth)      /* XXX - for gdb */
        !           630:     minsize = _rl_screenwidth + 1;
        !           631:   if (line_size >= minsize)
        !           632:     return;
        !           633: 
        !           634:   newsize = minimum_size;
        !           635:   while (newsize < minsize)
        !           636:     newsize *= 2;
        !           637: 
        !           638:   visible_line = (char *)xrealloc (visible_line, newsize);
        !           639:   vis_face = (char *)xrealloc (vis_face, newsize);
        !           640: 
        !           641:   invisible_line = (char *)xrealloc (invisible_line, newsize);
        !           642:   inv_face = (char *)xrealloc (inv_face, newsize);
        !           643: 
        !           644:   delta = newsize - line_size;  
        !           645:   memset (visible_line + line_size, 0, delta);
        !           646:   memset (vis_face + line_size, FACE_NORMAL, delta);
        !           647:   memset (invisible_line + line_size, 1, delta);
        !           648:   memset (inv_face + line_size, FACE_INVALID, delta);
        !           649: 
        !           650:   line_size = newsize;
        !           651: }
        !           652: 
1.1       misho     653: /* Initialize the VISIBLE_LINE and INVISIBLE_LINE arrays, and their associated
                    654:    arrays of line break markers.  MINSIZE is the minimum size of VISIBLE_LINE
                    655:    and INVISIBLE_LINE; if it is greater than LINE_SIZE, LINE_SIZE is
                    656:    increased.  If the lines have already been allocated, this ensures that
                    657:    they can hold at least MINSIZE characters. */
                    658: static void
1.1.1.3 ! misho     659: init_line_structures (int minsize)
1.1       misho     660: {
                    661:   if (invisible_line == 0)     /* initialize it */
                    662:     {
1.1.1.3 ! misho     663:       if (line_size > minsize)
        !           664:        minsize = line_size;
1.1       misho     665:     }
1.1.1.3 ! misho     666:    realloc_line (minsize); 
1.1       misho     667: 
                    668:   if (vis_lbreaks == 0)
                    669:     {
                    670:       /* should be enough. */
                    671:       inv_lbsize = vis_lbsize = 256;
                    672: 
                    673: #if defined (HANDLE_MULTIBYTE)
                    674:       line_state_visible->wbsize = vis_lbsize;
                    675:       line_state_visible->wrapped_line = (int *)xmalloc (line_state_visible->wbsize * sizeof (int));
                    676: 
                    677:       line_state_invisible->wbsize = inv_lbsize;
                    678:       line_state_invisible->wrapped_line = (int *)xmalloc (line_state_invisible->wbsize * sizeof (int));
                    679: #endif
                    680: 
                    681:       inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int));
                    682:       vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int));
                    683:       inv_lbreaks[0] = vis_lbreaks[0] = 0;
                    684:     }
                    685: 
                    686:   line_structures_initialized = 1;
                    687: }
1.1.1.3 ! misho     688: 
        !           689: /* Convenience functions to add chars to the invisible line that update the
        !           690:    face information at the same time. */
        !           691: static void            /* XXX - change this */
        !           692: invis_addc (int *outp, char c, char face)
        !           693: {
        !           694:   realloc_line (*outp + 1);
        !           695:   invisible_line[*outp] = c;
        !           696:   inv_face[*outp] = face;
        !           697:   *outp += 1;
        !           698: }
        !           699: 
        !           700: static void
        !           701: invis_adds (int *outp, const char *str, int n, char face)
        !           702: {
        !           703:   int i;
        !           704: 
        !           705:   for (i = 0; i < n; i++)
        !           706:     invis_addc (outp, str[i], face);
        !           707: }
        !           708: 
        !           709: static void
        !           710: invis_nul (int *outp)
        !           711: {
        !           712:   invis_addc (outp, '\0', 0);
        !           713:   *outp -= 1;
        !           714: }
        !           715: 
        !           716: static void
        !           717: set_active_region (int *beg, int *end)
        !           718: {
        !           719:   if (rl_point >= 0 && rl_point <= rl_end && rl_mark >= 0 && rl_mark <= rl_end)
        !           720:     {
        !           721:       *beg = (rl_mark < rl_point) ? rl_mark : rl_point;
        !           722:       *end = (rl_mark < rl_point) ? rl_point : rl_mark;
        !           723:     }
        !           724: }
        !           725: 
        !           726: /* Do whatever tests are necessary and tell update_line that it can do a
        !           727:    quick, dumb redisplay on the assumption that there are so many
        !           728:    differences between the old and new lines that it would be a waste to
        !           729:    compute all the differences.
        !           730:    Right now, it just sets _rl_quick_redisplay if the current visible line
        !           731:    is a single line (so we don't have to move vertically or mess with line
        !           732:    wrapping). */
1.1       misho     733: void
1.1.1.3 ! misho     734: _rl_optimize_redisplay (void)
1.1       misho     735: {
1.1.1.3 ! misho     736:   if (_rl_vis_botlin == 0)
        !           737:     _rl_quick_redisplay = 1;
        !           738: }  
        !           739: 
        !           740: /* Basic redisplay algorithm.  See comments inline. */
        !           741: void
        !           742: rl_redisplay (void)
        !           743: {
        !           744:   int in, out, c, linenum, cursor_linenum;
1.1       misho     745:   int inv_botlin, lb_botlin, lb_linenum, o_cpos;
                    746:   int newlines, lpos, temp, n0, num, prompt_lines_estimate;
                    747:   char *prompt_this_line;
1.1.1.3 ! misho     748:   char cur_face;
        !           749:   int hl_begin, hl_end;
        !           750:   int mb_cur_max = MB_CUR_MAX;
1.1       misho     751: #if defined (HANDLE_MULTIBYTE)
                    752:   wchar_t wc;
                    753:   size_t wc_bytes;
                    754:   int wc_width;
                    755:   mbstate_t ps;
                    756:   int _rl_wrapped_multicolumn = 0;
                    757: #endif
                    758: 
                    759:   if (_rl_echoing_p == 0)
                    760:     return;
                    761: 
                    762:   /* Block keyboard interrupts because this function manipulates global
                    763:      data structures. */
                    764:   _rl_block_sigint ();  
                    765:   RL_SETSTATE (RL_STATE_REDISPLAYING);
                    766: 
1.1.1.3 ! misho     767:   cur_face = FACE_NORMAL;
        !           768:   /* Can turn this into an array for multiple highlighted objects in addition
        !           769:      to the region */
        !           770:   hl_begin = hl_end = -1;
        !           771: 
        !           772:   if (rl_mark_active_p ())
        !           773:     set_active_region (&hl_begin, &hl_end);
        !           774: 
1.1       misho     775:   if (!rl_display_prompt)
                    776:     rl_display_prompt = "";
                    777: 
                    778:   if (line_structures_initialized == 0)
                    779:     {
                    780:       init_line_structures (0);
                    781:       rl_on_new_line ();
                    782:     }
1.1.1.3 ! misho     783:   else if (line_size <= _rl_screenwidth)
        !           784:     init_line_structures (_rl_screenwidth + 1);
        !           785: 
        !           786:   /* Enable horizontal scrolling automatically for terminals of height 1
        !           787:      where wrapping lines doesn't work. Disable it as soon as the terminal
        !           788:      height is increased again if it was automatically enabled. */
        !           789:   if (_rl_screenheight <= 1)
        !           790:     {
        !           791:       if (_rl_horizontal_scroll_mode == 0)
        !           792:         horizontal_scrolling_autoset = 1;
        !           793:       _rl_horizontal_scroll_mode = 1;
        !           794:     }
        !           795:   else if (horizontal_scrolling_autoset)
        !           796:     _rl_horizontal_scroll_mode = 0;
1.1       misho     797: 
                    798:   /* Draw the line into the buffer. */
                    799:   cpos_buffer_position = -1;
                    800: 
                    801:   prompt_multibyte_chars = prompt_visible_length - prompt_physical_chars;
                    802: 
                    803:   out = inv_botlin = 0;
                    804: 
                    805:   /* Mark the line as modified or not.  We only do this for history
                    806:      lines. */
                    807:   modmark = 0;
                    808:   if (_rl_mark_modified_lines && current_history () && rl_undo_list)
                    809:     {
1.1.1.3 ! misho     810:       invis_addc (&out, '*', cur_face);
        !           811:       invis_nul (&out);
1.1       misho     812:       modmark = 1;
                    813:     }
                    814: 
                    815:   /* If someone thought that the redisplay was handled, but the currently
                    816:      visible line has a different modification state than the one about
                    817:      to become visible, then correct the caller's misconception. */
                    818:   if (visible_line[0] != invisible_line[0])
                    819:     rl_display_fixed = 0;
                    820: 
                    821:   /* If the prompt to be displayed is the `primary' readline prompt (the
                    822:      one passed to readline()), use the values we have already expanded.
                    823:      If not, use what's already in rl_display_prompt.  WRAP_OFFSET is the
1.1.1.3 ! misho     824:      number of non-visible characters (bytes) in the prompt string. */
        !           825:   /* This is where we output the characters in the prompt before the last
        !           826:      newline, if any.  If there aren't any embedded newlines, we don't
        !           827:      write anything. Copy the last line of the prompt string into the line in
        !           828:      any case */
1.1       misho     829:   if (rl_display_prompt == rl_prompt || local_prompt)
                    830:     {
                    831:       if (local_prompt_prefix && forced_display)
                    832:        _rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix));
                    833: 
                    834:       if (local_prompt_len > 0)
1.1.1.3 ! misho     835:        invis_adds (&out, local_prompt, local_prompt_len, cur_face);
        !           836:       invis_nul (&out);
1.1       misho     837:       wrap_offset = local_prompt_len - prompt_visible_length;
                    838:     }
                    839:   else
                    840:     {
                    841:       int pmtlen;
                    842:       prompt_this_line = strrchr (rl_display_prompt, '\n');
                    843:       if (!prompt_this_line)
                    844:        prompt_this_line = rl_display_prompt;
                    845:       else
                    846:        {
                    847:          prompt_this_line++;
                    848:          pmtlen = prompt_this_line - rl_display_prompt;        /* temp var */
                    849:          if (forced_display)
                    850:            {
                    851:              _rl_output_some_chars (rl_display_prompt, pmtlen);
                    852:              /* Make sure we are at column zero even after a newline,
                    853:                 regardless of the state of terminal output processing. */
                    854:              if (pmtlen < 2 || prompt_this_line[-2] != '\r')
                    855:                cr ();
                    856:            }
                    857:        }
                    858: 
1.1.1.3 ! misho     859:       prompt_physical_chars = pmtlen = strlen (prompt_this_line);      /* XXX */
        !           860:       invis_adds (&out, prompt_this_line, pmtlen, cur_face);
        !           861:       invis_nul (&out);
1.1       misho     862:       wrap_offset = prompt_invis_chars_first_line = 0;
                    863:     }
                    864: 
1.1.1.3 ! misho     865: #if defined (HANDLE_MULTIBYTE)
1.1       misho     866: #define CHECK_INV_LBREAKS() \
                    867:       do { \
                    868:        if (newlines >= (inv_lbsize - 2)) \
                    869:          { \
                    870:            inv_lbsize *= 2; \
                    871:            inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
                    872:          } \
1.1.1.3 ! misho     873:        if (newlines >= (line_state_invisible->wbsize - 2)) \
        !           874:          { \
        !           875:            line_state_invisible->wbsize *= 2; \
        !           876:            line_state_invisible->wrapped_line = (int *)xrealloc (line_state_invisible->wrapped_line, line_state_invisible->wbsize * sizeof(int)); \
        !           877:          } \
1.1       misho     878:       } while (0)
1.1.1.3 ! misho     879: #else
        !           880: #define CHECK_INV_LBREAKS() \
        !           881:       do { \
        !           882:        if (newlines >= (inv_lbsize - 2)) \
        !           883:          { \
        !           884:            inv_lbsize *= 2; \
        !           885:            inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
        !           886:          } \
        !           887:       } while (0)
        !           888: #endif /* !HANDLE_MULTIBYTE */
1.1       misho     889: 
                    890: #if defined (HANDLE_MULTIBYTE)   
                    891: #define CHECK_LPOS() \
                    892:       do { \
                    893:        lpos++; \
                    894:        if (lpos >= _rl_screenwidth) \
                    895:          { \
                    896:            if (newlines >= (inv_lbsize - 2)) \
                    897:              { \
                    898:                inv_lbsize *= 2; \
                    899:                inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
                    900:              } \
                    901:            inv_lbreaks[++newlines] = out; \
1.1.1.3 ! misho     902:            if (newlines >= (line_state_invisible->wbsize - 2)) \
1.1       misho     903:              { \
                    904:                line_state_invisible->wbsize *= 2; \
                    905:                line_state_invisible->wrapped_line = (int *)xrealloc (line_state_invisible->wrapped_line, line_state_invisible->wbsize * sizeof(int)); \
                    906:              } \
                    907:            line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn; \
                    908:            lpos = 0; \
                    909:          } \
                    910:       } while (0)
                    911: #else
                    912: #define CHECK_LPOS() \
                    913:       do { \
                    914:        lpos++; \
                    915:        if (lpos >= _rl_screenwidth) \
                    916:          { \
                    917:            if (newlines >= (inv_lbsize - 2)) \
                    918:              { \
                    919:                inv_lbsize *= 2; \
                    920:                inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
                    921:              } \
                    922:            inv_lbreaks[++newlines] = out; \
                    923:            lpos = 0; \
                    924:          } \
                    925:       } while (0)
                    926: #endif
                    927: 
                    928:   /* inv_lbreaks[i] is where line i starts in the buffer. */
                    929:   inv_lbreaks[newlines = 0] = 0;
1.1.1.3 ! misho     930:   /* lpos is a physical cursor position, so it needs to be adjusted by the
        !           931:      number of invisible characters in the prompt, per line.  We compute
        !           932:      the line breaks in the prompt string in expand_prompt, taking invisible
        !           933:      characters into account, and if lpos exceeds the screen width, we copy
        !           934:      the data in the loop below. */
1.1       misho     935:   lpos = prompt_physical_chars + modmark;
                    936: 
                    937: #if defined (HANDLE_MULTIBYTE)
                    938:   memset (line_state_invisible->wrapped_line, 0, line_state_invisible->wbsize * sizeof (int));
                    939:   num = 0;
                    940: #endif
                    941: 
1.1.1.3 ! misho     942:   /* prompt_invis_chars_first_line is the number of invisible characters (bytes)
        !           943:      in the first physical line of the prompt.
        !           944:      wrap_offset - prompt_invis_chars_first_line is usually the number of
        !           945:      invis chars on the second (or, more generally, last) line. */
1.1       misho     946: 
                    947:   /* This is zero-based, used to set the newlines */
                    948:   prompt_lines_estimate = lpos / _rl_screenwidth;
                    949: 
                    950:   /* what if lpos is already >= _rl_screenwidth before we start drawing the
                    951:      contents of the command line? */
1.1.1.3 ! misho     952:   if (lpos >= _rl_screenwidth)
1.1       misho     953:     {
1.1.1.3 ! misho     954:       temp = 0;
1.1       misho     955: 
1.1.1.3 ! misho     956:       /* first copy the linebreaks array we computed in expand_prompt */
        !           957:       while (local_prompt_newlines[newlines+1] != -1)
        !           958:        {
        !           959:          temp = local_prompt_newlines[newlines+1];
        !           960:          inv_lbreaks[++newlines] = temp;
        !           961:        }  
1.1       misho     962: 
1.1.1.3 ! misho     963:       /* Now set lpos from the last newline */
        !           964:       if (mb_cur_max > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0)
        !           965:         lpos = _rl_col_width (local_prompt, temp, local_prompt_len, 1) - (wrap_offset - prompt_invis_chars_first_line);
1.1       misho     966:       else
1.1.1.3 ! misho     967:         lpos -= (_rl_screenwidth * newlines);
1.1       misho     968:     }
                    969: 
                    970:   prompt_last_screen_line = newlines;
                    971: 
                    972:   /* Draw the rest of the line (after the prompt) into invisible_line, keeping
1.1.1.3 ! misho     973:      track of where the cursor is (cpos_buffer_position), the number of the
        !           974:      line containing the cursor (lb_linenum), the last line number (lb_botlin
        !           975:      and inv_botlin).
1.1       misho     976:      It maintains an array of line breaks for display (inv_lbreaks).
                    977:      This handles expanding tabs for display and displaying meta characters. */
                    978:   lb_linenum = 0;
                    979: #if defined (HANDLE_MULTIBYTE)
                    980:   in = 0;
1.1.1.3 ! misho     981:   if (mb_cur_max > 1 && rl_byte_oriented == 0)
1.1       misho     982:     {
                    983:       memset (&ps, 0, sizeof (mbstate_t));
1.1.1.3 ! misho     984:       if (_rl_utf8locale && UTF8_SINGLEBYTE(rl_line_buffer[0]))
        !           985:        {
        !           986:          wc = (wchar_t)rl_line_buffer[0];
        !           987:          wc_bytes = 1;
        !           988:        }
        !           989:       else
        !           990:        wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps);
1.1       misho     991:     }
                    992:   else
                    993:     wc_bytes = 1;
                    994:   while (in < rl_end)
                    995: #else
                    996:   for (in = 0; in < rl_end; in++)
                    997: #endif
                    998:     {
1.1.1.3 ! misho     999:       if (in == hl_begin)
        !          1000:        cur_face = FACE_STANDOUT;
        !          1001:       else if (in == hl_end)
        !          1002:        cur_face = FACE_NORMAL;
        !          1003: 
1.1       misho    1004:       c = (unsigned char)rl_line_buffer[in];
                   1005: 
                   1006: #if defined (HANDLE_MULTIBYTE)
1.1.1.3 ! misho    1007:       if (mb_cur_max > 1 && rl_byte_oriented == 0)
1.1       misho    1008:        {
                   1009:          if (MB_INVALIDCH (wc_bytes))
                   1010:            {
                   1011:              /* Byte sequence is invalid or shortened.  Assume that the
                   1012:                 first byte represents a character. */
                   1013:              wc_bytes = 1;
                   1014:              /* Assume that a character occupies a single column. */
                   1015:              wc_width = 1;
                   1016:              memset (&ps, 0, sizeof (mbstate_t));
                   1017:            }
                   1018:          else if (MB_NULLWCH (wc_bytes))
                   1019:            break;                      /* Found '\0' */
                   1020:          else
                   1021:            {
                   1022:              temp = WCWIDTH (wc);
                   1023:              wc_width = (temp >= 0) ? temp : 1;
                   1024:            }
                   1025:        }
                   1026: #endif
                   1027: 
                   1028:       if (in == rl_point)
                   1029:        {
                   1030:          cpos_buffer_position = out;
                   1031:          lb_linenum = newlines;
                   1032:        }
                   1033: 
                   1034: #if defined (HANDLE_MULTIBYTE)
                   1035:       if (META_CHAR (c) && _rl_output_meta_chars == 0) /* XXX - clean up */
                   1036: #else
                   1037:       if (META_CHAR (c))
                   1038: #endif
                   1039:        {
                   1040:          if (_rl_output_meta_chars == 0)
                   1041:            {
1.1.1.3 ! misho    1042:              char obuf[5];
        !          1043:              int olen;
1.1       misho    1044: 
1.1.1.3 ! misho    1045:              olen = sprintf (obuf, "\\%o", c);
        !          1046:          
        !          1047:              if (lpos + olen >= _rl_screenwidth)
1.1       misho    1048:                {
                   1049:                  temp = _rl_screenwidth - lpos;
                   1050:                  CHECK_INV_LBREAKS ();
                   1051:                  inv_lbreaks[++newlines] = out + temp;
1.1.1.3 ! misho    1052: #if defined (HANDLE_MULTIBYTE)
        !          1053:                  line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn;
        !          1054: #endif
        !          1055:                  lpos = olen - temp;
1.1       misho    1056:                }
                   1057:              else
1.1.1.3 ! misho    1058:                lpos += olen;
1.1       misho    1059: 
1.1.1.3 ! misho    1060:              for (temp = 0; temp < olen; temp++)
        !          1061:                {
        !          1062:                  invis_addc (&out, obuf[temp], cur_face);
        !          1063:                  CHECK_LPOS ();
        !          1064:                }
1.1       misho    1065:            }
                   1066:          else
                   1067:            {
1.1.1.3 ! misho    1068:              invis_addc (&out, c, cur_face);
1.1       misho    1069:              CHECK_LPOS();
                   1070:            }
                   1071:        }
                   1072: #if defined (DISPLAY_TABS)
                   1073:       else if (c == '\t')
                   1074:        {
                   1075:          register int newout;
                   1076: 
                   1077:          newout = out + 8 - lpos % 8;
                   1078:          temp = newout - out;
                   1079:          if (lpos + temp >= _rl_screenwidth)
                   1080:            {
                   1081:              register int temp2;
                   1082:              temp2 = _rl_screenwidth - lpos;
                   1083:              CHECK_INV_LBREAKS ();
                   1084:              inv_lbreaks[++newlines] = out + temp2;
1.1.1.3 ! misho    1085: #if defined (HANDLE_MULTIBYTE)
        !          1086:              line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn;
        !          1087: #endif
1.1       misho    1088:              lpos = temp - temp2;
                   1089:              while (out < newout)
1.1.1.3 ! misho    1090:                invis_addc (&out, ' ', cur_face);
1.1       misho    1091:            }
                   1092:          else
                   1093:            {
                   1094:              while (out < newout)
1.1.1.3 ! misho    1095:                invis_addc (&out, ' ', cur_face);
1.1       misho    1096:              lpos += temp;
                   1097:            }
                   1098:        }
                   1099: #endif
                   1100:       else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
                   1101:        {
1.1.1.3 ! misho    1102:          invis_addc (&out, '\0', cur_face);
1.1       misho    1103:          CHECK_INV_LBREAKS ();
                   1104:          inv_lbreaks[++newlines] = out;
1.1.1.3 ! misho    1105: #if defined (HANDLE_MULTIBYTE)
        !          1106:          line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn;
        !          1107: #endif
1.1       misho    1108:          lpos = 0;
                   1109:        }
                   1110:       else if (CTRL_CHAR (c) || c == RUBOUT)
                   1111:        {
1.1.1.3 ! misho    1112:          invis_addc (&out, '^', cur_face);
1.1       misho    1113:          CHECK_LPOS();
1.1.1.3 ! misho    1114:          invis_addc (&out, CTRL_CHAR (c) ? UNCTRL (c) : '?', cur_face);
1.1       misho    1115:          CHECK_LPOS();
                   1116:        }
                   1117:       else
                   1118:        {
                   1119: #if defined (HANDLE_MULTIBYTE)
1.1.1.3 ! misho    1120:          if (mb_cur_max > 1 && rl_byte_oriented == 0)
1.1       misho    1121:            {
                   1122:              register int i;
                   1123: 
                   1124:              _rl_wrapped_multicolumn = 0;
                   1125: 
                   1126:              if (_rl_screenwidth < lpos + wc_width)
                   1127:                for (i = lpos; i < _rl_screenwidth; i++)
                   1128:                  {
                   1129:                    /* The space will be removed in update_line() */
1.1.1.3 ! misho    1130:                    invis_addc (&out, ' ', cur_face);
1.1       misho    1131:                    _rl_wrapped_multicolumn++;
                   1132:                    CHECK_LPOS();
                   1133:                  }
                   1134:              if (in == rl_point)
                   1135:                {
                   1136:                  cpos_buffer_position = out;
                   1137:                  lb_linenum = newlines;
                   1138:                }
                   1139:              for (i = in; i < in+wc_bytes; i++)
1.1.1.3 ! misho    1140:                invis_addc (&out, rl_line_buffer[i], cur_face);
1.1       misho    1141:              for (i = 0; i < wc_width; i++)
                   1142:                CHECK_LPOS();
                   1143:            }
                   1144:          else
                   1145:            {
1.1.1.3 ! misho    1146:              invis_addc (&out, c, cur_face);
1.1       misho    1147:              CHECK_LPOS();
                   1148:            }
                   1149: #else
1.1.1.3 ! misho    1150:          invis_addc (&out, c, cur_face);
1.1       misho    1151:          CHECK_LPOS();
                   1152: #endif
                   1153:        }
                   1154: 
                   1155: #if defined (HANDLE_MULTIBYTE)
1.1.1.3 ! misho    1156:       if (mb_cur_max > 1 && rl_byte_oriented == 0)
1.1       misho    1157:        {
                   1158:          in += wc_bytes;
1.1.1.3 ! misho    1159:          if (_rl_utf8locale && UTF8_SINGLEBYTE(rl_line_buffer[in]))
        !          1160:            {
        !          1161:              wc = (wchar_t)rl_line_buffer[in];
        !          1162:              wc_bytes = 1;
        !          1163:              memset (&ps, 0, sizeof (mbstate_t));      /* re-init state */
        !          1164:            }
        !          1165:          else
        !          1166:            wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps);
1.1       misho    1167:        }
                   1168:       else
                   1169:         in++;
                   1170: #endif
                   1171:     }
1.1.1.3 ! misho    1172:   invis_nul (&out);
        !          1173:   line_totbytes = out;
1.1       misho    1174:   if (cpos_buffer_position < 0)
                   1175:     {
                   1176:       cpos_buffer_position = out;
                   1177:       lb_linenum = newlines;
                   1178:     }
                   1179: 
1.1.1.3 ! misho    1180:   /* If we are switching from one line to multiple wrapped lines, we don't
        !          1181:      want to do a dumb update (or we want to make it smarter). */
        !          1182:   if (_rl_quick_redisplay && newlines > 0)
        !          1183:     _rl_quick_redisplay = 0;
        !          1184: 
        !          1185:   inv_botlin = lb_botlin = _rl_inv_botlin = newlines;
1.1       misho    1186:   CHECK_INV_LBREAKS ();
                   1187:   inv_lbreaks[newlines+1] = out;
1.1.1.3 ! misho    1188: #if defined (HANDLE_MULTIBYTE)
        !          1189:   /* This should be 0 anyway */
        !          1190:   line_state_invisible->wrapped_line[newlines+1] = _rl_wrapped_multicolumn;
        !          1191: #endif
1.1       misho    1192:   cursor_linenum = lb_linenum;
                   1193: 
                   1194:   /* CPOS_BUFFER_POSITION == position in buffer where cursor should be placed.
                   1195:      CURSOR_LINENUM == line number where the cursor should be placed. */
                   1196: 
                   1197:   /* PWP: now is when things get a bit hairy.  The visible and invisible
                   1198:      line buffers are really multiple lines, which would wrap every
                   1199:      (screenwidth - 1) characters.  Go through each in turn, finding
                   1200:      the changed region and updating it.  The line order is top to bottom. */
                   1201: 
                   1202:   /* If we can move the cursor up and down, then use multiple lines,
                   1203:      otherwise, let long lines display in a single terminal line, and
                   1204:      horizontally scroll it. */
                   1205:   displaying_prompt_first_line = 1;
                   1206:   if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
                   1207:     {
                   1208:       int nleft, pos, changed_screen_line, tx;
                   1209: 
                   1210:       if (!rl_display_fixed || forced_display)
                   1211:        {
                   1212:          forced_display = 0;
                   1213: 
                   1214:          /* If we have more than a screenful of material to display, then
                   1215:             only display a screenful.  We should display the last screen,
                   1216:             not the first.  */
                   1217:          if (out >= _rl_screenchars)
                   1218:            {
1.1.1.3 ! misho    1219: #if defined (HANDLE_MULTIBYTE)
        !          1220:              if (mb_cur_max > 1 && rl_byte_oriented == 0)
        !          1221:                out = _rl_find_prev_mbchar (invisible_line, _rl_screenchars, MB_FIND_ANY);
1.1       misho    1222:              else
1.1.1.3 ! misho    1223: #endif
1.1       misho    1224:                out = _rl_screenchars - 1;
                   1225:            }
                   1226: 
                   1227:          /* The first line is at character position 0 in the buffer.  The
                   1228:             second and subsequent lines start at inv_lbreaks[N], offset by
                   1229:             OFFSET (which has already been calculated above).  */
                   1230: 
                   1231: #define INVIS_FIRST()  (prompt_physical_chars > _rl_screenwidth ? prompt_invis_chars_first_line : wrap_offset)
                   1232: #define WRAP_OFFSET(line, offset)  ((line == 0) \
                   1233:                                        ? (offset ? INVIS_FIRST() : 0) \
                   1234:                                        : ((line == prompt_last_screen_line) ? wrap_offset-prompt_invis_chars_first_line : 0))
                   1235: #define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
                   1236: #define VIS_LLEN(l)    ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
                   1237: #define INV_LLEN(l)    (inv_lbreaks[l+1] - inv_lbreaks[l])
                   1238: #define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
1.1.1.3 ! misho    1239: #define VIS_FACE(line) (vis_face + vis_lbreaks[line])
1.1       misho    1240: #define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
1.1.1.3 ! misho    1241: #define VIS_LINE_FACE(line) ((line) > _rl_vis_botlin) ? "" : VIS_FACE(line)
1.1       misho    1242: #define INV_LINE(line) (invisible_line + inv_lbreaks[line])
1.1.1.3 ! misho    1243: #define INV_LINE_FACE(line) (inv_face + inv_lbreaks[line])
1.1       misho    1244: 
                   1245: #define OLD_CPOS_IN_PROMPT() (cpos_adjusted == 0 && \
                   1246:                        _rl_last_c_pos != o_cpos && \
                   1247:                        _rl_last_c_pos > wrap_offset && \
                   1248:                        o_cpos < prompt_last_invisible)
                   1249: 
1.1.1.3 ! misho    1250: 
        !          1251:          /* We don't want to highlight anything that's going to be off the top
        !          1252:             of the display; if the current line takes up more than an entire
        !          1253:            screen, just mark the lines that won't be displayed as having a
        !          1254:            `normal' face.
        !          1255:            It's imperfect, but better than display corruption. */
        !          1256:          if (rl_mark_active_p () && inv_botlin > _rl_screenheight)
        !          1257:            {
        !          1258:              int extra;
        !          1259: 
        !          1260:              extra = inv_botlin - _rl_screenheight;
        !          1261:              for (linenum = 0; linenum <= extra; linenum++)
        !          1262:                norm_face (INV_LINE_FACE(linenum), INV_LLEN (linenum));
        !          1263:            }
        !          1264: 
1.1       misho    1265:          /* For each line in the buffer, do the updating display. */
                   1266:          for (linenum = 0; linenum <= inv_botlin; linenum++)
                   1267:            {
                   1268:              /* This can lead us astray if we execute a program that changes
                   1269:                 the locale from a non-multibyte to a multibyte one. */
                   1270:              o_cpos = _rl_last_c_pos;
                   1271:              cpos_adjusted = 0;
1.1.1.3 ! misho    1272:              update_line (VIS_LINE(linenum), VIS_LINE_FACE(linenum),
        !          1273:                           INV_LINE(linenum), INV_LINE_FACE(linenum),
        !          1274:                           linenum,
1.1       misho    1275:                           VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin);
                   1276: 
                   1277:              /* update_line potentially changes _rl_last_c_pos, but doesn't
                   1278:                 take invisible characters into account, since _rl_last_c_pos
1.1.1.3 ! misho    1279:                 is an absolute cursor position in a multibyte locale.  We
        !          1280:                 choose to (mostly) compensate for that here, rather than
1.1       misho    1281:                 change update_line itself.  There are several cases in which
                   1282:                 update_line adjusts _rl_last_c_pos itself (so it can pass
                   1283:                 _rl_move_cursor_relative accurate values); it communicates
                   1284:                 this back by setting cpos_adjusted.  If we assume that
                   1285:                 _rl_last_c_pos is correct (an absolute cursor position) each
                   1286:                 time update_line is called, then we can assume in our
                   1287:                 calculations that o_cpos does not need to be adjusted by
                   1288:                 wrap_offset. */
1.1.1.3 ! misho    1289:              if (linenum == 0 && (mb_cur_max > 1 && rl_byte_oriented == 0) && OLD_CPOS_IN_PROMPT())
1.1       misho    1290:                _rl_last_c_pos -= prompt_invis_chars_first_line;        /* XXX - was wrap_offset */
1.1.1.3 ! misho    1291:              else if (cpos_adjusted == 0 &&
        !          1292:                        linenum == prompt_last_screen_line &&
        !          1293:                        prompt_physical_chars > _rl_screenwidth &&
        !          1294:                        (mb_cur_max > 1 && rl_byte_oriented == 0) &&
1.1       misho    1295:                        _rl_last_c_pos != o_cpos &&
1.1.1.3 ! misho    1296:                        _rl_last_c_pos > (prompt_last_invisible - _rl_screenwidth - prompt_invis_chars_first_line))     /* XXX - rethink this last one */
        !          1297:                /* This assumes that all the invisible characters are split
        !          1298:                   between the first and last lines of the prompt, if the 
        !          1299:                   prompt consumes more than two lines. It's usually right */
        !          1300:                /* XXX - not sure this is ever executed */
1.1       misho    1301:                _rl_last_c_pos -= (wrap_offset-prompt_invis_chars_first_line);
1.1.1.3 ! misho    1302: 
1.1       misho    1303:              /* If this is the line with the prompt, we might need to
                   1304:                 compensate for invisible characters in the new line. Do
                   1305:                 this only if there is not more than one new line (which
                   1306:                 implies that we completely overwrite the old visible line)
                   1307:                 and the new line is shorter than the old.  Make sure we are
                   1308:                 at the end of the new line before clearing. */
                   1309:              if (linenum == 0 &&
                   1310:                  inv_botlin == 0 && _rl_last_c_pos == out &&
                   1311:                  (wrap_offset > visible_wrap_offset) &&
                   1312:                  (_rl_last_c_pos < visible_first_line_len))
                   1313:                {
1.1.1.3 ! misho    1314:                  if (mb_cur_max > 1 && rl_byte_oriented == 0)
1.1       misho    1315:                    nleft = _rl_screenwidth - _rl_last_c_pos;
                   1316:                  else
                   1317:                    nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos;
                   1318:                  if (nleft)
                   1319:                    _rl_clear_to_eol (nleft);
                   1320:                }
                   1321: #if 0
1.1.1.3 ! misho    1322:              /* This segment is intended to handle the case where the old
        !          1323:                 visible prompt has invisible characters and the new line
1.1       misho    1324:                 to be displayed needs to clear the rest of the old characters
1.1.1.3 ! misho    1325:                 out (e.g., when printing the i-search prompt): in general,
        !          1326:                 the case of the new line being shorter than the old.  We need
        !          1327:                 to be at the end of the new line and the old line needs to be
        !          1328:                 longer than the current cursor position. It's not perfect,
        !          1329:                 since it uses the byte length of the first line, but this will
        !          1330:                 at worst result in some extra clear-to-end-of-lines. We can't
        !          1331:                 use the prompt length variables because they may not
        !          1332:                 correspond to the visible line (see printing the i-search
        !          1333:                 prompt above). The tests for differing numbers of invisible
        !          1334:                 characters may not matter and can probably be removed. */
        !          1335:              else if (linenum == 0 &&
        !          1336:                       linenum == prompt_last_screen_line &&
1.1       misho    1337:                       _rl_last_c_pos == out &&
1.1.1.3 ! misho    1338:                       _rl_last_c_pos < visible_first_line_len &&
        !          1339:                       visible_wrap_offset &&
        !          1340:                       visible_wrap_offset != wrap_offset)
        !          1341:                {
        !          1342:                  if (mb_cur_max > 1 && rl_byte_oriented == 0)
        !          1343:                    nleft = _rl_screenwidth - _rl_last_c_pos;
        !          1344:                  else
        !          1345:                    nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos;
        !          1346:                  if (nleft)
        !          1347:                    _rl_clear_to_eol (nleft);
        !          1348:                }
1.1       misho    1349: #endif
                   1350: 
                   1351:              /* Since the new first line is now visible, save its length. */
                   1352:              if (linenum == 0)
                   1353:                visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset;
                   1354:            }
                   1355: 
                   1356:          /* We may have deleted some lines.  If so, clear the left over
                   1357:             blank ones at the bottom out. */
                   1358:          if (_rl_vis_botlin > inv_botlin)
                   1359:            {
                   1360:              char *tt;
                   1361:              for (; linenum <= _rl_vis_botlin; linenum++)
                   1362:                {
                   1363:                  tt = VIS_CHARS (linenum);
                   1364:                  _rl_move_vert (linenum);
1.1.1.3 ! misho    1365:                  _rl_move_cursor_relative (0, tt, VIS_FACE(linenum));
1.1       misho    1366:                  _rl_clear_to_eol
                   1367:                    ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth);
                   1368:                }
                   1369:            }
                   1370:          _rl_vis_botlin = inv_botlin;
                   1371: 
                   1372:          /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
                   1373:             different screen line during this redisplay. */
                   1374:          changed_screen_line = _rl_last_v_pos != cursor_linenum;
                   1375:          if (changed_screen_line)
                   1376:            {
                   1377:              _rl_move_vert (cursor_linenum);
                   1378:              /* If we moved up to the line with the prompt using _rl_term_up,
                   1379:                 the physical cursor position on the screen stays the same,
                   1380:                 but the buffer position needs to be adjusted to account
                   1381:                 for invisible characters. */
1.1.1.3 ! misho    1382:              if ((mb_cur_max == 1 || rl_byte_oriented) && cursor_linenum == 0 && wrap_offset)
1.1       misho    1383:                _rl_last_c_pos += wrap_offset;
                   1384:            }
                   1385: 
1.1.1.3 ! misho    1386:          /* Now we move the cursor to where it needs to be.  First, make
        !          1387:             sure we are on the correct line (cursor_linenum). */
        !          1388: 
1.1       misho    1389:          /* We have to reprint the prompt if it contains invisible
                   1390:             characters, since it's not generally OK to just reprint
                   1391:             the characters from the current cursor position.  But we
                   1392:             only need to reprint it if the cursor is before the last
                   1393:             invisible character in the prompt string. */
1.1.1.3 ! misho    1394:          /* XXX - why not use local_prompt_len? */
1.1       misho    1395:          nleft = prompt_visible_length + wrap_offset;
                   1396:          if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
                   1397:              _rl_last_c_pos < PROMPT_ENDING_INDEX && local_prompt)
                   1398:            {
1.1.1.3 ! misho    1399:              _rl_cr ();
1.1       misho    1400:              if (modmark)
                   1401:                _rl_output_some_chars ("*", 1);
                   1402: 
                   1403:              _rl_output_some_chars (local_prompt, nleft);
1.1.1.3 ! misho    1404:              if (mb_cur_max > 1 && rl_byte_oriented == 0)
1.1       misho    1405:                _rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft, 1) - wrap_offset + modmark;
                   1406:              else
                   1407:                _rl_last_c_pos = nleft + modmark;
                   1408:            }
                   1409: 
                   1410:          /* Where on that line?  And where does that line start
                   1411:             in the buffer? */
                   1412:          pos = inv_lbreaks[cursor_linenum];
1.1.1.3 ! misho    1413:          /* nleft == number of characters (bytes) in the line buffer between
        !          1414:             the start of the line and the desired cursor position. */
1.1       misho    1415:          nleft = cpos_buffer_position - pos;
                   1416: 
                   1417:          /* NLEFT is now a number of characters in a buffer.  When in a
                   1418:             multibyte locale, however, _rl_last_c_pos is an absolute cursor
                   1419:             position that doesn't take invisible characters in the prompt
                   1420:             into account.  We use a fudge factor to compensate. */
                   1421: 
1.1.1.3 ! misho    1422:          /* Since _rl_backspace() doesn't know about invisible characters in
        !          1423:             the prompt, and there's no good way to tell it, we compensate for
        !          1424:             those characters here and call _rl_backspace() directly if
        !          1425:             necessary */
1.1       misho    1426:          if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
                   1427:            {
                   1428:              /* TX == new physical cursor position in multibyte locale. */
1.1.1.3 ! misho    1429:              if (mb_cur_max > 1 && rl_byte_oriented == 0)
1.1       misho    1430:                tx = _rl_col_width (&visible_line[pos], 0, nleft, 1) - visible_wrap_offset;
                   1431:              else
                   1432:                tx = nleft;
                   1433:              if (tx >= 0 && _rl_last_c_pos > tx)
                   1434:                {
                   1435:                  _rl_backspace (_rl_last_c_pos - tx);  /* XXX */
                   1436:                  _rl_last_c_pos = tx;
                   1437:                }
                   1438:            }
                   1439: 
                   1440:          /* We need to note that in a multibyte locale we are dealing with
                   1441:             _rl_last_c_pos as an absolute cursor position, but moving to a
                   1442:             point specified by a buffer position (NLEFT) that doesn't take
                   1443:             invisible characters into account. */
1.1.1.3 ! misho    1444:          if (mb_cur_max > 1 && rl_byte_oriented == 0)
        !          1445:            _rl_move_cursor_relative (nleft, &invisible_line[pos], &inv_face[pos]);
1.1       misho    1446:          else if (nleft != _rl_last_c_pos)
1.1.1.3 ! misho    1447:            _rl_move_cursor_relative (nleft, &invisible_line[pos], &inv_face[pos]);
1.1       misho    1448:        }
                   1449:     }
1.1.1.3 ! misho    1450:   else                         /* Do horizontal scrolling. Much simpler */
1.1       misho    1451:     {
                   1452: #define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
                   1453:       int lmargin, ndisp, nleft, phys_c_pos, t;
                   1454: 
                   1455:       /* Always at top line. */
                   1456:       _rl_last_v_pos = 0;
                   1457: 
                   1458:       /* Compute where in the buffer the displayed line should start.  This
                   1459:         will be LMARGIN. */
                   1460: 
                   1461:       /* The number of characters that will be displayed before the cursor. */
                   1462:       ndisp = cpos_buffer_position - wrap_offset;
                   1463:       nleft  = prompt_visible_length + wrap_offset;
                   1464:       /* Where the new cursor position will be on the screen.  This can be
                   1465:         longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
                   1466:       phys_c_pos = cpos_buffer_position - (last_lmargin ? last_lmargin : wrap_offset);
                   1467:       t = _rl_screenwidth / 3;
                   1468: 
                   1469:       /* If the number of characters had already exceeded the screenwidth,
                   1470:         last_lmargin will be > 0. */
                   1471: 
                   1472:       /* If the number of characters to be displayed is more than the screen
                   1473:         width, compute the starting offset so that the cursor is about
                   1474:         two-thirds of the way across the screen. */
                   1475:       if (phys_c_pos > _rl_screenwidth - 2)
                   1476:        {
                   1477:          lmargin = cpos_buffer_position - (2 * t);
                   1478:          if (lmargin < 0)
                   1479:            lmargin = 0;
                   1480:          /* If the left margin would be in the middle of a prompt with
                   1481:             invisible characters, don't display the prompt at all. */
                   1482:          if (wrap_offset && lmargin > 0 && lmargin < nleft)
                   1483:            lmargin = nleft;
                   1484:        }
                   1485:       else if (ndisp < _rl_screenwidth - 2)            /* XXX - was -1 */
                   1486:        lmargin = 0;
                   1487:       else if (phys_c_pos < 1)
                   1488:        {
                   1489:          /* If we are moving back towards the beginning of the line and
                   1490:             the last margin is no longer correct, compute a new one. */
                   1491:          lmargin = ((cpos_buffer_position - 1) / t) * t;       /* XXX */
                   1492:          if (wrap_offset && lmargin > 0 && lmargin < nleft)
                   1493:            lmargin = nleft;
                   1494:        }
                   1495:       else
                   1496:        lmargin = last_lmargin;
                   1497: 
                   1498:       displaying_prompt_first_line = lmargin < nleft;
                   1499: 
                   1500:       /* If the first character on the screen isn't the first character
                   1501:         in the display line, indicate this with a special character. */
                   1502:       if (lmargin > 0)
1.1.1.3 ! misho    1503:        invisible_line[lmargin] = '<';
1.1       misho    1504: 
                   1505:       /* If SCREENWIDTH characters starting at LMARGIN do not encompass
                   1506:         the whole line, indicate that with a special character at the
                   1507:         right edge of the screen.  If LMARGIN is 0, we need to take the
                   1508:         wrap offset into account. */
                   1509:       t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth;
1.1.1.3 ! misho    1510:       if (t > 0 && t < out)
        !          1511:        invisible_line[t - 1] = '>';
1.1       misho    1512: 
                   1513:       if (rl_display_fixed == 0 || forced_display || lmargin != last_lmargin)
                   1514:        {
                   1515:          forced_display = 0;
                   1516:          o_cpos = _rl_last_c_pos;
                   1517:          cpos_adjusted = 0;
1.1.1.3 ! misho    1518:          update_line (&visible_line[last_lmargin], &vis_face[last_lmargin],
        !          1519:                       &invisible_line[lmargin], &inv_face[lmargin],
1.1       misho    1520:                       0,
                   1521:                       _rl_screenwidth + visible_wrap_offset,
                   1522:                       _rl_screenwidth + (lmargin ? 0 : wrap_offset),
                   1523:                       0);
                   1524: 
1.1.1.3 ! misho    1525:          if ((mb_cur_max > 1 && rl_byte_oriented == 0) &&
1.1       misho    1526:                displaying_prompt_first_line && OLD_CPOS_IN_PROMPT())
                   1527:            _rl_last_c_pos -= prompt_invis_chars_first_line;    /* XXX - was wrap_offset */
                   1528: 
                   1529:          /* If the visible new line is shorter than the old, but the number
                   1530:             of invisible characters is greater, and we are at the end of
                   1531:             the new line, we need to clear to eol. */
                   1532:          t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
                   1533:          if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
                   1534:              (_rl_last_c_pos == out) && displaying_prompt_first_line &&
                   1535:              t < visible_first_line_len)
                   1536:            {
                   1537:              nleft = _rl_screenwidth - t;
                   1538:              _rl_clear_to_eol (nleft);
                   1539:            }
                   1540:          visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
                   1541:          if (visible_first_line_len > _rl_screenwidth)
                   1542:            visible_first_line_len = _rl_screenwidth;
                   1543: 
1.1.1.3 ! misho    1544:          _rl_move_cursor_relative (cpos_buffer_position - lmargin, &invisible_line[lmargin], &inv_face[lmargin]);
1.1       misho    1545:          last_lmargin = lmargin;
                   1546:        }
                   1547:     }
                   1548:   fflush (rl_outstream);
                   1549: 
                   1550:   /* Swap visible and non-visible lines. */
                   1551:   {
                   1552:     struct line_state *vtemp = line_state_visible;
                   1553: 
                   1554:     line_state_visible = line_state_invisible;
                   1555:     line_state_invisible = vtemp;
                   1556: 
                   1557:     rl_display_fixed = 0;
                   1558:     /* If we are displaying on a single line, and last_lmargin is > 0, we
                   1559:        are not displaying any invisible characters, so set visible_wrap_offset
                   1560:        to 0. */
                   1561:     if (_rl_horizontal_scroll_mode && last_lmargin)
                   1562:       visible_wrap_offset = 0;
                   1563:     else
                   1564:       visible_wrap_offset = wrap_offset;
1.1.1.3 ! misho    1565: 
        !          1566:     _rl_quick_redisplay = 0;
1.1       misho    1567:   }
                   1568: 
                   1569:   RL_UNSETSTATE (RL_STATE_REDISPLAYING);
                   1570:   _rl_release_sigint ();
                   1571: }
                   1572: 
1.1.1.3 ! misho    1573: static void
        !          1574: putc_face (int c, int face, char *cur_face)
        !          1575: {
        !          1576:   char cf;
        !          1577:   cf = *cur_face;
        !          1578:   if (cf != face)
        !          1579:     {
        !          1580:       if (cf != FACE_NORMAL && cf != FACE_STANDOUT)
        !          1581:        return;
        !          1582:       if (face != FACE_NORMAL && face != FACE_STANDOUT)
        !          1583:        return;
        !          1584:       if (face == FACE_STANDOUT && cf == FACE_NORMAL)
        !          1585:         _rl_standout_on ();
        !          1586:       if (face == FACE_NORMAL && cf == FACE_STANDOUT)
        !          1587:         _rl_standout_off ();
        !          1588:       *cur_face = face;
        !          1589:     }
        !          1590:   if (c != EOF)
        !          1591:     putc (c, rl_outstream);
        !          1592: }
        !          1593: 
        !          1594: static void
        !          1595: puts_face (const char *str, const char *face, int n)
        !          1596: {
        !          1597:   int i;
        !          1598:   char cur_face;
        !          1599: 
        !          1600:   for (cur_face = FACE_NORMAL, i = 0; i < n; i++)
        !          1601:     putc_face (str[i], face[i], &cur_face);
        !          1602:   putc_face (EOF, FACE_NORMAL, &cur_face);
        !          1603: }
        !          1604: 
        !          1605: static void
        !          1606: norm_face (char *face, int n)
        !          1607: {
        !          1608:   memset (face, FACE_NORMAL, n);
        !          1609: }
        !          1610: 
        !          1611: #define ADJUST_CPOS(x) do { _rl_last_c_pos -= (x) ; cpos_adjusted = 1; } while (0)
        !          1612: 
1.1       misho    1613: /* PWP: update_line() is based on finding the middle difference of each
                   1614:    line on the screen; vis:
                   1615: 
                   1616:                             /old first difference
1.1.1.3 ! misho    1617:        /beginning of line   |              /old last same       /old EOL
        !          1618:        v                    v              v                    v
1.1       misho    1619: old:   eddie> Oh, my little gruntle-buggy is to me, as lurgid as
                   1620: new:   eddie> Oh, my little buggy says to me, as lurgid as
1.1.1.3 ! misho    1621:        ^                    ^        ^                    ^
        !          1622:        \beginning of line   |        \new last same       \new end of line
1.1       misho    1623:                             \new first difference
                   1624: 
                   1625:    All are character pointers for the sake of speed.  Special cases for
                   1626:    no differences, as well as for end of line additions must be handled.
                   1627: 
                   1628:    Could be made even smarter, but this works well enough */
                   1629: static void
1.1.1.3 ! misho    1630: update_line (char *old, char *old_face, char *new, char *new_face, int current_line, int omax, int nmax, int inv_botlin)
1.1       misho    1631: {
1.1.1.3 ! misho    1632:   char *ofd, *ols, *oe, *nfd, *nls, *ne;
        !          1633:   char *ofdf, *nfdf, *olsf, *nlsf;
1.1       misho    1634:   int temp, lendiff, wsatend, od, nd, twidth, o_cpos;
                   1635:   int current_invis_chars;
                   1636:   int col_lendiff, col_temp;
                   1637:   int bytes_to_insert;
1.1.1.3 ! misho    1638:   int mb_cur_max = MB_CUR_MAX;
1.1       misho    1639: #if defined (HANDLE_MULTIBYTE)
                   1640:   mbstate_t ps_new, ps_old;
                   1641:   int new_offset, old_offset;
                   1642: #endif
                   1643: 
                   1644:   /* If we're at the right edge of a terminal that supports xn, we're
                   1645:      ready to wrap around, so do so.  This fixes problems with knowing
                   1646:      the exact cursor position and cut-and-paste with certain terminal
                   1647:      emulators.  In this calculation, TEMP is the physical screen
                   1648:      position of the cursor. */
1.1.1.3 ! misho    1649:   if (mb_cur_max > 1 && rl_byte_oriented == 0)
1.1       misho    1650:     temp = _rl_last_c_pos;
                   1651:   else
                   1652:     temp = _rl_last_c_pos - WRAP_OFFSET (_rl_last_v_pos, visible_wrap_offset);
                   1653:   if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
                   1654:        && _rl_last_v_pos == current_line - 1)
                   1655:     {
1.1.1.3 ! misho    1656:       /* We're going to wrap around by writing the first character of NEW to
        !          1657:         the screen and dealing with changes to what's visible by modifying
        !          1658:         OLD to match it.  Complicated by the presence of multi-width
        !          1659:         characters at the end of the line or beginning of the new one. */
        !          1660:       /* old is always somewhere in visible_line; new is always somewhere in
        !          1661:          invisible_line.  These should always be null-terminated. */
1.1       misho    1662: #if defined (HANDLE_MULTIBYTE)
1.1.1.3 ! misho    1663:       if (mb_cur_max > 1 && rl_byte_oriented == 0)
1.1       misho    1664:        {
                   1665:          wchar_t wc;
                   1666:          mbstate_t ps;
1.1.1.3 ! misho    1667:          int oldwidth, newwidth;
        !          1668:          int oldbytes, newbytes;
1.1       misho    1669:          size_t ret;
                   1670: 
                   1671:          /* This fixes only double-column characters, but if the wrapped
                   1672:             character consumes more than three columns, spaces will be
                   1673:             inserted in the string buffer. */
1.1.1.3 ! misho    1674:          /* XXX remember that we are working on the invisible line right now;
        !          1675:             we don't swap visible and invisible until just before rl_redisplay
        !          1676:             returns */
        !          1677:          /* This will remove the extra placeholder space we added with
        !          1678:             _rl_wrapped_multicolumn */
        !          1679:          if (current_line < line_state_invisible->wbsize && line_state_invisible->wrapped_line[current_line] > 0)
        !          1680:            _rl_clear_to_eol (line_state_invisible->wrapped_line[current_line]);
1.1       misho    1681: 
1.1.1.3 ! misho    1682:          /* 1. how many screen positions does first char in old consume? */
1.1       misho    1683:          memset (&ps, 0, sizeof (mbstate_t));
1.1.1.3 ! misho    1684:          ret = mbrtowc (&wc, old, mb_cur_max, &ps);
        !          1685:          oldbytes = ret;
1.1       misho    1686:          if (MB_INVALIDCH (ret))
                   1687:            {
1.1.1.3 ! misho    1688:              oldwidth = 1;
        !          1689:              oldbytes = 1;
1.1       misho    1690:            }
                   1691:          else if (MB_NULLWCH (ret))
1.1.1.3 ! misho    1692:            oldwidth = 0;
1.1       misho    1693:          else
1.1.1.3 ! misho    1694:            oldwidth = WCWIDTH (wc);
        !          1695:          if (oldwidth < 0)
        !          1696:            oldwidth = 1;
1.1       misho    1697: 
1.1.1.3 ! misho    1698:          /* 2. how many screen positions does the first char in new consume? */
        !          1699:          memset (&ps, 0, sizeof (mbstate_t));
        !          1700:          ret = mbrtowc (&wc, new, mb_cur_max, &ps);
        !          1701:          newbytes = ret;
        !          1702:          if (MB_INVALIDCH (ret))
        !          1703:            {
        !          1704:              newwidth = 1;
        !          1705:              newbytes = 1;
        !          1706:            }
        !          1707:          else if (MB_NULLWCH (ret))
        !          1708:            newwidth = 0;
        !          1709:          else
        !          1710:            newwidth = WCWIDTH (wc);
        !          1711:          if (newwidth < 0)
        !          1712:            newwidth = 1;
        !          1713: 
        !          1714:          /* 3. if the new width is less than the old width, we need to keep
        !          1715:             going in new until we have consumed at least that many screen
        !          1716:             positions, and figure out how many bytes that will take */
        !          1717:          while (newbytes < nmax && newwidth < oldwidth)
1.1       misho    1718:            {
1.1.1.3 ! misho    1719:              int t;
        !          1720: 
        !          1721:              ret = mbrtowc (&wc, new+newbytes, mb_cur_max, &ps);
        !          1722:              if (MB_INVALIDCH (ret))
        !          1723:                {
        !          1724:                  newwidth += 1;
        !          1725:                  newbytes += 1;
        !          1726:                }
        !          1727:              else if (MB_NULLWCH (ret))
        !          1728:                break;
        !          1729:              else
        !          1730:                {
        !          1731:                  t = WCWIDTH (wc);
        !          1732:                  newwidth += (t >= 0) ? t : 1;
        !          1733:                  newbytes += ret;
        !          1734:                }
        !          1735:            }
        !          1736:          /* 4. If the new width is more than the old width, keep going in old
        !          1737:             until we have consumed exactly that many screen positions, and
        !          1738:             figure out how many bytes that will take.  This is an optimization */
        !          1739:          while (oldbytes < omax && oldwidth < newwidth)
        !          1740:            {
        !          1741:              int t;
        !          1742: 
        !          1743:              ret = mbrtowc (&wc, old+oldbytes, mb_cur_max, &ps);
        !          1744:              if (MB_INVALIDCH (ret))
        !          1745:                {
        !          1746:                  oldwidth += 1;
        !          1747:                  oldbytes += 1;
        !          1748:                }
        !          1749:              else if (MB_NULLWCH (ret))
        !          1750:                break;
        !          1751:              else
        !          1752:                {
        !          1753:                  t = WCWIDTH (wc);
        !          1754:                  oldwidth += (t >= 0) ? t : 1;
        !          1755:                  oldbytes += ret;
        !          1756:                }
        !          1757:            }
        !          1758:          /* 5. write the first newbytes of new, which takes newwidth.  This is
        !          1759:             where the screen wrapping takes place, and we are now writing
        !          1760:             characters onto the new line. We need to fix up old so it
        !          1761:             accurately reflects what is on the screen after the
        !          1762:             _rl_output_some_chars below. */
        !          1763:          if (newwidth > 0)
        !          1764:            {
        !          1765:              int count, i, j;
        !          1766:              char *optr;
        !          1767: 
        !          1768:              puts_face (new, new_face, newbytes);
        !          1769:              _rl_last_c_pos = newwidth;
1.1       misho    1770:              _rl_last_v_pos++;
1.1.1.3 ! misho    1771: 
        !          1772:              /* 5a. If the number of screen positions doesn't match, punt
        !          1773:                 and do a dumb update.
        !          1774:                 5b. If the number of bytes is greater in the new line than
        !          1775:                 the old, do a dumb update, because there is no guarantee we
        !          1776:                 can extend the old line enough to fit the new bytes. */
        !          1777:              if (newwidth != oldwidth || newbytes > oldbytes)
        !          1778:                {
        !          1779:                  oe = old + omax;
        !          1780:                  ne = new + nmax;
        !          1781:                  nd = newbytes;
        !          1782:                  nfd = new + nd;
        !          1783:                  ofdf = old_face + oldbytes;
        !          1784:                  nfdf = new_face + newbytes;
        !          1785: 
        !          1786:                  goto dumb_update;
        !          1787:                }
        !          1788:              if (oldbytes != 0 && newbytes != 0)
1.1       misho    1789:                {
1.1.1.3 ! misho    1790:                  /* We have written as many bytes from new as we need to
        !          1791:                     consume the first character of old. Fix up `old' so it
        !          1792:                     reflects the new screen contents.  We use +1 in the
        !          1793:                     memmove call to copy the trailing NUL. */
        !          1794:                  /* (strlen(old+oldbytes) == (omax - oldbytes - 1)) */
        !          1795: 
        !          1796:                  /* Don't bother trying to fit the bytes if the number of bytes
        !          1797:                     doesn't change. */
        !          1798:                  if (oldbytes != newbytes)
        !          1799:                    {
        !          1800:                      memmove (old+newbytes, old+oldbytes, strlen (old+oldbytes) + 1);
        !          1801:                      memmove (old_face+newbytes, old_face+oldbytes, strlen (old+oldbytes) + 1);
        !          1802:                    }
        !          1803:                  memcpy (old, new, newbytes);
        !          1804:                  memcpy (old_face, new_face, newbytes);
        !          1805:                  j = newbytes - oldbytes;
        !          1806:                  omax += j;
1.1       misho    1807:                  /* Fix up indices if we copy data from one line to another */
1.1.1.3 ! misho    1808:                  for (i = current_line+1; j != 0 && i <= inv_botlin+1 && i <=_rl_vis_botlin+1; i++)
        !          1809:                    vis_lbreaks[i] += j;
1.1       misho    1810:                }
                   1811:            }
                   1812:          else
                   1813:            {
                   1814:              putc (' ', rl_outstream);
                   1815:              _rl_last_c_pos = 1;
                   1816:              _rl_last_v_pos++;
                   1817:              if (old[0] && new[0])
1.1.1.3 ! misho    1818:                {
        !          1819:                  old[0] = new[0];
        !          1820:                  old_face[0] = new_face[0];
        !          1821:                }
1.1       misho    1822:            }
                   1823:        }
                   1824:       else
                   1825: #endif
                   1826:        {
                   1827:          if (new[0])
1.1.1.3 ! misho    1828:            puts_face (new, new_face, 1);
1.1       misho    1829:          else
                   1830:            putc (' ', rl_outstream);
                   1831:          _rl_last_c_pos = 1;
                   1832:          _rl_last_v_pos++;
                   1833:          if (old[0] && new[0])
1.1.1.3 ! misho    1834:            {
        !          1835:              old[0] = new[0];
        !          1836:              old_face[0] = new_face[0];
        !          1837:            }
1.1       misho    1838:        }
                   1839:     }
                   1840: 
1.1.1.3 ! misho    1841:   /* We know that we are dealing with a single screen line here */
        !          1842:   if (_rl_quick_redisplay)
        !          1843:     {
        !          1844:       nfd = new;
        !          1845:       nfdf = new_face;
        !          1846:       ofd = old;
        !          1847:       ofdf = old_face;
        !          1848:       for (od = 0, oe = ofd; od < omax && *oe; oe++, od++);
        !          1849:       for (nd = 0, ne = nfd; nd < nmax && *ne; ne++, nd++);
        !          1850:       od = nd = 0;
        !          1851:       _rl_move_cursor_relative (0, old, old_face);
        !          1852: 
        !          1853:       bytes_to_insert = ne - nfd;
        !          1854:       if (bytes_to_insert < local_prompt_len)  /* ??? */
        !          1855:        goto dumb_update;
        !          1856: 
        !          1857:       /* output the prompt, output the line contents, clear the rest */
        !          1858:       _rl_output_some_chars (nfd, local_prompt_len);
        !          1859:       if (mb_cur_max > 1 && rl_byte_oriented == 0)
        !          1860:        _rl_last_c_pos = prompt_physical_chars;
        !          1861:       else
        !          1862:        _rl_last_c_pos = local_prompt_len;
        !          1863: 
        !          1864:       bytes_to_insert -= local_prompt_len;
        !          1865:       if (bytes_to_insert > 0)
        !          1866:        {
        !          1867:          puts_face (new+local_prompt_len, nfdf+local_prompt_len, bytes_to_insert);
        !          1868:          if (mb_cur_max > 1 && rl_byte_oriented)
        !          1869:            _rl_last_c_pos += _rl_col_width (new, local_prompt_len, ne-new, 1);
        !          1870:          else
        !          1871:            _rl_last_c_pos += bytes_to_insert;
        !          1872:        }
        !          1873: 
        !          1874:       /* See comments at dumb_update: for an explanation of this heuristic */
        !          1875:       if (nmax < omax)
        !          1876:        goto clear_rest_of_line;
        !          1877:       else if ((nmax - W_OFFSET(current_line, wrap_offset)) < (omax - W_OFFSET (current_line, visible_wrap_offset)))
        !          1878:        goto clear_rest_of_line;
        !          1879:       else
        !          1880:        return;
        !          1881:     }
        !          1882: 
1.1       misho    1883:   /* Find first difference. */
                   1884: #if defined (HANDLE_MULTIBYTE)
1.1.1.3 ! misho    1885:   if (mb_cur_max > 1 && rl_byte_oriented == 0)
1.1       misho    1886:     {
                   1887:       /* See if the old line is a subset of the new line, so that the
                   1888:         only change is adding characters. */
                   1889:       temp = (omax < nmax) ? omax : nmax;
1.1.1.3 ! misho    1890:       if (memcmp (old, new, temp) == 0 && memcmp (old_face, new_face, temp) == 0)
1.1       misho    1891:        {
1.1.1.3 ! misho    1892:          new_offset = old_offset = temp;       /* adding at the end */
1.1       misho    1893:          ofd = old + temp;
1.1.1.3 ! misho    1894:          ofdf = old_face + temp;
1.1       misho    1895:          nfd = new + temp;
1.1.1.3 ! misho    1896:          nfdf = new_face + temp;
1.1       misho    1897:        }
                   1898:       else
                   1899:        {      
                   1900:          memset (&ps_new, 0, sizeof(mbstate_t));
                   1901:          memset (&ps_old, 0, sizeof(mbstate_t));
                   1902: 
1.1.1.3 ! misho    1903:          /* Are the old and new lines the same? */
        !          1904:          if (omax == nmax && memcmp (new, old, omax) == 0 && memcmp (new_face, old_face, omax) == 0)
1.1       misho    1905:            {
                   1906:              old_offset = omax;
                   1907:              new_offset = nmax;
                   1908:              ofd = old + omax;
1.1.1.3 ! misho    1909:              ofdf = old_face + omax;
1.1       misho    1910:              nfd = new + nmax;
1.1.1.3 ! misho    1911:              nfdf = new_face + nmax;
1.1       misho    1912:            }
                   1913:          else
                   1914:            {
1.1.1.3 ! misho    1915:              /* Go through the line from the beginning and find the first
        !          1916:                 difference. We assume that faces change at (possibly multi-
        !          1917:                 byte) character boundaries. */
1.1       misho    1918:              new_offset = old_offset = 0;
1.1.1.3 ! misho    1919:              for (ofd = old, ofdf = old_face, nfd = new, nfdf = new_face;
1.1       misho    1920:                    (ofd - old < omax) && *ofd &&
1.1.1.3 ! misho    1921:                    _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new) &&
        !          1922:                    *ofdf == *nfdf; )
1.1       misho    1923:                {
                   1924:                  old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY);
                   1925:                  new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY);
                   1926: 
                   1927:                  ofd = old + old_offset;
1.1.1.3 ! misho    1928:                  ofdf = old_face + old_offset;
1.1       misho    1929:                  nfd = new + new_offset;
1.1.1.3 ! misho    1930:                  nfdf = new_face + new_offset;
1.1       misho    1931:                }
                   1932:            }
                   1933:        }
                   1934:     }
                   1935:   else
                   1936: #endif
1.1.1.3 ! misho    1937:   for (ofd = old, ofdf = old_face, nfd = new, nfdf = new_face;
        !          1938:        (ofd - old < omax) && *ofd && (*ofd == *nfd) && (*ofdf == *nfdf);
        !          1939:        ofd++, nfd++, ofdf++, nfdf++)
1.1       misho    1940:     ;
                   1941: 
                   1942:   /* Move to the end of the screen line.  ND and OD are used to keep track
                   1943:      of the distance between ne and new and oe and old, respectively, to
                   1944:      move a subtraction out of each loop. */
                   1945:   for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
                   1946:   for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
                   1947: 
                   1948:   /* If no difference, continue to next line. */
                   1949:   if (ofd == oe && nfd == ne)
                   1950:     return;
                   1951: 
                   1952: #if defined (HANDLE_MULTIBYTE)
1.1.1.3 ! misho    1953:   if (mb_cur_max > 1 && rl_byte_oriented == 0 && _rl_utf8locale)
1.1       misho    1954:     {
                   1955:       wchar_t wc;
                   1956:       mbstate_t ps = { 0 };
                   1957:       int t;
                   1958: 
                   1959:       /* If the first character in the difference is a zero-width character,
                   1960:         assume it's a combining character and back one up so the two base
                   1961:         characters no longer compare equivalently. */
1.1.1.3 ! misho    1962:       t = mbrtowc (&wc, ofd, mb_cur_max, &ps);
1.1       misho    1963:       if (t > 0 && UNICODE_COMBINING_CHAR (wc) && WCWIDTH (wc) == 0)
                   1964:        {
                   1965:          old_offset = _rl_find_prev_mbchar (old, ofd - old, MB_FIND_ANY);
                   1966:          new_offset = _rl_find_prev_mbchar (new, nfd - new, MB_FIND_ANY);
                   1967:          ofd = old + old_offset;       /* equal by definition */
1.1.1.3 ! misho    1968:          ofdf = old_face + old_offset;
1.1       misho    1969:          nfd = new + new_offset;
1.1.1.3 ! misho    1970:          nfdf = new_face + new_offset;
1.1       misho    1971:        }
                   1972:     }
                   1973: #endif
                   1974: 
                   1975:   wsatend = 1;                 /* flag for trailing whitespace */
                   1976: 
                   1977: #if defined (HANDLE_MULTIBYTE)
1.1.1.3 ! misho    1978:   /* Find the last character that is the same between the two lines.  This
        !          1979:      bounds the region that needs to change. */
        !          1980:   if (mb_cur_max > 1 && rl_byte_oriented == 0)
1.1       misho    1981:     {
                   1982:       ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY);
1.1.1.3 ! misho    1983:       olsf = old_face + (ols - old);
1.1       misho    1984:       nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY);
1.1.1.3 ! misho    1985:       nlsf = new_face + (nls - new);
1.1       misho    1986: 
                   1987:       while ((ols > ofd) && (nls > nfd))
                   1988:        {
                   1989:          memset (&ps_old, 0, sizeof (mbstate_t));
                   1990:          memset (&ps_new, 0, sizeof (mbstate_t));
                   1991: 
1.1.1.3 ! misho    1992:          if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0 ||
        !          1993:                *olsf != *nlsf)
1.1       misho    1994:            break;
                   1995: 
                   1996:          if (*ols == ' ')
                   1997:            wsatend = 0;
                   1998: 
                   1999:          ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY);
1.1.1.3 ! misho    2000:          olsf = old_face + (ols - old);
1.1       misho    2001:          nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY);
1.1.1.3 ! misho    2002:          nlsf = new_face + (nls - new);
1.1       misho    2003:        }
                   2004:     }
                   2005:   else
                   2006:     {
                   2007: #endif /* HANDLE_MULTIBYTE */
                   2008:   ols = oe - 1;                        /* find last same */
1.1.1.3 ! misho    2009:   olsf = old_face + (ols - old);
1.1       misho    2010:   nls = ne - 1;
1.1.1.3 ! misho    2011:   nlsf = new_face + (nls - new);
        !          2012:   while ((ols > ofd) && (nls > nfd) && (*ols == *nls) && (*olsf == *nlsf))
1.1       misho    2013:     {
                   2014:       if (*ols != ' ')
                   2015:        wsatend = 0;
1.1.1.3 ! misho    2016:       ols--; olsf--;
        !          2017:       nls--; nlsf--;
1.1       misho    2018:     }
                   2019: #if defined (HANDLE_MULTIBYTE)
                   2020:     }
                   2021: #endif
                   2022: 
                   2023:   if (wsatend)
                   2024:     {
                   2025:       ols = oe;
1.1.1.3 ! misho    2026:       olsf = old_face + (ols - old);
1.1       misho    2027:       nls = ne;
1.1.1.3 ! misho    2028:       nlsf = new_face + (nls - new);
1.1       misho    2029:     }
                   2030: #if defined (HANDLE_MULTIBYTE)
                   2031:   /* This may not work for stateful encoding, but who cares?  To handle
                   2032:      stateful encoding properly, we have to scan each string from the
                   2033:      beginning and compare. */
1.1.1.3 ! misho    2034:   else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0 || *olsf != *nlsf)
1.1       misho    2035: #else
1.1.1.3 ! misho    2036:   else if (*ols != *nls || *olsf != *nlsf)
1.1       misho    2037: #endif
                   2038:     {
                   2039:       if (*ols)                        /* don't step past the NUL */
                   2040:        {
1.1.1.3 ! misho    2041:          if (mb_cur_max > 1 && rl_byte_oriented == 0)
1.1       misho    2042:            ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY);
                   2043:          else
                   2044:            ols++;
                   2045:        }
                   2046:       if (*nls)
                   2047:        {
1.1.1.3 ! misho    2048:          if (mb_cur_max > 1 && rl_byte_oriented == 0)
1.1       misho    2049:            nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY);
                   2050:          else
                   2051:            nls++;
                   2052:        }
1.1.1.3 ! misho    2053:       olsf = old_face + (ols - old);
        !          2054:       nlsf = new_face + (nls - new);
1.1       misho    2055:     }
                   2056: 
                   2057:   /* count of invisible characters in the current invisible line. */
                   2058:   current_invis_chars = W_OFFSET (current_line, wrap_offset);
                   2059:   if (_rl_last_v_pos != current_line)
                   2060:     {
                   2061:       _rl_move_vert (current_line);
1.1.1.3 ! misho    2062:       /* We have moved up to a new screen line.  This line may or may not have
        !          2063:          invisible characters on it, but we do our best to recalculate
        !          2064:          visible_wrap_offset based on what we know. */
        !          2065:       if (current_line == 0)
        !          2066:        visible_wrap_offset = prompt_invis_chars_first_line;    /* XXX */
        !          2067: #if 0          /* XXX - not yet */
        !          2068:       else if (current_line == prompt_last_screen_line && wrap_offset > prompt_invis_chars_first_line)
        !          2069:        visible_wrap_offset = wrap_offset - prompt_invis_chars_first_line
        !          2070: #endif
        !          2071:       if ((mb_cur_max == 1 || rl_byte_oriented) && current_line == 0 && visible_wrap_offset)
1.1       misho    2072:        _rl_last_c_pos += visible_wrap_offset;
                   2073:     }
                   2074: 
                   2075:   /* If this is the first line and there are invisible characters in the
                   2076:      prompt string, and the prompt string has not changed, and the current
                   2077:      cursor position is before the last invisible character in the prompt,
                   2078:      and the index of the character to move to is past the end of the prompt
                   2079:      string, then redraw the entire prompt string.  We can only do this
                   2080:      reliably if the terminal supports a `cr' capability.
                   2081: 
1.1.1.3 ! misho    2082:      This can also happen if the prompt string has changed, and the first
        !          2083:      difference in the line is in the middle of the prompt string, after a
        !          2084:      sequence of invisible characters (worst case) and before the end of
        !          2085:      the prompt.  In this case, we have to redraw the entire prompt string
        !          2086:      so that the entire sequence of invisible characters is drawn.  We need
        !          2087:      to handle the worst case, when the difference is after (or in the middle
        !          2088:      of) a sequence of invisible characters that changes the text color and
        !          2089:      before the sequence that restores the text color to normal.  Then we have
        !          2090:      to make sure that the lines still differ -- if they don't, we can
        !          2091:      return immediately.
        !          2092: 
1.1       misho    2093:      This is not an efficiency hack -- there is a problem with redrawing
                   2094:      portions of the prompt string if they contain terminal escape
                   2095:      sequences (like drawing the `unbold' sequence without a corresponding
                   2096:      `bold') that manifests itself on certain terminals. */
                   2097: 
                   2098:   lendiff = local_prompt_len;
1.1.1.3 ! misho    2099:   if (lendiff > nmax)
        !          2100:     lendiff = nmax;
1.1       misho    2101:   od = ofd - old;      /* index of first difference in visible line */
1.1.1.3 ! misho    2102:   nd = nfd - new;      /* nd, od are buffer indexes */
1.1       misho    2103:   if (current_line == 0 && !_rl_horizontal_scroll_mode &&
                   2104:       _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 &&
1.1.1.3 ! misho    2105:       (((od > 0 || nd > 0) && (od <= prompt_last_invisible || nd <= prompt_last_invisible)) ||
        !          2106:                ((od >= lendiff) && _rl_last_c_pos < PROMPT_ENDING_INDEX)))
1.1       misho    2107:     {
1.1.1.3 ! misho    2108:       _rl_cr ();
1.1       misho    2109:       if (modmark)
                   2110:        _rl_output_some_chars ("*", 1);
                   2111:       _rl_output_some_chars (local_prompt, lendiff);
1.1.1.3 ! misho    2112:       if (mb_cur_max > 1 && rl_byte_oriented == 0)
1.1       misho    2113:        {
1.1.1.3 ! misho    2114:          /* If we just output the entire prompt string we can take advantage
        !          2115:             of knowing the number of physical characters in the prompt. If
        !          2116:             the prompt wraps lines (lendiff clamped at nmax), we can't. */
        !          2117:          if (lendiff == local_prompt_len)
        !          2118:            _rl_last_c_pos = prompt_physical_chars + modmark;
        !          2119:          else
        !          2120:            /* We take wrap_offset into account here so we can pass correct
        !          2121:               information to _rl_move_cursor_relative. */
        !          2122:            _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff, 1) - wrap_offset + modmark;
1.1       misho    2123:          cpos_adjusted = 1;
                   2124:        }
                   2125:       else
                   2126:        _rl_last_c_pos = lendiff + modmark;
1.1.1.3 ! misho    2127: 
        !          2128:       /* Now if we have printed the prompt string because the first difference
        !          2129:         was within the prompt, see if we need to recompute where the lines
        !          2130:         differ.  Check whether where we are now is past the last place where
        !          2131:         the old and new lines are the same and short-circuit now if we are. */
        !          2132:       if ((od <= prompt_last_invisible || nd <= prompt_last_invisible) &&
        !          2133:           omax == nmax &&
        !          2134:          lendiff > (ols-old) && lendiff > (nls-new))
        !          2135:        return;
        !          2136: 
        !          2137:       /* XXX - we need to fix up our calculations if we are now past the
        !          2138:         old ofd/nfd and the prompt length (or line length) has changed.
        !          2139:         We punt on the problem and do a dumb update.  We'd like to be able
        !          2140:         to just output the prompt from the beginning of the line up to the
        !          2141:         first difference, but you don't know the number of invisible
        !          2142:         characters in that case.
        !          2143:         This needs a lot of work to be efficient, but it usually doesn't matter. */
        !          2144:       if ((od <= prompt_last_invisible || nd <= prompt_last_invisible))
        !          2145:        {
        !          2146:          nfd = new + lendiff;  /* number of characters we output above */
        !          2147:          nfdf = new_face + lendiff;
        !          2148:          nd = lendiff;
        !          2149: 
        !          2150:          /* Do a dumb update and return */
        !          2151: dumb_update:
        !          2152:          temp = ne - nfd;
        !          2153:          if (temp > 0)
        !          2154:            {
        !          2155:              puts_face (nfd, nfdf, temp);
        !          2156:              if (mb_cur_max > 1 && rl_byte_oriented == 0)
        !          2157:                {
        !          2158:                  _rl_last_c_pos += _rl_col_width (new, nd, ne - new, 1);
        !          2159:                  /* Need to adjust here based on wrap_offset. Guess that if
        !          2160:                     this is the line containing the last line of the prompt
        !          2161:                     we need to adjust by
        !          2162:                        wrap_offset-prompt_invis_chars_first_line
        !          2163:                     on the assumption that this is the number of invisible
        !          2164:                     characters in the last line of the prompt. */
        !          2165:                  if (wrap_offset > prompt_invis_chars_first_line &&
        !          2166:                      current_line == prompt_last_screen_line &&
        !          2167:                      prompt_physical_chars > _rl_screenwidth &&
        !          2168:                      _rl_horizontal_scroll_mode == 0)
        !          2169:                    ADJUST_CPOS (wrap_offset - prompt_invis_chars_first_line);
        !          2170: 
        !          2171:                  /* If we just output a new line including the prompt, and
        !          2172:                     the prompt includes invisible characters, we need to
        !          2173:                     account for them in the _rl_last_c_pos calculation, since
        !          2174:                     _rl_col_width does not. This happens when other code does
        !          2175:                     a goto dumb_update; */
        !          2176:                  else if (current_line == 0 &&
        !          2177:                           nfd == new &&
        !          2178:                           prompt_invis_chars_first_line &&
        !          2179:                           local_prompt_len <= temp &&
        !          2180:                           wrap_offset >= prompt_invis_chars_first_line &&
        !          2181:                           _rl_horizontal_scroll_mode == 0)
        !          2182:                    ADJUST_CPOS (prompt_invis_chars_first_line);
        !          2183:                }
        !          2184:              else
        !          2185:                _rl_last_c_pos += temp;
        !          2186:            }
        !          2187:          /* This is a useful heuristic, but what we really want is to clear
        !          2188:             if the new number of visible screen characters is less than the
        !          2189:             old number of visible screen characters. If the prompt has changed,
        !          2190:             we don't really have enough information about the visible line to
        !          2191:             know for sure, so we use another heuristic calclulation below. */
        !          2192:          if (nmax < omax)
        !          2193:            goto clear_rest_of_line;    /* XXX */
        !          2194:          else if ((nmax - W_OFFSET(current_line, wrap_offset)) < (omax - W_OFFSET (current_line, visible_wrap_offset)))
        !          2195:            goto clear_rest_of_line;
        !          2196:          else
        !          2197:            return;
        !          2198:        }
1.1       misho    2199:     }
                   2200: 
                   2201:   o_cpos = _rl_last_c_pos;
                   2202: 
                   2203:   /* When this function returns, _rl_last_c_pos is correct, and an absolute
                   2204:      cursor position in multibyte mode, but a buffer index when not in a
                   2205:      multibyte locale. */
1.1.1.3 ! misho    2206:   _rl_move_cursor_relative (od, old, old_face);
1.1       misho    2207: 
                   2208: #if defined (HANDLE_MULTIBYTE)
                   2209:   /* We need to indicate that the cursor position is correct in the presence of
                   2210:      invisible characters in the prompt string.  Let's see if setting this when
                   2211:      we make sure we're at the end of the drawn prompt string works. */
1.1.1.3 ! misho    2212:   if (current_line == 0 && mb_cur_max > 1 && rl_byte_oriented == 0 &&
1.1       misho    2213:       (_rl_last_c_pos > 0 || o_cpos > 0) &&
                   2214:       _rl_last_c_pos == prompt_physical_chars)
                   2215:     cpos_adjusted = 1;
                   2216: #endif
                   2217: 
                   2218:   /* if (len (new) > len (old))
                   2219:      lendiff == difference in buffer (bytes)
                   2220:      col_lendiff == difference on screen (columns)
                   2221:      When not using multibyte characters, these are equal */
                   2222:   lendiff = (nls - nfd) - (ols - ofd);
1.1.1.3 ! misho    2223:   if (mb_cur_max > 1 && rl_byte_oriented == 0)
        !          2224:     {
        !          2225:       int newchars, newwidth, newind;
        !          2226:       int oldchars, oldwidth, oldind;
        !          2227: 
        !          2228:       newchars = nls - new;
        !          2229:       oldchars = ols - old;
        !          2230: 
        !          2231:       /* If we can do it, try to adjust nls and ols so that nls-new will
        !          2232:         contain the entire new prompt string. That way we can use
        !          2233:         prompt_physical_chars and not have to recompute column widths.
        !          2234:         _rl_col_width adds wrap_offset and expects the caller to compensate,
        !          2235:         which we do below, so we do the same thing if we don't call
        !          2236:         _rl_col_width.
        !          2237:         We don't have to compare, since we know the characters are the same.
        !          2238:         The check of differing numbers of invisible chars may be extraneous.
        !          2239:         XXX - experimental */
        !          2240:       if (current_line == 0 && nfd == new && newchars > prompt_last_invisible &&
        !          2241:          newchars <= local_prompt_len &&
        !          2242:          local_prompt_len <= nmax &&
        !          2243:          current_invis_chars != visible_wrap_offset)
        !          2244:        {
        !          2245:          while (newchars < nmax && oldchars < omax &&  newchars < local_prompt_len)
        !          2246:            {
        !          2247: #if defined (HANDLE_MULTIBYTE)
        !          2248:              newind = _rl_find_next_mbchar (new, newchars, 1, MB_FIND_NONZERO);
        !          2249:              oldind = _rl_find_next_mbchar (old, oldchars, 1, MB_FIND_NONZERO);
        !          2250: 
        !          2251:              nls += newind - newchars;
        !          2252:              ols += oldind - oldchars;
        !          2253: 
        !          2254:              newchars = newind;
        !          2255:              oldchars = oldind;
        !          2256: #else
        !          2257:              nls++; ols++;
        !          2258:              newchars++; oldchars++;
        !          2259: #endif
        !          2260:            }
        !          2261:          newwidth = (newchars == local_prompt_len) ? prompt_physical_chars + wrap_offset
        !          2262:                                                    : _rl_col_width (new, 0, nls - new, 1);
        !          2263:          /* if we changed nls and ols, we need to recompute lendiff */
        !          2264:          lendiff = (nls - nfd) - (ols - ofd);
        !          2265: 
        !          2266:          nlsf = new_face + (nls - new);
        !          2267:          olsf = old_face + (ols - old);
        !          2268:        }
        !          2269:       else
        !          2270:        newwidth = _rl_col_width (new, nfd - new, nls - new, 1);
        !          2271: 
        !          2272:       oldwidth = _rl_col_width (old, ofd - old, ols - old, 1);
        !          2273: 
        !          2274:       col_lendiff = newwidth - oldwidth;
        !          2275:     }
1.1       misho    2276:   else
                   2277:     col_lendiff = lendiff;
                   2278: 
1.1.1.3 ! misho    2279:   /* col_lendiff uses _rl_col_width(), which doesn't know about whether or not
        !          2280:      the multibyte characters it counts are invisible, so unless we're printing
        !          2281:      the entire prompt string (in which case we can use prompt_physical_chars)
        !          2282:      the count is short by the number of bytes in the invisible multibyte
        !          2283:      characters - the number of multibyte characters.
        !          2284: 
        !          2285:      We don't have a good way to solve this without moving to something like
        !          2286:      a bitmap that indicates which characters are visible and which are
        !          2287:      invisible. We fix it up (imperfectly) in the caller and by trying to use
        !          2288:      the entire prompt string wherever we can. */
        !          2289:      
1.1       misho    2290:   /* If we are changing the number of invisible characters in a line, and
                   2291:      the spot of first difference is before the end of the invisible chars,
                   2292:      lendiff needs to be adjusted. */
1.1.1.3 ! misho    2293:   if (current_line == 0 && current_invis_chars != visible_wrap_offset)
1.1       misho    2294:     {
1.1.1.3 ! misho    2295:       if (mb_cur_max > 1 && rl_byte_oriented == 0)
1.1       misho    2296:        {
                   2297:          lendiff += visible_wrap_offset - current_invis_chars;
                   2298:          col_lendiff += visible_wrap_offset - current_invis_chars;
                   2299:        }
                   2300:       else
                   2301:        {
                   2302:          lendiff += visible_wrap_offset - current_invis_chars;
                   2303:          col_lendiff = lendiff;
                   2304:        }
                   2305:     }
                   2306: 
                   2307:   /* We use temp as a count of the number of bytes from the first difference
                   2308:      to the end of the new line.  col_temp is the corresponding number of
                   2309:      screen columns.  A `dumb' update moves to the spot of first difference
                   2310:      and writes TEMP bytes. */
                   2311:   /* Insert (diff (len (old), len (new)) ch. */
                   2312:   temp = ne - nfd;
1.1.1.3 ! misho    2313:   if (mb_cur_max > 1 && rl_byte_oriented == 0)
1.1       misho    2314:     col_temp = _rl_col_width (new, nfd - new, ne - new, 1);
                   2315:   else
                   2316:     col_temp = temp;
                   2317: 
                   2318:   /* how many bytes from the new line buffer to write to the display */
                   2319:   bytes_to_insert = nls - nfd;
                   2320: 
                   2321:   /* col_lendiff > 0 if we are adding characters to the line */
                   2322:   if (col_lendiff > 0) /* XXX - was lendiff */
                   2323:     {
                   2324:       /* Non-zero if we're increasing the number of lines. */
                   2325:       int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
1.1.1.3 ! misho    2326: 
1.1       misho    2327:       /* If col_lendiff is > 0, implying that the new string takes up more
                   2328:         screen real estate than the old, but lendiff is < 0, meaning that it
                   2329:         takes fewer bytes, we need to just output the characters starting
                   2330:         from the first difference.  These will overwrite what is on the
                   2331:         display, so there's no reason to do a smart update.  This can really
                   2332:         only happen in a multibyte environment. */
                   2333:       if (lendiff < 0)
                   2334:        {
1.1.1.3 ! misho    2335:          puts_face (nfd, nfdf, temp);
        !          2336:          _rl_last_c_pos += col_temp;
1.1       misho    2337:          /* If nfd begins before any invisible characters in the prompt,
                   2338:             adjust _rl_last_c_pos to account for wrap_offset and set
                   2339:             cpos_adjusted to let the caller know. */
                   2340:          if (current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
1.1.1.3 ! misho    2341:            ADJUST_CPOS (wrap_offset);  /* XXX - prompt_invis_chars_first_line? */
1.1       misho    2342:          return;
                   2343:        }
                   2344:       /* Sometimes it is cheaper to print the characters rather than
                   2345:         use the terminal's capabilities.  If we're growing the number
                   2346:         of lines, make sure we actually cause the new line to wrap
                   2347:         around on auto-wrapping terminals. */
                   2348:       else if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
                   2349:        {
                   2350:          /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
                   2351:             _rl_horizontal_scroll_mode == 1, inserting the characters with
                   2352:             _rl_term_IC or _rl_term_ic will screw up the screen because of the
                   2353:             invisible characters.  We need to just draw them. */
                   2354:          /* The same thing happens if we're trying to draw before the last
                   2355:             invisible character in the prompt string or we're increasing the
                   2356:             number of invisible characters in the line and we're not drawing
                   2357:             the entire prompt string. */
                   2358:          if (*ols && ((_rl_horizontal_scroll_mode &&
                   2359:                        _rl_last_c_pos == 0 &&
                   2360:                        lendiff > prompt_visible_length &&
                   2361:                        current_invis_chars > 0) == 0) &&
1.1.1.3 ! misho    2362:                      (((mb_cur_max > 1 && rl_byte_oriented == 0) &&
1.1       misho    2363:                        current_line == 0 && wrap_offset &&
                   2364:                        ((nfd - new) <= prompt_last_invisible) &&
                   2365:                        (col_lendiff < prompt_visible_length)) == 0) &&
                   2366:                      (visible_wrap_offset >= current_invis_chars))
                   2367:            {
                   2368:              open_some_spaces (col_lendiff);
1.1.1.3 ! misho    2369:              puts_face (nfd, nfdf, bytes_to_insert);
        !          2370:              if (mb_cur_max > 1 && rl_byte_oriented == 0)
1.1       misho    2371:                _rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
                   2372:              else
                   2373:                _rl_last_c_pos += bytes_to_insert;
                   2374:            }
1.1.1.3 ! misho    2375:          else if ((mb_cur_max == 1 || rl_byte_oriented != 0) && *ols == 0 && lendiff > 0)
1.1       misho    2376:            {
                   2377:              /* At the end of a line the characters do not have to
                   2378:                 be "inserted".  They can just be placed on the screen. */
1.1.1.3 ! misho    2379:              puts_face (nfd, nfdf, temp);
1.1       misho    2380:              _rl_last_c_pos += col_temp;
                   2381:              return;
                   2382:            }
                   2383:          else  /* just write from first difference to end of new line */
                   2384:            {
1.1.1.3 ! misho    2385:              puts_face (nfd, nfdf, temp);
1.1       misho    2386:              _rl_last_c_pos += col_temp;
                   2387:              /* If nfd begins before the last invisible character in the
                   2388:                 prompt, adjust _rl_last_c_pos to account for wrap_offset
                   2389:                 and set cpos_adjusted to let the caller know. */
1.1.1.3 ! misho    2390:              if ((mb_cur_max > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
        !          2391:                ADJUST_CPOS (wrap_offset);      /* XXX - prompt_invis_chars_first_line? */
1.1       misho    2392:              return;
                   2393:            }
                   2394: 
                   2395:          if (bytes_to_insert > lendiff)
                   2396:            {
                   2397:              /* If nfd begins before the last invisible character in the
                   2398:                 prompt, adjust _rl_last_c_pos to account for wrap_offset
                   2399:                 and set cpos_adjusted to let the caller know. */
1.1.1.3 ! misho    2400:              if ((mb_cur_max > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
        !          2401:                ADJUST_CPOS (wrap_offset);      /* XXX - prompt_invis_chars_first_line? */
1.1       misho    2402:            }
                   2403:        }
                   2404:       else
                   2405:        {
                   2406:          /* cannot insert chars, write to EOL */
1.1.1.3 ! misho    2407:          puts_face (nfd, nfdf, temp);
1.1       misho    2408:          _rl_last_c_pos += col_temp;
                   2409:          /* If we're in a multibyte locale and were before the last invisible
                   2410:             char in the current line (which implies we just output some invisible
                   2411:             characters) we need to adjust _rl_last_c_pos, since it represents
                   2412:             a physical character position. */
1.1.1.3 ! misho    2413:          /* The current_line*rl_screenwidth+prompt_invis_chars_first_line is a
        !          2414:             crude attempt to compute how far into the new line buffer we are.
        !          2415:             It doesn't work well in the face of multibyte characters and needs
        !          2416:             to be rethought. XXX */
        !          2417:          if ((mb_cur_max > 1 && rl_byte_oriented == 0) &&
1.1       misho    2418:                current_line == prompt_last_screen_line && wrap_offset &&
                   2419:                displaying_prompt_first_line &&
                   2420:                wrap_offset != prompt_invis_chars_first_line &&
1.1.1.3 ! misho    2421:                ((nfd-new) < (prompt_last_invisible-(current_line*_rl_screenwidth+prompt_invis_chars_first_line))))
        !          2422:            ADJUST_CPOS (wrap_offset - prompt_invis_chars_first_line);
        !          2423: 
        !          2424:          /* XXX - what happens if wrap_offset == prompt_invis_chars_first_line
        !          2425:             and we are drawing the first line (current_line == 0)? We should
        !          2426:             adjust by _rl_last_c_pos -= prompt_invis_chars_first_line */
1.1       misho    2427:        }
                   2428:     }
                   2429:   else                         /* Delete characters from line. */
                   2430:     {
                   2431:       /* If possible and inexpensive to use terminal deletion, then do so. */
                   2432:       if (_rl_term_dc && (2 * col_temp) >= -col_lendiff)
                   2433:        {
                   2434:          /* If all we're doing is erasing the invisible characters in the
                   2435:             prompt string, don't bother.  It screws up the assumptions
                   2436:             about what's on the screen. */
                   2437:          if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
                   2438:              displaying_prompt_first_line &&
                   2439:              -lendiff == visible_wrap_offset)
                   2440:            col_lendiff = 0;
                   2441: 
                   2442:          /* If we have moved lmargin and we're shrinking the line, we've
                   2443:             already moved the cursor to the first character of the new line,
                   2444:             so deleting -col_lendiff characters will mess up the cursor
                   2445:             position calculation */
                   2446:          if (_rl_horizontal_scroll_mode && displaying_prompt_first_line == 0 &&
                   2447:                col_lendiff && _rl_last_c_pos < -col_lendiff)
                   2448:            col_lendiff = 0;
                   2449: 
                   2450:          if (col_lendiff)
                   2451:            delete_chars (-col_lendiff); /* delete (diff) characters */
                   2452: 
                   2453:          /* Copy (new) chars to screen from first diff to last match,
                   2454:             overwriting what is there. */
                   2455:          if (bytes_to_insert > 0)
                   2456:            {
                   2457:              /* If nfd begins at the prompt, or before the invisible
                   2458:                 characters in the prompt, we need to adjust _rl_last_c_pos
                   2459:                 in a multibyte locale to account for the wrap offset and
                   2460:                 set cpos_adjusted accordingly. */
1.1.1.3 ! misho    2461:              puts_face (nfd, nfdf, bytes_to_insert);
        !          2462:              if (mb_cur_max > 1 && rl_byte_oriented == 0)
1.1       misho    2463:                {
1.1.1.3 ! misho    2464:                  /* This still doesn't take into account whether or not the
        !          2465:                     characters that this counts are invisible. */
1.1       misho    2466:                  _rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
                   2467:                  if (current_line == 0 && wrap_offset &&
                   2468:                        displaying_prompt_first_line &&
1.1.1.3 ! misho    2469:                        prompt_invis_chars_first_line &&
        !          2470:                        _rl_last_c_pos >= prompt_invis_chars_first_line &&
1.1       misho    2471:                        ((nfd - new) <= prompt_last_invisible))
1.1.1.3 ! misho    2472:                    ADJUST_CPOS (prompt_invis_chars_first_line);
        !          2473: 
        !          2474: #if 1
        !          2475: #ifdef HANDLE_MULTIBYTE
        !          2476:                  /* If we write a non-space into the last screen column,
        !          2477:                     remove the note that we added a space to compensate for
        !          2478:                     a multibyte double-width character that didn't fit, since
        !          2479:                     it's only valid for what was previously there. */
        !          2480:                  /* XXX - watch this */
        !          2481:                  if (_rl_last_c_pos == _rl_screenwidth &&
        !          2482:                        line_state_invisible->wrapped_line[current_line+1] &&
        !          2483:                        nfd[bytes_to_insert-1] != ' ')
        !          2484:                    line_state_invisible->wrapped_line[current_line+1] = 0;
        !          2485: #endif
        !          2486: #endif
1.1       misho    2487:                }
                   2488:              else
                   2489:                _rl_last_c_pos += bytes_to_insert;
                   2490: 
1.1.1.2   misho    2491:              /* XXX - we only want to do this if we are at the end of the line
                   2492:                 so we move there with _rl_move_cursor_relative */
1.1       misho    2493:              if (_rl_horizontal_scroll_mode && ((oe-old) > (ne-new)))
1.1.1.2   misho    2494:                {
1.1.1.3 ! misho    2495:                  _rl_move_cursor_relative (ne-new, new, new_face);
1.1.1.2   misho    2496:                  goto clear_rest_of_line;
                   2497:                }
1.1       misho    2498:            }
                   2499:        }
                   2500:       /* Otherwise, print over the existing material. */
                   2501:       else
                   2502:        {
                   2503:          if (temp > 0)
                   2504:            {
                   2505:              /* If nfd begins at the prompt, or before the invisible
                   2506:                 characters in the prompt, we need to adjust _rl_last_c_pos
                   2507:                 in a multibyte locale to account for the wrap offset and
                   2508:                 set cpos_adjusted accordingly. */
1.1.1.3 ! misho    2509:              puts_face (nfd, nfdf, temp);
1.1       misho    2510:              _rl_last_c_pos += col_temp;               /* XXX */
1.1.1.3 ! misho    2511:              if (mb_cur_max > 1 && rl_byte_oriented == 0)
1.1       misho    2512:                {
                   2513:                  if (current_line == 0 && wrap_offset &&
                   2514:                        displaying_prompt_first_line &&
                   2515:                        _rl_last_c_pos > wrap_offset &&
                   2516:                        ((nfd - new) <= prompt_last_invisible))
1.1.1.3 ! misho    2517:                    ADJUST_CPOS (wrap_offset);  /* XXX - prompt_invis_chars_first_line? */
1.1       misho    2518:                }
                   2519:            }
                   2520: clear_rest_of_line:
                   2521:          lendiff = (oe - old) - (ne - new);
1.1.1.3 ! misho    2522:          if (mb_cur_max > 1 && rl_byte_oriented == 0)
1.1       misho    2523:            col_lendiff = _rl_col_width (old, 0, oe - old, 1) - _rl_col_width (new, 0, ne - new, 1);
                   2524:          else
                   2525:            col_lendiff = lendiff;
                   2526: 
                   2527:          /* If we've already printed over the entire width of the screen,
                   2528:             including the old material, then col_lendiff doesn't matter and
                   2529:             space_to_eol will insert too many spaces.  XXX - maybe we should
                   2530:             adjust col_lendiff based on the difference between _rl_last_c_pos
                   2531:             and _rl_screenwidth */
1.1.1.3 ! misho    2532:          if (col_lendiff && ((mb_cur_max == 1 || rl_byte_oriented) || (_rl_last_c_pos < _rl_screenwidth)))
1.1       misho    2533:            {     
                   2534:              if (_rl_term_autowrap && current_line < inv_botlin)
                   2535:                space_to_eol (col_lendiff);
                   2536:              else
                   2537:                _rl_clear_to_eol (col_lendiff);
                   2538:            }
                   2539:        }
                   2540:     }
                   2541: }
                   2542: 
                   2543: /* Tell the update routines that we have moved onto a new (empty) line. */
                   2544: int
1.1.1.3 ! misho    2545: rl_on_new_line (void)
1.1       misho    2546: {
                   2547:   if (visible_line)
                   2548:     visible_line[0] = '\0';
                   2549: 
                   2550:   _rl_last_c_pos = _rl_last_v_pos = 0;
                   2551:   _rl_vis_botlin = last_lmargin = 0;
                   2552:   if (vis_lbreaks)
                   2553:     vis_lbreaks[0] = vis_lbreaks[1] = 0;
                   2554:   visible_wrap_offset = 0;
                   2555:   return 0;
                   2556: }
                   2557: 
1.1.1.3 ! misho    2558: /* Clear all screen lines occupied by the current readline line buffer
        !          2559:    (visible line) */
        !          2560: int
        !          2561: rl_clear_visible_line (void)
        !          2562: {
        !          2563:   int curr_line;
        !          2564: 
        !          2565:   /* Make sure we move to column 0 so we clear the entire line */
        !          2566:   _rl_cr ();
        !          2567:   _rl_last_c_pos = 0;
        !          2568: 
        !          2569:   /* Move to the last screen line of the current visible line */
        !          2570:   _rl_move_vert (_rl_vis_botlin);
        !          2571: 
        !          2572:   /* And erase screen lines going up to line 0 (first visible line) */
        !          2573:   for (curr_line = _rl_last_v_pos; curr_line >= 0; curr_line--)
        !          2574:     {
        !          2575:       _rl_move_vert (curr_line);
        !          2576:       _rl_clear_to_eol (0);
        !          2577:     }
        !          2578: 
        !          2579:   return 0;
        !          2580: }
        !          2581: 
1.1       misho    2582: /* Tell the update routines that we have moved onto a new line with the
                   2583:    prompt already displayed.  Code originally from the version of readline
                   2584:    distributed with CLISP.  rl_expand_prompt must have already been called
1.1.1.3 ! misho    2585:    (explicitly or implicitly).  This still doesn't work exactly right; it
        !          2586:    should use expand_prompt() */
1.1       misho    2587: int
1.1.1.3 ! misho    2588: rl_on_new_line_with_prompt (void)
1.1       misho    2589: {
                   2590:   int prompt_size, i, l, real_screenwidth, newlines;
                   2591:   char *prompt_last_line, *lprompt;
                   2592: 
                   2593:   /* Initialize visible_line and invisible_line to ensure that they can hold
                   2594:      the already-displayed prompt. */
                   2595:   prompt_size = strlen (rl_prompt) + 1;
                   2596:   init_line_structures (prompt_size);
                   2597: 
                   2598:   /* Make sure the line structures hold the already-displayed prompt for
                   2599:      redisplay. */
                   2600:   lprompt = local_prompt ? local_prompt : rl_prompt;
                   2601:   strcpy (visible_line, lprompt);
                   2602:   strcpy (invisible_line, lprompt);
                   2603: 
                   2604:   /* If the prompt contains newlines, take the last tail. */
                   2605:   prompt_last_line = strrchr (rl_prompt, '\n');
                   2606:   if (!prompt_last_line)
                   2607:     prompt_last_line = rl_prompt;
                   2608: 
                   2609:   l = strlen (prompt_last_line);
                   2610:   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
                   2611:     _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l, 1);        /* XXX */
                   2612:   else
                   2613:     _rl_last_c_pos = l;
                   2614: 
                   2615:   /* Dissect prompt_last_line into screen lines. Note that here we have
                   2616:      to use the real screenwidth. Readline's notion of screenwidth might be
                   2617:      one less, see terminal.c. */
                   2618:   real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1);
                   2619:   _rl_last_v_pos = l / real_screenwidth;
                   2620:   /* If the prompt length is a multiple of real_screenwidth, we don't know
                   2621:      whether the cursor is at the end of the last line, or already at the
                   2622:      beginning of the next line. Output a newline just to be safe. */
                   2623:   if (l > 0 && (l % real_screenwidth) == 0)
                   2624:     _rl_output_some_chars ("\n", 1);
                   2625:   last_lmargin = 0;
                   2626: 
                   2627:   newlines = 0; i = 0;
                   2628:   while (i <= l)
                   2629:     {
                   2630:       _rl_vis_botlin = newlines;
                   2631:       vis_lbreaks[newlines++] = i;
                   2632:       i += real_screenwidth;
                   2633:     }
                   2634:   vis_lbreaks[newlines] = l;
                   2635:   visible_wrap_offset = 0;
                   2636: 
                   2637:   rl_display_prompt = rl_prompt;       /* XXX - make sure it's set */
                   2638: 
                   2639:   return 0;
                   2640: }
                   2641: 
                   2642: /* Actually update the display, period. */
                   2643: int
1.1.1.3 ! misho    2644: rl_forced_update_display (void)
1.1       misho    2645: {
                   2646:   register char *temp;
                   2647: 
                   2648:   if (visible_line)
                   2649:     {
                   2650:       temp = visible_line;
                   2651:       while (*temp)
                   2652:        *temp++ = '\0';
                   2653:     }
                   2654:   rl_on_new_line ();
                   2655:   forced_display++;
                   2656:   (*rl_redisplay_function) ();
                   2657:   return 0;
                   2658: }
                   2659: 
1.1.1.3 ! misho    2660: /* Redraw only the last line of a multi-line prompt. */
        !          2661: void
        !          2662: rl_redraw_prompt_last_line (void)
        !          2663: {
        !          2664:   char *t;
        !          2665: 
        !          2666:   t = strrchr (rl_display_prompt, '\n');
        !          2667:   if (t)
        !          2668:     redraw_prompt (++t);
        !          2669:   else
        !          2670:     rl_forced_update_display ();
        !          2671: }
        !          2672: 
1.1       misho    2673: /* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
                   2674:    (Well, when we don't have multibyte characters, _rl_last_c_pos is a
                   2675:    buffer index.)
                   2676:    DATA is the contents of the screen line of interest; i.e., where
1.1.1.3 ! misho    2677:    the movement is being done.
        !          2678:    DATA is always the visible line or the invisible line */
        !          2679: static void
        !          2680: _rl_move_cursor_relative (int new, const char *data, const char *dataf)
1.1       misho    2681: {
                   2682:   register int i;
                   2683:   int woff;                    /* number of invisible chars on current line */
                   2684:   int cpos, dpos;              /* current and desired cursor positions */
                   2685:   int adjust;
1.1.1.3 ! misho    2686:   int in_invisline;
        !          2687:   int mb_cur_max = MB_CUR_MAX;
1.1       misho    2688: 
                   2689:   woff = WRAP_OFFSET (_rl_last_v_pos, wrap_offset);
                   2690:   cpos = _rl_last_c_pos;
                   2691: 
                   2692:   if (cpos == 0 && cpos == new)
                   2693:     return;
                   2694: 
                   2695: #if defined (HANDLE_MULTIBYTE)
                   2696:   /* If we have multibyte characters, NEW is indexed by the buffer point in
                   2697:      a multibyte string, but _rl_last_c_pos is the display position.  In
                   2698:      this case, NEW's display position is not obvious and must be
                   2699:      calculated.  We need to account for invisible characters in this line,
                   2700:      as long as we are past them and they are counted by _rl_col_width. */
1.1.1.3 ! misho    2701:   if (mb_cur_max > 1 && rl_byte_oriented == 0)
1.1       misho    2702:     {
                   2703:       adjust = 1;
                   2704:       /* Try to short-circuit common cases and eliminate a bunch of multibyte
                   2705:         character function calls. */
                   2706:       /* 1.  prompt string */
                   2707:       if (new == local_prompt_len && memcmp (data, local_prompt, new) == 0)
                   2708:        {
                   2709:          dpos = prompt_physical_chars;
                   2710:          cpos_adjusted = 1;
                   2711:          adjust = 0;
                   2712:        }
                   2713:       /* 2.  prompt_string + line contents */
                   2714:       else if (new > local_prompt_len && local_prompt && memcmp (data, local_prompt, local_prompt_len) == 0)
                   2715:        {
                   2716:          dpos = prompt_physical_chars + _rl_col_width (data, local_prompt_len, new, 1);
                   2717:          cpos_adjusted = 1;
                   2718:          adjust = 0;
                   2719:        }
                   2720:       else
                   2721:         dpos = _rl_col_width (data, 0, new, 1);
                   2722: 
                   2723:       if (displaying_prompt_first_line == 0)
                   2724:        adjust = 0;
                   2725: 
1.1.1.3 ! misho    2726:       /* yet another special case: printing the last line of a prompt with
        !          2727:         multibyte characters and invisible characters whose printable length
        !          2728:         exceeds the screen width with the last invisible character
        !          2729:         (prompt_last_invisible) in the last line.  IN_INVISLINE is the
        !          2730:         offset of DATA in invisible_line */
        !          2731:       in_invisline = 0;
        !          2732:       if (data > invisible_line && data < invisible_line+inv_lbreaks[_rl_inv_botlin+1])
        !          2733:        in_invisline = data - invisible_line;
        !          2734: 
1.1       misho    2735:       /* Use NEW when comparing against the last invisible character in the
                   2736:         prompt string, since they're both buffer indices and DPOS is a
                   2737:         desired display position. */
1.1.1.3 ! misho    2738:       /* NEW is relative to the current displayed line, while
        !          2739:         PROMPT_LAST_INVISIBLE is relative to the entire (wrapped) line.
        !          2740:         Need a way to reconcile these two variables by turning NEW into a
        !          2741:         buffer position relative to the start of the line */
1.1       misho    2742:       if (adjust && ((new > prompt_last_invisible) ||          /* XXX - don't use woff here */
1.1.1.3 ! misho    2743:                     (new+in_invisline > prompt_last_invisible) ||      /* invisible line */
        !          2744:          (prompt_physical_chars >= _rl_screenwidth &&          /* visible line */
1.1       misho    2745:           _rl_last_v_pos == prompt_last_screen_line &&
                   2746:           wrap_offset >= woff && dpos >= woff &&
1.1.1.3 ! misho    2747:           new > (prompt_last_invisible-(vis_lbreaks[_rl_last_v_pos])-wrap_offset))))
1.1       misho    2748:           /* XXX last comparison might need to be >= */
                   2749:        {
                   2750:          dpos -= woff;
                   2751:          /* Since this will be assigned to _rl_last_c_pos at the end (more
                   2752:             precisely, _rl_last_c_pos == dpos when this function returns),
                   2753:             let the caller know. */
                   2754:          cpos_adjusted = 1;
                   2755:        }
                   2756:     }
                   2757:   else
                   2758: #endif
                   2759:     dpos = new;
                   2760: 
                   2761:   /* If we don't have to do anything, then return. */
                   2762:   if (cpos == dpos)
                   2763:     return;
                   2764: 
                   2765:   /* It may be faster to output a CR, and then move forwards instead
                   2766:      of moving backwards. */
                   2767:   /* i == current physical cursor position. */
                   2768: #if defined (HANDLE_MULTIBYTE)
1.1.1.3 ! misho    2769:   if (mb_cur_max > 1 && rl_byte_oriented == 0)
1.1       misho    2770:     i = _rl_last_c_pos;
                   2771:   else
                   2772: #endif
                   2773:   i = _rl_last_c_pos - woff;
                   2774:   if (dpos == 0 || CR_FASTER (dpos, _rl_last_c_pos) ||
                   2775:       (_rl_term_autowrap && i == _rl_screenwidth))
                   2776:     {
1.1.1.3 ! misho    2777:       _rl_cr ();
1.1       misho    2778:       cpos = _rl_last_c_pos = 0;
                   2779:     }
                   2780: 
                   2781:   if (cpos < dpos)
                   2782:     {
                   2783:       /* Move the cursor forward.  We do it by printing the command
                   2784:         to move the cursor forward if there is one, else print that
                   2785:         portion of the output buffer again.  Which is cheaper? */
                   2786: 
                   2787:       /* The above comment is left here for posterity.  It is faster
                   2788:         to print one character (non-control) than to print a control
                   2789:         sequence telling the terminal to move forward one character.
                   2790:         That kind of control is for people who don't know what the
                   2791:         data is underneath the cursor. */
                   2792: 
                   2793:       /* However, we need a handle on where the current display position is
                   2794:         in the buffer for the immediately preceding comment to be true.
                   2795:         In multibyte locales, we don't currently have that info available.
                   2796:         Without it, we don't know where the data we have to display begins
                   2797:         in the buffer and we have to go back to the beginning of the screen
                   2798:         line.  In this case, we can use the terminal sequence to move forward
                   2799:         if it's available. */
1.1.1.3 ! misho    2800:       if (mb_cur_max > 1 && rl_byte_oriented == 0)
1.1       misho    2801:        {
                   2802:          if (_rl_term_forward_char)
                   2803:            {
                   2804:              for (i = cpos; i < dpos; i++)
                   2805:                tputs (_rl_term_forward_char, 1, _rl_output_character_function);
                   2806:            }
                   2807:          else
                   2808:            {
1.1.1.3 ! misho    2809:              _rl_cr ();
        !          2810:              puts_face (data, dataf, new);
1.1       misho    2811:            }
                   2812:        }
                   2813:       else
1.1.1.3 ! misho    2814:        puts_face (data + cpos, dataf + cpos, new - cpos);
1.1       misho    2815:     }
                   2816: 
                   2817: #if defined (HANDLE_MULTIBYTE)
                   2818:   /* NEW points to the buffer point, but _rl_last_c_pos is the display point.
                   2819:      The byte length of the string is probably bigger than the column width
                   2820:      of the string, which means that if NEW == _rl_last_c_pos, then NEW's
                   2821:      display point is less than _rl_last_c_pos. */
                   2822: #endif
                   2823:   else if (cpos > dpos)
                   2824:     _rl_backspace (cpos - dpos);
                   2825: 
                   2826:   _rl_last_c_pos = dpos;
                   2827: }
                   2828: 
                   2829: /* PWP: move the cursor up or down. */
                   2830: void
1.1.1.3 ! misho    2831: _rl_move_vert (int to)
1.1       misho    2832: {
                   2833:   register int delta, i;
                   2834: 
                   2835:   if (_rl_last_v_pos == to || to > _rl_screenheight)
                   2836:     return;
                   2837: 
                   2838:   if ((delta = to - _rl_last_v_pos) > 0)
                   2839:     {
                   2840:       for (i = 0; i < delta; i++)
                   2841:        putc ('\n', rl_outstream);
1.1.1.3 ! misho    2842:       _rl_cr ();
1.1       misho    2843:       _rl_last_c_pos = 0;
                   2844:     }
                   2845:   else
                   2846:     {                  /* delta < 0 */
                   2847: #ifdef __DJGPP__
                   2848:       int row, col;
                   2849: 
                   2850:       fflush (rl_outstream);
                   2851:       ScreenGetCursor (&row, &col);
                   2852:       ScreenSetCursor (row + delta, col);
                   2853:       i = -delta;
                   2854: #else
                   2855:       if (_rl_term_up && *_rl_term_up)
                   2856:        for (i = 0; i < -delta; i++)
                   2857:          tputs (_rl_term_up, 1, _rl_output_character_function);
                   2858: #endif /* !__DJGPP__ */
                   2859:     }
                   2860: 
                   2861:   _rl_last_v_pos = to;         /* Now TO is here */
                   2862: }
                   2863: 
                   2864: /* Physically print C on rl_outstream.  This is for functions which know
                   2865:    how to optimize the display.  Return the number of characters output. */
                   2866: int
1.1.1.3 ! misho    2867: rl_show_char (int c)
1.1       misho    2868: {
                   2869:   int n = 1;
                   2870:   if (META_CHAR (c) && (_rl_output_meta_chars == 0))
                   2871:     {
                   2872:       fprintf (rl_outstream, "M-");
                   2873:       n += 2;
                   2874:       c = UNMETA (c);
                   2875:     }
                   2876: 
                   2877: #if defined (DISPLAY_TABS)
                   2878:   if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
                   2879: #else
                   2880:   if (CTRL_CHAR (c) || c == RUBOUT)
                   2881: #endif /* !DISPLAY_TABS */
                   2882:     {
                   2883:       fprintf (rl_outstream, "C-");
                   2884:       n += 2;
                   2885:       c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
                   2886:     }
                   2887: 
                   2888:   putc (c, rl_outstream);
                   2889:   fflush (rl_outstream);
                   2890:   return n;
                   2891: }
                   2892: 
                   2893: int
1.1.1.3 ! misho    2894: rl_character_len (int c, int pos)
1.1       misho    2895: {
                   2896:   unsigned char uc;
                   2897: 
                   2898:   uc = (unsigned char)c;
                   2899: 
                   2900:   if (META_CHAR (uc))
                   2901:     return ((_rl_output_meta_chars == 0) ? 4 : 1);
                   2902: 
                   2903:   if (uc == '\t')
                   2904:     {
                   2905: #if defined (DISPLAY_TABS)
                   2906:       return (((pos | 7) + 1) - pos);
                   2907: #else
                   2908:       return (2);
                   2909: #endif /* !DISPLAY_TABS */
                   2910:     }
                   2911: 
                   2912:   if (CTRL_CHAR (c) || c == RUBOUT)
                   2913:     return (2);
                   2914: 
                   2915:   return ((ISPRINT (uc)) ? 1 : 2);
                   2916: }
                   2917: /* How to print things in the "echo-area".  The prompt is treated as a
                   2918:    mini-modeline. */
                   2919: static int msg_saved_prompt = 0;
                   2920: 
                   2921: #if defined (USE_VARARGS)
                   2922: int
                   2923: #if defined (PREFER_STDARG)
                   2924: rl_message (const char *format, ...)
                   2925: #else
                   2926: rl_message (va_alist)
                   2927:      va_dcl
                   2928: #endif
                   2929: {
                   2930:   va_list args;
                   2931: #if defined (PREFER_VARARGS)
                   2932:   char *format;
                   2933: #endif
                   2934: #if defined (HAVE_VSNPRINTF)
                   2935:   int bneed;
                   2936: #endif
                   2937: 
                   2938: #if defined (PREFER_STDARG)
                   2939:   va_start (args, format);
                   2940: #else
                   2941:   va_start (args);
                   2942:   format = va_arg (args, char *);
                   2943: #endif
                   2944: 
                   2945:   if (msg_buf == 0)
                   2946:     msg_buf = xmalloc (msg_bufsiz = 128);
                   2947: 
                   2948: #if defined (HAVE_VSNPRINTF)
1.1.1.3 ! misho    2949:   bneed = vsnprintf (msg_buf, msg_bufsiz, format, args);
1.1       misho    2950:   if (bneed >= msg_bufsiz - 1)
                   2951:     {
                   2952:       msg_bufsiz = bneed + 1;
                   2953:       msg_buf = xrealloc (msg_buf, msg_bufsiz);
                   2954:       va_end (args);
                   2955: 
                   2956: #if defined (PREFER_STDARG)
                   2957:       va_start (args, format);
                   2958: #else
                   2959:       va_start (args);
                   2960:       format = va_arg (args, char *);
                   2961: #endif
                   2962:       vsnprintf (msg_buf, msg_bufsiz - 1, format, args);
                   2963:     }
                   2964: #else
                   2965:   vsprintf (msg_buf, format, args);
                   2966:   msg_buf[msg_bufsiz - 1] = '\0';      /* overflow? */
                   2967: #endif
                   2968:   va_end (args);
                   2969: 
                   2970:   if (saved_local_prompt == 0)
                   2971:     {
                   2972:       rl_save_prompt ();
                   2973:       msg_saved_prompt = 1;
                   2974:     }
                   2975:   else if (local_prompt != saved_local_prompt)
                   2976:     {
                   2977:       FREE (local_prompt);
                   2978:       FREE (local_prompt_prefix);
                   2979:       local_prompt = (char *)NULL;
                   2980:     }
                   2981:   rl_display_prompt = msg_buf;
1.1.1.3 ! misho    2982:   local_prompt = expand_prompt (msg_buf, 0, &prompt_visible_length,
        !          2983:                                            &prompt_last_invisible,
        !          2984:                                            &prompt_invis_chars_first_line,
        !          2985:                                            &prompt_physical_chars);
1.1       misho    2986:   local_prompt_prefix = (char *)NULL;
                   2987:   local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
                   2988:   (*rl_redisplay_function) ();
                   2989: 
                   2990:   return 0;
                   2991: }
                   2992: #else /* !USE_VARARGS */
                   2993: int
                   2994: rl_message (format, arg1, arg2)
                   2995:      char *format;
                   2996: {
                   2997:   if (msg_buf == 0)
                   2998:     msg_buf = xmalloc (msg_bufsiz = 128);
                   2999: 
                   3000:   sprintf (msg_buf, format, arg1, arg2);
                   3001:   msg_buf[msg_bufsiz - 1] = '\0';      /* overflow? */
                   3002: 
                   3003:   rl_display_prompt = msg_buf;
                   3004:   if (saved_local_prompt == 0)
                   3005:     {
                   3006:       rl_save_prompt ();
                   3007:       msg_saved_prompt = 1;
                   3008:     }
                   3009:   else if (local_prompt != saved_local_prompt)
                   3010:     {
                   3011:       FREE (local_prompt);
                   3012:       FREE (local_prompt_prefix);
                   3013:       local_prompt = (char *)NULL;
                   3014:     }
1.1.1.3 ! misho    3015:   local_prompt = expand_prompt (msg_buf, 0, &prompt_visible_length,
        !          3016:                                            &prompt_last_invisible,
        !          3017:                                            &prompt_invis_chars_first_line,
        !          3018:                                            &prompt_physical_chars);
1.1       misho    3019:   local_prompt_prefix = (char *)NULL;
                   3020:   local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
                   3021:   (*rl_redisplay_function) ();
                   3022:       
                   3023:   return 0;
                   3024: }
                   3025: #endif /* !USE_VARARGS */
                   3026: 
                   3027: /* How to clear things from the "echo-area". */
                   3028: int
1.1.1.3 ! misho    3029: rl_clear_message (void)
1.1       misho    3030: {
                   3031:   rl_display_prompt = rl_prompt;
                   3032:   if (msg_saved_prompt)
                   3033:     {
                   3034:       rl_restore_prompt ();
                   3035:       msg_saved_prompt = 0;
                   3036:     }
                   3037:   (*rl_redisplay_function) ();
                   3038:   return 0;
                   3039: }
                   3040: 
                   3041: int
1.1.1.3 ! misho    3042: rl_reset_line_state (void)
1.1       misho    3043: {
                   3044:   rl_on_new_line ();
                   3045: 
                   3046:   rl_display_prompt = rl_prompt ? rl_prompt : "";
                   3047:   forced_display = 1;
                   3048:   return 0;
                   3049: }
                   3050: 
1.1.1.3 ! misho    3051: /* Save all of the variables associated with the prompt and its display. Most
        !          3052:    of the complexity is dealing with the invisible characters in the prompt
        !          3053:    string and where they are. There are enough of these that I should consider
        !          3054:    a struct. */
1.1       misho    3055: void
1.1.1.3 ! misho    3056: rl_save_prompt (void)
1.1       misho    3057: {
                   3058:   saved_local_prompt = local_prompt;
                   3059:   saved_local_prefix = local_prompt_prefix;
                   3060:   saved_prefix_length = prompt_prefix_length;
                   3061:   saved_local_length = local_prompt_len;
                   3062:   saved_last_invisible = prompt_last_invisible;
                   3063:   saved_visible_length = prompt_visible_length;
                   3064:   saved_invis_chars_first_line = prompt_invis_chars_first_line;
                   3065:   saved_physical_chars = prompt_physical_chars;
1.1.1.3 ! misho    3066:   saved_local_prompt_newlines = local_prompt_newlines;
1.1       misho    3067: 
                   3068:   local_prompt = local_prompt_prefix = (char *)0;
                   3069:   local_prompt_len = 0;
1.1.1.3 ! misho    3070:   local_prompt_newlines = (int *)0;
        !          3071: 
1.1       misho    3072:   prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0;
                   3073:   prompt_invis_chars_first_line = prompt_physical_chars = 0;
                   3074: }
                   3075: 
                   3076: void
1.1.1.3 ! misho    3077: rl_restore_prompt (void)
1.1       misho    3078: {
                   3079:   FREE (local_prompt);
                   3080:   FREE (local_prompt_prefix);
1.1.1.3 ! misho    3081:   FREE (local_prompt_newlines);
1.1       misho    3082: 
                   3083:   local_prompt = saved_local_prompt;
                   3084:   local_prompt_prefix = saved_local_prefix;
                   3085:   local_prompt_len = saved_local_length;
1.1.1.3 ! misho    3086:   local_prompt_newlines = saved_local_prompt_newlines;
        !          3087: 
1.1       misho    3088:   prompt_prefix_length = saved_prefix_length;
                   3089:   prompt_last_invisible = saved_last_invisible;
                   3090:   prompt_visible_length = saved_visible_length;
                   3091:   prompt_invis_chars_first_line = saved_invis_chars_first_line;
                   3092:   prompt_physical_chars = saved_physical_chars;
                   3093: 
                   3094:   /* can test saved_local_prompt to see if prompt info has been saved. */
                   3095:   saved_local_prompt = saved_local_prefix = (char *)0;
                   3096:   saved_local_length = 0;
                   3097:   saved_last_invisible = saved_visible_length = saved_prefix_length = 0;
                   3098:   saved_invis_chars_first_line = saved_physical_chars = 0;
1.1.1.3 ! misho    3099:   saved_local_prompt_newlines = 0;
1.1       misho    3100: }
                   3101: 
                   3102: char *
1.1.1.3 ! misho    3103: _rl_make_prompt_for_search (int pchar)
1.1       misho    3104: {
                   3105:   int len;
                   3106:   char *pmt, *p;
                   3107: 
                   3108:   rl_save_prompt ();
                   3109: 
                   3110:   /* We've saved the prompt, and can do anything with the various prompt
                   3111:      strings we need before they're restored.  We want the unexpanded
                   3112:      portion of the prompt string after any final newline. */
                   3113:   p = rl_prompt ? strrchr (rl_prompt, '\n') : 0;
                   3114:   if (p == 0)
                   3115:     {
                   3116:       len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
                   3117:       pmt = (char *)xmalloc (len + 2);
                   3118:       if (len)
                   3119:        strcpy (pmt, rl_prompt);
                   3120:       pmt[len] = pchar;
                   3121:       pmt[len+1] = '\0';
                   3122:     }
                   3123:   else
                   3124:     {
                   3125:       p++;
                   3126:       len = strlen (p);
                   3127:       pmt = (char *)xmalloc (len + 2);
                   3128:       if (len)
                   3129:        strcpy (pmt, p);
                   3130:       pmt[len] = pchar;
                   3131:       pmt[len+1] = '\0';
                   3132:     }  
                   3133: 
                   3134:   /* will be overwritten by expand_prompt, called from rl_message */
                   3135:   prompt_physical_chars = saved_physical_chars + 1;
                   3136:   return pmt;
                   3137: }
                   3138: 
                   3139: /* Quick redisplay hack when erasing characters at the end of the line. */
                   3140: void
1.1.1.3 ! misho    3141: _rl_erase_at_end_of_line (int l)
1.1       misho    3142: {
                   3143:   register int i;
                   3144: 
                   3145:   _rl_backspace (l);
                   3146:   for (i = 0; i < l; i++)
                   3147:     putc (' ', rl_outstream);
                   3148:   _rl_backspace (l);
                   3149:   for (i = 0; i < l; i++)
                   3150:     visible_line[--_rl_last_c_pos] = '\0';
                   3151:   rl_display_fixed++;
                   3152: }
                   3153: 
                   3154: /* Clear to the end of the line.  COUNT is the minimum
1.1.1.3 ! misho    3155:    number of character spaces to clear, but we use a terminal escape
        !          3156:    sequence if available. */
1.1       misho    3157: void
1.1.1.3 ! misho    3158: _rl_clear_to_eol (int count)
1.1       misho    3159: {
                   3160: #ifndef __MSDOS__
                   3161:   if (_rl_term_clreol)
                   3162:     tputs (_rl_term_clreol, 1, _rl_output_character_function);
                   3163:   else
                   3164: #endif
                   3165:     if (count)
                   3166:       space_to_eol (count);
                   3167: }
                   3168: 
                   3169: /* Clear to the end of the line using spaces.  COUNT is the minimum
                   3170:    number of character spaces to clear, */
                   3171: static void
1.1.1.3 ! misho    3172: space_to_eol (int count)
1.1       misho    3173: {
                   3174:   register int i;
                   3175: 
                   3176:   for (i = 0; i < count; i++)
1.1.1.3 ! misho    3177:     putc (' ', rl_outstream);
1.1       misho    3178: 
                   3179:   _rl_last_c_pos += count;
                   3180: }
                   3181: 
                   3182: void
1.1.1.3 ! misho    3183: _rl_clear_screen (int clrscr)
1.1       misho    3184: {
1.1.1.3 ! misho    3185: #if defined (__DJGPP__)
        !          3186:   ScreenClear ();
        !          3187:   ScreenSetCursor (0, 0);
        !          3188: #else
1.1       misho    3189:   if (_rl_term_clrpag)
1.1.1.3 ! misho    3190:     {
        !          3191:       tputs (_rl_term_clrpag, 1, _rl_output_character_function);
        !          3192:       if (clrscr && _rl_term_clrscroll)
        !          3193:        tputs (_rl_term_clrscroll, 1, _rl_output_character_function);
        !          3194:     }
1.1       misho    3195:   else
                   3196:     rl_crlf ();
                   3197: #endif /* __DJGPP__ */
                   3198: }
                   3199: 
                   3200: /* Insert COUNT characters from STRING to the output stream at column COL. */
                   3201: static void
1.1.1.3 ! misho    3202: insert_some_chars (char *string, int count, int col)
1.1       misho    3203: {
                   3204:   open_some_spaces (col);
                   3205:   _rl_output_some_chars (string, count);
                   3206: }
                   3207: 
                   3208: /* Insert COL spaces, keeping the cursor at the same position.  We follow the
                   3209:    ncurses documentation and use either im/ei with explicit spaces, or IC/ic
                   3210:    by itself.  We assume there will either be ei or we don't need to use it. */
                   3211: static void
1.1.1.3 ! misho    3212: open_some_spaces (int col)
1.1       misho    3213: {
1.1.1.3 ! misho    3214: #if !defined (__MSDOS__) && (!defined (__MINGW32__) || defined (NCURSES_VERSION))
1.1       misho    3215:   char *buffer;
                   3216:   register int i;
                   3217: 
                   3218:   /* If IC is defined, then we do not have to "enter" insert mode. */
                   3219:   if (_rl_term_IC)
                   3220:     {
                   3221:       buffer = tgoto (_rl_term_IC, 0, col);
                   3222:       tputs (buffer, 1, _rl_output_character_function);
                   3223:     }
                   3224:   else if (_rl_term_im && *_rl_term_im)
                   3225:     {
                   3226:       tputs (_rl_term_im, 1, _rl_output_character_function);
                   3227:       /* just output the desired number of spaces */
                   3228:       for (i = col; i--; )
                   3229:        _rl_output_character_function (' ');
                   3230:       /* If there is a string to turn off insert mode, use it now. */
                   3231:       if (_rl_term_ei && *_rl_term_ei)
                   3232:        tputs (_rl_term_ei, 1, _rl_output_character_function);
                   3233:       /* and move back the right number of spaces */
                   3234:       _rl_backspace (col);
                   3235:     }
                   3236:   else if (_rl_term_ic && *_rl_term_ic)
                   3237:     {
                   3238:       /* If there is a special command for inserting characters, then
                   3239:         use that first to open up the space. */
                   3240:       for (i = col; i--; )
                   3241:        tputs (_rl_term_ic, 1, _rl_output_character_function);
                   3242:     }
1.1.1.3 ! misho    3243: #endif /* !__MSDOS__ && (!__MINGW32__ || NCURSES_VERSION)*/
1.1       misho    3244: }
                   3245: 
                   3246: /* Delete COUNT characters from the display line. */
                   3247: static void
1.1.1.3 ! misho    3248: delete_chars (int count)
1.1       misho    3249: {
                   3250:   if (count > _rl_screenwidth) /* XXX */
                   3251:     return;
                   3252: 
1.1.1.3 ! misho    3253: #if !defined (__MSDOS__) && (!defined (__MINGW32__) || defined (NCURSES_VERSION))
1.1       misho    3254:   if (_rl_term_DC && *_rl_term_DC)
                   3255:     {
                   3256:       char *buffer;
                   3257:       buffer = tgoto (_rl_term_DC, count, count);
                   3258:       tputs (buffer, count, _rl_output_character_function);
                   3259:     }
                   3260:   else
                   3261:     {
                   3262:       if (_rl_term_dc && *_rl_term_dc)
                   3263:        while (count--)
                   3264:          tputs (_rl_term_dc, 1, _rl_output_character_function);
                   3265:     }
1.1.1.3 ! misho    3266: #endif /* !__MSDOS__ && (!__MINGW32__ || NCURSES_VERSION)*/
1.1       misho    3267: }
                   3268: 
                   3269: void
1.1.1.3 ! misho    3270: _rl_update_final (void)
1.1       misho    3271: {
1.1.1.3 ! misho    3272:   int full_lines, woff, botline_length;
        !          3273: 
        !          3274:   if (line_structures_initialized == 0)
        !          3275:     return;
1.1       misho    3276: 
                   3277:   full_lines = 0;
                   3278:   /* If the cursor is the only thing on an otherwise-blank last line,
                   3279:      compensate so we don't print an extra CRLF. */
                   3280:   if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
                   3281:        visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
                   3282:     {
                   3283:       _rl_vis_botlin--;
                   3284:       full_lines = 1;
                   3285:     }
                   3286:   _rl_move_vert (_rl_vis_botlin);
1.1.1.3 ! misho    3287:   woff = W_OFFSET(_rl_vis_botlin, wrap_offset);
        !          3288:   botline_length = VIS_LLEN(_rl_vis_botlin) - woff;
1.1       misho    3289:   /* If we've wrapped lines, remove the final xterm line-wrap flag. */
1.1.1.3 ! misho    3290:   if (full_lines && _rl_term_autowrap && botline_length == _rl_screenwidth)
1.1       misho    3291:     {
1.1.1.3 ! misho    3292:       char *last_line, *last_face;
1.1       misho    3293: 
1.1.1.3 ! misho    3294:       /* LAST_LINE includes invisible characters, so if you want to get the
        !          3295:         last character of the first line, you have to take WOFF into account.
        !          3296:         This needs to be done for both calls to _rl_move_cursor_relative,
        !          3297:         which takes a buffer position as the first argument, and any direct
        !          3298:         subscripts of LAST_LINE. */
        !          3299:       last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]]; /* = VIS_CHARS(_rl_vis_botlin); */
        !          3300:       last_face = &vis_face[vis_lbreaks[_rl_vis_botlin]]; /* = VIS_CHARS(_rl_vis_botlin); */
1.1       misho    3301:       cpos_buffer_position = -1;       /* don't know where we are in buffer */
1.1.1.3 ! misho    3302:       _rl_move_cursor_relative (_rl_screenwidth - 1 + woff, last_line, last_face);     /* XXX */
1.1       misho    3303:       _rl_clear_to_eol (0);
1.1.1.3 ! misho    3304:       puts_face (&last_line[_rl_screenwidth - 1 + woff],
        !          3305:                 &last_face[_rl_screenwidth - 1 + woff], 1);
1.1       misho    3306:     }
                   3307:   _rl_vis_botlin = 0;
1.1.1.3 ! misho    3308:   if (botline_length > 0 || _rl_last_c_pos > 0)
        !          3309:     rl_crlf ();
1.1       misho    3310:   fflush (rl_outstream);
                   3311:   rl_display_fixed++;
                   3312: }
                   3313: 
                   3314: /* Move to the start of the current line. */
                   3315: static void
1.1.1.3 ! misho    3316: cr (void)
1.1       misho    3317: {
1.1.1.3 ! misho    3318:   _rl_cr ();
        !          3319:   _rl_last_c_pos = 0;
1.1       misho    3320: }
                   3321: 
                   3322: /* Redraw the last line of a multi-line prompt that may possibly contain
                   3323:    terminal escape sequences.  Called with the cursor at column 0 of the
                   3324:    line to draw the prompt on. */
                   3325: static void
1.1.1.3 ! misho    3326: redraw_prompt (char *t)
1.1       misho    3327: {
                   3328:   char *oldp;
                   3329: 
                   3330:   oldp = rl_display_prompt;
                   3331:   rl_save_prompt ();
                   3332: 
                   3333:   rl_display_prompt = t;
1.1.1.3 ! misho    3334:   local_prompt = expand_prompt (t, PMT_MULTILINE,
        !          3335:                                   &prompt_visible_length,
1.1       misho    3336:                                   &prompt_last_invisible,
                   3337:                                   &prompt_invis_chars_first_line,
                   3338:                                   &prompt_physical_chars);
                   3339:   local_prompt_prefix = (char *)NULL;
                   3340:   local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
                   3341: 
                   3342:   rl_forced_update_display ();
                   3343: 
                   3344:   rl_display_prompt = oldp;
                   3345:   rl_restore_prompt();
                   3346: }
                   3347:       
                   3348: /* Redisplay the current line after a SIGWINCH is received. */
                   3349: void
1.1.1.3 ! misho    3350: _rl_redisplay_after_sigwinch (void)
1.1       misho    3351: {
                   3352:   char *t;
                   3353: 
                   3354:   /* Clear the last line (assuming that the screen size change will result in
                   3355:      either more or fewer characters on that line only) and put the cursor at
                   3356:      column 0.  Make sure the right thing happens if we have wrapped to a new
                   3357:      screen line. */
                   3358:   if (_rl_term_cr)
                   3359:     {
                   3360:       _rl_move_vert (_rl_vis_botlin);
                   3361: 
1.1.1.3 ! misho    3362:       _rl_cr ();
1.1       misho    3363:       _rl_last_c_pos = 0;
1.1.1.3 ! misho    3364: 
        !          3365: #if !defined (__MSDOS__)
1.1       misho    3366:       if (_rl_term_clreol)
                   3367:        tputs (_rl_term_clreol, 1, _rl_output_character_function);
                   3368:       else
1.1.1.3 ! misho    3369: #endif
1.1       misho    3370:        {
                   3371:          space_to_eol (_rl_screenwidth);
1.1.1.3 ! misho    3372:          _rl_cr ();
1.1       misho    3373:        }
1.1.1.3 ! misho    3374: 
1.1       misho    3375:       if (_rl_last_v_pos > 0)
                   3376:        _rl_move_vert (0);
                   3377:     }
                   3378:   else
                   3379:     rl_crlf ();
                   3380: 
                   3381:   /* Redraw only the last line of a multi-line prompt. */
                   3382:   t = strrchr (rl_display_prompt, '\n');
                   3383:   if (t)
                   3384:     redraw_prompt (++t);
                   3385:   else
                   3386:     rl_forced_update_display ();
                   3387: }
                   3388: 
                   3389: void
1.1.1.3 ! misho    3390: _rl_clean_up_for_exit (void)
1.1       misho    3391: {
                   3392:   if (_rl_echoing_p)
                   3393:     {
1.1.1.2   misho    3394:       if (_rl_vis_botlin > 0)  /* minor optimization plus bug fix */
                   3395:        _rl_move_vert (_rl_vis_botlin);
1.1       misho    3396:       _rl_vis_botlin = 0;
                   3397:       fflush (rl_outstream);
                   3398:       rl_restart_output (1, 0);
                   3399:     }
                   3400: }
                   3401: 
                   3402: void
1.1.1.3 ! misho    3403: _rl_erase_entire_line (void)
1.1       misho    3404: {
                   3405:   cr ();
                   3406:   _rl_clear_to_eol (0);
                   3407:   cr ();
                   3408:   fflush (rl_outstream);
                   3409: }
                   3410: 
1.1.1.3 ! misho    3411: void
        !          3412: _rl_ttyflush (void)
        !          3413: {
        !          3414:   fflush (rl_outstream);
        !          3415: }
        !          3416: 
1.1       misho    3417: /* return the `current display line' of the cursor -- the number of lines to
                   3418:    move up to get to the first screen line of the current readline line. */
                   3419: int
1.1.1.3 ! misho    3420: _rl_current_display_line (void)
1.1       misho    3421: {
                   3422:   int ret, nleft;
                   3423: 
                   3424:   /* Find out whether or not there might be invisible characters in the
                   3425:      editing buffer. */
                   3426:   if (rl_display_prompt == rl_prompt)
                   3427:     nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length;
                   3428:   else
                   3429:     nleft = _rl_last_c_pos - _rl_screenwidth;
                   3430: 
                   3431:   if (nleft > 0)
                   3432:     ret = 1 + nleft / _rl_screenwidth;
                   3433:   else
                   3434:     ret = 0;
                   3435: 
                   3436:   return ret;
                   3437: }
                   3438: 
1.1.1.3 ! misho    3439: void
        !          3440: _rl_refresh_line (void)
        !          3441: {
        !          3442:   rl_clear_visible_line ();
        !          3443:   rl_redraw_prompt_last_line ();
        !          3444:   rl_keep_mark_active ();
        !          3445: }
        !          3446: 
1.1       misho    3447: #if defined (HANDLE_MULTIBYTE)
                   3448: /* Calculate the number of screen columns occupied by STR from START to END.
                   3449:    In the case of multibyte characters with stateful encoding, we have to
                   3450:    scan from the beginning of the string to take the state into account. */
                   3451: static int
1.1.1.3 ! misho    3452: _rl_col_width (const char *str, int start, int end, int flags)
1.1       misho    3453: {
                   3454:   wchar_t wc;
                   3455:   mbstate_t ps;
                   3456:   int tmp, point, width, max;
                   3457: 
                   3458:   if (end <= start)
                   3459:     return 0;
                   3460:   if (MB_CUR_MAX == 1 || rl_byte_oriented)
                   3461:     /* this can happen in some cases where it's inconvenient to check */
                   3462:     return (end - start);
                   3463: 
                   3464:   memset (&ps, 0, sizeof (mbstate_t));
                   3465: 
                   3466:   point = 0;
                   3467:   max = end;
                   3468: 
                   3469:   /* Try to short-circuit common cases.  The adjustment to remove wrap_offset
                   3470:      is done by the caller. */
                   3471:   /* 1.  prompt string */
                   3472:   if (flags && start == 0 && end == local_prompt_len && memcmp (str, local_prompt, local_prompt_len) == 0)
                   3473:     return (prompt_physical_chars + wrap_offset);
                   3474:   /* 2.  prompt string + line contents */
                   3475:   else if (flags && start == 0 && local_prompt_len > 0 && end > local_prompt_len && local_prompt && memcmp (str, local_prompt, local_prompt_len) == 0)
                   3476:     {
                   3477:       tmp = prompt_physical_chars + wrap_offset;
                   3478:       /* XXX - try to call ourselves recursively with non-prompt portion */
                   3479:       tmp += _rl_col_width (str, local_prompt_len, end, flags);
                   3480:       return (tmp);
                   3481:     }
                   3482: 
                   3483:   while (point < start)
                   3484:     {
1.1.1.3 ! misho    3485:       if (_rl_utf8locale && UTF8_SINGLEBYTE(str[point]))
        !          3486:        {
        !          3487:          memset (&ps, 0, sizeof (mbstate_t));
        !          3488:          tmp = 1;
        !          3489:        }
        !          3490:       else
        !          3491:        tmp = mbrlen (str + point, max, &ps);
1.1       misho    3492:       if (MB_INVALIDCH ((size_t)tmp))
                   3493:        {
                   3494:          /* In this case, the bytes are invalid or too short to compose a
                   3495:             multibyte character, so we assume that the first byte represents
                   3496:             a single character. */
                   3497:          point++;
                   3498:          max--;
                   3499: 
                   3500:          /* Clear the state of the byte sequence, because in this case the
                   3501:             effect of mbstate is undefined. */
                   3502:          memset (&ps, 0, sizeof (mbstate_t));
                   3503:        }
                   3504:       else if (MB_NULLWCH (tmp))
                   3505:        break;          /* Found '\0' */
                   3506:       else
                   3507:        {
                   3508:          point += tmp;
                   3509:          max -= tmp;
                   3510:        }
                   3511:     }
                   3512: 
                   3513:   /* If START is not a byte that starts a character, then POINT will be
                   3514:      greater than START.  In this case, assume that (POINT - START) gives
                   3515:      a byte count that is the number of columns of difference. */
                   3516:   width = point - start;
                   3517: 
                   3518:   while (point < end)
                   3519:     {
1.1.1.3 ! misho    3520:       if (_rl_utf8locale && UTF8_SINGLEBYTE(str[point]))
        !          3521:        {
        !          3522:          tmp = 1;
        !          3523:          wc = (wchar_t) str[point];
        !          3524:        }
        !          3525:       else
        !          3526:        tmp = mbrtowc (&wc, str + point, max, &ps);
1.1       misho    3527:       if (MB_INVALIDCH ((size_t)tmp))
                   3528:        {
                   3529:          /* In this case, the bytes are invalid or too short to compose a
                   3530:             multibyte character, so we assume that the first byte represents
                   3531:             a single character. */
                   3532:          point++;
                   3533:          max--;
                   3534: 
                   3535:          /* and assume that the byte occupies a single column. */
                   3536:          width++;
                   3537: 
                   3538:          /* Clear the state of the byte sequence, because in this case the
                   3539:             effect of mbstate is undefined. */
                   3540:          memset (&ps, 0, sizeof (mbstate_t));
                   3541:        }
                   3542:       else if (MB_NULLWCH (tmp))
                   3543:        break;                  /* Found '\0' */
                   3544:       else
                   3545:        {
                   3546:          point += tmp;
                   3547:          max -= tmp;
                   3548:          tmp = WCWIDTH(wc);
                   3549:          width += (tmp >= 0) ? tmp : 1;
                   3550:        }
                   3551:     }
                   3552: 
                   3553:   width += point - end;
                   3554: 
                   3555:   return width;
                   3556: }
                   3557: #endif /* HANDLE_MULTIBYTE */

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