File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / readline / display.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jul 30 08:16:45 2014 UTC (9 years, 10 months ago) by misho
Branches: readline, MAIN
CVS tags: v6_3, p6, HEAD
readline 6.3

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

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