158314Sache/* $FreeBSD$ */
221308Sache/* display.c -- readline redisplay facility. */
321308Sache
4165675Sache/* Copyright (C) 1987-2006 Free Software Foundation, Inc.
521308Sache
621308Sache   This file is part of the GNU Readline Library, a library for
721308Sache   reading lines of text with interactive input and history editing.
821308Sache
921308Sache   The GNU Readline Library is free software; you can redistribute it
1021308Sache   and/or modify it under the terms of the GNU General Public License
1158314Sache   as published by the Free Software Foundation; either version 2, or
1221308Sache   (at your option) any later version.
1321308Sache
1421308Sache   The GNU Readline Library is distributed in the hope that it will be
1521308Sache   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
1621308Sache   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1721308Sache   GNU General Public License for more details.
1821308Sache
1921308Sache   The GNU General Public License is often shipped with GNU software, and
2021308Sache   is generally kept in a file called COPYING or LICENSE.  If you do not
2121308Sache   have a copy of the license, write to the Free Software Foundation,
2258314Sache   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
2321308Sache#define READLINE_LIBRARY
2421308Sache
2521308Sache#if defined (HAVE_CONFIG_H)
2621308Sache#  include <config.h>
2721308Sache#endif
2821308Sache
2921308Sache#include <sys/types.h>
3021308Sache
3121308Sache#if defined (HAVE_UNISTD_H)
3221308Sache#  include <unistd.h>
3321308Sache#endif /* HAVE_UNISTD_H */
3421308Sache
3526497Sache#include "posixstat.h"
3626497Sache
3721308Sache#if defined (HAVE_STDLIB_H)
3821308Sache#  include <stdlib.h>
3921308Sache#else
4021308Sache#  include "ansi_stdlib.h"
4121308Sache#endif /* HAVE_STDLIB_H */
4221308Sache
4326497Sache#include <stdio.h>
4421308Sache
4521308Sache/* System-specific feature definitions and include files. */
4621308Sache#include "rldefs.h"
47119614Sache#include "rlmbutil.h"
4821308Sache
4921308Sache/* Termcap library stuff. */
5021308Sache#include "tcap.h"
5121308Sache
5221308Sache/* Some standard library routines. */
5321308Sache#include "readline.h"
5421308Sache#include "history.h"
5521308Sache
5658314Sache#include "rlprivate.h"
5758314Sache#include "xmalloc.h"
5858314Sache
5921308Sache#if !defined (strchr) && !defined (__STDC__)
6021308Sacheextern char *strchr (), *strrchr ();
6121308Sache#endif /* !strchr && !__STDC__ */
6221308Sache
63119614Sachestatic void update_line PARAMS((char *, char *, int, int, int, int));
64119614Sachestatic void space_to_eol PARAMS((int));
65119614Sachestatic void delete_chars PARAMS((int));
66119614Sachestatic void insert_some_chars PARAMS((char *, int, int));
67119614Sachestatic void cr PARAMS((void));
6821308Sache
69119614Sache#if defined (HANDLE_MULTIBYTE)
70136759Speterstatic int _rl_col_width PARAMS((const char *, int, int));
71119614Sachestatic int *_rl_wrapped_line;
72119614Sache#else
73119614Sache#  define _rl_col_width(l, s, e)	(((e) <= (s)) ? 0 : (e) - (s))
74119614Sache#endif
75119614Sache
7621308Sachestatic int *inv_lbreaks, *vis_lbreaks;
7758314Sachestatic int inv_lbsize, vis_lbsize;
7821308Sache
7921308Sache/* Heuristic used to decide whether it is faster to move from CUR to NEW
80165675Sache   by backing up or outputting a carriage return and moving forward.  CUR
81165675Sache   and NEW are either both buffer positions or absolute screen positions. */
8221308Sache#define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new)))
8321308Sache
84165675Sache/* _rl_last_c_pos is an absolute cursor position in multibyte locales and a
85165675Sache   buffer index in others.  This macro is used when deciding whether the
86165675Sache   current cursor position is in the middle of a prompt string containing
87165675Sache   invisible characters. */
88165675Sache#define PROMPT_ENDING_INDEX \
89165675Sache  ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) ? prompt_physical_chars : prompt_last_invisible+1)
90165675Sache
91165675Sache
9221308Sache/* **************************************************************** */
9321308Sache/*								    */
9421308Sache/*			Display stuff				    */
9521308Sache/*								    */
9621308Sache/* **************************************************************** */
9721308Sache
9821308Sache/* This is the stuff that is hard for me.  I never seem to write good
9921308Sache   display routines in C.  Let's see how I do this time. */
10021308Sache
10121308Sache/* (PWP) Well... Good for a simple line updater, but totally ignores
10221308Sache   the problems of input lines longer than the screen width.
10321308Sache
10421308Sache   update_line and the code that calls it makes a multiple line,
10521308Sache   automatically wrapping line update.  Careful attention needs
10621308Sache   to be paid to the vertical position variables. */
10721308Sache
10821308Sache/* Keep two buffers; one which reflects the current contents of the
10921308Sache   screen, and the other to draw what we think the new contents should
11021308Sache   be.  Then compare the buffers, and make whatever changes to the
11121308Sache   screen itself that we should.  Finally, make the buffer that we
11221308Sache   just drew into be the one which reflects the current contents of the
11321308Sache   screen, and place the cursor where it belongs.
11421308Sache
11521308Sache   Commands that want to can fix the display themselves, and then let
11621308Sache   this function know that the display has been fixed by setting the
11721308Sache   RL_DISPLAY_FIXED variable.  This is good for efficiency. */
11821308Sache
11921308Sache/* Application-specific redisplay function. */
12075409Sacherl_voidfunc_t *rl_redisplay_function = rl_redisplay;
12121308Sache
12221308Sache/* Global variables declared here. */
12321308Sache/* What YOU turn on when you have handled all redisplay yourself. */
12421308Sacheint rl_display_fixed = 0;
12521308Sache
12621308Sacheint _rl_suppress_redisplay = 0;
127157188Sacheint _rl_want_redisplay = 0;
12821308Sache
12921308Sache/* The stuff that gets printed out before the actual text of the line.
13021308Sache   This is usually pointing to rl_prompt. */
13121308Sachechar *rl_display_prompt = (char *)NULL;
13221308Sache
13321308Sache/* Pseudo-global variables declared here. */
134157188Sache
13521308Sache/* The visible cursor position.  If you print some text, adjust this. */
136157188Sache/* NOTE: _rl_last_c_pos is used as a buffer index when not in a locale
137157188Sache   supporting multibyte characters, and an absolute cursor position when
138157188Sache   in such a locale.  This is an artifact of the donated multibyte support.
139157188Sache   Care must be taken when modifying its value. */
14021308Sacheint _rl_last_c_pos = 0;
14121308Sacheint _rl_last_v_pos = 0;
14221308Sache
143157188Sachestatic int cpos_adjusted;
144165675Sachestatic int cpos_buffer_position;
145157188Sache
14621308Sache/* Number of lines currently on screen minus 1. */
14721308Sacheint _rl_vis_botlin = 0;
14821308Sache
14921308Sache/* Variables used only in this file. */
15021308Sache/* The last left edge of text that was displayed.  This is used when
15121308Sache   doing horizontal scrolling.  It shifts in thirds of a screenwidth. */
15221308Sachestatic int last_lmargin;
15321308Sache
15421308Sache/* The line display buffers.  One is the line currently displayed on
15521308Sache   the screen.  The other is the line about to be displayed. */
15621308Sachestatic char *visible_line = (char *)NULL;
15721308Sachestatic char *invisible_line = (char *)NULL;
15821308Sache
15921308Sache/* A buffer for `modeline' messages. */
16021308Sachestatic char msg_buf[128];
16121308Sache
16221308Sache/* Non-zero forces the redisplay even if we thought it was unnecessary. */
16321308Sachestatic int forced_display;
16421308Sache
16521308Sache/* Default and initial buffer size.  Can grow. */
16621308Sachestatic int line_size = 1024;
16721308Sache
16875409Sache/* Variables to keep track of the expanded prompt string, which may
16975409Sache   include invisible characters. */
17075409Sache
17121308Sachestatic char *local_prompt, *local_prompt_prefix;
172165675Sachestatic int local_prompt_len;
17375409Sachestatic int prompt_visible_length, prompt_prefix_length;
17421308Sache
17521308Sache/* The number of invisible characters in the line currently being
17621308Sache   displayed on the screen. */
17721308Sachestatic int visible_wrap_offset;
17821308Sache
17975409Sache/* The number of invisible characters in the prompt string.  Static so it
18075409Sache   can be shared between rl_redisplay and update_line */
18121308Sachestatic int wrap_offset;
18221308Sache
18375409Sache/* The index of the last invisible character in the prompt string. */
18475409Sachestatic int prompt_last_invisible;
18521308Sache
18621308Sache/* The length (buffer offset) of the first line of the last (possibly
18721308Sache   multi-line) buffer displayed on the screen. */
18821308Sachestatic int visible_first_line_len;
18921308Sache
19075409Sache/* Number of invisible characters on the first physical line of the prompt.
19175409Sache   Only valid when the number of physical characters in the prompt exceeds
19275409Sache   (or is equal to) _rl_screenwidth. */
19375409Sachestatic int prompt_invis_chars_first_line;
19475409Sache
19575409Sachestatic int prompt_last_screen_line;
19675409Sache
197136759Speterstatic int prompt_physical_chars;
198136759Speter
199157188Sache/* Variables to save and restore prompt and display information. */
200157188Sache
201157188Sache/* These are getting numerous enough that it's time to create a struct. */
202157188Sache
203157188Sachestatic char *saved_local_prompt;
204157188Sachestatic char *saved_local_prefix;
205157188Sachestatic int saved_last_invisible;
206157188Sachestatic int saved_visible_length;
207157188Sachestatic int saved_prefix_length;
208165675Sachestatic int saved_local_length;
209157188Sachestatic int saved_invis_chars_first_line;
210157188Sachestatic int saved_physical_chars;
211157188Sache
21221308Sache/* Expand the prompt string S and return the number of visible
21321308Sache   characters in *LP, if LP is not null.  This is currently more-or-less
21421308Sache   a placeholder for expansion.  LIP, if non-null is a place to store the
21575409Sache   index of the last invisible character in the returned string. NIFLP,
21675409Sache   if non-zero, is a place to store the number of invisible characters in
217136759Speter   the first prompt line.  The previous are used as byte counts -- indexes
218136759Speter   into a character buffer. */
21921308Sache
22021308Sache/* Current implementation:
22121308Sache	\001 (^A) start non-visible characters
22221308Sache	\002 (^B) end non-visible characters
22321308Sache   all characters except \001 and \002 (following a \001) are copied to
22421308Sache   the returned string; all characters except those between \001 and
22521308Sache   \002 are assumed to be `visible'. */
22621308Sache
22721308Sachestatic char *
228136759Speterexpand_prompt (pmt, lp, lip, niflp, vlp)
22921308Sache     char *pmt;
230136759Speter     int *lp, *lip, *niflp, *vlp;
23121308Sache{
232165675Sache  char *r, *ret, *p, *igstart;
233136759Speter  int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars;
23421308Sache
23521308Sache  /* Short-circuit if we can. */
236136759Speter  if ((MB_CUR_MAX <= 1 || rl_byte_oriented) && strchr (pmt, RL_PROMPT_START_IGNORE) == 0)
23721308Sache    {
23821308Sache      r = savestring (pmt);
23921308Sache      if (lp)
24021308Sache	*lp = strlen (r);
241136759Speter      if (lip)
242136759Speter	*lip = 0;
243136759Speter      if (niflp)
244136759Speter	*niflp = 0;
245136759Speter      if (vlp)
246136759Speter	*vlp = lp ? *lp : strlen (r);
24721308Sache      return r;
24821308Sache    }
24921308Sache
25021308Sache  l = strlen (pmt);
251119614Sache  r = ret = (char *)xmalloc (l + 1);
25275409Sache
25375409Sache  invfl = 0;	/* invisible chars in first line of prompt */
254136759Speter  invflset = 0;	/* we only want to set invfl once */
25575409Sache
256165675Sache  igstart = 0;
257136759Speter  for (rl = ignoring = last = ninvis = physchars = 0, p = pmt; p && *p; p++)
25821308Sache    {
25921308Sache      /* This code strips the invisible character string markers
26021308Sache	 RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
261165675Sache      if (ignoring == 0 && *p == RL_PROMPT_START_IGNORE)		/* XXX - check ignoring? */
26221308Sache	{
263165675Sache	  ignoring = 1;
264165675Sache	  igstart = p;
26521308Sache	  continue;
26621308Sache	}
26721308Sache      else if (ignoring && *p == RL_PROMPT_END_IGNORE)
26821308Sache	{
26921308Sache	  ignoring = 0;
270165675Sache	  if (p != (igstart + 1))
271157188Sache	    last = r - ret - 1;
27221308Sache	  continue;
27321308Sache	}
27421308Sache      else
27521308Sache	{
276136759Speter#if defined (HANDLE_MULTIBYTE)
277136759Speter	  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
278136759Speter	    {
279136759Speter	      pind = p - pmt;
280136759Speter	      ind = _rl_find_next_mbchar (pmt, pind, 1, MB_FIND_NONZERO);
281136759Speter	      l = ind - pind;
282136759Speter	      while (l--)
283136759Speter	        *r++ = *p++;
284136759Speter	      if (!ignoring)
285136759Speter		{
286136759Speter		  rl += ind - pind;
287136759Speter		  physchars += _rl_col_width (pmt, pind, ind);
288136759Speter		}
289136759Speter	      else
290136759Speter		ninvis += ind - pind;
291136759Speter	      p--;			/* compensate for later increment */
292136759Speter	    }
29375409Sache	  else
294136759Speter#endif
295136759Speter	    {
296136759Speter	      *r++ = *p;
297136759Speter	      if (!ignoring)
298136759Speter		{
299136759Speter		  rl++;			/* visible length byte counter */
300136759Speter		  physchars++;
301136759Speter		}
302136759Speter	      else
303136759Speter		ninvis++;		/* invisible chars byte counter */
304136759Speter	    }
305136759Speter
306136759Speter	  if (invflset == 0 && rl >= _rl_screenwidth)
307136759Speter	    {
308136759Speter	      invfl = ninvis;
309136759Speter	      invflset = 1;
310136759Speter	    }
31121308Sache	}
31221308Sache    }
31321308Sache
31475409Sache  if (rl < _rl_screenwidth)
31575409Sache    invfl = ninvis;
31675409Sache
31721308Sache  *r = '\0';
31821308Sache  if (lp)
31921308Sache    *lp = rl;
32021308Sache  if (lip)
32121308Sache    *lip = last;
32275409Sache  if (niflp)
32375409Sache    *niflp = invfl;
324136759Speter  if  (vlp)
325136759Speter    *vlp = physchars;
32621308Sache  return ret;
32721308Sache}
32821308Sache
32958314Sache/* Just strip out RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE from
33058314Sache   PMT and return the rest of PMT. */
33158314Sachechar *
33258314Sache_rl_strip_prompt (pmt)
33358314Sache     char *pmt;
33458314Sache{
33558314Sache  char *ret;
33658314Sache
337136759Speter  ret = expand_prompt (pmt, (int *)NULL, (int *)NULL, (int *)NULL, (int *)NULL);
33858314Sache  return ret;
33958314Sache}
34058314Sache
34121308Sache/*
34221308Sache * Expand the prompt string into the various display components, if
34321308Sache * necessary.
34421308Sache *
34521308Sache * local_prompt = expanded last line of string in rl_display_prompt
34621308Sache *		  (portion after the final newline)
34721308Sache * local_prompt_prefix = portion before last newline of rl_display_prompt,
34821308Sache *			 expanded via expand_prompt
34975409Sache * prompt_visible_length = number of visible characters in local_prompt
35075409Sache * prompt_prefix_length = number of visible characters in local_prompt_prefix
35121308Sache *
35221308Sache * This function is called once per call to readline().  It may also be
35321308Sache * called arbitrarily to expand the primary prompt.
35421308Sache *
35521308Sache * The return value is the number of visible characters on the last line
35621308Sache * of the (possibly multi-line) prompt.
35721308Sache */
35821308Sacheint
35921308Sacherl_expand_prompt (prompt)
36021308Sache     char *prompt;
36121308Sache{
36221308Sache  char *p, *t;
36321308Sache  int c;
36421308Sache
36521308Sache  /* Clear out any saved values. */
36675409Sache  FREE (local_prompt);
36775409Sache  FREE (local_prompt_prefix);
36875409Sache
36921308Sache  local_prompt = local_prompt_prefix = (char *)0;
370165675Sache  local_prompt_len = 0;
371157188Sache  prompt_last_invisible = prompt_invis_chars_first_line = 0;
372157188Sache  prompt_visible_length = prompt_physical_chars = 0;
37321308Sache
37421308Sache  if (prompt == 0 || *prompt == 0)
37521308Sache    return (0);
37621308Sache
37721308Sache  p = strrchr (prompt, '\n');
37821308Sache  if (!p)
37921308Sache    {
38075409Sache      /* The prompt is only one logical line, though it might wrap. */
38175409Sache      local_prompt = expand_prompt (prompt, &prompt_visible_length,
38275409Sache					    &prompt_last_invisible,
383136759Speter					    &prompt_invis_chars_first_line,
384136759Speter					    &prompt_physical_chars);
38521308Sache      local_prompt_prefix = (char *)0;
386165675Sache      local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
38775409Sache      return (prompt_visible_length);
38821308Sache    }
38921308Sache  else
39021308Sache    {
39121308Sache      /* The prompt spans multiple lines. */
39221308Sache      t = ++p;
39375409Sache      local_prompt = expand_prompt (p, &prompt_visible_length,
39475409Sache				       &prompt_last_invisible,
395257586Ssbruno				       &prompt_invis_chars_first_line,
396136759Speter				       &prompt_physical_chars);
39721308Sache      c = *t; *t = '\0';
39821308Sache      /* The portion of the prompt string up to and including the
39921308Sache	 final newline is now null-terminated. */
40075409Sache      local_prompt_prefix = expand_prompt (prompt, &prompt_prefix_length,
40175409Sache						   (int *)NULL,
402257586Ssbruno						   (int *)NULL,
403136759Speter						   (int *)NULL);
40421308Sache      *t = c;
405165675Sache      local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
40675409Sache      return (prompt_prefix_length);
40721308Sache    }
40821308Sache}
40921308Sache
41058314Sache/* Initialize the VISIBLE_LINE and INVISIBLE_LINE arrays, and their associated
41158314Sache   arrays of line break markers.  MINSIZE is the minimum size of VISIBLE_LINE
41258314Sache   and INVISIBLE_LINE; if it is greater than LINE_SIZE, LINE_SIZE is
41358314Sache   increased.  If the lines have already been allocated, this ensures that
41458314Sache   they can hold at least MINSIZE characters. */
41558314Sachestatic void
41658314Sacheinit_line_structures (minsize)
41758314Sache      int minsize;
41858314Sache{
41958314Sache  register int n;
42058314Sache
42158314Sache  if (invisible_line == 0)	/* initialize it */
42258314Sache    {
42358314Sache      if (line_size < minsize)
42458314Sache	line_size = minsize;
425119614Sache      visible_line = (char *)xmalloc (line_size);
426119614Sache      invisible_line = (char *)xmalloc (line_size);
42758314Sache    }
42858314Sache  else if (line_size < minsize)	/* ensure it can hold MINSIZE chars */
42958314Sache    {
43058314Sache      line_size *= 2;
43158314Sache      if (line_size < minsize)
43258314Sache	line_size = minsize;
433119614Sache      visible_line = (char *)xrealloc (visible_line, line_size);
434119614Sache      invisible_line = (char *)xrealloc (invisible_line, line_size);
43558314Sache    }
43658314Sache
43758314Sache  for (n = minsize; n < line_size; n++)
43858314Sache    {
43958314Sache      visible_line[n] = 0;
44058314Sache      invisible_line[n] = 1;
44158314Sache    }
44258314Sache
44358314Sache  if (vis_lbreaks == 0)
44458314Sache    {
44558314Sache      /* should be enough. */
44658314Sache      inv_lbsize = vis_lbsize = 256;
44758314Sache      inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int));
44858314Sache      vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int));
449119614Sache#if defined (HANDLE_MULTIBYTE)
450119614Sache      _rl_wrapped_line = (int *)xmalloc (vis_lbsize * sizeof (int));
451119614Sache#endif
45258314Sache      inv_lbreaks[0] = vis_lbreaks[0] = 0;
45358314Sache    }
45458314Sache}
45558314Sache
45621308Sache/* Basic redisplay algorithm. */
45721308Sachevoid
45821308Sacherl_redisplay ()
45921308Sache{
46021308Sache  register int in, out, c, linenum, cursor_linenum;
46121308Sache  register char *line;
462165675Sache  int inv_botlin, lb_botlin, lb_linenum, o_cpos;
463136759Speter  int newlines, lpos, temp, modmark, n0, num;
46421308Sache  char *prompt_this_line;
465119614Sache#if defined (HANDLE_MULTIBYTE)
466119614Sache  wchar_t wc;
467119614Sache  size_t wc_bytes;
468119614Sache  int wc_width;
469119614Sache  mbstate_t ps;
470119614Sache  int _rl_wrapped_multicolumn = 0;
471119614Sache#endif
47221308Sache
47321308Sache  if (!readline_echoing_p)
47421308Sache    return;
47521308Sache
47621308Sache  if (!rl_display_prompt)
47721308Sache    rl_display_prompt = "";
47821308Sache
479157188Sache  if (invisible_line == 0 || vis_lbreaks == 0)
48021308Sache    {
48158314Sache      init_line_structures (0);
48221308Sache      rl_on_new_line ();
48321308Sache    }
48421308Sache
48521308Sache  /* Draw the line into the buffer. */
486165675Sache  cpos_buffer_position = -1;
48721308Sache
48821308Sache  line = invisible_line;
48921308Sache  out = inv_botlin = 0;
49021308Sache
49121308Sache  /* Mark the line as modified or not.  We only do this for history
49221308Sache     lines. */
493136759Speter  modmark = 0;
49421308Sache  if (_rl_mark_modified_lines && current_history () && rl_undo_list)
49521308Sache    {
49621308Sache      line[out++] = '*';
49721308Sache      line[out] = '\0';
498136759Speter      modmark = 1;
49921308Sache    }
50021308Sache
50121308Sache  /* If someone thought that the redisplay was handled, but the currently
50221308Sache     visible line has a different modification state than the one about
50321308Sache     to become visible, then correct the caller's misconception. */
50421308Sache  if (visible_line[0] != invisible_line[0])
50521308Sache    rl_display_fixed = 0;
50621308Sache
50721308Sache  /* If the prompt to be displayed is the `primary' readline prompt (the
50821308Sache     one passed to readline()), use the values we have already expanded.
50921308Sache     If not, use what's already in rl_display_prompt.  WRAP_OFFSET is the
51021308Sache     number of non-visible characters in the prompt string. */
51121308Sache  if (rl_display_prompt == rl_prompt || local_prompt)
51221308Sache    {
51321308Sache      if (local_prompt_prefix && forced_display)
51421308Sache	_rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix));
51521308Sache
516165675Sache      if (local_prompt_len > 0)
51721308Sache	{
518165675Sache	  temp = local_prompt_len + out + 2;
51947563Sache	  if (temp >= line_size)
52047563Sache	    {
52147563Sache	      line_size = (temp + 1024) - (temp % 1024);
522119614Sache	      visible_line = (char *)xrealloc (visible_line, line_size);
523119614Sache	      line = invisible_line = (char *)xrealloc (invisible_line, line_size);
52447563Sache	    }
525165675Sache	  strncpy (line + out, local_prompt, local_prompt_len);
526165675Sache	  out += local_prompt_len;
52721308Sache	}
52821308Sache      line[out] = '\0';
529165675Sache      wrap_offset = local_prompt_len - prompt_visible_length;
53021308Sache    }
53121308Sache  else
53221308Sache    {
53321308Sache      int pmtlen;
53421308Sache      prompt_this_line = strrchr (rl_display_prompt, '\n');
53521308Sache      if (!prompt_this_line)
53621308Sache	prompt_this_line = rl_display_prompt;
53721308Sache      else
53821308Sache	{
53921308Sache	  prompt_this_line++;
54058314Sache	  pmtlen = prompt_this_line - rl_display_prompt;	/* temp var */
54121308Sache	  if (forced_display)
54221308Sache	    {
54358314Sache	      _rl_output_some_chars (rl_display_prompt, pmtlen);
54421308Sache	      /* Make sure we are at column zero even after a newline,
54521308Sache		 regardless of the state of terminal output processing. */
54658314Sache	      if (pmtlen < 2 || prompt_this_line[-2] != '\r')
54721308Sache		cr ();
54821308Sache	    }
54921308Sache	}
55021308Sache
551136759Speter      prompt_physical_chars = pmtlen = strlen (prompt_this_line);
55247563Sache      temp = pmtlen + out + 2;
55347563Sache      if (temp >= line_size)
55447563Sache	{
55547563Sache	  line_size = (temp + 1024) - (temp % 1024);
556119614Sache	  visible_line = (char *)xrealloc (visible_line, line_size);
557119614Sache	  line = invisible_line = (char *)xrealloc (invisible_line, line_size);
55847563Sache	}
55921308Sache      strncpy (line + out,  prompt_this_line, pmtlen);
56021308Sache      out += pmtlen;
56121308Sache      line[out] = '\0';
56275409Sache      wrap_offset = prompt_invis_chars_first_line = 0;
56321308Sache    }
56421308Sache
565168666Sache#if defined (HANDLE_MULTIBYTE)
56658314Sache#define CHECK_INV_LBREAKS() \
56758314Sache      do { \
56858314Sache	if (newlines >= (inv_lbsize - 2)) \
56958314Sache	  { \
57058314Sache	    inv_lbsize *= 2; \
57158314Sache	    inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
572168666Sache	    _rl_wrapped_line = (int *)xrealloc (_rl_wrapped_line, inv_lbsize * sizeof (int)); \
57358314Sache	  } \
57458314Sache      } while (0)
575168666Sache#else
576168666Sache#define CHECK_INV_LBREAKS() \
577168666Sache      do { \
578168666Sache	if (newlines >= (inv_lbsize - 2)) \
579168666Sache	  { \
580168666Sache	    inv_lbsize *= 2; \
581168666Sache	    inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
582168666Sache	  } \
583168666Sache      } while (0)
584168666Sache#endif /* HANDLE_MULTIBYTE */
585119614Sache
586119614Sache#if defined (HANDLE_MULTIBYTE)
58721308Sache#define CHECK_LPOS() \
58821308Sache      do { \
58947563Sache	lpos++; \
59075409Sache	if (lpos >= _rl_screenwidth) \
59147563Sache	  { \
59258314Sache	    if (newlines >= (inv_lbsize - 2)) \
59358314Sache	      { \
59458314Sache		inv_lbsize *= 2; \
59558314Sache		inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
596119614Sache		_rl_wrapped_line = (int *)xrealloc (_rl_wrapped_line, inv_lbsize * sizeof (int)); \
59758314Sache	      } \
59847563Sache	    inv_lbreaks[++newlines] = out; \
599119614Sache	    _rl_wrapped_line[newlines] = _rl_wrapped_multicolumn; \
60047563Sache	    lpos = 0; \
60147563Sache	  } \
60221308Sache      } while (0)
603119614Sache#else
604119614Sache#define CHECK_LPOS() \
605119614Sache      do { \
606119614Sache	lpos++; \
607119614Sache	if (lpos >= _rl_screenwidth) \
608119614Sache	  { \
609119614Sache	    if (newlines >= (inv_lbsize - 2)) \
610119614Sache	      { \
611119614Sache		inv_lbsize *= 2; \
612119614Sache		inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
613119614Sache	      } \
614119614Sache	    inv_lbreaks[++newlines] = out; \
615119614Sache	    lpos = 0; \
616119614Sache	  } \
617119614Sache      } while (0)
618119614Sache#endif
61921308Sache
62021308Sache  /* inv_lbreaks[i] is where line i starts in the buffer. */
62121308Sache  inv_lbreaks[newlines = 0] = 0;
622136759Speter#if 0
62326497Sache  lpos = out - wrap_offset;
624136759Speter#else
625136759Speter  lpos = prompt_physical_chars + modmark;
626136759Speter#endif
627136759Speter
628119614Sache#if defined (HANDLE_MULTIBYTE)
629119614Sache  memset (_rl_wrapped_line, 0, vis_lbsize);
630136759Speter  num = 0;
631119614Sache#endif
63221308Sache
63375409Sache  /* prompt_invis_chars_first_line is the number of invisible characters in
63475409Sache     the first physical line of the prompt.
63575409Sache     wrap_offset - prompt_invis_chars_first_line is the number of invis
63675409Sache     chars on the second line. */
63775409Sache
63875409Sache  /* what if lpos is already >= _rl_screenwidth before we start drawing the
63926497Sache     contents of the command line? */
64075409Sache  while (lpos >= _rl_screenwidth)
64121308Sache    {
642165675Sache      int z;
64375409Sache      /* fix from Darin Johnson <darin@acuson.com> for prompt string with
64475409Sache         invisible characters that is longer than the screen width.  The
64575409Sache         prompt_invis_chars_first_line variable could be made into an array
64675409Sache         saying how many invisible characters there are per line, but that's
64775409Sache         probably too much work for the benefit gained.  How many people have
648136759Speter         prompts that exceed two physical lines?
649136759Speter         Additional logic fix from Edward Catmur <ed@catmur.co.uk> */
650136759Speter#if defined (HANDLE_MULTIBYTE)
651165675Sache      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
652136759Speter	{
653165675Sache	  n0 = num;
654165675Sache          temp = local_prompt_len;
655165675Sache          while (num < temp)
656136759Speter	    {
657165675Sache	      z = _rl_col_width  (local_prompt, n0, num);
658165675Sache	      if (z > _rl_screenwidth)
659165675Sache		{
660165675Sache	          num = _rl_find_prev_mbchar (local_prompt, num, MB_FIND_ANY);
661165675Sache	          break;
662165675Sache		}
663165675Sache	      else if (z == _rl_screenwidth)
664165675Sache	        break;
665165675Sache	      num++;
666136759Speter	    }
667165675Sache          temp = num;
668136759Speter	}
669165675Sache      else
670136759Speter#endif /* !HANDLE_MULTIBYTE */
671165675Sache	temp = ((newlines + 1) * _rl_screenwidth);
672165675Sache
673165675Sache      /* Now account for invisible characters in the current line. */
674165675Sache      temp += ((local_prompt_prefix == 0) ? ((newlines == 0) ? prompt_invis_chars_first_line
675165675Sache							     : ((newlines == 1) ? wrap_offset : 0))
676165675Sache					  : ((newlines == 0) ? wrap_offset :0));
677136759Speter
678136759Speter      inv_lbreaks[++newlines] = temp;
679136759Speter#if defined (HANDLE_MULTIBYTE)
680165675Sache      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
681165675Sache	lpos -= _rl_col_width (local_prompt, n0, num);
682165675Sache      else
683119614Sache#endif
684165675Sache	lpos -= _rl_screenwidth;
68526497Sache    }
68626497Sache
68775409Sache  prompt_last_screen_line = newlines;
68875409Sache
68975409Sache  /* Draw the rest of the line (after the prompt) into invisible_line, keeping
690165675Sache     track of where the cursor is (cpos_buffer_position), the number of the line containing
69175409Sache     the cursor (lb_linenum), the last line number (lb_botlin and inv_botlin).
69275409Sache     It maintains an array of line breaks for display (inv_lbreaks).
69375409Sache     This handles expanding tabs for display and displaying meta characters. */
69426497Sache  lb_linenum = 0;
695119614Sache#if defined (HANDLE_MULTIBYTE)
696119614Sache  in = 0;
697119614Sache  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
698119614Sache    {
699119614Sache      memset (&ps, 0, sizeof (mbstate_t));
700119614Sache      wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps);
701119614Sache    }
702119614Sache  else
703119614Sache    wc_bytes = 1;
704119614Sache  while (in < rl_end)
705119614Sache#else
70626497Sache  for (in = 0; in < rl_end; in++)
707119614Sache#endif
70826497Sache    {
70921308Sache      c = (unsigned char)rl_line_buffer[in];
71021308Sache
711119614Sache#if defined (HANDLE_MULTIBYTE)
712119614Sache      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
713119614Sache	{
714136759Speter	  if (MB_INVALIDCH (wc_bytes))
715119614Sache	    {
716119614Sache	      /* Byte sequence is invalid or shortened.  Assume that the
717119614Sache	         first byte represents a character. */
718119614Sache	      wc_bytes = 1;
719119614Sache	      /* Assume that a character occupies a single column. */
720119614Sache	      wc_width = 1;
721119614Sache	      memset (&ps, 0, sizeof (mbstate_t));
722119614Sache	    }
723136759Speter	  else if (MB_NULLWCH (wc_bytes))
724119614Sache	    break;			/* Found '\0' */
725119614Sache	  else
726119614Sache	    {
727119614Sache	      temp = wcwidth (wc);
728136759Speter	      wc_width = (temp >= 0) ? temp : 1;
729119614Sache	    }
730119614Sache	}
731119614Sache#endif
732119614Sache
73321308Sache      if (out + 8 >= line_size)		/* XXX - 8 for \t */
73421308Sache	{
73521308Sache	  line_size *= 2;
736119614Sache	  visible_line = (char *)xrealloc (visible_line, line_size);
737119614Sache	  invisible_line = (char *)xrealloc (invisible_line, line_size);
73821308Sache	  line = invisible_line;
73921308Sache	}
74021308Sache
74121308Sache      if (in == rl_point)
74221308Sache	{
743165675Sache	  cpos_buffer_position = out;
74421308Sache	  lb_linenum = newlines;
74521308Sache	}
74621308Sache
747119614Sache#if defined (HANDLE_MULTIBYTE)
748119614Sache      if (META_CHAR (c) && _rl_output_meta_chars == 0)	/* XXX - clean up */
749119614Sache#else
75021308Sache      if (META_CHAR (c))
751119614Sache#endif
75221308Sache	{
75321308Sache	  if (_rl_output_meta_chars == 0)
75421308Sache	    {
75521308Sache	      sprintf (line + out, "\\%o", c);
75621308Sache
75775409Sache	      if (lpos + 4 >= _rl_screenwidth)
75821308Sache		{
75975409Sache		  temp = _rl_screenwidth - lpos;
76058314Sache		  CHECK_INV_LBREAKS ();
76121308Sache		  inv_lbreaks[++newlines] = out + temp;
76221308Sache		  lpos = 4 - temp;
76321308Sache		}
76421308Sache	      else
76521308Sache		lpos += 4;
76621308Sache
76721308Sache	      out += 4;
76821308Sache	    }
76921308Sache	  else
77021308Sache	    {
77121308Sache	      line[out++] = c;
77221308Sache	      CHECK_LPOS();
77321308Sache	    }
77421308Sache	}
77521308Sache#if defined (DISPLAY_TABS)
77621308Sache      else if (c == '\t')
77721308Sache	{
77875409Sache	  register int newout;
77947563Sache
78047563Sache#if 0
78121308Sache	  newout = (out | (int)7) + 1;
78247563Sache#else
78347563Sache	  newout = out + 8 - lpos % 8;
78447563Sache#endif
78521308Sache	  temp = newout - out;
78675409Sache	  if (lpos + temp >= _rl_screenwidth)
78721308Sache	    {
78821308Sache	      register int temp2;
78975409Sache	      temp2 = _rl_screenwidth - lpos;
79058314Sache	      CHECK_INV_LBREAKS ();
79121308Sache	      inv_lbreaks[++newlines] = out + temp2;
79221308Sache	      lpos = temp - temp2;
79321308Sache	      while (out < newout)
79421308Sache		line[out++] = ' ';
79521308Sache	    }
79621308Sache	  else
79721308Sache	    {
79821308Sache	      while (out < newout)
79921308Sache		line[out++] = ' ';
80021308Sache	      lpos += temp;
80121308Sache	    }
80221308Sache	}
80321308Sache#endif
80475409Sache      else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
80547563Sache	{
80647563Sache	  line[out++] = '\0';	/* XXX - sentinel */
80758314Sache	  CHECK_INV_LBREAKS ();
80847563Sache	  inv_lbreaks[++newlines] = out;
80947563Sache	  lpos = 0;
81047563Sache	}
81121308Sache      else if (CTRL_CHAR (c) || c == RUBOUT)
81221308Sache	{
81321308Sache	  line[out++] = '^';
81421308Sache	  CHECK_LPOS();
81521308Sache	  line[out++] = CTRL_CHAR (c) ? UNCTRL (c) : '?';
81621308Sache	  CHECK_LPOS();
81721308Sache	}
81821308Sache      else
81921308Sache	{
820119614Sache#if defined (HANDLE_MULTIBYTE)
821119614Sache	  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
822119614Sache	    {
823119614Sache	      register int i;
824119614Sache
825119614Sache	      _rl_wrapped_multicolumn = 0;
826119614Sache
827119614Sache	      if (_rl_screenwidth < lpos + wc_width)
828119614Sache		for (i = lpos; i < _rl_screenwidth; i++)
829119614Sache		  {
830119614Sache		    /* The space will be removed in update_line() */
831119614Sache		    line[out++] = ' ';
832119614Sache		    _rl_wrapped_multicolumn++;
833119614Sache		    CHECK_LPOS();
834119614Sache		  }
835119614Sache	      if (in == rl_point)
836119614Sache		{
837165675Sache		  cpos_buffer_position = out;
838119614Sache		  lb_linenum = newlines;
839119614Sache		}
840119614Sache	      for (i = in; i < in+wc_bytes; i++)
841119614Sache		line[out++] = rl_line_buffer[i];
842119614Sache	      for (i = 0; i < wc_width; i++)
843119614Sache		CHECK_LPOS();
844119614Sache	    }
845119614Sache	  else
846119614Sache	    {
847119614Sache	      line[out++] = c;
848119614Sache	      CHECK_LPOS();
849119614Sache	    }
850119614Sache#else
85121308Sache	  line[out++] = c;
85221308Sache	  CHECK_LPOS();
853119614Sache#endif
85421308Sache	}
855119614Sache
856119614Sache#if defined (HANDLE_MULTIBYTE)
857119614Sache      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
858119614Sache	{
859119614Sache	  in += wc_bytes;
860119614Sache	  wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps);
861119614Sache	}
862119614Sache      else
863119614Sache        in++;
864119614Sache#endif
865119614Sache
86621308Sache    }
86721308Sache  line[out] = '\0';
868165675Sache  if (cpos_buffer_position < 0)
86921308Sache    {
870165675Sache      cpos_buffer_position = out;
87121308Sache      lb_linenum = newlines;
87221308Sache    }
87321308Sache
87421308Sache  inv_botlin = lb_botlin = newlines;
87558314Sache  CHECK_INV_LBREAKS ();
87621308Sache  inv_lbreaks[newlines+1] = out;
87721308Sache  cursor_linenum = lb_linenum;
87821308Sache
879165675Sache  /* CPOS_BUFFER_POSITION == position in buffer where cursor should be placed.
88075409Sache     CURSOR_LINENUM == line number where the cursor should be placed. */
88121308Sache
88221308Sache  /* PWP: now is when things get a bit hairy.  The visible and invisible
88321308Sache     line buffers are really multiple lines, which would wrap every
88421308Sache     (screenwidth - 1) characters.  Go through each in turn, finding
88521308Sache     the changed region and updating it.  The line order is top to bottom. */
88621308Sache
88721308Sache  /* If we can move the cursor up and down, then use multiple lines,
88821308Sache     otherwise, let long lines display in a single terminal line, and
88921308Sache     horizontally scroll it. */
89021308Sache
89175409Sache  if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
89221308Sache    {
893157188Sache      int nleft, pos, changed_screen_line, tx;
89421308Sache
89521308Sache      if (!rl_display_fixed || forced_display)
89621308Sache	{
89721308Sache	  forced_display = 0;
89821308Sache
89921308Sache	  /* If we have more than a screenful of material to display, then
90021308Sache	     only display a screenful.  We should display the last screen,
90121308Sache	     not the first.  */
90275409Sache	  if (out >= _rl_screenchars)
903119614Sache	    {
904119614Sache	      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
905119614Sache		out = _rl_find_prev_mbchar (line, _rl_screenchars, MB_FIND_ANY);
906119614Sache	      else
907119614Sache		out = _rl_screenchars - 1;
908119614Sache	    }
90921308Sache
91021308Sache	  /* The first line is at character position 0 in the buffer.  The
91121308Sache	     second and subsequent lines start at inv_lbreaks[N], offset by
91221308Sache	     OFFSET (which has already been calculated above).  */
91321308Sache
914257586Ssbruno#define INVIS_FIRST()	(prompt_physical_chars > _rl_screenwidth ? prompt_invis_chars_first_line : wrap_offset)
915257586Ssbruno#define WRAP_OFFSET(line, offset)  ((line == 0) \
916257586Ssbruno					? (offset ? INVIS_FIRST() : 0) \
917257586Ssbruno					: ((line == prompt_last_screen_line) ? wrap_offset-prompt_invis_chars_first_line : 0))
91821308Sache#define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
91921308Sache#define VIS_LLEN(l)	((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
92021308Sache#define INV_LLEN(l)	(inv_lbreaks[l+1] - inv_lbreaks[l])
92121308Sache#define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
92221308Sache#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
92321308Sache#define INV_LINE(line) (invisible_line + inv_lbreaks[line])
92421308Sache
92521308Sache	  /* For each line in the buffer, do the updating display. */
92621308Sache	  for (linenum = 0; linenum <= inv_botlin; linenum++)
92721308Sache	    {
928165675Sache	      /* This can lead us astray if we execute a program that changes
929165675Sache		 the locale from a non-multibyte to a multibyte one. */
930157188Sache	      o_cpos = _rl_last_c_pos;
931157188Sache	      cpos_adjusted = 0;
93221308Sache	      update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum,
93321308Sache			   VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin);
93421308Sache
935157188Sache	      /* update_line potentially changes _rl_last_c_pos, but doesn't
936157188Sache		 take invisible characters into account, since _rl_last_c_pos
937157188Sache		 is an absolute cursor position in a multibyte locale.  See
938157188Sache		 if compensating here is the right thing, or if we have to
939157188Sache		 change update_line itself.  There is one case in which
940157188Sache		 update_line adjusts _rl_last_c_pos itself (so it can pass
941157188Sache		 _rl_move_cursor_relative accurate values); it communicates
942165675Sache		 this back by setting cpos_adjusted.  If we assume that
943165675Sache		 _rl_last_c_pos is correct (an absolute cursor position) each
944165675Sache		 time update_line is called, then we can assume in our
945165675Sache		 calculations that o_cpos does not need to be adjusted by
946165675Sache		 wrap_offset. */
947157188Sache	      if (linenum == 0 && (MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
948157188Sache		  cpos_adjusted == 0 &&
949157188Sache		  _rl_last_c_pos != o_cpos &&
950157188Sache		  _rl_last_c_pos > wrap_offset &&
951157188Sache		  o_cpos < prompt_last_invisible)
952257586Ssbruno		_rl_last_c_pos -= prompt_invis_chars_first_line;	/* XXX - was wrap_offset */
953257586Ssbruno	      else if (linenum == prompt_last_screen_line && prompt_physical_chars > _rl_screenwidth &&
954257586Ssbruno			(MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
955257586Ssbruno			cpos_adjusted == 0 &&
956257586Ssbruno			_rl_last_c_pos != o_cpos &&
957257586Ssbruno			_rl_last_c_pos > (prompt_last_invisible - _rl_screenwidth - prompt_invis_chars_first_line))
958257586Ssbruno		_rl_last_c_pos -= (wrap_offset-prompt_invis_chars_first_line);
959157188Sache
96021308Sache	      /* If this is the line with the prompt, we might need to
96121308Sache		 compensate for invisible characters in the new line. Do
96221308Sache		 this only if there is not more than one new line (which
96321308Sache		 implies that we completely overwrite the old visible line)
96421308Sache		 and the new line is shorter than the old.  Make sure we are
96521308Sache		 at the end of the new line before clearing. */
96621308Sache	      if (linenum == 0 &&
96721308Sache		  inv_botlin == 0 && _rl_last_c_pos == out &&
96821308Sache		  (wrap_offset > visible_wrap_offset) &&
96921308Sache		  (_rl_last_c_pos < visible_first_line_len))
97021308Sache		{
971157188Sache		  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
972157188Sache		    nleft = _rl_screenwidth - _rl_last_c_pos;
973157188Sache		  else
974157188Sache		    nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos;
97521308Sache		  if (nleft)
97626497Sache		    _rl_clear_to_eol (nleft);
97721308Sache		}
97821308Sache
97921308Sache	      /* Since the new first line is now visible, save its length. */
98021308Sache	      if (linenum == 0)
98121308Sache		visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset;
98221308Sache	    }
98321308Sache
98421308Sache	  /* We may have deleted some lines.  If so, clear the left over
98521308Sache	     blank ones at the bottom out. */
98621308Sache	  if (_rl_vis_botlin > inv_botlin)
98721308Sache	    {
98821308Sache	      char *tt;
98921308Sache	      for (; linenum <= _rl_vis_botlin; linenum++)
99021308Sache		{
99121308Sache		  tt = VIS_CHARS (linenum);
99221308Sache		  _rl_move_vert (linenum);
99321308Sache		  _rl_move_cursor_relative (0, tt);
99426497Sache		  _rl_clear_to_eol
99575409Sache		    ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth);
99621308Sache		}
99721308Sache	    }
99821308Sache	  _rl_vis_botlin = inv_botlin;
99921308Sache
100021308Sache	  /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
100121308Sache	     different screen line during this redisplay. */
100221308Sache	  changed_screen_line = _rl_last_v_pos != cursor_linenum;
100321308Sache	  if (changed_screen_line)
100421308Sache	    {
100521308Sache	      _rl_move_vert (cursor_linenum);
100675409Sache	      /* If we moved up to the line with the prompt using _rl_term_up,
100747563Sache		 the physical cursor position on the screen stays the same,
100847563Sache		 but the buffer position needs to be adjusted to account
100947563Sache		 for invisible characters. */
1010157188Sache	      if ((MB_CUR_MAX == 1 || rl_byte_oriented) && cursor_linenum == 0 && wrap_offset)
101147563Sache		_rl_last_c_pos += wrap_offset;
101221308Sache	    }
101321308Sache
101421308Sache	  /* We have to reprint the prompt if it contains invisible
101521308Sache	     characters, since it's not generally OK to just reprint
101621308Sache	     the characters from the current cursor position.  But we
101721308Sache	     only need to reprint it if the cursor is before the last
101821308Sache	     invisible character in the prompt string. */
101975409Sache	  nleft = prompt_visible_length + wrap_offset;
102021308Sache	  if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
1021165675Sache#if 0
1022165675Sache	      _rl_last_c_pos <= PROMPT_ENDING_INDEX && local_prompt)
1023165675Sache#else
1024165675Sache	      _rl_last_c_pos < PROMPT_ENDING_INDEX && local_prompt)
1025165675Sache#endif
102621308Sache	    {
102758314Sache#if defined (__MSDOS__)
102858314Sache	      putc ('\r', rl_outstream);
102958314Sache#else
103075409Sache	      if (_rl_term_cr)
103175409Sache		tputs (_rl_term_cr, 1, _rl_output_character_function);
103258314Sache#endif
103321308Sache	      _rl_output_some_chars (local_prompt, nleft);
1034119614Sache	      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1035157188Sache		_rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft) - wrap_offset;
1036119614Sache	      else
1037119614Sache		_rl_last_c_pos = nleft;
103821308Sache	    }
103921308Sache
104021308Sache	  /* Where on that line?  And where does that line start
104121308Sache	     in the buffer? */
104221308Sache	  pos = inv_lbreaks[cursor_linenum];
104321308Sache	  /* nleft == number of characters in the line buffer between the
1044165675Sache	     start of the line and the desired cursor position. */
1045165675Sache	  nleft = cpos_buffer_position - pos;
104621308Sache
1047157188Sache	  /* NLEFT is now a number of characters in a buffer.  When in a
1048157188Sache	     multibyte locale, however, _rl_last_c_pos is an absolute cursor
1049157188Sache	     position that doesn't take invisible characters in the prompt
1050157188Sache	     into account.  We use a fudge factor to compensate. */
1051157188Sache
105221308Sache	  /* Since _rl_backspace() doesn't know about invisible characters in the
105321308Sache	     prompt, and there's no good way to tell it, we compensate for
105421308Sache	     those characters here and call _rl_backspace() directly. */
105521308Sache	  if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
105621308Sache	    {
1057165675Sache	      /* TX == new physical cursor position in multibyte locale. */
1058119614Sache	      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1059157188Sache		tx = _rl_col_width (&visible_line[pos], 0, nleft) - visible_wrap_offset;
1060119614Sache	      else
1061157188Sache		tx = nleft;
1062257586Ssbruno	      if (tx >= 0 && _rl_last_c_pos > tx)
1063157188Sache		{
1064157188Sache	          _rl_backspace (_rl_last_c_pos - tx);	/* XXX */
1065157188Sache	          _rl_last_c_pos = tx;
1066157188Sache		}
106721308Sache	    }
106821308Sache
1069157188Sache	  /* We need to note that in a multibyte locale we are dealing with
1070157188Sache	     _rl_last_c_pos as an absolute cursor position, but moving to a
1071157188Sache	     point specified by a buffer position (NLEFT) that doesn't take
1072157188Sache	     invisible characters into account. */
1073119614Sache	  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
107421308Sache	    _rl_move_cursor_relative (nleft, &invisible_line[pos]);
1075119614Sache	  else if (nleft != _rl_last_c_pos)
1076119614Sache	    _rl_move_cursor_relative (nleft, &invisible_line[pos]);
107721308Sache	}
107821308Sache    }
107921308Sache  else				/* Do horizontal scrolling. */
108021308Sache    {
108121308Sache#define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
108221308Sache      int lmargin, ndisp, nleft, phys_c_pos, t;
108321308Sache
108421308Sache      /* Always at top line. */
108521308Sache      _rl_last_v_pos = 0;
108621308Sache
108721308Sache      /* Compute where in the buffer the displayed line should start.  This
108821308Sache	 will be LMARGIN. */
108921308Sache
109021308Sache      /* The number of characters that will be displayed before the cursor. */
1091165675Sache      ndisp = cpos_buffer_position - wrap_offset;
109275409Sache      nleft  = prompt_visible_length + wrap_offset;
109321308Sache      /* Where the new cursor position will be on the screen.  This can be
109447563Sache	 longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
1095165675Sache      phys_c_pos = cpos_buffer_position - (last_lmargin ? last_lmargin : wrap_offset);
109675409Sache      t = _rl_screenwidth / 3;
109721308Sache
109821308Sache      /* If the number of characters had already exceeded the screenwidth,
109947563Sache	 last_lmargin will be > 0. */
110021308Sache
110121308Sache      /* If the number of characters to be displayed is more than the screen
110247563Sache	 width, compute the starting offset so that the cursor is about
110347563Sache	 two-thirds of the way across the screen. */
110475409Sache      if (phys_c_pos > _rl_screenwidth - 2)
110521308Sache	{
1106165675Sache	  lmargin = cpos_buffer_position - (2 * t);
110721308Sache	  if (lmargin < 0)
110821308Sache	    lmargin = 0;
110921308Sache	  /* If the left margin would be in the middle of a prompt with
111021308Sache	     invisible characters, don't display the prompt at all. */
111121308Sache	  if (wrap_offset && lmargin > 0 && lmargin < nleft)
111221308Sache	    lmargin = nleft;
111321308Sache	}
111475409Sache      else if (ndisp < _rl_screenwidth - 2)		/* XXX - was -1 */
111547563Sache	lmargin = 0;
111621308Sache      else if (phys_c_pos < 1)
111721308Sache	{
111821308Sache	  /* If we are moving back towards the beginning of the line and
111921308Sache	     the last margin is no longer correct, compute a new one. */
1120165675Sache	  lmargin = ((cpos_buffer_position - 1) / t) * t;	/* XXX */
112121308Sache	  if (wrap_offset && lmargin > 0 && lmargin < nleft)
112221308Sache	    lmargin = nleft;
112321308Sache	}
112421308Sache      else
112547563Sache	lmargin = last_lmargin;
112621308Sache
112721308Sache      /* If the first character on the screen isn't the first character
112821308Sache	 in the display line, indicate this with a special character. */
112921308Sache      if (lmargin > 0)
113021308Sache	line[lmargin] = '<';
113121308Sache
113221308Sache      /* If SCREENWIDTH characters starting at LMARGIN do not encompass
113347563Sache	 the whole line, indicate that with a special character at the
113447563Sache	 right edge of the screen.  If LMARGIN is 0, we need to take the
113547563Sache	 wrap offset into account. */
113675409Sache      t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth;
113721308Sache      if (t < out)
113847563Sache	line[t - 1] = '>';
113921308Sache
114021308Sache      if (!rl_display_fixed || forced_display || lmargin != last_lmargin)
114121308Sache	{
114221308Sache	  forced_display = 0;
114321308Sache	  update_line (&visible_line[last_lmargin],
114421308Sache		       &invisible_line[lmargin],
114521308Sache		       0,
114675409Sache		       _rl_screenwidth + visible_wrap_offset,
114775409Sache		       _rl_screenwidth + (lmargin ? 0 : wrap_offset),
114821308Sache		       0);
114921308Sache
115021308Sache	  /* If the visible new line is shorter than the old, but the number
115121308Sache	     of invisible characters is greater, and we are at the end of
115221308Sache	     the new line, we need to clear to eol. */
115321308Sache	  t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
115421308Sache	  if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
115521308Sache	      (_rl_last_c_pos == out) &&
115621308Sache	      t < visible_first_line_len)
115721308Sache	    {
115875409Sache	      nleft = _rl_screenwidth - t;
115926497Sache	      _rl_clear_to_eol (nleft);
116021308Sache	    }
116121308Sache	  visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
116275409Sache	  if (visible_first_line_len > _rl_screenwidth)
116375409Sache	    visible_first_line_len = _rl_screenwidth;
116421308Sache
1165165675Sache	  _rl_move_cursor_relative (cpos_buffer_position - lmargin, &invisible_line[lmargin]);
116621308Sache	  last_lmargin = lmargin;
116721308Sache	}
116821308Sache    }
116921308Sache  fflush (rl_outstream);
117021308Sache
117121308Sache  /* Swap visible and non-visible lines. */
117221308Sache  {
117375409Sache    char *vtemp = visible_line;
117458314Sache    int *itemp = vis_lbreaks, ntemp = vis_lbsize;
117558314Sache
117621308Sache    visible_line = invisible_line;
117775409Sache    invisible_line = vtemp;
117858314Sache
117921308Sache    vis_lbreaks = inv_lbreaks;
118021308Sache    inv_lbreaks = itemp;
118158314Sache
118258314Sache    vis_lbsize = inv_lbsize;
118358314Sache    inv_lbsize = ntemp;
118458314Sache
118521308Sache    rl_display_fixed = 0;
118621308Sache    /* If we are displaying on a single line, and last_lmargin is > 0, we
118721308Sache       are not displaying any invisible characters, so set visible_wrap_offset
118821308Sache       to 0. */
118921308Sache    if (_rl_horizontal_scroll_mode && last_lmargin)
119021308Sache      visible_wrap_offset = 0;
119121308Sache    else
119221308Sache      visible_wrap_offset = wrap_offset;
119321308Sache  }
119421308Sache}
119521308Sache
119621308Sache/* PWP: update_line() is based on finding the middle difference of each
119721308Sache   line on the screen; vis:
119821308Sache
119921308Sache			     /old first difference
120021308Sache	/beginning of line   |	      /old last same       /old EOL
120121308Sache	v		     v	      v		    v
120221308Sacheold:	eddie> Oh, my little gruntle-buggy is to me, as lurgid as
120321308Sachenew:	eddie> Oh, my little buggy says to me, as lurgid as
120421308Sache	^		     ^	^			   ^
120521308Sache	\beginning of line   |	\new last same	   \new end of line
120621308Sache			     \new first difference
120721308Sache
120821308Sache   All are character pointers for the sake of speed.  Special cases for
120947563Sache   no differences, as well as for end of line additions must be handled.
121021308Sache
121121308Sache   Could be made even smarter, but this works well enough */
121221308Sachestatic void
121321308Sacheupdate_line (old, new, current_line, omax, nmax, inv_botlin)
121421308Sache     register char *old, *new;
121521308Sache     int current_line, omax, nmax, inv_botlin;
121621308Sache{
121721308Sache  register char *ofd, *ols, *oe, *nfd, *nls, *ne;
1218257586Ssbruno  int temp, lendiff, wsatend, od, nd, twidth, o_cpos;
121921308Sache  int current_invis_chars;
1220119614Sache  int col_lendiff, col_temp;
1221119614Sache#if defined (HANDLE_MULTIBYTE)
1222119614Sache  mbstate_t ps_new, ps_old;
1223165675Sache  int new_offset, old_offset;
1224119614Sache#endif
122521308Sache
122621308Sache  /* If we're at the right edge of a terminal that supports xn, we're
122721308Sache     ready to wrap around, so do so.  This fixes problems with knowing
122821308Sache     the exact cursor position and cut-and-paste with certain terminal
122921308Sache     emulators.  In this calculation, TEMP is the physical screen
123021308Sache     position of the cursor. */
1231157188Sache  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1232157188Sache    temp = _rl_last_c_pos;
1233157188Sache  else
1234257586Ssbruno    temp = _rl_last_c_pos - WRAP_OFFSET (_rl_last_v_pos, visible_wrap_offset);
123575409Sache  if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
1236119614Sache	&& _rl_last_v_pos == current_line - 1)
123721308Sache    {
1238119614Sache#if defined (HANDLE_MULTIBYTE)
1239119614Sache      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1240119614Sache	{
1241119614Sache	  wchar_t wc;
1242119614Sache	  mbstate_t ps;
1243119614Sache	  int tempwidth, bytes;
1244119614Sache	  size_t ret;
1245119614Sache
1246119614Sache	  /* This fixes only double-column characters, but if the wrapped
1247119614Sache	     character comsumes more than three columns, spaces will be
1248119614Sache	     inserted in the string buffer. */
1249119614Sache	  if (_rl_wrapped_line[current_line] > 0)
1250119614Sache	    _rl_clear_to_eol (_rl_wrapped_line[current_line]);
1251119614Sache
1252119614Sache	  memset (&ps, 0, sizeof (mbstate_t));
1253119614Sache	  ret = mbrtowc (&wc, new, MB_CUR_MAX, &ps);
1254136759Speter	  if (MB_INVALIDCH (ret))
1255119614Sache	    {
1256119614Sache	      tempwidth = 1;
1257119614Sache	      ret = 1;
1258119614Sache	    }
1259136759Speter	  else if (MB_NULLWCH (ret))
1260119614Sache	    tempwidth = 0;
1261119614Sache	  else
1262119614Sache	    tempwidth = wcwidth (wc);
1263119614Sache
1264119614Sache	  if (tempwidth > 0)
1265119614Sache	    {
1266119614Sache	      int count;
1267119614Sache	      bytes = ret;
1268119614Sache	      for (count = 0; count < bytes; count++)
1269119614Sache		putc (new[count], rl_outstream);
1270119614Sache	      _rl_last_c_pos = tempwidth;
1271119614Sache	      _rl_last_v_pos++;
1272119614Sache	      memset (&ps, 0, sizeof (mbstate_t));
1273119614Sache	      ret = mbrtowc (&wc, old, MB_CUR_MAX, &ps);
1274119614Sache	      if (ret != 0 && bytes != 0)
1275119614Sache		{
1276136759Speter		  if (MB_INVALIDCH (ret))
1277119614Sache		    memmove (old+bytes, old+1, strlen (old+1));
1278119614Sache		  else
1279119614Sache		    memmove (old+bytes, old+ret, strlen (old+ret));
1280119614Sache		  memcpy (old, new, bytes);
1281119614Sache		}
1282119614Sache	    }
1283119614Sache	  else
1284119614Sache	    {
1285119614Sache	      putc (' ', rl_outstream);
1286119614Sache	      _rl_last_c_pos = 1;
1287119614Sache	      _rl_last_v_pos++;
1288119614Sache	      if (old[0] && new[0])
1289119614Sache		old[0] = new[0];
1290119614Sache	    }
1291119614Sache	}
129221308Sache      else
1293119614Sache#endif
1294119614Sache	{
1295119614Sache	  if (new[0])
1296119614Sache	    putc (new[0], rl_outstream);
1297119614Sache	  else
1298119614Sache	    putc (' ', rl_outstream);
1299157188Sache	  _rl_last_c_pos = 1;
1300119614Sache	  _rl_last_v_pos++;
1301119614Sache	  if (old[0] && new[0])
1302119614Sache	    old[0] = new[0];
1303119614Sache	}
130421308Sache    }
1305119614Sache
130621308Sache
130721308Sache  /* Find first difference. */
1308119614Sache#if defined (HANDLE_MULTIBYTE)
1309119614Sache  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1310119614Sache    {
1311136759Speter      /* See if the old line is a subset of the new line, so that the
1312136759Speter	 only change is adding characters. */
1313136759Speter      temp = (omax < nmax) ? omax : nmax;
1314136759Speter      if (memcmp (old, new, temp) == 0)
1315119614Sache	{
1316136759Speter	  ofd = old + temp;
1317136759Speter	  nfd = new + temp;
1318119614Sache	}
1319136759Speter      else
1320136759Speter	{
1321136759Speter	  memset (&ps_new, 0, sizeof(mbstate_t));
1322136759Speter	  memset (&ps_old, 0, sizeof(mbstate_t));
1323136759Speter
1324136759Speter	  if (omax == nmax && STREQN (new, old, omax))
1325136759Speter	    {
1326136759Speter	      ofd = old + omax;
1327136759Speter	      nfd = new + nmax;
1328136759Speter	    }
1329136759Speter	  else
1330136759Speter	    {
1331136759Speter	      new_offset = old_offset = 0;
1332136759Speter	      for (ofd = old, nfd = new;
1333136759Speter		    (ofd - old < omax) && *ofd &&
1334136759Speter		    _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new); )
1335136759Speter		{
1336136759Speter		  old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY);
1337136759Speter		  new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY);
1338136759Speter		  ofd = old + old_offset;
1339136759Speter		  nfd = new + new_offset;
1340136759Speter		}
1341136759Speter	    }
1342136759Speter	}
1343119614Sache    }
1344119614Sache  else
1345119614Sache#endif
134621308Sache  for (ofd = old, nfd = new;
134721308Sache       (ofd - old < omax) && *ofd && (*ofd == *nfd);
134821308Sache       ofd++, nfd++)
134921308Sache    ;
135021308Sache
135121308Sache  /* Move to the end of the screen line.  ND and OD are used to keep track
135221308Sache     of the distance between ne and new and oe and old, respectively, to
135321308Sache     move a subtraction out of each loop. */
135421308Sache  for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
135521308Sache  for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
135621308Sache
135721308Sache  /* If no difference, continue to next line. */
135821308Sache  if (ofd == oe && nfd == ne)
135921308Sache    return;
136021308Sache
136121308Sache  wsatend = 1;			/* flag for trailing whitespace */
1362119614Sache
1363119614Sache#if defined (HANDLE_MULTIBYTE)
1364119614Sache  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1365119614Sache    {
1366119614Sache      ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY);
1367119614Sache      nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY);
1368119614Sache      while ((ols > ofd) && (nls > nfd))
1369119614Sache	{
1370119614Sache	  memset (&ps_old, 0, sizeof (mbstate_t));
1371119614Sache	  memset (&ps_new, 0, sizeof (mbstate_t));
1372119614Sache
1373136759Speter#if 0
1374136759Speter	  /* On advice from jir@yamato.ibm.com */
1375119614Sache	  _rl_adjust_point (old, ols - old, &ps_old);
1376119614Sache	  _rl_adjust_point (new, nls - new, &ps_new);
1377136759Speter#endif
1378119614Sache
1379119614Sache	  if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0)
1380119614Sache	    break;
1381119614Sache
1382119614Sache	  if (*ols == ' ')
1383119614Sache	    wsatend = 0;
1384119614Sache
1385119614Sache	  ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY);
1386119614Sache	  nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY);
1387119614Sache	}
1388119614Sache    }
1389119614Sache  else
1390119614Sache    {
1391119614Sache#endif /* HANDLE_MULTIBYTE */
139221308Sache  ols = oe - 1;			/* find last same */
139321308Sache  nls = ne - 1;
139421308Sache  while ((ols > ofd) && (nls > nfd) && (*ols == *nls))
139521308Sache    {
139621308Sache      if (*ols != ' ')
139721308Sache	wsatend = 0;
139821308Sache      ols--;
139921308Sache      nls--;
140021308Sache    }
1401119614Sache#if defined (HANDLE_MULTIBYTE)
1402119614Sache    }
1403119614Sache#endif
140421308Sache
140521308Sache  if (wsatend)
140621308Sache    {
140721308Sache      ols = oe;
140821308Sache      nls = ne;
140921308Sache    }
1410119614Sache#if defined (HANDLE_MULTIBYTE)
1411119614Sache  /* This may not work for stateful encoding, but who cares?  To handle
1412119614Sache     stateful encoding properly, we have to scan each string from the
1413119614Sache     beginning and compare. */
1414119614Sache  else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0)
1415119614Sache#else
141621308Sache  else if (*ols != *nls)
1417119614Sache#endif
141821308Sache    {
141921308Sache      if (*ols)			/* don't step past the NUL */
1420119614Sache	{
1421119614Sache	  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1422119614Sache	    ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY);
1423119614Sache	  else
1424119614Sache	    ols++;
1425119614Sache	}
142621308Sache      if (*nls)
1427119614Sache	{
1428119614Sache	  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1429119614Sache	    nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY);
1430119614Sache	  else
1431119614Sache	    nls++;
1432119614Sache	}
143321308Sache    }
143421308Sache
143521308Sache  /* count of invisible characters in the current invisible line. */
143621308Sache  current_invis_chars = W_OFFSET (current_line, wrap_offset);
143721308Sache  if (_rl_last_v_pos != current_line)
143821308Sache    {
143921308Sache      _rl_move_vert (current_line);
1440157188Sache      if ((MB_CUR_MAX == 1 || rl_byte_oriented) && current_line == 0 && visible_wrap_offset)
144121308Sache	_rl_last_c_pos += visible_wrap_offset;
144221308Sache    }
144321308Sache
144421308Sache  /* If this is the first line and there are invisible characters in the
144521308Sache     prompt string, and the prompt string has not changed, and the current
144621308Sache     cursor position is before the last invisible character in the prompt,
144721308Sache     and the index of the character to move to is past the end of the prompt
144821308Sache     string, then redraw the entire prompt string.  We can only do this
144921308Sache     reliably if the terminal supports a `cr' capability.
145021308Sache
145121308Sache     This is not an efficiency hack -- there is a problem with redrawing
145221308Sache     portions of the prompt string if they contain terminal escape
145321308Sache     sequences (like drawing the `unbold' sequence without a corresponding
145421308Sache     `bold') that manifests itself on certain terminals. */
145521308Sache
1456165675Sache  lendiff = local_prompt_len;
145721308Sache  od = ofd - old;	/* index of first difference in visible line */
145821308Sache  if (current_line == 0 && !_rl_horizontal_scroll_mode &&
145975409Sache      _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 &&
1460165675Sache      od >= lendiff && _rl_last_c_pos < PROMPT_ENDING_INDEX)
146121308Sache    {
146258314Sache#if defined (__MSDOS__)
146358314Sache      putc ('\r', rl_outstream);
146458314Sache#else
146575409Sache      tputs (_rl_term_cr, 1, _rl_output_character_function);
146658314Sache#endif
146721308Sache      _rl_output_some_chars (local_prompt, lendiff);
1468119614Sache      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1469157188Sache	{
1470157188Sache	  /* We take wrap_offset into account here so we can pass correct
1471157188Sache	     information to _rl_move_cursor_relative. */
1472157188Sache	  _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff) - wrap_offset;
1473157188Sache	  cpos_adjusted = 1;
1474157188Sache	}
1475119614Sache      else
1476119614Sache	_rl_last_c_pos = lendiff;
147721308Sache    }
147821308Sache
1479257586Ssbruno  o_cpos = _rl_last_c_pos;
1480257586Ssbruno
1481165675Sache  /* When this function returns, _rl_last_c_pos is correct, and an absolute
1482165675Sache     cursor postion in multibyte mode, but a buffer index when not in a
1483165675Sache     multibyte locale. */
148421308Sache  _rl_move_cursor_relative (od, old);
1485165675Sache#if 1
1486165675Sache#if defined (HANDLE_MULTIBYTE)
1487165675Sache  /* We need to indicate that the cursor position is correct in the presence of
1488165675Sache     invisible characters in the prompt string.  Let's see if setting this when
1489165675Sache     we make sure we're at the end of the drawn prompt string works. */
1490257586Ssbruno  if (current_line == 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0 &&
1491257586Ssbruno      (_rl_last_c_pos > 0 || o_cpos > 0) &&
1492257586Ssbruno      _rl_last_c_pos == prompt_physical_chars)
1493165675Sache    cpos_adjusted = 1;
1494165675Sache#endif
1495165675Sache#endif
149621308Sache
1497119614Sache  /* if (len (new) > len (old))
1498119614Sache     lendiff == difference in buffer
1499119614Sache     col_lendiff == difference on screen
1500119614Sache     When not using multibyte characters, these are equal */
150121308Sache  lendiff = (nls - nfd) - (ols - ofd);
1502119614Sache  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1503119614Sache    col_lendiff = _rl_col_width (new, nfd - new, nls - new) - _rl_col_width (old, ofd - old, ols - old);
1504119614Sache  else
1505119614Sache    col_lendiff = lendiff;
150621308Sache
150721308Sache  /* If we are changing the number of invisible characters in a line, and
150821308Sache     the spot of first difference is before the end of the invisible chars,
150921308Sache     lendiff needs to be adjusted. */
151021308Sache  if (current_line == 0 && !_rl_horizontal_scroll_mode &&
151121308Sache      current_invis_chars != visible_wrap_offset)
1512119614Sache    {
1513119614Sache      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1514119614Sache	{
1515119614Sache	  lendiff += visible_wrap_offset - current_invis_chars;
1516119614Sache	  col_lendiff += visible_wrap_offset - current_invis_chars;
1517119614Sache	}
1518119614Sache      else
1519119614Sache	{
1520119614Sache	  lendiff += visible_wrap_offset - current_invis_chars;
1521119614Sache	  col_lendiff = lendiff;
1522119614Sache	}
1523119614Sache    }
152421308Sache
152521308Sache  /* Insert (diff (len (old), len (new)) ch. */
152621308Sache  temp = ne - nfd;
1527119614Sache  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1528119614Sache    col_temp = _rl_col_width (new, nfd - new, ne - new);
1529119614Sache  else
1530119614Sache    col_temp = temp;
1531119614Sache
1532119614Sache  if (col_lendiff > 0)	/* XXX - was lendiff */
153321308Sache    {
153421308Sache      /* Non-zero if we're increasing the number of lines. */
153521308Sache      int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
1536173406Sache      /* If col_lendiff is > 0, implying that the new string takes up more
1537173406Sache	 screen real estate than the old, but lendiff is < 0, meaning that it
1538173406Sache	 takes fewer bytes, we need to just output the characters starting
1539173406Sache	 from the first difference.  These will overwrite what is on the
1540173406Sache	 display, so there's no reason to do a smart update.  This can really
1541173406Sache	 only happen in a multibyte environment. */
1542173406Sache      if (lendiff < 0)
1543173406Sache	{
1544173406Sache	  _rl_output_some_chars (nfd, temp);
1545173406Sache	  _rl_last_c_pos += _rl_col_width (nfd, 0, temp);
1546173406Sache	  /* If nfd begins before any invisible characters in the prompt,
1547173406Sache	     adjust _rl_last_c_pos to account for wrap_offset and set
1548173406Sache	     cpos_adjusted to let the caller know. */
1549173406Sache	  if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible))
1550173406Sache	    {
1551173406Sache	      _rl_last_c_pos -= wrap_offset;
1552173406Sache	      cpos_adjusted = 1;
1553173406Sache	    }
1554173406Sache	  return;
1555173406Sache	}
155621308Sache      /* Sometimes it is cheaper to print the characters rather than
155721308Sache	 use the terminal's capabilities.  If we're growing the number
155821308Sache	 of lines, make sure we actually cause the new line to wrap
155921308Sache	 around on auto-wrapping terminals. */
1560173406Sache      else if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
156121308Sache	{
156275409Sache	  /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
156321308Sache	     _rl_horizontal_scroll_mode == 1, inserting the characters with
156475409Sache	     _rl_term_IC or _rl_term_ic will screw up the screen because of the
156521308Sache	     invisible characters.  We need to just draw them. */
156621308Sache	  if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 ||
156775409Sache			lendiff <= prompt_visible_length || !current_invis_chars))
156821308Sache	    {
1569119614Sache	      insert_some_chars (nfd, lendiff, col_lendiff);
1570119614Sache	      _rl_last_c_pos += col_lendiff;
157121308Sache	    }
1572157188Sache	  else if ((MB_CUR_MAX == 1 || rl_byte_oriented != 0) && *ols == 0 && lendiff > 0)
157321308Sache	    {
157421308Sache	      /* At the end of a line the characters do not have to
157521308Sache		 be "inserted".  They can just be placed on the screen. */
157621308Sache	      /* However, this screws up the rest of this block, which
157747563Sache		 assumes you've done the insert because you can. */
157821308Sache	      _rl_output_some_chars (nfd, lendiff);
1579119614Sache	      _rl_last_c_pos += col_lendiff;
158021308Sache	    }
158121308Sache	  else
158221308Sache	    {
158321308Sache	      _rl_output_some_chars (nfd, temp);
1584119614Sache	      _rl_last_c_pos += col_temp;
1585257586Ssbruno	      /* If nfd begins before any invisible characters in the prompt,
1586257586Ssbruno		 adjust _rl_last_c_pos to account for wrap_offset and set
1587257586Ssbruno		 cpos_adjusted to let the caller know. */
1588257586Ssbruno	      if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible))
1589257586Ssbruno		{
1590257586Ssbruno		  _rl_last_c_pos -= wrap_offset;
1591257586Ssbruno		  cpos_adjusted = 1;
1592257586Ssbruno		}
159321308Sache	      return;
159421308Sache	    }
159521308Sache	  /* Copy (new) chars to screen from first diff to last match. */
159621308Sache	  temp = nls - nfd;
159721308Sache	  if ((temp - lendiff) > 0)
159821308Sache	    {
159921308Sache	      _rl_output_some_chars (nfd + lendiff, temp - lendiff);
1600136759Speter	     /* XXX -- this bears closer inspection.  Fixes a redisplay bug
1601136759Speter		reported against bash-3.0-alpha by Andreas Schwab involving
1602136759Speter		multibyte characters and prompt strings with invisible
1603136759Speter		characters, but was previously disabled. */
1604257586Ssbruno	      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1605257586Ssbruno		twidth = _rl_col_width (nfd+lendiff, 0, temp-col_lendiff);
1606257586Ssbruno	      else
1607257586Ssbruno		twidth = temp - lendiff;
1608257586Ssbruno	      _rl_last_c_pos += twidth;
160921308Sache	    }
161021308Sache	}
161121308Sache      else
161221308Sache	{
161321308Sache	  /* cannot insert chars, write to EOL */
161421308Sache	  _rl_output_some_chars (nfd, temp);
1615119614Sache	  _rl_last_c_pos += col_temp;
1616157188Sache	  /* If we're in a multibyte locale and were before the last invisible
1617157188Sache	     char in the current line (which implies we just output some invisible
1618157188Sache	     characters) we need to adjust _rl_last_c_pos, since it represents
1619157188Sache	     a physical character position. */
162021308Sache	}
162121308Sache    }
162221308Sache  else				/* Delete characters from line. */
162321308Sache    {
162421308Sache      /* If possible and inexpensive to use terminal deletion, then do so. */
1625119614Sache      if (_rl_term_dc && (2 * col_temp) >= -col_lendiff)
162621308Sache	{
162721308Sache	  /* If all we're doing is erasing the invisible characters in the
162821308Sache	     prompt string, don't bother.  It screws up the assumptions
162921308Sache	     about what's on the screen. */
163021308Sache	  if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
163121308Sache	      -lendiff == visible_wrap_offset)
1632119614Sache	    col_lendiff = 0;
163321308Sache
1634119614Sache	  if (col_lendiff)
1635119614Sache	    delete_chars (-col_lendiff); /* delete (diff) characters */
163621308Sache
163721308Sache	  /* Copy (new) chars to screen from first diff to last match */
163821308Sache	  temp = nls - nfd;
163921308Sache	  if (temp > 0)
164021308Sache	    {
1641173406Sache	      /* If nfd begins at the prompt, or before the invisible
1642173406Sache		 characters in the prompt, we need to adjust _rl_last_c_pos
1643173406Sache		 in a multibyte locale to account for the wrap offset and
1644173406Sache		 set cpos_adjusted accordingly. */
164521308Sache	      _rl_output_some_chars (nfd, temp);
1646173406Sache	      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1647173406Sache		{
1648173406Sache                  _rl_last_c_pos += _rl_col_width (nfd, 0, temp);
1649173406Sache                  if (current_line == 0 && wrap_offset &&  ((nfd - new) <= prompt_last_invisible))
1650173406Sache		    {
1651173406Sache		      _rl_last_c_pos -= wrap_offset;
1652173406Sache		      cpos_adjusted = 1;
1653173406Sache		    }
1654173406Sache		}
1655173406Sache              else
1656173406Sache                _rl_last_c_pos += temp;
165721308Sache	    }
165821308Sache	}
165921308Sache      /* Otherwise, print over the existing material. */
166021308Sache      else
166121308Sache	{
166221308Sache	  if (temp > 0)
166321308Sache	    {
1664173406Sache	      /* If nfd begins at the prompt, or before the invisible
1665173406Sache		 characters in the prompt, we need to adjust _rl_last_c_pos
1666173406Sache		 in a multibyte locale to account for the wrap offset and
1667173406Sache		 set cpos_adjusted accordingly. */
166821308Sache	      _rl_output_some_chars (nfd, temp);
1669157188Sache	      _rl_last_c_pos += col_temp;		/* XXX */
1670173406Sache	      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1671173406Sache		{
1672173406Sache		  if (current_line == 0 && wrap_offset &&  ((nfd - new) <= prompt_last_invisible))
1673173406Sache		    {
1674173406Sache		      _rl_last_c_pos -= wrap_offset;
1675173406Sache		      cpos_adjusted = 1;
1676173406Sache		    }
1677173406Sache		}
167821308Sache	    }
167921308Sache	  lendiff = (oe - old) - (ne - new);
1680119614Sache	  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1681119614Sache	    col_lendiff = _rl_col_width (old, 0, oe - old) - _rl_col_width (new, 0, ne - new);
1682119614Sache	  else
1683119614Sache	    col_lendiff = lendiff;
1684119614Sache
1685119614Sache	  if (col_lendiff)
168647563Sache	    {
168747563Sache	      if (_rl_term_autowrap && current_line < inv_botlin)
1688119614Sache		space_to_eol (col_lendiff);
168947563Sache	      else
1690119614Sache		_rl_clear_to_eol (col_lendiff);
169147563Sache	    }
169221308Sache	}
169321308Sache    }
169421308Sache}
169521308Sache
169621308Sache/* Tell the update routines that we have moved onto a new (empty) line. */
169721308Sacheint
169821308Sacherl_on_new_line ()
169921308Sache{
170021308Sache  if (visible_line)
170121308Sache    visible_line[0] = '\0';
170221308Sache
170321308Sache  _rl_last_c_pos = _rl_last_v_pos = 0;
170421308Sache  _rl_vis_botlin = last_lmargin = 0;
170521308Sache  if (vis_lbreaks)
170621308Sache    vis_lbreaks[0] = vis_lbreaks[1] = 0;
170721308Sache  visible_wrap_offset = 0;
170821308Sache  return 0;
170921308Sache}
171021308Sache
171158314Sache/* Tell the update routines that we have moved onto a new line with the
171258314Sache   prompt already displayed.  Code originally from the version of readline
1713136759Speter   distributed with CLISP.  rl_expand_prompt must have already been called
1714136759Speter   (explicitly or implicitly).  This still doesn't work exactly right. */
171558314Sacheint
171658314Sacherl_on_new_line_with_prompt ()
171758314Sache{
171858314Sache  int prompt_size, i, l, real_screenwidth, newlines;
1719136759Speter  char *prompt_last_line, *lprompt;
172058314Sache
172158314Sache  /* Initialize visible_line and invisible_line to ensure that they can hold
172258314Sache     the already-displayed prompt. */
172358314Sache  prompt_size = strlen (rl_prompt) + 1;
172458314Sache  init_line_structures (prompt_size);
172558314Sache
172658314Sache  /* Make sure the line structures hold the already-displayed prompt for
172758314Sache     redisplay. */
1728136759Speter  lprompt = local_prompt ? local_prompt : rl_prompt;
1729136759Speter  strcpy (visible_line, lprompt);
1730136759Speter  strcpy (invisible_line, lprompt);
173158314Sache
173258314Sache  /* If the prompt contains newlines, take the last tail. */
173358314Sache  prompt_last_line = strrchr (rl_prompt, '\n');
173458314Sache  if (!prompt_last_line)
173558314Sache    prompt_last_line = rl_prompt;
173658314Sache
173758314Sache  l = strlen (prompt_last_line);
1738119614Sache  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1739157188Sache    _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l);	/* XXX */
1740119614Sache  else
1741119614Sache    _rl_last_c_pos = l;
174258314Sache
174358314Sache  /* Dissect prompt_last_line into screen lines. Note that here we have
174458314Sache     to use the real screenwidth. Readline's notion of screenwidth might be
174558314Sache     one less, see terminal.c. */
174675409Sache  real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1);
174758314Sache  _rl_last_v_pos = l / real_screenwidth;
174858314Sache  /* If the prompt length is a multiple of real_screenwidth, we don't know
174958314Sache     whether the cursor is at the end of the last line, or already at the
175058314Sache     beginning of the next line. Output a newline just to be safe. */
175158314Sache  if (l > 0 && (l % real_screenwidth) == 0)
175258314Sache    _rl_output_some_chars ("\n", 1);
175358314Sache  last_lmargin = 0;
175458314Sache
175558314Sache  newlines = 0; i = 0;
175658314Sache  while (i <= l)
175758314Sache    {
175858314Sache      _rl_vis_botlin = newlines;
175958314Sache      vis_lbreaks[newlines++] = i;
176058314Sache      i += real_screenwidth;
176158314Sache    }
176258314Sache  vis_lbreaks[newlines] = l;
176358314Sache  visible_wrap_offset = 0;
176458314Sache
1765136759Speter  rl_display_prompt = rl_prompt;	/* XXX - make sure it's set */
1766136759Speter
176758314Sache  return 0;
176858314Sache}
176958314Sache
177021308Sache/* Actually update the display, period. */
177121308Sacheint
177221308Sacherl_forced_update_display ()
177321308Sache{
1774165675Sache  register char *temp;
1775165675Sache
177621308Sache  if (visible_line)
177721308Sache    {
1778165675Sache      temp = visible_line;
177921308Sache      while (*temp)
178047563Sache	*temp++ = '\0';
178121308Sache    }
178221308Sache  rl_on_new_line ();
178321308Sache  forced_display++;
178421308Sache  (*rl_redisplay_function) ();
178521308Sache  return 0;
178621308Sache}
178721308Sache
178821308Sache/* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
1789157188Sache   (Well, when we don't have multibyte characters, _rl_last_c_pos is a
1790157188Sache   buffer index.)
179121308Sache   DATA is the contents of the screen line of interest; i.e., where
179221308Sache   the movement is being done. */
179321308Sachevoid
179421308Sache_rl_move_cursor_relative (new, data)
179521308Sache     int new;
179675409Sache     const char *data;
179721308Sache{
179821308Sache  register int i;
1799157188Sache  int woff;			/* number of invisible chars on current line */
1800157188Sache  int cpos, dpos;		/* current and desired cursor positions */
180121308Sache
1802257586Ssbruno  woff = WRAP_OFFSET (_rl_last_v_pos, wrap_offset);
1803157188Sache  cpos = _rl_last_c_pos;
1804119614Sache#if defined (HANDLE_MULTIBYTE)
1805119614Sache  /* If we have multibyte characters, NEW is indexed by the buffer point in
1806119614Sache     a multibyte string, but _rl_last_c_pos is the display position.  In
1807136759Speter     this case, NEW's display position is not obvious and must be
1808157188Sache     calculated.  We need to account for invisible characters in this line,
1809157188Sache     as long as we are past them and they are counted by _rl_col_width. */
1810157188Sache  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1811136759Speter    {
1812157188Sache      dpos = _rl_col_width (data, 0, new);
1813173406Sache      /* Use NEW when comparing against the last invisible character in the
1814173406Sache	 prompt string, since they're both buffer indices and DPOS is a
1815173406Sache	 desired display position. */
1816257586Ssbruno      if ((new > prompt_last_invisible) ||		/* XXX - don't use woff here */
1817257586Ssbruno	  (prompt_physical_chars > _rl_screenwidth &&
1818257586Ssbruno	   _rl_last_v_pos == prompt_last_screen_line &&
1819257586Ssbruno	   wrap_offset != woff &&
1820257586Ssbruno	   new > (prompt_last_invisible-_rl_screenwidth-wrap_offset)))
1821165675Sache	{
1822165675Sache	  dpos -= woff;
1823165675Sache	  /* Since this will be assigned to _rl_last_c_pos at the end (more
1824165675Sache	     precisely, _rl_last_c_pos == dpos when this function returns),
1825165675Sache	     let the caller know. */
1826165675Sache	  cpos_adjusted = 1;
1827165675Sache	}
1828136759Speter    }
1829157188Sache  else
1830119614Sache#endif
1831157188Sache    dpos = new;
183221308Sache
1833157188Sache  /* If we don't have to do anything, then return. */
1834157188Sache  if (cpos == dpos)
1835157188Sache    return;
1836157188Sache
183721308Sache  /* It may be faster to output a CR, and then move forwards instead
183821308Sache     of moving backwards. */
183921308Sache  /* i == current physical cursor position. */
1840157188Sache#if defined (HANDLE_MULTIBYTE)
1841157188Sache  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1842157188Sache    i = _rl_last_c_pos;
1843157188Sache  else
1844157188Sache#endif
1845157188Sache  i = _rl_last_c_pos - woff;
1846165675Sache  if (dpos == 0 || CR_FASTER (dpos, _rl_last_c_pos) ||
184775409Sache      (_rl_term_autowrap && i == _rl_screenwidth))
184821308Sache    {
184921308Sache#if defined (__MSDOS__)
185021308Sache      putc ('\r', rl_outstream);
185121308Sache#else
185275409Sache      tputs (_rl_term_cr, 1, _rl_output_character_function);
185321308Sache#endif /* !__MSDOS__ */
1854157188Sache      cpos = _rl_last_c_pos = 0;
185521308Sache    }
185621308Sache
1857157188Sache  if (cpos < dpos)
185821308Sache    {
185921308Sache      /* Move the cursor forward.  We do it by printing the command
186021308Sache	 to move the cursor forward if there is one, else print that
186121308Sache	 portion of the output buffer again.  Which is cheaper? */
186221308Sache
186321308Sache      /* The above comment is left here for posterity.  It is faster
186421308Sache	 to print one character (non-control) than to print a control
186521308Sache	 sequence telling the terminal to move forward one character.
186621308Sache	 That kind of control is for people who don't know what the
186721308Sache	 data is underneath the cursor. */
1868165675Sache
1869165675Sache      /* However, we need a handle on where the current display position is
1870165675Sache	 in the buffer for the immediately preceding comment to be true.
1871165675Sache	 In multibyte locales, we don't currently have that info available.
1872165675Sache	 Without it, we don't know where the data we have to display begins
1873165675Sache	 in the buffer and we have to go back to the beginning of the screen
1874165675Sache	 line.  In this case, we can use the terminal sequence to move forward
1875165675Sache	 if it's available. */
1876119614Sache      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1877119614Sache	{
1878165675Sache	  if (_rl_term_forward_char)
1879165675Sache	    {
1880165675Sache	      for (i = cpos; i < dpos; i++)
1881165675Sache	        tputs (_rl_term_forward_char, 1, _rl_output_character_function);
1882165675Sache	    }
1883165675Sache	  else
1884165675Sache	    {
1885165675Sache	      tputs (_rl_term_cr, 1, _rl_output_character_function);
1886165675Sache	      for (i = 0; i < new; i++)
1887165675Sache		putc (data[i], rl_outstream);
1888165675Sache	    }
1889119614Sache	}
189021308Sache      else
1891157188Sache	for (i = cpos; i < new; i++)
189221308Sache	  putc (data[i], rl_outstream);
1893157188Sache    }
1894119614Sache
1895119614Sache#if defined (HANDLE_MULTIBYTE)
1896119614Sache  /* NEW points to the buffer point, but _rl_last_c_pos is the display point.
1897119614Sache     The byte length of the string is probably bigger than the column width
1898119614Sache     of the string, which means that if NEW == _rl_last_c_pos, then NEW's
1899119614Sache     display point is less than _rl_last_c_pos. */
1900119614Sache#endif
1901157188Sache  else if (cpos > dpos)
1902157188Sache    _rl_backspace (cpos - dpos);
1903119614Sache
1904157188Sache  _rl_last_c_pos = dpos;
190521308Sache}
190621308Sache
190721308Sache/* PWP: move the cursor up or down. */
190821308Sachevoid
190921308Sache_rl_move_vert (to)
191021308Sache     int to;
191121308Sache{
191221308Sache  register int delta, i;
191321308Sache
191475409Sache  if (_rl_last_v_pos == to || to > _rl_screenheight)
191521308Sache    return;
191621308Sache
191721308Sache  if ((delta = to - _rl_last_v_pos) > 0)
191821308Sache    {
191921308Sache      for (i = 0; i < delta; i++)
192021308Sache	putc ('\n', rl_outstream);
192158314Sache#if defined (__MSDOS__)
192258314Sache      putc ('\r', rl_outstream);
192358314Sache#else
192475409Sache      tputs (_rl_term_cr, 1, _rl_output_character_function);
192558314Sache#endif
192621308Sache      _rl_last_c_pos = 0;
192721308Sache    }
192821308Sache  else
192921308Sache    {			/* delta < 0 */
193075409Sache      if (_rl_term_up && *_rl_term_up)
193121308Sache	for (i = 0; i < -delta; i++)
193275409Sache	  tputs (_rl_term_up, 1, _rl_output_character_function);
193321308Sache    }
193458314Sache
193521308Sache  _rl_last_v_pos = to;		/* Now TO is here */
193621308Sache}
193721308Sache
193821308Sache/* Physically print C on rl_outstream.  This is for functions which know
193921308Sache   how to optimize the display.  Return the number of characters output. */
194021308Sacheint
194121308Sacherl_show_char (c)
194221308Sache     int c;
194321308Sache{
194421308Sache  int n = 1;
194521308Sache  if (META_CHAR (c) && (_rl_output_meta_chars == 0))
194621308Sache    {
194721308Sache      fprintf (rl_outstream, "M-");
194821308Sache      n += 2;
194921308Sache      c = UNMETA (c);
195021308Sache    }
195121308Sache
195221308Sache#if defined (DISPLAY_TABS)
195321308Sache  if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
195421308Sache#else
195521308Sache  if (CTRL_CHAR (c) || c == RUBOUT)
195621308Sache#endif /* !DISPLAY_TABS */
195721308Sache    {
195821308Sache      fprintf (rl_outstream, "C-");
195921308Sache      n += 2;
196021308Sache      c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
196121308Sache    }
196221308Sache
196321308Sache  putc (c, rl_outstream);
196421308Sache  fflush (rl_outstream);
196521308Sache  return n;
196621308Sache}
196721308Sache
196821308Sacheint
196921308Sacherl_character_len (c, pos)
197021308Sache     register int c, pos;
197121308Sache{
197221308Sache  unsigned char uc;
197321308Sache
197421308Sache  uc = (unsigned char)c;
197521308Sache
197621308Sache  if (META_CHAR (uc))
197721308Sache    return ((_rl_output_meta_chars == 0) ? 4 : 1);
197821308Sache
197921308Sache  if (uc == '\t')
198021308Sache    {
198121308Sache#if defined (DISPLAY_TABS)
198221308Sache      return (((pos | 7) + 1) - pos);
198321308Sache#else
198421308Sache      return (2);
198521308Sache#endif /* !DISPLAY_TABS */
198621308Sache    }
198721308Sache
198821308Sache  if (CTRL_CHAR (c) || c == RUBOUT)
198921308Sache    return (2);
199021308Sache
1991119614Sache  return ((ISPRINT (uc)) ? 1 : 2);
199221308Sache}
199321308Sache/* How to print things in the "echo-area".  The prompt is treated as a
199421308Sache   mini-modeline. */
1995157188Sachestatic int msg_saved_prompt = 0;
199621308Sache
199721308Sache#if defined (USE_VARARGS)
199821308Sacheint
199921308Sache#if defined (PREFER_STDARG)
200021308Sacherl_message (const char *format, ...)
200121308Sache#else
200221308Sacherl_message (va_alist)
200321308Sache     va_dcl
200421308Sache#endif
200521308Sache{
200621308Sache  va_list args;
200721308Sache#if defined (PREFER_VARARGS)
200821308Sache  char *format;
200921308Sache#endif
201021308Sache
201121308Sache#if defined (PREFER_STDARG)
201221308Sache  va_start (args, format);
201321308Sache#else
201421308Sache  va_start (args);
201521308Sache  format = va_arg (args, char *);
201621308Sache#endif
201721308Sache
2018119614Sache#if defined (HAVE_VSNPRINTF)
2019119614Sache  vsnprintf (msg_buf, sizeof (msg_buf) - 1, format, args);
2020119614Sache#else
202121308Sache  vsprintf (msg_buf, format, args);
2022119614Sache  msg_buf[sizeof(msg_buf) - 1] = '\0';	/* overflow? */
2023119614Sache#endif
202421308Sache  va_end (args);
202521308Sache
2026157188Sache  if (saved_local_prompt == 0)
2027157188Sache    {
2028157188Sache      rl_save_prompt ();
2029157188Sache      msg_saved_prompt = 1;
2030157188Sache    }
203121308Sache  rl_display_prompt = msg_buf;
2032157188Sache  local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
2033157188Sache					 &prompt_last_invisible,
2034157188Sache					 &prompt_invis_chars_first_line,
2035157188Sache					 &prompt_physical_chars);
2036157188Sache  local_prompt_prefix = (char *)NULL;
2037165675Sache  local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
203821308Sache  (*rl_redisplay_function) ();
2039157188Sache
204021308Sache  return 0;
204121308Sache}
204221308Sache#else /* !USE_VARARGS */
204321308Sacheint
204421308Sacherl_message (format, arg1, arg2)
204521308Sache     char *format;
204621308Sache{
204721308Sache  sprintf (msg_buf, format, arg1, arg2);
2048119614Sache  msg_buf[sizeof(msg_buf) - 1] = '\0';	/* overflow? */
2049157188Sache
205021308Sache  rl_display_prompt = msg_buf;
2051157188Sache  if (saved_local_prompt == 0)
2052157188Sache    {
2053157188Sache      rl_save_prompt ();
2054157188Sache      msg_saved_prompt = 1;
2055157188Sache    }
2056157188Sache  local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
2057157188Sache					 &prompt_last_invisible,
2058157188Sache					 &prompt_invis_chars_first_line,
2059157188Sache					 &prompt_physical_chars);
2060157188Sache  local_prompt_prefix = (char *)NULL;
2061165675Sache  local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
206221308Sache  (*rl_redisplay_function) ();
2063157188Sache
206421308Sache  return 0;
206521308Sache}
206621308Sache#endif /* !USE_VARARGS */
206721308Sache
206821308Sache/* How to clear things from the "echo-area". */
206921308Sacheint
207021308Sacherl_clear_message ()
207121308Sache{
207221308Sache  rl_display_prompt = rl_prompt;
2073157188Sache  if (msg_saved_prompt)
2074157188Sache    {
2075157188Sache      rl_restore_prompt ();
2076157188Sache      msg_saved_prompt = 0;
2077157188Sache    }
207821308Sache  (*rl_redisplay_function) ();
207921308Sache  return 0;
208021308Sache}
208121308Sache
208221308Sacheint
208321308Sacherl_reset_line_state ()
208421308Sache{
208521308Sache  rl_on_new_line ();
208621308Sache
208721308Sache  rl_display_prompt = rl_prompt ? rl_prompt : "";
208821308Sache  forced_display = 1;
208921308Sache  return 0;
209021308Sache}
209121308Sache
209221308Sachevoid
209347563Sacherl_save_prompt ()
209421308Sache{
209521308Sache  saved_local_prompt = local_prompt;
209621308Sache  saved_local_prefix = local_prompt_prefix;
2097157188Sache  saved_prefix_length = prompt_prefix_length;
2098165675Sache  saved_local_length = local_prompt_len;
209975409Sache  saved_last_invisible = prompt_last_invisible;
210075409Sache  saved_visible_length = prompt_visible_length;
2101136759Speter  saved_invis_chars_first_line = prompt_invis_chars_first_line;
2102136759Speter  saved_physical_chars = prompt_physical_chars;
210321308Sache
210421308Sache  local_prompt = local_prompt_prefix = (char *)0;
2105165675Sache  local_prompt_len = 0;
2106157188Sache  prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0;
2107136759Speter  prompt_invis_chars_first_line = prompt_physical_chars = 0;
210821308Sache}
210921308Sache
211021308Sachevoid
211147563Sacherl_restore_prompt ()
211221308Sache{
211375409Sache  FREE (local_prompt);
211475409Sache  FREE (local_prompt_prefix);
211521308Sache
211621308Sache  local_prompt = saved_local_prompt;
211721308Sache  local_prompt_prefix = saved_local_prefix;
2118165675Sache  local_prompt_len = saved_local_length;
2119157188Sache  prompt_prefix_length = saved_prefix_length;
212075409Sache  prompt_last_invisible = saved_last_invisible;
212175409Sache  prompt_visible_length = saved_visible_length;
2122136759Speter  prompt_invis_chars_first_line = saved_invis_chars_first_line;
2123136759Speter  prompt_physical_chars = saved_physical_chars;
2124157188Sache
2125157188Sache  /* can test saved_local_prompt to see if prompt info has been saved. */
2126157188Sache  saved_local_prompt = saved_local_prefix = (char *)0;
2127165675Sache  saved_local_length = 0;
2128157188Sache  saved_last_invisible = saved_visible_length = saved_prefix_length = 0;
2129157188Sache  saved_invis_chars_first_line = saved_physical_chars = 0;
213021308Sache}
213121308Sache
213221308Sachechar *
213321308Sache_rl_make_prompt_for_search (pchar)
213421308Sache     int pchar;
213521308Sache{
213621308Sache  int len;
2137157195Sache  char *pmt, *p;
213821308Sache
213947563Sache  rl_save_prompt ();
214021308Sache
2141157195Sache  /* We've saved the prompt, and can do anything with the various prompt
2142157195Sache     strings we need before they're restored.  We want the unexpanded
2143157195Sache     portion of the prompt string after any final newline. */
2144157195Sache  p = rl_prompt ? strrchr (rl_prompt, '\n') : 0;
2145157195Sache  if (p == 0)
214621308Sache    {
214721308Sache      len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
2148119614Sache      pmt = (char *)xmalloc (len + 2);
214921308Sache      if (len)
215047563Sache	strcpy (pmt, rl_prompt);
215121308Sache      pmt[len] = pchar;
215221308Sache      pmt[len+1] = '\0';
215321308Sache    }
215421308Sache  else
215521308Sache    {
2156157195Sache      p++;
2157157195Sache      len = strlen (p);
2158119614Sache      pmt = (char *)xmalloc (len + 2);
215921308Sache      if (len)
2160157195Sache	strcpy (pmt, p);
216121308Sache      pmt[len] = pchar;
216221308Sache      pmt[len+1] = '\0';
2163157195Sache    }
2164136759Speter
2165157195Sache  /* will be overwritten by expand_prompt, called from rl_message */
2166157188Sache  prompt_physical_chars = saved_physical_chars + 1;
216721308Sache  return pmt;
216821308Sache}
216921308Sache
217021308Sache/* Quick redisplay hack when erasing characters at the end of the line. */
217121308Sachevoid
217221308Sache_rl_erase_at_end_of_line (l)
217321308Sache     int l;
217421308Sache{
217521308Sache  register int i;
217621308Sache
217721308Sache  _rl_backspace (l);
217821308Sache  for (i = 0; i < l; i++)
217921308Sache    putc (' ', rl_outstream);
218021308Sache  _rl_backspace (l);
218121308Sache  for (i = 0; i < l; i++)
218221308Sache    visible_line[--_rl_last_c_pos] = '\0';
218321308Sache  rl_display_fixed++;
218421308Sache}
218521308Sache
218621308Sache/* Clear to the end of the line.  COUNT is the minimum
218721308Sache   number of character spaces to clear, */
218826497Sachevoid
218926497Sache_rl_clear_to_eol (count)
219021308Sache     int count;
219121308Sache{
219275409Sache  if (_rl_term_clreol)
219375409Sache    tputs (_rl_term_clreol, 1, _rl_output_character_function);
219426497Sache  else if (count)
219521308Sache    space_to_eol (count);
219621308Sache}
219721308Sache
219821308Sache/* Clear to the end of the line using spaces.  COUNT is the minimum
219921308Sache   number of character spaces to clear, */
220021308Sachestatic void
220121308Sachespace_to_eol (count)
220221308Sache     int count;
220321308Sache{
220421308Sache  register int i;
220521308Sache
220621308Sache  for (i = 0; i < count; i++)
220721308Sache   putc (' ', rl_outstream);
220821308Sache
220921308Sache  _rl_last_c_pos += count;
221021308Sache}
221121308Sache
221226497Sachevoid
221326497Sache_rl_clear_screen ()
221426497Sache{
221575409Sache  if (_rl_term_clrpag)
221675409Sache    tputs (_rl_term_clrpag, 1, _rl_output_character_function);
221726497Sache  else
221875409Sache    rl_crlf ();
221926497Sache}
222026497Sache
2221119614Sache/* Insert COUNT characters from STRING to the output stream at column COL. */
222221308Sachestatic void
2223119614Sacheinsert_some_chars (string, count, col)
222421308Sache     char *string;
2225119614Sache     int count, col;
222621308Sache{
2227157188Sache#if defined (__MSDOS__) || defined (__MINGW32__)
2228157188Sache  _rl_output_some_chars (string, count);
2229157188Sache#else
2230119614Sache  /* DEBUGGING */
2231119614Sache  if (MB_CUR_MAX == 1 || rl_byte_oriented)
2232119614Sache    if (count != col)
2233119614Sache      fprintf(stderr, "readline: debug: insert_some_chars: count (%d) != col (%d)\n", count, col);
2234119614Sache
223521308Sache  /* If IC is defined, then we do not have to "enter" insert mode. */
223675409Sache  if (_rl_term_IC)
223721308Sache    {
223821308Sache      char *buffer;
2239119614Sache
2240119614Sache      buffer = tgoto (_rl_term_IC, 0, col);
224121308Sache      tputs (buffer, 1, _rl_output_character_function);
224221308Sache      _rl_output_some_chars (string, count);
224321308Sache    }
224421308Sache  else
224521308Sache    {
224621308Sache      register int i;
224721308Sache
224821308Sache      /* If we have to turn on insert-mode, then do so. */
224975409Sache      if (_rl_term_im && *_rl_term_im)
225075409Sache	tputs (_rl_term_im, 1, _rl_output_character_function);
225121308Sache
225221308Sache      /* If there is a special command for inserting characters, then
225321308Sache	 use that first to open up the space. */
225475409Sache      if (_rl_term_ic && *_rl_term_ic)
225521308Sache	{
2256119614Sache	  for (i = col; i--; )
225775409Sache	    tputs (_rl_term_ic, 1, _rl_output_character_function);
225821308Sache	}
225921308Sache
226021308Sache      /* Print the text. */
226121308Sache      _rl_output_some_chars (string, count);
226221308Sache
226321308Sache      /* If there is a string to turn off insert mode, we had best use
226421308Sache	 it now. */
226575409Sache      if (_rl_term_ei && *_rl_term_ei)
226675409Sache	tputs (_rl_term_ei, 1, _rl_output_character_function);
226721308Sache    }
2268157188Sache#endif /* __MSDOS__ || __MINGW32__ */
226921308Sache}
227021308Sache
227121308Sache/* Delete COUNT characters from the display line. */
227221308Sachestatic void
227321308Sachedelete_chars (count)
227421308Sache     int count;
227521308Sache{
227675409Sache  if (count > _rl_screenwidth)	/* XXX */
227721308Sache    return;
227821308Sache
2279157188Sache#if !defined (__MSDOS__) && !defined (__MINGW32__)
228075409Sache  if (_rl_term_DC && *_rl_term_DC)
228121308Sache    {
228221308Sache      char *buffer;
228375409Sache      buffer = tgoto (_rl_term_DC, count, count);
228421308Sache      tputs (buffer, count, _rl_output_character_function);
228521308Sache    }
228621308Sache  else
228721308Sache    {
228875409Sache      if (_rl_term_dc && *_rl_term_dc)
228921308Sache	while (count--)
229075409Sache	  tputs (_rl_term_dc, 1, _rl_output_character_function);
229121308Sache    }
2292157188Sache#endif /* !__MSDOS__ && !__MINGW32__ */
229321308Sache}
229421308Sache
229521308Sachevoid
229621308Sache_rl_update_final ()
229721308Sache{
229821308Sache  int full_lines;
229921308Sache
230021308Sache  full_lines = 0;
230121308Sache  /* If the cursor is the only thing on an otherwise-blank last line,
230221308Sache     compensate so we don't print an extra CRLF. */
230321308Sache  if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
230426497Sache	visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
230521308Sache    {
230621308Sache      _rl_vis_botlin--;
230721308Sache      full_lines = 1;
230821308Sache    }
230921308Sache  _rl_move_vert (_rl_vis_botlin);
231021308Sache  /* If we've wrapped lines, remove the final xterm line-wrap flag. */
231175409Sache  if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth))
231221308Sache    {
231321308Sache      char *last_line;
2314119614Sache
231558314Sache      last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]];
2316165675Sache      cpos_buffer_position = -1;	/* don't know where we are in buffer */
2317165675Sache      _rl_move_cursor_relative (_rl_screenwidth - 1, last_line);	/* XXX */
231826497Sache      _rl_clear_to_eol (0);
231975409Sache      putc (last_line[_rl_screenwidth - 1], rl_outstream);
232021308Sache    }
232121308Sache  _rl_vis_botlin = 0;
232275409Sache  rl_crlf ();
232321308Sache  fflush (rl_outstream);
232421308Sache  rl_display_fixed++;
232521308Sache}
232621308Sache
232721308Sache/* Move to the start of the current line. */
232821308Sachestatic void
232921308Sachecr ()
233021308Sache{
233175409Sache  if (_rl_term_cr)
233221308Sache    {
233358314Sache#if defined (__MSDOS__)
233458314Sache      putc ('\r', rl_outstream);
233558314Sache#else
233675409Sache      tputs (_rl_term_cr, 1, _rl_output_character_function);
233758314Sache#endif
233821308Sache      _rl_last_c_pos = 0;
233921308Sache    }
234021308Sache}
234121308Sache
234258314Sache/* Redraw the last line of a multi-line prompt that may possibly contain
234358314Sache   terminal escape sequences.  Called with the cursor at column 0 of the
234458314Sache   line to draw the prompt on. */
234558314Sachestatic void
234658314Sacheredraw_prompt (t)
234758314Sache     char *t;
234858314Sache{
2349157188Sache  char *oldp;
235058314Sache
235158314Sache  oldp = rl_display_prompt;
2352157188Sache  rl_save_prompt ();
235358314Sache
235458314Sache  rl_display_prompt = t;
235575409Sache  local_prompt = expand_prompt (t, &prompt_visible_length,
235675409Sache				   &prompt_last_invisible,
2357136759Speter				   &prompt_invis_chars_first_line,
2358136759Speter				   &prompt_physical_chars);
235958314Sache  local_prompt_prefix = (char *)NULL;
2360165675Sache  local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
2361157188Sache
236258314Sache  rl_forced_update_display ();
236358314Sache
236458314Sache  rl_display_prompt = oldp;
2365157188Sache  rl_restore_prompt();
236658314Sache}
236758314Sache
236821308Sache/* Redisplay the current line after a SIGWINCH is received. */
236921308Sachevoid
237021308Sache_rl_redisplay_after_sigwinch ()
237121308Sache{
237258314Sache  char *t;
237321308Sache
237421308Sache  /* Clear the current line and put the cursor at column 0.  Make sure
237521308Sache     the right thing happens if we have wrapped to a new screen line. */
237675409Sache  if (_rl_term_cr)
237721308Sache    {
237858314Sache#if defined (__MSDOS__)
237958314Sache      putc ('\r', rl_outstream);
238058314Sache#else
238175409Sache      tputs (_rl_term_cr, 1, _rl_output_character_function);
238258314Sache#endif
238321308Sache      _rl_last_c_pos = 0;
238458314Sache#if defined (__MSDOS__)
238575409Sache      space_to_eol (_rl_screenwidth);
238658314Sache      putc ('\r', rl_outstream);
238758314Sache#else
238875409Sache      if (_rl_term_clreol)
238975409Sache	tputs (_rl_term_clreol, 1, _rl_output_character_function);
239021308Sache      else
239121308Sache	{
239275409Sache	  space_to_eol (_rl_screenwidth);
239375409Sache	  tputs (_rl_term_cr, 1, _rl_output_character_function);
239421308Sache	}
239558314Sache#endif
239621308Sache      if (_rl_last_v_pos > 0)
239721308Sache	_rl_move_vert (0);
239821308Sache    }
239921308Sache  else
240075409Sache    rl_crlf ();
240121308Sache
240221308Sache  /* Redraw only the last line of a multi-line prompt. */
240321308Sache  t = strrchr (rl_display_prompt, '\n');
240421308Sache  if (t)
240558314Sache    redraw_prompt (++t);
240621308Sache  else
240721308Sache    rl_forced_update_display ();
240821308Sache}
240921308Sache
241021308Sachevoid
241121308Sache_rl_clean_up_for_exit ()
241221308Sache{
241321308Sache  if (readline_echoing_p)
241421308Sache    {
241521308Sache      _rl_move_vert (_rl_vis_botlin);
241621308Sache      _rl_vis_botlin = 0;
241721308Sache      fflush (rl_outstream);
241847563Sache      rl_restart_output (1, 0);
241921308Sache    }
242021308Sache}
242147563Sache
242247563Sachevoid
242347563Sache_rl_erase_entire_line ()
242447563Sache{
242547563Sache  cr ();
242647563Sache  _rl_clear_to_eol (0);
242747563Sache  cr ();
242847563Sache  fflush (rl_outstream);
242947563Sache}
243058314Sache
243158314Sache/* return the `current display line' of the cursor -- the number of lines to
243258314Sache   move up to get to the first screen line of the current readline line. */
243358314Sacheint
243458314Sache_rl_current_display_line ()
243558314Sache{
243658314Sache  int ret, nleft;
243758314Sache
243858314Sache  /* Find out whether or not there might be invisible characters in the
243958314Sache     editing buffer. */
244058314Sache  if (rl_display_prompt == rl_prompt)
244175409Sache    nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length;
244258314Sache  else
244375409Sache    nleft = _rl_last_c_pos - _rl_screenwidth;
244458314Sache
244558314Sache  if (nleft > 0)
244675409Sache    ret = 1 + nleft / _rl_screenwidth;
244758314Sache  else
244858314Sache    ret = 0;
244958314Sache
245058314Sache  return ret;
245158314Sache}
2452119614Sache
2453119614Sache#if defined (HANDLE_MULTIBYTE)
2454119614Sache/* Calculate the number of screen columns occupied by STR from START to END.
2455119614Sache   In the case of multibyte characters with stateful encoding, we have to
2456119614Sache   scan from the beginning of the string to take the state into account. */
2457119614Sachestatic int
2458119614Sache_rl_col_width (str, start, end)
2459136759Speter     const char *str;
2460119614Sache     int start, end;
2461119614Sache{
2462119614Sache  wchar_t wc;
2463165675Sache  mbstate_t ps;
2464119614Sache  int tmp, point, width, max;
2465119614Sache
2466119614Sache  if (end <= start)
2467119614Sache    return 0;
2468165680Sache  if (MB_CUR_MAX == 1 || rl_byte_oriented)
2469165680Sache    return (end - start);
2470119614Sache
2471165675Sache  memset (&ps, 0, sizeof (mbstate_t));
2472165675Sache
2473119614Sache  point = 0;
2474119614Sache  max = end;
2475119614Sache
2476119614Sache  while (point < start)
2477119614Sache    {
2478119614Sache      tmp = mbrlen (str + point, max, &ps);
2479136759Speter      if (MB_INVALIDCH ((size_t)tmp))
2480119614Sache	{
2481119614Sache	  /* In this case, the bytes are invalid or too short to compose a
2482119614Sache	     multibyte character, so we assume that the first byte represents
2483119614Sache	     a single character. */
2484119614Sache	  point++;
2485119614Sache	  max--;
2486119614Sache
2487119614Sache	  /* Clear the state of the byte sequence, because in this case the
2488119614Sache	     effect of mbstate is undefined. */
2489119614Sache	  memset (&ps, 0, sizeof (mbstate_t));
2490119614Sache	}
2491136759Speter      else if (MB_NULLWCH (tmp))
2492136759Speter	break;		/* Found '\0' */
2493119614Sache      else
2494119614Sache	{
2495119614Sache	  point += tmp;
2496119614Sache	  max -= tmp;
2497119614Sache	}
2498119614Sache    }
2499119614Sache
2500119614Sache  /* If START is not a byte that starts a character, then POINT will be
2501119614Sache     greater than START.  In this case, assume that (POINT - START) gives
2502119614Sache     a byte count that is the number of columns of difference. */
2503119614Sache  width = point - start;
2504119614Sache
2505119614Sache  while (point < end)
2506119614Sache    {
2507119614Sache      tmp = mbrtowc (&wc, str + point, max, &ps);
2508136759Speter      if (MB_INVALIDCH ((size_t)tmp))
2509119614Sache	{
2510119614Sache	  /* In this case, the bytes are invalid or too short to compose a
2511119614Sache	     multibyte character, so we assume that the first byte represents
2512119614Sache	     a single character. */
2513119614Sache	  point++;
2514119614Sache	  max--;
2515119614Sache
2516119614Sache	  /* and assume that the byte occupies a single column. */
2517119614Sache	  width++;
2518119614Sache
2519119614Sache	  /* Clear the state of the byte sequence, because in this case the
2520119614Sache	     effect of mbstate is undefined. */
2521119614Sache	  memset (&ps, 0, sizeof (mbstate_t));
2522119614Sache	}
2523136759Speter      else if (MB_NULLWCH (tmp))
2524136759Speter	break;			/* Found '\0' */
2525119614Sache      else
2526119614Sache	{
2527119614Sache	  point += tmp;
2528119614Sache	  max -= tmp;
2529119614Sache	  tmp = wcwidth(wc);
2530119614Sache	  width += (tmp >= 0) ? tmp : 1;
2531119614Sache	}
2532119614Sache    }
2533119614Sache
2534119614Sache  width += point - end;
2535119614Sache
2536119614Sache  return width;
2537119614Sache}
2538119614Sache#endif /* HANDLE_MULTIBYTE */
2539