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,
395136759Speter				       (int *)NULL,
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,
402136759Speter						   &prompt_invis_chars_first_line,
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
91421308Sache#define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
91521308Sache#define VIS_LLEN(l)	((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
91621308Sache#define INV_LLEN(l)	(inv_lbreaks[l+1] - inv_lbreaks[l])
91721308Sache#define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
91821308Sache#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
91921308Sache#define INV_LINE(line) (invisible_line + inv_lbreaks[line])
92021308Sache
92121308Sache	  /* For each line in the buffer, do the updating display. */
92221308Sache	  for (linenum = 0; linenum <= inv_botlin; linenum++)
92321308Sache	    {
924165675Sache	      /* This can lead us astray if we execute a program that changes
925165675Sache		 the locale from a non-multibyte to a multibyte one. */
926157188Sache	      o_cpos = _rl_last_c_pos;
927157188Sache	      cpos_adjusted = 0;
92821308Sache	      update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum,
92921308Sache			   VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin);
93021308Sache
931157188Sache	      /* update_line potentially changes _rl_last_c_pos, but doesn't
932157188Sache		 take invisible characters into account, since _rl_last_c_pos
933157188Sache		 is an absolute cursor position in a multibyte locale.  See
934157188Sache		 if compensating here is the right thing, or if we have to
935157188Sache		 change update_line itself.  There is one case in which
936157188Sache		 update_line adjusts _rl_last_c_pos itself (so it can pass
937157188Sache		 _rl_move_cursor_relative accurate values); it communicates
938165675Sache		 this back by setting cpos_adjusted.  If we assume that
939165675Sache		 _rl_last_c_pos is correct (an absolute cursor position) each
940165675Sache		 time update_line is called, then we can assume in our
941165675Sache		 calculations that o_cpos does not need to be adjusted by
942165675Sache		 wrap_offset. */
943157188Sache	      if (linenum == 0 && (MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
944157188Sache		  cpos_adjusted == 0 &&
945157188Sache		  _rl_last_c_pos != o_cpos &&
946157188Sache		  _rl_last_c_pos > wrap_offset &&
947157188Sache		  o_cpos < prompt_last_invisible)
948157188Sache		_rl_last_c_pos -= wrap_offset;
949157188Sache
95021308Sache	      /* If this is the line with the prompt, we might need to
95121308Sache		 compensate for invisible characters in the new line. Do
95221308Sache		 this only if there is not more than one new line (which
95321308Sache		 implies that we completely overwrite the old visible line)
95421308Sache		 and the new line is shorter than the old.  Make sure we are
95521308Sache		 at the end of the new line before clearing. */
95621308Sache	      if (linenum == 0 &&
95721308Sache		  inv_botlin == 0 && _rl_last_c_pos == out &&
95821308Sache		  (wrap_offset > visible_wrap_offset) &&
95921308Sache		  (_rl_last_c_pos < visible_first_line_len))
96021308Sache		{
961157188Sache		  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
962157188Sache		    nleft = _rl_screenwidth - _rl_last_c_pos;
963157188Sache		  else
964157188Sache		    nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos;
96521308Sache		  if (nleft)
96626497Sache		    _rl_clear_to_eol (nleft);
96721308Sache		}
96821308Sache
96921308Sache	      /* Since the new first line is now visible, save its length. */
97021308Sache	      if (linenum == 0)
97121308Sache		visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset;
97221308Sache	    }
97321308Sache
97421308Sache	  /* We may have deleted some lines.  If so, clear the left over
97521308Sache	     blank ones at the bottom out. */
97621308Sache	  if (_rl_vis_botlin > inv_botlin)
97721308Sache	    {
97821308Sache	      char *tt;
97921308Sache	      for (; linenum <= _rl_vis_botlin; linenum++)
98021308Sache		{
98121308Sache		  tt = VIS_CHARS (linenum);
98221308Sache		  _rl_move_vert (linenum);
98321308Sache		  _rl_move_cursor_relative (0, tt);
98426497Sache		  _rl_clear_to_eol
98575409Sache		    ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth);
98621308Sache		}
98721308Sache	    }
98821308Sache	  _rl_vis_botlin = inv_botlin;
98921308Sache
99021308Sache	  /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
99121308Sache	     different screen line during this redisplay. */
99221308Sache	  changed_screen_line = _rl_last_v_pos != cursor_linenum;
99321308Sache	  if (changed_screen_line)
99421308Sache	    {
99521308Sache	      _rl_move_vert (cursor_linenum);
99675409Sache	      /* If we moved up to the line with the prompt using _rl_term_up,
99747563Sache		 the physical cursor position on the screen stays the same,
99847563Sache		 but the buffer position needs to be adjusted to account
99947563Sache		 for invisible characters. */
1000157188Sache	      if ((MB_CUR_MAX == 1 || rl_byte_oriented) && cursor_linenum == 0 && wrap_offset)
100147563Sache		_rl_last_c_pos += wrap_offset;
100221308Sache	    }
100321308Sache
100421308Sache	  /* We have to reprint the prompt if it contains invisible
100521308Sache	     characters, since it's not generally OK to just reprint
100621308Sache	     the characters from the current cursor position.  But we
100721308Sache	     only need to reprint it if the cursor is before the last
100821308Sache	     invisible character in the prompt string. */
100975409Sache	  nleft = prompt_visible_length + wrap_offset;
101021308Sache	  if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
1011165675Sache#if 0
1012165675Sache	      _rl_last_c_pos <= PROMPT_ENDING_INDEX && local_prompt)
1013165675Sache#else
1014165675Sache	      _rl_last_c_pos < PROMPT_ENDING_INDEX && local_prompt)
1015165675Sache#endif
101621308Sache	    {
101758314Sache#if defined (__MSDOS__)
101858314Sache	      putc ('\r', rl_outstream);
101958314Sache#else
102075409Sache	      if (_rl_term_cr)
102175409Sache		tputs (_rl_term_cr, 1, _rl_output_character_function);
102258314Sache#endif
102321308Sache	      _rl_output_some_chars (local_prompt, nleft);
1024119614Sache	      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1025157188Sache		_rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft) - wrap_offset;
1026119614Sache	      else
1027119614Sache		_rl_last_c_pos = nleft;
102821308Sache	    }
102921308Sache
103021308Sache	  /* Where on that line?  And where does that line start
103121308Sache	     in the buffer? */
103221308Sache	  pos = inv_lbreaks[cursor_linenum];
103321308Sache	  /* nleft == number of characters in the line buffer between the
1034165675Sache	     start of the line and the desired cursor position. */
1035165675Sache	  nleft = cpos_buffer_position - pos;
103621308Sache
1037157188Sache	  /* NLEFT is now a number of characters in a buffer.  When in a
1038157188Sache	     multibyte locale, however, _rl_last_c_pos is an absolute cursor
1039157188Sache	     position that doesn't take invisible characters in the prompt
1040157188Sache	     into account.  We use a fudge factor to compensate. */
1041157188Sache
104221308Sache	  /* Since _rl_backspace() doesn't know about invisible characters in the
104321308Sache	     prompt, and there's no good way to tell it, we compensate for
104421308Sache	     those characters here and call _rl_backspace() directly. */
104521308Sache	  if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
104621308Sache	    {
1047165675Sache	      /* TX == new physical cursor position in multibyte locale. */
1048119614Sache	      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1049157188Sache		tx = _rl_col_width (&visible_line[pos], 0, nleft) - visible_wrap_offset;
1050119614Sache	      else
1051157188Sache		tx = nleft;
1052157188Sache	      if (_rl_last_c_pos > tx)
1053157188Sache		{
1054157188Sache	          _rl_backspace (_rl_last_c_pos - tx);	/* XXX */
1055157188Sache	          _rl_last_c_pos = tx;
1056157188Sache		}
105721308Sache	    }
105821308Sache
1059157188Sache	  /* We need to note that in a multibyte locale we are dealing with
1060157188Sache	     _rl_last_c_pos as an absolute cursor position, but moving to a
1061157188Sache	     point specified by a buffer position (NLEFT) that doesn't take
1062157188Sache	     invisible characters into account. */
1063119614Sache	  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
106421308Sache	    _rl_move_cursor_relative (nleft, &invisible_line[pos]);
1065119614Sache	  else if (nleft != _rl_last_c_pos)
1066119614Sache	    _rl_move_cursor_relative (nleft, &invisible_line[pos]);
106721308Sache	}
106821308Sache    }
106921308Sache  else				/* Do horizontal scrolling. */
107021308Sache    {
107121308Sache#define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
107221308Sache      int lmargin, ndisp, nleft, phys_c_pos, t;
107321308Sache
107421308Sache      /* Always at top line. */
107521308Sache      _rl_last_v_pos = 0;
107621308Sache
107721308Sache      /* Compute where in the buffer the displayed line should start.  This
107821308Sache	 will be LMARGIN. */
107921308Sache
108021308Sache      /* The number of characters that will be displayed before the cursor. */
1081165675Sache      ndisp = cpos_buffer_position - wrap_offset;
108275409Sache      nleft  = prompt_visible_length + wrap_offset;
108321308Sache      /* Where the new cursor position will be on the screen.  This can be
108447563Sache	 longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
1085165675Sache      phys_c_pos = cpos_buffer_position - (last_lmargin ? last_lmargin : wrap_offset);
108675409Sache      t = _rl_screenwidth / 3;
108721308Sache
108821308Sache      /* If the number of characters had already exceeded the screenwidth,
108947563Sache	 last_lmargin will be > 0. */
109021308Sache
109121308Sache      /* If the number of characters to be displayed is more than the screen
109247563Sache	 width, compute the starting offset so that the cursor is about
109347563Sache	 two-thirds of the way across the screen. */
109475409Sache      if (phys_c_pos > _rl_screenwidth - 2)
109521308Sache	{
1096165675Sache	  lmargin = cpos_buffer_position - (2 * t);
109721308Sache	  if (lmargin < 0)
109821308Sache	    lmargin = 0;
109921308Sache	  /* If the left margin would be in the middle of a prompt with
110021308Sache	     invisible characters, don't display the prompt at all. */
110121308Sache	  if (wrap_offset && lmargin > 0 && lmargin < nleft)
110221308Sache	    lmargin = nleft;
110321308Sache	}
110475409Sache      else if (ndisp < _rl_screenwidth - 2)		/* XXX - was -1 */
110547563Sache	lmargin = 0;
110621308Sache      else if (phys_c_pos < 1)
110721308Sache	{
110821308Sache	  /* If we are moving back towards the beginning of the line and
110921308Sache	     the last margin is no longer correct, compute a new one. */
1110165675Sache	  lmargin = ((cpos_buffer_position - 1) / t) * t;	/* XXX */
111121308Sache	  if (wrap_offset && lmargin > 0 && lmargin < nleft)
111221308Sache	    lmargin = nleft;
111321308Sache	}
111421308Sache      else
111547563Sache	lmargin = last_lmargin;
111621308Sache
111721308Sache      /* If the first character on the screen isn't the first character
111821308Sache	 in the display line, indicate this with a special character. */
111921308Sache      if (lmargin > 0)
112021308Sache	line[lmargin] = '<';
112121308Sache
112221308Sache      /* If SCREENWIDTH characters starting at LMARGIN do not encompass
112347563Sache	 the whole line, indicate that with a special character at the
112447563Sache	 right edge of the screen.  If LMARGIN is 0, we need to take the
112547563Sache	 wrap offset into account. */
112675409Sache      t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth;
112721308Sache      if (t < out)
112847563Sache	line[t - 1] = '>';
112921308Sache
113021308Sache      if (!rl_display_fixed || forced_display || lmargin != last_lmargin)
113121308Sache	{
113221308Sache	  forced_display = 0;
113321308Sache	  update_line (&visible_line[last_lmargin],
113421308Sache		       &invisible_line[lmargin],
113521308Sache		       0,
113675409Sache		       _rl_screenwidth + visible_wrap_offset,
113775409Sache		       _rl_screenwidth + (lmargin ? 0 : wrap_offset),
113821308Sache		       0);
113921308Sache
114021308Sache	  /* If the visible new line is shorter than the old, but the number
114121308Sache	     of invisible characters is greater, and we are at the end of
114221308Sache	     the new line, we need to clear to eol. */
114321308Sache	  t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
114421308Sache	  if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
114521308Sache	      (_rl_last_c_pos == out) &&
114621308Sache	      t < visible_first_line_len)
114721308Sache	    {
114875409Sache	      nleft = _rl_screenwidth - t;
114926497Sache	      _rl_clear_to_eol (nleft);
115021308Sache	    }
115121308Sache	  visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
115275409Sache	  if (visible_first_line_len > _rl_screenwidth)
115375409Sache	    visible_first_line_len = _rl_screenwidth;
115421308Sache
1155165675Sache	  _rl_move_cursor_relative (cpos_buffer_position - lmargin, &invisible_line[lmargin]);
115621308Sache	  last_lmargin = lmargin;
115721308Sache	}
115821308Sache    }
115921308Sache  fflush (rl_outstream);
116021308Sache
116121308Sache  /* Swap visible and non-visible lines. */
116221308Sache  {
116375409Sache    char *vtemp = visible_line;
116458314Sache    int *itemp = vis_lbreaks, ntemp = vis_lbsize;
116558314Sache
116621308Sache    visible_line = invisible_line;
116775409Sache    invisible_line = vtemp;
116858314Sache
116921308Sache    vis_lbreaks = inv_lbreaks;
117021308Sache    inv_lbreaks = itemp;
117158314Sache
117258314Sache    vis_lbsize = inv_lbsize;
117358314Sache    inv_lbsize = ntemp;
117458314Sache
117521308Sache    rl_display_fixed = 0;
117621308Sache    /* If we are displaying on a single line, and last_lmargin is > 0, we
117721308Sache       are not displaying any invisible characters, so set visible_wrap_offset
117821308Sache       to 0. */
117921308Sache    if (_rl_horizontal_scroll_mode && last_lmargin)
118021308Sache      visible_wrap_offset = 0;
118121308Sache    else
118221308Sache      visible_wrap_offset = wrap_offset;
118321308Sache  }
118421308Sache}
118521308Sache
118621308Sache/* PWP: update_line() is based on finding the middle difference of each
118721308Sache   line on the screen; vis:
118821308Sache
118921308Sache			     /old first difference
119021308Sache	/beginning of line   |	      /old last same       /old EOL
119121308Sache	v		     v	      v		    v
119221308Sacheold:	eddie> Oh, my little gruntle-buggy is to me, as lurgid as
119321308Sachenew:	eddie> Oh, my little buggy says to me, as lurgid as
119421308Sache	^		     ^	^			   ^
119521308Sache	\beginning of line   |	\new last same	   \new end of line
119621308Sache			     \new first difference
119721308Sache
119821308Sache   All are character pointers for the sake of speed.  Special cases for
119947563Sache   no differences, as well as for end of line additions must be handled.
120021308Sache
120121308Sache   Could be made even smarter, but this works well enough */
120221308Sachestatic void
120321308Sacheupdate_line (old, new, current_line, omax, nmax, inv_botlin)
120421308Sache     register char *old, *new;
120521308Sache     int current_line, omax, nmax, inv_botlin;
120621308Sache{
120721308Sache  register char *ofd, *ols, *oe, *nfd, *nls, *ne;
120821308Sache  int temp, lendiff, wsatend, od, nd;
120921308Sache  int current_invis_chars;
1210119614Sache  int col_lendiff, col_temp;
1211119614Sache#if defined (HANDLE_MULTIBYTE)
1212119614Sache  mbstate_t ps_new, ps_old;
1213165675Sache  int new_offset, old_offset;
1214119614Sache#endif
121521308Sache
121621308Sache  /* If we're at the right edge of a terminal that supports xn, we're
121721308Sache     ready to wrap around, so do so.  This fixes problems with knowing
121821308Sache     the exact cursor position and cut-and-paste with certain terminal
121921308Sache     emulators.  In this calculation, TEMP is the physical screen
122021308Sache     position of the cursor. */
1221157188Sache  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1222157188Sache    temp = _rl_last_c_pos;
1223157188Sache  else
1224157188Sache    temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
122575409Sache  if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
1226119614Sache	&& _rl_last_v_pos == current_line - 1)
122721308Sache    {
1228119614Sache#if defined (HANDLE_MULTIBYTE)
1229119614Sache      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1230119614Sache	{
1231119614Sache	  wchar_t wc;
1232119614Sache	  mbstate_t ps;
1233119614Sache	  int tempwidth, bytes;
1234119614Sache	  size_t ret;
1235119614Sache
1236119614Sache	  /* This fixes only double-column characters, but if the wrapped
1237119614Sache	     character comsumes more than three columns, spaces will be
1238119614Sache	     inserted in the string buffer. */
1239119614Sache	  if (_rl_wrapped_line[current_line] > 0)
1240119614Sache	    _rl_clear_to_eol (_rl_wrapped_line[current_line]);
1241119614Sache
1242119614Sache	  memset (&ps, 0, sizeof (mbstate_t));
1243119614Sache	  ret = mbrtowc (&wc, new, MB_CUR_MAX, &ps);
1244136759Speter	  if (MB_INVALIDCH (ret))
1245119614Sache	    {
1246119614Sache	      tempwidth = 1;
1247119614Sache	      ret = 1;
1248119614Sache	    }
1249136759Speter	  else if (MB_NULLWCH (ret))
1250119614Sache	    tempwidth = 0;
1251119614Sache	  else
1252119614Sache	    tempwidth = wcwidth (wc);
1253119614Sache
1254119614Sache	  if (tempwidth > 0)
1255119614Sache	    {
1256119614Sache	      int count;
1257119614Sache	      bytes = ret;
1258119614Sache	      for (count = 0; count < bytes; count++)
1259119614Sache		putc (new[count], rl_outstream);
1260119614Sache	      _rl_last_c_pos = tempwidth;
1261119614Sache	      _rl_last_v_pos++;
1262119614Sache	      memset (&ps, 0, sizeof (mbstate_t));
1263119614Sache	      ret = mbrtowc (&wc, old, MB_CUR_MAX, &ps);
1264119614Sache	      if (ret != 0 && bytes != 0)
1265119614Sache		{
1266136759Speter		  if (MB_INVALIDCH (ret))
1267119614Sache		    memmove (old+bytes, old+1, strlen (old+1));
1268119614Sache		  else
1269119614Sache		    memmove (old+bytes, old+ret, strlen (old+ret));
1270119614Sache		  memcpy (old, new, bytes);
1271119614Sache		}
1272119614Sache	    }
1273119614Sache	  else
1274119614Sache	    {
1275119614Sache	      putc (' ', rl_outstream);
1276119614Sache	      _rl_last_c_pos = 1;
1277119614Sache	      _rl_last_v_pos++;
1278119614Sache	      if (old[0] && new[0])
1279119614Sache		old[0] = new[0];
1280119614Sache	    }
1281119614Sache	}
128221308Sache      else
1283119614Sache#endif
1284119614Sache	{
1285119614Sache	  if (new[0])
1286119614Sache	    putc (new[0], rl_outstream);
1287119614Sache	  else
1288119614Sache	    putc (' ', rl_outstream);
1289157188Sache	  _rl_last_c_pos = 1;
1290119614Sache	  _rl_last_v_pos++;
1291119614Sache	  if (old[0] && new[0])
1292119614Sache	    old[0] = new[0];
1293119614Sache	}
129421308Sache    }
1295119614Sache
129621308Sache
129721308Sache  /* Find first difference. */
1298119614Sache#if defined (HANDLE_MULTIBYTE)
1299119614Sache  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1300119614Sache    {
1301136759Speter      /* See if the old line is a subset of the new line, so that the
1302136759Speter	 only change is adding characters. */
1303136759Speter      temp = (omax < nmax) ? omax : nmax;
1304136759Speter      if (memcmp (old, new, temp) == 0)
1305119614Sache	{
1306136759Speter	  ofd = old + temp;
1307136759Speter	  nfd = new + temp;
1308119614Sache	}
1309136759Speter      else
1310136759Speter	{
1311136759Speter	  memset (&ps_new, 0, sizeof(mbstate_t));
1312136759Speter	  memset (&ps_old, 0, sizeof(mbstate_t));
1313136759Speter
1314136759Speter	  if (omax == nmax && STREQN (new, old, omax))
1315136759Speter	    {
1316136759Speter	      ofd = old + omax;
1317136759Speter	      nfd = new + nmax;
1318136759Speter	    }
1319136759Speter	  else
1320136759Speter	    {
1321136759Speter	      new_offset = old_offset = 0;
1322136759Speter	      for (ofd = old, nfd = new;
1323136759Speter		    (ofd - old < omax) && *ofd &&
1324136759Speter		    _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new); )
1325136759Speter		{
1326136759Speter		  old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY);
1327136759Speter		  new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY);
1328136759Speter		  ofd = old + old_offset;
1329136759Speter		  nfd = new + new_offset;
1330136759Speter		}
1331136759Speter	    }
1332136759Speter	}
1333119614Sache    }
1334119614Sache  else
1335119614Sache#endif
133621308Sache  for (ofd = old, nfd = new;
133721308Sache       (ofd - old < omax) && *ofd && (*ofd == *nfd);
133821308Sache       ofd++, nfd++)
133921308Sache    ;
134021308Sache
134121308Sache  /* Move to the end of the screen line.  ND and OD are used to keep track
134221308Sache     of the distance between ne and new and oe and old, respectively, to
134321308Sache     move a subtraction out of each loop. */
134421308Sache  for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
134521308Sache  for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
134621308Sache
134721308Sache  /* If no difference, continue to next line. */
134821308Sache  if (ofd == oe && nfd == ne)
134921308Sache    return;
135021308Sache
135121308Sache  wsatend = 1;			/* flag for trailing whitespace */
1352119614Sache
1353119614Sache#if defined (HANDLE_MULTIBYTE)
1354119614Sache  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1355119614Sache    {
1356119614Sache      ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY);
1357119614Sache      nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY);
1358119614Sache      while ((ols > ofd) && (nls > nfd))
1359119614Sache	{
1360119614Sache	  memset (&ps_old, 0, sizeof (mbstate_t));
1361119614Sache	  memset (&ps_new, 0, sizeof (mbstate_t));
1362119614Sache
1363136759Speter#if 0
1364136759Speter	  /* On advice from jir@yamato.ibm.com */
1365119614Sache	  _rl_adjust_point (old, ols - old, &ps_old);
1366119614Sache	  _rl_adjust_point (new, nls - new, &ps_new);
1367136759Speter#endif
1368119614Sache
1369119614Sache	  if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0)
1370119614Sache	    break;
1371119614Sache
1372119614Sache	  if (*ols == ' ')
1373119614Sache	    wsatend = 0;
1374119614Sache
1375119614Sache	  ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY);
1376119614Sache	  nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY);
1377119614Sache	}
1378119614Sache    }
1379119614Sache  else
1380119614Sache    {
1381119614Sache#endif /* HANDLE_MULTIBYTE */
138221308Sache  ols = oe - 1;			/* find last same */
138321308Sache  nls = ne - 1;
138421308Sache  while ((ols > ofd) && (nls > nfd) && (*ols == *nls))
138521308Sache    {
138621308Sache      if (*ols != ' ')
138721308Sache	wsatend = 0;
138821308Sache      ols--;
138921308Sache      nls--;
139021308Sache    }
1391119614Sache#if defined (HANDLE_MULTIBYTE)
1392119614Sache    }
1393119614Sache#endif
139421308Sache
139521308Sache  if (wsatend)
139621308Sache    {
139721308Sache      ols = oe;
139821308Sache      nls = ne;
139921308Sache    }
1400119614Sache#if defined (HANDLE_MULTIBYTE)
1401119614Sache  /* This may not work for stateful encoding, but who cares?  To handle
1402119614Sache     stateful encoding properly, we have to scan each string from the
1403119614Sache     beginning and compare. */
1404119614Sache  else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0)
1405119614Sache#else
140621308Sache  else if (*ols != *nls)
1407119614Sache#endif
140821308Sache    {
140921308Sache      if (*ols)			/* don't step past the NUL */
1410119614Sache	{
1411119614Sache	  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1412119614Sache	    ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY);
1413119614Sache	  else
1414119614Sache	    ols++;
1415119614Sache	}
141621308Sache      if (*nls)
1417119614Sache	{
1418119614Sache	  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1419119614Sache	    nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY);
1420119614Sache	  else
1421119614Sache	    nls++;
1422119614Sache	}
142321308Sache    }
142421308Sache
142521308Sache  /* count of invisible characters in the current invisible line. */
142621308Sache  current_invis_chars = W_OFFSET (current_line, wrap_offset);
142721308Sache  if (_rl_last_v_pos != current_line)
142821308Sache    {
142921308Sache      _rl_move_vert (current_line);
1430157188Sache      if ((MB_CUR_MAX == 1 || rl_byte_oriented) && current_line == 0 && visible_wrap_offset)
143121308Sache	_rl_last_c_pos += visible_wrap_offset;
143221308Sache    }
143321308Sache
143421308Sache  /* If this is the first line and there are invisible characters in the
143521308Sache     prompt string, and the prompt string has not changed, and the current
143621308Sache     cursor position is before the last invisible character in the prompt,
143721308Sache     and the index of the character to move to is past the end of the prompt
143821308Sache     string, then redraw the entire prompt string.  We can only do this
143921308Sache     reliably if the terminal supports a `cr' capability.
144021308Sache
144121308Sache     This is not an efficiency hack -- there is a problem with redrawing
144221308Sache     portions of the prompt string if they contain terminal escape
144321308Sache     sequences (like drawing the `unbold' sequence without a corresponding
144421308Sache     `bold') that manifests itself on certain terminals. */
144521308Sache
1446165675Sache  lendiff = local_prompt_len;
144721308Sache  od = ofd - old;	/* index of first difference in visible line */
144821308Sache  if (current_line == 0 && !_rl_horizontal_scroll_mode &&
144975409Sache      _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 &&
1450165675Sache      od >= lendiff && _rl_last_c_pos < PROMPT_ENDING_INDEX)
145121308Sache    {
145258314Sache#if defined (__MSDOS__)
145358314Sache      putc ('\r', rl_outstream);
145458314Sache#else
145575409Sache      tputs (_rl_term_cr, 1, _rl_output_character_function);
145658314Sache#endif
145721308Sache      _rl_output_some_chars (local_prompt, lendiff);
1458119614Sache      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1459157188Sache	{
1460157188Sache	  /* We take wrap_offset into account here so we can pass correct
1461157188Sache	     information to _rl_move_cursor_relative. */
1462157188Sache	  _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff) - wrap_offset;
1463157188Sache	  cpos_adjusted = 1;
1464157188Sache	}
1465119614Sache      else
1466119614Sache	_rl_last_c_pos = lendiff;
146721308Sache    }
146821308Sache
1469165675Sache  /* When this function returns, _rl_last_c_pos is correct, and an absolute
1470165675Sache     cursor postion in multibyte mode, but a buffer index when not in a
1471165675Sache     multibyte locale. */
147221308Sache  _rl_move_cursor_relative (od, old);
1473165675Sache#if 1
1474165675Sache#if defined (HANDLE_MULTIBYTE)
1475165675Sache  /* We need to indicate that the cursor position is correct in the presence of
1476165675Sache     invisible characters in the prompt string.  Let's see if setting this when
1477165675Sache     we make sure we're at the end of the drawn prompt string works. */
1478165675Sache  if (current_line == 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0 && _rl_last_c_pos == prompt_physical_chars)
1479165675Sache    cpos_adjusted = 1;
1480165675Sache#endif
1481165675Sache#endif
148221308Sache
1483119614Sache  /* if (len (new) > len (old))
1484119614Sache     lendiff == difference in buffer
1485119614Sache     col_lendiff == difference on screen
1486119614Sache     When not using multibyte characters, these are equal */
148721308Sache  lendiff = (nls - nfd) - (ols - ofd);
1488119614Sache  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1489119614Sache    col_lendiff = _rl_col_width (new, nfd - new, nls - new) - _rl_col_width (old, ofd - old, ols - old);
1490119614Sache  else
1491119614Sache    col_lendiff = lendiff;
149221308Sache
149321308Sache  /* If we are changing the number of invisible characters in a line, and
149421308Sache     the spot of first difference is before the end of the invisible chars,
149521308Sache     lendiff needs to be adjusted. */
149621308Sache  if (current_line == 0 && !_rl_horizontal_scroll_mode &&
149721308Sache      current_invis_chars != visible_wrap_offset)
1498119614Sache    {
1499119614Sache      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1500119614Sache	{
1501119614Sache	  lendiff += visible_wrap_offset - current_invis_chars;
1502119614Sache	  col_lendiff += visible_wrap_offset - current_invis_chars;
1503119614Sache	}
1504119614Sache      else
1505119614Sache	{
1506119614Sache	  lendiff += visible_wrap_offset - current_invis_chars;
1507119614Sache	  col_lendiff = lendiff;
1508119614Sache	}
1509119614Sache    }
151021308Sache
151121308Sache  /* Insert (diff (len (old), len (new)) ch. */
151221308Sache  temp = ne - nfd;
1513119614Sache  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1514119614Sache    col_temp = _rl_col_width (new, nfd - new, ne - new);
1515119614Sache  else
1516119614Sache    col_temp = temp;
1517119614Sache
1518119614Sache  if (col_lendiff > 0)	/* XXX - was lendiff */
151921308Sache    {
152021308Sache      /* Non-zero if we're increasing the number of lines. */
152121308Sache      int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
1522173406Sache      /* If col_lendiff is > 0, implying that the new string takes up more
1523173406Sache	 screen real estate than the old, but lendiff is < 0, meaning that it
1524173406Sache	 takes fewer bytes, we need to just output the characters starting
1525173406Sache	 from the first difference.  These will overwrite what is on the
1526173406Sache	 display, so there's no reason to do a smart update.  This can really
1527173406Sache	 only happen in a multibyte environment. */
1528173406Sache      if (lendiff < 0)
1529173406Sache	{
1530173406Sache	  _rl_output_some_chars (nfd, temp);
1531173406Sache	  _rl_last_c_pos += _rl_col_width (nfd, 0, temp);
1532173406Sache	  /* If nfd begins before any invisible characters in the prompt,
1533173406Sache	     adjust _rl_last_c_pos to account for wrap_offset and set
1534173406Sache	     cpos_adjusted to let the caller know. */
1535173406Sache	  if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible))
1536173406Sache	    {
1537173406Sache	      _rl_last_c_pos -= wrap_offset;
1538173406Sache	      cpos_adjusted = 1;
1539173406Sache	    }
1540173406Sache	  return;
1541173406Sache	}
154221308Sache      /* Sometimes it is cheaper to print the characters rather than
154321308Sache	 use the terminal's capabilities.  If we're growing the number
154421308Sache	 of lines, make sure we actually cause the new line to wrap
154521308Sache	 around on auto-wrapping terminals. */
1546173406Sache      else if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
154721308Sache	{
154875409Sache	  /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
154921308Sache	     _rl_horizontal_scroll_mode == 1, inserting the characters with
155075409Sache	     _rl_term_IC or _rl_term_ic will screw up the screen because of the
155121308Sache	     invisible characters.  We need to just draw them. */
155221308Sache	  if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 ||
155375409Sache			lendiff <= prompt_visible_length || !current_invis_chars))
155421308Sache	    {
1555119614Sache	      insert_some_chars (nfd, lendiff, col_lendiff);
1556119614Sache	      _rl_last_c_pos += col_lendiff;
155721308Sache	    }
1558157188Sache	  else if ((MB_CUR_MAX == 1 || rl_byte_oriented != 0) && *ols == 0 && lendiff > 0)
155921308Sache	    {
156021308Sache	      /* At the end of a line the characters do not have to
156121308Sache		 be "inserted".  They can just be placed on the screen. */
156221308Sache	      /* However, this screws up the rest of this block, which
156347563Sache		 assumes you've done the insert because you can. */
156421308Sache	      _rl_output_some_chars (nfd, lendiff);
1565119614Sache	      _rl_last_c_pos += col_lendiff;
156621308Sache	    }
156721308Sache	  else
156821308Sache	    {
156921308Sache	      /* We have horizontal scrolling and we are not inserting at
157021308Sache		 the end.  We have invisible characters in this line.  This
157121308Sache		 is a dumb update. */
157221308Sache	      _rl_output_some_chars (nfd, temp);
1573119614Sache	      _rl_last_c_pos += col_temp;
157421308Sache	      return;
157521308Sache	    }
157621308Sache	  /* Copy (new) chars to screen from first diff to last match. */
157721308Sache	  temp = nls - nfd;
157821308Sache	  if ((temp - lendiff) > 0)
157921308Sache	    {
158021308Sache	      _rl_output_some_chars (nfd + lendiff, temp - lendiff);
1581136759Speter#if 1
1582136759Speter	     /* XXX -- this bears closer inspection.  Fixes a redisplay bug
1583136759Speter		reported against bash-3.0-alpha by Andreas Schwab involving
1584136759Speter		multibyte characters and prompt strings with invisible
1585136759Speter		characters, but was previously disabled. */
1586136759Speter	      _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-col_lendiff);
1587119614Sache#else
1588136759Speter	      _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-lendiff);
1589119614Sache#endif
159021308Sache	    }
159121308Sache	}
159221308Sache      else
159321308Sache	{
159421308Sache	  /* cannot insert chars, write to EOL */
159521308Sache	  _rl_output_some_chars (nfd, temp);
1596119614Sache	  _rl_last_c_pos += col_temp;
1597157188Sache	  /* If we're in a multibyte locale and were before the last invisible
1598157188Sache	     char in the current line (which implies we just output some invisible
1599157188Sache	     characters) we need to adjust _rl_last_c_pos, since it represents
1600157188Sache	     a physical character position. */
160121308Sache	}
160221308Sache    }
160321308Sache  else				/* Delete characters from line. */
160421308Sache    {
160521308Sache      /* If possible and inexpensive to use terminal deletion, then do so. */
1606119614Sache      if (_rl_term_dc && (2 * col_temp) >= -col_lendiff)
160721308Sache	{
160821308Sache	  /* If all we're doing is erasing the invisible characters in the
160921308Sache	     prompt string, don't bother.  It screws up the assumptions
161021308Sache	     about what's on the screen. */
161121308Sache	  if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
161221308Sache	      -lendiff == visible_wrap_offset)
1613119614Sache	    col_lendiff = 0;
161421308Sache
1615119614Sache	  if (col_lendiff)
1616119614Sache	    delete_chars (-col_lendiff); /* delete (diff) characters */
161721308Sache
161821308Sache	  /* Copy (new) chars to screen from first diff to last match */
161921308Sache	  temp = nls - nfd;
162021308Sache	  if (temp > 0)
162121308Sache	    {
1622173406Sache	      /* If nfd begins at the prompt, or before the invisible
1623173406Sache		 characters in the prompt, we need to adjust _rl_last_c_pos
1624173406Sache		 in a multibyte locale to account for the wrap offset and
1625173406Sache		 set cpos_adjusted accordingly. */
162621308Sache	      _rl_output_some_chars (nfd, temp);
1627173406Sache	      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1628173406Sache		{
1629173406Sache                  _rl_last_c_pos += _rl_col_width (nfd, 0, temp);
1630173406Sache                  if (current_line == 0 && wrap_offset &&  ((nfd - new) <= prompt_last_invisible))
1631173406Sache		    {
1632173406Sache		      _rl_last_c_pos -= wrap_offset;
1633173406Sache		      cpos_adjusted = 1;
1634173406Sache		    }
1635173406Sache		}
1636173406Sache              else
1637173406Sache                _rl_last_c_pos += temp;
163821308Sache	    }
163921308Sache	}
164021308Sache      /* Otherwise, print over the existing material. */
164121308Sache      else
164221308Sache	{
164321308Sache	  if (temp > 0)
164421308Sache	    {
1645173406Sache	      /* If nfd begins at the prompt, or before the invisible
1646173406Sache		 characters in the prompt, we need to adjust _rl_last_c_pos
1647173406Sache		 in a multibyte locale to account for the wrap offset and
1648173406Sache		 set cpos_adjusted accordingly. */
164921308Sache	      _rl_output_some_chars (nfd, temp);
1650157188Sache	      _rl_last_c_pos += col_temp;		/* XXX */
1651173406Sache	      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1652173406Sache		{
1653173406Sache		  if (current_line == 0 && wrap_offset &&  ((nfd - new) <= prompt_last_invisible))
1654173406Sache		    {
1655173406Sache		      _rl_last_c_pos -= wrap_offset;
1656173406Sache		      cpos_adjusted = 1;
1657173406Sache		    }
1658173406Sache		}
165921308Sache	    }
166021308Sache	  lendiff = (oe - old) - (ne - new);
1661119614Sache	  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1662119614Sache	    col_lendiff = _rl_col_width (old, 0, oe - old) - _rl_col_width (new, 0, ne - new);
1663119614Sache	  else
1664119614Sache	    col_lendiff = lendiff;
1665119614Sache
1666119614Sache	  if (col_lendiff)
166747563Sache	    {
166847563Sache	      if (_rl_term_autowrap && current_line < inv_botlin)
1669119614Sache		space_to_eol (col_lendiff);
167047563Sache	      else
1671119614Sache		_rl_clear_to_eol (col_lendiff);
167247563Sache	    }
167321308Sache	}
167421308Sache    }
167521308Sache}
167621308Sache
167721308Sache/* Tell the update routines that we have moved onto a new (empty) line. */
167821308Sacheint
167921308Sacherl_on_new_line ()
168021308Sache{
168121308Sache  if (visible_line)
168221308Sache    visible_line[0] = '\0';
168321308Sache
168421308Sache  _rl_last_c_pos = _rl_last_v_pos = 0;
168521308Sache  _rl_vis_botlin = last_lmargin = 0;
168621308Sache  if (vis_lbreaks)
168721308Sache    vis_lbreaks[0] = vis_lbreaks[1] = 0;
168821308Sache  visible_wrap_offset = 0;
168921308Sache  return 0;
169021308Sache}
169121308Sache
169258314Sache/* Tell the update routines that we have moved onto a new line with the
169358314Sache   prompt already displayed.  Code originally from the version of readline
1694136759Speter   distributed with CLISP.  rl_expand_prompt must have already been called
1695136759Speter   (explicitly or implicitly).  This still doesn't work exactly right. */
169658314Sacheint
169758314Sacherl_on_new_line_with_prompt ()
169858314Sache{
169958314Sache  int prompt_size, i, l, real_screenwidth, newlines;
1700136759Speter  char *prompt_last_line, *lprompt;
170158314Sache
170258314Sache  /* Initialize visible_line and invisible_line to ensure that they can hold
170358314Sache     the already-displayed prompt. */
170458314Sache  prompt_size = strlen (rl_prompt) + 1;
170558314Sache  init_line_structures (prompt_size);
170658314Sache
170758314Sache  /* Make sure the line structures hold the already-displayed prompt for
170858314Sache     redisplay. */
1709136759Speter  lprompt = local_prompt ? local_prompt : rl_prompt;
1710136759Speter  strcpy (visible_line, lprompt);
1711136759Speter  strcpy (invisible_line, lprompt);
171258314Sache
171358314Sache  /* If the prompt contains newlines, take the last tail. */
171458314Sache  prompt_last_line = strrchr (rl_prompt, '\n');
171558314Sache  if (!prompt_last_line)
171658314Sache    prompt_last_line = rl_prompt;
171758314Sache
171858314Sache  l = strlen (prompt_last_line);
1719119614Sache  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1720157188Sache    _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l);	/* XXX */
1721119614Sache  else
1722119614Sache    _rl_last_c_pos = l;
172358314Sache
172458314Sache  /* Dissect prompt_last_line into screen lines. Note that here we have
172558314Sache     to use the real screenwidth. Readline's notion of screenwidth might be
172658314Sache     one less, see terminal.c. */
172775409Sache  real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1);
172858314Sache  _rl_last_v_pos = l / real_screenwidth;
172958314Sache  /* If the prompt length is a multiple of real_screenwidth, we don't know
173058314Sache     whether the cursor is at the end of the last line, or already at the
173158314Sache     beginning of the next line. Output a newline just to be safe. */
173258314Sache  if (l > 0 && (l % real_screenwidth) == 0)
173358314Sache    _rl_output_some_chars ("\n", 1);
173458314Sache  last_lmargin = 0;
173558314Sache
173658314Sache  newlines = 0; i = 0;
173758314Sache  while (i <= l)
173858314Sache    {
173958314Sache      _rl_vis_botlin = newlines;
174058314Sache      vis_lbreaks[newlines++] = i;
174158314Sache      i += real_screenwidth;
174258314Sache    }
174358314Sache  vis_lbreaks[newlines] = l;
174458314Sache  visible_wrap_offset = 0;
174558314Sache
1746136759Speter  rl_display_prompt = rl_prompt;	/* XXX - make sure it's set */
1747136759Speter
174858314Sache  return 0;
174958314Sache}
175058314Sache
175121308Sache/* Actually update the display, period. */
175221308Sacheint
175321308Sacherl_forced_update_display ()
175421308Sache{
1755165675Sache  register char *temp;
1756165675Sache
175721308Sache  if (visible_line)
175821308Sache    {
1759165675Sache      temp = visible_line;
176021308Sache      while (*temp)
176147563Sache	*temp++ = '\0';
176221308Sache    }
176321308Sache  rl_on_new_line ();
176421308Sache  forced_display++;
176521308Sache  (*rl_redisplay_function) ();
176621308Sache  return 0;
176721308Sache}
176821308Sache
176921308Sache/* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
1770157188Sache   (Well, when we don't have multibyte characters, _rl_last_c_pos is a
1771157188Sache   buffer index.)
177221308Sache   DATA is the contents of the screen line of interest; i.e., where
177321308Sache   the movement is being done. */
177421308Sachevoid
177521308Sache_rl_move_cursor_relative (new, data)
177621308Sache     int new;
177775409Sache     const char *data;
177821308Sache{
177921308Sache  register int i;
1780157188Sache  int woff;			/* number of invisible chars on current line */
1781157188Sache  int cpos, dpos;		/* current and desired cursor positions */
178221308Sache
1783157188Sache  woff = W_OFFSET (_rl_last_v_pos, wrap_offset);
1784157188Sache  cpos = _rl_last_c_pos;
1785119614Sache#if defined (HANDLE_MULTIBYTE)
1786119614Sache  /* If we have multibyte characters, NEW is indexed by the buffer point in
1787119614Sache     a multibyte string, but _rl_last_c_pos is the display position.  In
1788136759Speter     this case, NEW's display position is not obvious and must be
1789157188Sache     calculated.  We need to account for invisible characters in this line,
1790157188Sache     as long as we are past them and they are counted by _rl_col_width. */
1791157188Sache  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1792136759Speter    {
1793157188Sache      dpos = _rl_col_width (data, 0, new);
1794173406Sache      /* Use NEW when comparing against the last invisible character in the
1795173406Sache	 prompt string, since they're both buffer indices and DPOS is a
1796173406Sache	 desired display position. */
1797173406Sache      if (new > prompt_last_invisible)		/* XXX - don't use woff here */
1798165675Sache	{
1799165675Sache	  dpos -= woff;
1800165675Sache	  /* Since this will be assigned to _rl_last_c_pos at the end (more
1801165675Sache	     precisely, _rl_last_c_pos == dpos when this function returns),
1802165675Sache	     let the caller know. */
1803165675Sache	  cpos_adjusted = 1;
1804165675Sache	}
1805136759Speter    }
1806157188Sache  else
1807119614Sache#endif
1808157188Sache    dpos = new;
180921308Sache
1810157188Sache  /* If we don't have to do anything, then return. */
1811157188Sache  if (cpos == dpos)
1812157188Sache    return;
1813157188Sache
181421308Sache  /* It may be faster to output a CR, and then move forwards instead
181521308Sache     of moving backwards. */
181621308Sache  /* i == current physical cursor position. */
1817157188Sache#if defined (HANDLE_MULTIBYTE)
1818157188Sache  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1819157188Sache    i = _rl_last_c_pos;
1820157188Sache  else
1821157188Sache#endif
1822157188Sache  i = _rl_last_c_pos - woff;
1823165675Sache  if (dpos == 0 || CR_FASTER (dpos, _rl_last_c_pos) ||
182475409Sache      (_rl_term_autowrap && i == _rl_screenwidth))
182521308Sache    {
182621308Sache#if defined (__MSDOS__)
182721308Sache      putc ('\r', rl_outstream);
182821308Sache#else
182975409Sache      tputs (_rl_term_cr, 1, _rl_output_character_function);
183021308Sache#endif /* !__MSDOS__ */
1831157188Sache      cpos = _rl_last_c_pos = 0;
183221308Sache    }
183321308Sache
1834157188Sache  if (cpos < dpos)
183521308Sache    {
183621308Sache      /* Move the cursor forward.  We do it by printing the command
183721308Sache	 to move the cursor forward if there is one, else print that
183821308Sache	 portion of the output buffer again.  Which is cheaper? */
183921308Sache
184021308Sache      /* The above comment is left here for posterity.  It is faster
184121308Sache	 to print one character (non-control) than to print a control
184221308Sache	 sequence telling the terminal to move forward one character.
184321308Sache	 That kind of control is for people who don't know what the
184421308Sache	 data is underneath the cursor. */
1845165675Sache
1846165675Sache      /* However, we need a handle on where the current display position is
1847165675Sache	 in the buffer for the immediately preceding comment to be true.
1848165675Sache	 In multibyte locales, we don't currently have that info available.
1849165675Sache	 Without it, we don't know where the data we have to display begins
1850165675Sache	 in the buffer and we have to go back to the beginning of the screen
1851165675Sache	 line.  In this case, we can use the terminal sequence to move forward
1852165675Sache	 if it's available. */
1853119614Sache      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1854119614Sache	{
1855165675Sache	  if (_rl_term_forward_char)
1856165675Sache	    {
1857165675Sache	      for (i = cpos; i < dpos; i++)
1858165675Sache	        tputs (_rl_term_forward_char, 1, _rl_output_character_function);
1859165675Sache	    }
1860165675Sache	  else
1861165675Sache	    {
1862165675Sache	      tputs (_rl_term_cr, 1, _rl_output_character_function);
1863165675Sache	      for (i = 0; i < new; i++)
1864165675Sache		putc (data[i], rl_outstream);
1865165675Sache	    }
1866119614Sache	}
186721308Sache      else
1868157188Sache	for (i = cpos; i < new; i++)
186921308Sache	  putc (data[i], rl_outstream);
1870157188Sache    }
1871119614Sache
1872119614Sache#if defined (HANDLE_MULTIBYTE)
1873119614Sache  /* NEW points to the buffer point, but _rl_last_c_pos is the display point.
1874119614Sache     The byte length of the string is probably bigger than the column width
1875119614Sache     of the string, which means that if NEW == _rl_last_c_pos, then NEW's
1876119614Sache     display point is less than _rl_last_c_pos. */
1877119614Sache#endif
1878157188Sache  else if (cpos > dpos)
1879157188Sache    _rl_backspace (cpos - dpos);
1880119614Sache
1881157188Sache  _rl_last_c_pos = dpos;
188221308Sache}
188321308Sache
188421308Sache/* PWP: move the cursor up or down. */
188521308Sachevoid
188621308Sache_rl_move_vert (to)
188721308Sache     int to;
188821308Sache{
188921308Sache  register int delta, i;
189021308Sache
189175409Sache  if (_rl_last_v_pos == to || to > _rl_screenheight)
189221308Sache    return;
189321308Sache
189421308Sache  if ((delta = to - _rl_last_v_pos) > 0)
189521308Sache    {
189621308Sache      for (i = 0; i < delta; i++)
189721308Sache	putc ('\n', rl_outstream);
189858314Sache#if defined (__MSDOS__)
189958314Sache      putc ('\r', rl_outstream);
190058314Sache#else
190175409Sache      tputs (_rl_term_cr, 1, _rl_output_character_function);
190258314Sache#endif
190321308Sache      _rl_last_c_pos = 0;
190421308Sache    }
190521308Sache  else
190621308Sache    {			/* delta < 0 */
190775409Sache      if (_rl_term_up && *_rl_term_up)
190821308Sache	for (i = 0; i < -delta; i++)
190975409Sache	  tputs (_rl_term_up, 1, _rl_output_character_function);
191021308Sache    }
191158314Sache
191221308Sache  _rl_last_v_pos = to;		/* Now TO is here */
191321308Sache}
191421308Sache
191521308Sache/* Physically print C on rl_outstream.  This is for functions which know
191621308Sache   how to optimize the display.  Return the number of characters output. */
191721308Sacheint
191821308Sacherl_show_char (c)
191921308Sache     int c;
192021308Sache{
192121308Sache  int n = 1;
192221308Sache  if (META_CHAR (c) && (_rl_output_meta_chars == 0))
192321308Sache    {
192421308Sache      fprintf (rl_outstream, "M-");
192521308Sache      n += 2;
192621308Sache      c = UNMETA (c);
192721308Sache    }
192821308Sache
192921308Sache#if defined (DISPLAY_TABS)
193021308Sache  if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
193121308Sache#else
193221308Sache  if (CTRL_CHAR (c) || c == RUBOUT)
193321308Sache#endif /* !DISPLAY_TABS */
193421308Sache    {
193521308Sache      fprintf (rl_outstream, "C-");
193621308Sache      n += 2;
193721308Sache      c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
193821308Sache    }
193921308Sache
194021308Sache  putc (c, rl_outstream);
194121308Sache  fflush (rl_outstream);
194221308Sache  return n;
194321308Sache}
194421308Sache
194521308Sacheint
194621308Sacherl_character_len (c, pos)
194721308Sache     register int c, pos;
194821308Sache{
194921308Sache  unsigned char uc;
195021308Sache
195121308Sache  uc = (unsigned char)c;
195221308Sache
195321308Sache  if (META_CHAR (uc))
195421308Sache    return ((_rl_output_meta_chars == 0) ? 4 : 1);
195521308Sache
195621308Sache  if (uc == '\t')
195721308Sache    {
195821308Sache#if defined (DISPLAY_TABS)
195921308Sache      return (((pos | 7) + 1) - pos);
196021308Sache#else
196121308Sache      return (2);
196221308Sache#endif /* !DISPLAY_TABS */
196321308Sache    }
196421308Sache
196521308Sache  if (CTRL_CHAR (c) || c == RUBOUT)
196621308Sache    return (2);
196721308Sache
1968119614Sache  return ((ISPRINT (uc)) ? 1 : 2);
196921308Sache}
197021308Sache/* How to print things in the "echo-area".  The prompt is treated as a
197121308Sache   mini-modeline. */
1972157188Sachestatic int msg_saved_prompt = 0;
197321308Sache
197421308Sache#if defined (USE_VARARGS)
197521308Sacheint
197621308Sache#if defined (PREFER_STDARG)
197721308Sacherl_message (const char *format, ...)
197821308Sache#else
197921308Sacherl_message (va_alist)
198021308Sache     va_dcl
198121308Sache#endif
198221308Sache{
198321308Sache  va_list args;
198421308Sache#if defined (PREFER_VARARGS)
198521308Sache  char *format;
198621308Sache#endif
198721308Sache
198821308Sache#if defined (PREFER_STDARG)
198921308Sache  va_start (args, format);
199021308Sache#else
199121308Sache  va_start (args);
199221308Sache  format = va_arg (args, char *);
199321308Sache#endif
199421308Sache
1995119614Sache#if defined (HAVE_VSNPRINTF)
1996119614Sache  vsnprintf (msg_buf, sizeof (msg_buf) - 1, format, args);
1997119614Sache#else
199821308Sache  vsprintf (msg_buf, format, args);
1999119614Sache  msg_buf[sizeof(msg_buf) - 1] = '\0';	/* overflow? */
2000119614Sache#endif
200121308Sache  va_end (args);
200221308Sache
2003157188Sache  if (saved_local_prompt == 0)
2004157188Sache    {
2005157188Sache      rl_save_prompt ();
2006157188Sache      msg_saved_prompt = 1;
2007157188Sache    }
200821308Sache  rl_display_prompt = msg_buf;
2009157188Sache  local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
2010157188Sache					 &prompt_last_invisible,
2011157188Sache					 &prompt_invis_chars_first_line,
2012157188Sache					 &prompt_physical_chars);
2013157188Sache  local_prompt_prefix = (char *)NULL;
2014165675Sache  local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
201521308Sache  (*rl_redisplay_function) ();
2016157188Sache
201721308Sache  return 0;
201821308Sache}
201921308Sache#else /* !USE_VARARGS */
202021308Sacheint
202121308Sacherl_message (format, arg1, arg2)
202221308Sache     char *format;
202321308Sache{
202421308Sache  sprintf (msg_buf, format, arg1, arg2);
2025119614Sache  msg_buf[sizeof(msg_buf) - 1] = '\0';	/* overflow? */
2026157188Sache
202721308Sache  rl_display_prompt = msg_buf;
2028157188Sache  if (saved_local_prompt == 0)
2029157188Sache    {
2030157188Sache      rl_save_prompt ();
2031157188Sache      msg_saved_prompt = 1;
2032157188Sache    }
2033157188Sache  local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
2034157188Sache					 &prompt_last_invisible,
2035157188Sache					 &prompt_invis_chars_first_line,
2036157188Sache					 &prompt_physical_chars);
2037157188Sache  local_prompt_prefix = (char *)NULL;
2038165675Sache  local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
203921308Sache  (*rl_redisplay_function) ();
2040157188Sache
204121308Sache  return 0;
204221308Sache}
204321308Sache#endif /* !USE_VARARGS */
204421308Sache
204521308Sache/* How to clear things from the "echo-area". */
204621308Sacheint
204721308Sacherl_clear_message ()
204821308Sache{
204921308Sache  rl_display_prompt = rl_prompt;
2050157188Sache  if (msg_saved_prompt)
2051157188Sache    {
2052157188Sache      rl_restore_prompt ();
2053157188Sache      msg_saved_prompt = 0;
2054157188Sache    }
205521308Sache  (*rl_redisplay_function) ();
205621308Sache  return 0;
205721308Sache}
205821308Sache
205921308Sacheint
206021308Sacherl_reset_line_state ()
206121308Sache{
206221308Sache  rl_on_new_line ();
206321308Sache
206421308Sache  rl_display_prompt = rl_prompt ? rl_prompt : "";
206521308Sache  forced_display = 1;
206621308Sache  return 0;
206721308Sache}
206821308Sache
206921308Sachevoid
207047563Sacherl_save_prompt ()
207121308Sache{
207221308Sache  saved_local_prompt = local_prompt;
207321308Sache  saved_local_prefix = local_prompt_prefix;
2074157188Sache  saved_prefix_length = prompt_prefix_length;
2075165675Sache  saved_local_length = local_prompt_len;
207675409Sache  saved_last_invisible = prompt_last_invisible;
207775409Sache  saved_visible_length = prompt_visible_length;
2078136759Speter  saved_invis_chars_first_line = prompt_invis_chars_first_line;
2079136759Speter  saved_physical_chars = prompt_physical_chars;
208021308Sache
208121308Sache  local_prompt = local_prompt_prefix = (char *)0;
2082165675Sache  local_prompt_len = 0;
2083157188Sache  prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0;
2084136759Speter  prompt_invis_chars_first_line = prompt_physical_chars = 0;
208521308Sache}
208621308Sache
208721308Sachevoid
208847563Sacherl_restore_prompt ()
208921308Sache{
209075409Sache  FREE (local_prompt);
209175409Sache  FREE (local_prompt_prefix);
209221308Sache
209321308Sache  local_prompt = saved_local_prompt;
209421308Sache  local_prompt_prefix = saved_local_prefix;
2095165675Sache  local_prompt_len = saved_local_length;
2096157188Sache  prompt_prefix_length = saved_prefix_length;
209775409Sache  prompt_last_invisible = saved_last_invisible;
209875409Sache  prompt_visible_length = saved_visible_length;
2099136759Speter  prompt_invis_chars_first_line = saved_invis_chars_first_line;
2100136759Speter  prompt_physical_chars = saved_physical_chars;
2101157188Sache
2102157188Sache  /* can test saved_local_prompt to see if prompt info has been saved. */
2103157188Sache  saved_local_prompt = saved_local_prefix = (char *)0;
2104165675Sache  saved_local_length = 0;
2105157188Sache  saved_last_invisible = saved_visible_length = saved_prefix_length = 0;
2106157188Sache  saved_invis_chars_first_line = saved_physical_chars = 0;
210721308Sache}
210821308Sache
210921308Sachechar *
211021308Sache_rl_make_prompt_for_search (pchar)
211121308Sache     int pchar;
211221308Sache{
211321308Sache  int len;
2114157195Sache  char *pmt, *p;
211521308Sache
211647563Sache  rl_save_prompt ();
211721308Sache
2118157195Sache  /* We've saved the prompt, and can do anything with the various prompt
2119157195Sache     strings we need before they're restored.  We want the unexpanded
2120157195Sache     portion of the prompt string after any final newline. */
2121157195Sache  p = rl_prompt ? strrchr (rl_prompt, '\n') : 0;
2122157195Sache  if (p == 0)
212321308Sache    {
212421308Sache      len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
2125119614Sache      pmt = (char *)xmalloc (len + 2);
212621308Sache      if (len)
212747563Sache	strcpy (pmt, rl_prompt);
212821308Sache      pmt[len] = pchar;
212921308Sache      pmt[len+1] = '\0';
213021308Sache    }
213121308Sache  else
213221308Sache    {
2133157195Sache      p++;
2134157195Sache      len = strlen (p);
2135119614Sache      pmt = (char *)xmalloc (len + 2);
213621308Sache      if (len)
2137157195Sache	strcpy (pmt, p);
213821308Sache      pmt[len] = pchar;
213921308Sache      pmt[len+1] = '\0';
2140157195Sache    }
2141136759Speter
2142157195Sache  /* will be overwritten by expand_prompt, called from rl_message */
2143157188Sache  prompt_physical_chars = saved_physical_chars + 1;
214421308Sache  return pmt;
214521308Sache}
214621308Sache
214721308Sache/* Quick redisplay hack when erasing characters at the end of the line. */
214821308Sachevoid
214921308Sache_rl_erase_at_end_of_line (l)
215021308Sache     int l;
215121308Sache{
215221308Sache  register int i;
215321308Sache
215421308Sache  _rl_backspace (l);
215521308Sache  for (i = 0; i < l; i++)
215621308Sache    putc (' ', rl_outstream);
215721308Sache  _rl_backspace (l);
215821308Sache  for (i = 0; i < l; i++)
215921308Sache    visible_line[--_rl_last_c_pos] = '\0';
216021308Sache  rl_display_fixed++;
216121308Sache}
216221308Sache
216321308Sache/* Clear to the end of the line.  COUNT is the minimum
216421308Sache   number of character spaces to clear, */
216526497Sachevoid
216626497Sache_rl_clear_to_eol (count)
216721308Sache     int count;
216821308Sache{
216975409Sache  if (_rl_term_clreol)
217075409Sache    tputs (_rl_term_clreol, 1, _rl_output_character_function);
217126497Sache  else if (count)
217221308Sache    space_to_eol (count);
217321308Sache}
217421308Sache
217521308Sache/* Clear to the end of the line using spaces.  COUNT is the minimum
217621308Sache   number of character spaces to clear, */
217721308Sachestatic void
217821308Sachespace_to_eol (count)
217921308Sache     int count;
218021308Sache{
218121308Sache  register int i;
218221308Sache
218321308Sache  for (i = 0; i < count; i++)
218421308Sache   putc (' ', rl_outstream);
218521308Sache
218621308Sache  _rl_last_c_pos += count;
218721308Sache}
218821308Sache
218926497Sachevoid
219026497Sache_rl_clear_screen ()
219126497Sache{
219275409Sache  if (_rl_term_clrpag)
219375409Sache    tputs (_rl_term_clrpag, 1, _rl_output_character_function);
219426497Sache  else
219575409Sache    rl_crlf ();
219626497Sache}
219726497Sache
2198119614Sache/* Insert COUNT characters from STRING to the output stream at column COL. */
219921308Sachestatic void
2200119614Sacheinsert_some_chars (string, count, col)
220121308Sache     char *string;
2202119614Sache     int count, col;
220321308Sache{
2204157188Sache#if defined (__MSDOS__) || defined (__MINGW32__)
2205157188Sache  _rl_output_some_chars (string, count);
2206157188Sache#else
2207119614Sache  /* DEBUGGING */
2208119614Sache  if (MB_CUR_MAX == 1 || rl_byte_oriented)
2209119614Sache    if (count != col)
2210119614Sache      fprintf(stderr, "readline: debug: insert_some_chars: count (%d) != col (%d)\n", count, col);
2211119614Sache
221221308Sache  /* If IC is defined, then we do not have to "enter" insert mode. */
221375409Sache  if (_rl_term_IC)
221421308Sache    {
221521308Sache      char *buffer;
2216119614Sache
2217119614Sache      buffer = tgoto (_rl_term_IC, 0, col);
221821308Sache      tputs (buffer, 1, _rl_output_character_function);
221921308Sache      _rl_output_some_chars (string, count);
222021308Sache    }
222121308Sache  else
222221308Sache    {
222321308Sache      register int i;
222421308Sache
222521308Sache      /* If we have to turn on insert-mode, then do so. */
222675409Sache      if (_rl_term_im && *_rl_term_im)
222775409Sache	tputs (_rl_term_im, 1, _rl_output_character_function);
222821308Sache
222921308Sache      /* If there is a special command for inserting characters, then
223021308Sache	 use that first to open up the space. */
223175409Sache      if (_rl_term_ic && *_rl_term_ic)
223221308Sache	{
2233119614Sache	  for (i = col; i--; )
223475409Sache	    tputs (_rl_term_ic, 1, _rl_output_character_function);
223521308Sache	}
223621308Sache
223721308Sache      /* Print the text. */
223821308Sache      _rl_output_some_chars (string, count);
223921308Sache
224021308Sache      /* If there is a string to turn off insert mode, we had best use
224121308Sache	 it now. */
224275409Sache      if (_rl_term_ei && *_rl_term_ei)
224375409Sache	tputs (_rl_term_ei, 1, _rl_output_character_function);
224421308Sache    }
2245157188Sache#endif /* __MSDOS__ || __MINGW32__ */
224621308Sache}
224721308Sache
224821308Sache/* Delete COUNT characters from the display line. */
224921308Sachestatic void
225021308Sachedelete_chars (count)
225121308Sache     int count;
225221308Sache{
225375409Sache  if (count > _rl_screenwidth)	/* XXX */
225421308Sache    return;
225521308Sache
2256157188Sache#if !defined (__MSDOS__) && !defined (__MINGW32__)
225775409Sache  if (_rl_term_DC && *_rl_term_DC)
225821308Sache    {
225921308Sache      char *buffer;
226075409Sache      buffer = tgoto (_rl_term_DC, count, count);
226121308Sache      tputs (buffer, count, _rl_output_character_function);
226221308Sache    }
226321308Sache  else
226421308Sache    {
226575409Sache      if (_rl_term_dc && *_rl_term_dc)
226621308Sache	while (count--)
226775409Sache	  tputs (_rl_term_dc, 1, _rl_output_character_function);
226821308Sache    }
2269157188Sache#endif /* !__MSDOS__ && !__MINGW32__ */
227021308Sache}
227121308Sache
227221308Sachevoid
227321308Sache_rl_update_final ()
227421308Sache{
227521308Sache  int full_lines;
227621308Sache
227721308Sache  full_lines = 0;
227821308Sache  /* If the cursor is the only thing on an otherwise-blank last line,
227921308Sache     compensate so we don't print an extra CRLF. */
228021308Sache  if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
228126497Sache	visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
228221308Sache    {
228321308Sache      _rl_vis_botlin--;
228421308Sache      full_lines = 1;
228521308Sache    }
228621308Sache  _rl_move_vert (_rl_vis_botlin);
228721308Sache  /* If we've wrapped lines, remove the final xterm line-wrap flag. */
228875409Sache  if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth))
228921308Sache    {
229021308Sache      char *last_line;
2291119614Sache
229258314Sache      last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]];
2293165675Sache      cpos_buffer_position = -1;	/* don't know where we are in buffer */
2294165675Sache      _rl_move_cursor_relative (_rl_screenwidth - 1, last_line);	/* XXX */
229526497Sache      _rl_clear_to_eol (0);
229675409Sache      putc (last_line[_rl_screenwidth - 1], rl_outstream);
229721308Sache    }
229821308Sache  _rl_vis_botlin = 0;
229975409Sache  rl_crlf ();
230021308Sache  fflush (rl_outstream);
230121308Sache  rl_display_fixed++;
230221308Sache}
230321308Sache
230421308Sache/* Move to the start of the current line. */
230521308Sachestatic void
230621308Sachecr ()
230721308Sache{
230875409Sache  if (_rl_term_cr)
230921308Sache    {
231058314Sache#if defined (__MSDOS__)
231158314Sache      putc ('\r', rl_outstream);
231258314Sache#else
231375409Sache      tputs (_rl_term_cr, 1, _rl_output_character_function);
231458314Sache#endif
231521308Sache      _rl_last_c_pos = 0;
231621308Sache    }
231721308Sache}
231821308Sache
231958314Sache/* Redraw the last line of a multi-line prompt that may possibly contain
232058314Sache   terminal escape sequences.  Called with the cursor at column 0 of the
232158314Sache   line to draw the prompt on. */
232258314Sachestatic void
232358314Sacheredraw_prompt (t)
232458314Sache     char *t;
232558314Sache{
2326157188Sache  char *oldp;
232758314Sache
232858314Sache  oldp = rl_display_prompt;
2329157188Sache  rl_save_prompt ();
233058314Sache
233158314Sache  rl_display_prompt = t;
233275409Sache  local_prompt = expand_prompt (t, &prompt_visible_length,
233375409Sache				   &prompt_last_invisible,
2334136759Speter				   &prompt_invis_chars_first_line,
2335136759Speter				   &prompt_physical_chars);
233658314Sache  local_prompt_prefix = (char *)NULL;
2337165675Sache  local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
2338157188Sache
233958314Sache  rl_forced_update_display ();
234058314Sache
234158314Sache  rl_display_prompt = oldp;
2342157188Sache  rl_restore_prompt();
234358314Sache}
234458314Sache
234521308Sache/* Redisplay the current line after a SIGWINCH is received. */
234621308Sachevoid
234721308Sache_rl_redisplay_after_sigwinch ()
234821308Sache{
234958314Sache  char *t;
235021308Sache
235121308Sache  /* Clear the current line and put the cursor at column 0.  Make sure
235221308Sache     the right thing happens if we have wrapped to a new screen line. */
235375409Sache  if (_rl_term_cr)
235421308Sache    {
235558314Sache#if defined (__MSDOS__)
235658314Sache      putc ('\r', rl_outstream);
235758314Sache#else
235875409Sache      tputs (_rl_term_cr, 1, _rl_output_character_function);
235958314Sache#endif
236021308Sache      _rl_last_c_pos = 0;
236158314Sache#if defined (__MSDOS__)
236275409Sache      space_to_eol (_rl_screenwidth);
236358314Sache      putc ('\r', rl_outstream);
236458314Sache#else
236575409Sache      if (_rl_term_clreol)
236675409Sache	tputs (_rl_term_clreol, 1, _rl_output_character_function);
236721308Sache      else
236821308Sache	{
236975409Sache	  space_to_eol (_rl_screenwidth);
237075409Sache	  tputs (_rl_term_cr, 1, _rl_output_character_function);
237121308Sache	}
237258314Sache#endif
237321308Sache      if (_rl_last_v_pos > 0)
237421308Sache	_rl_move_vert (0);
237521308Sache    }
237621308Sache  else
237775409Sache    rl_crlf ();
237821308Sache
237921308Sache  /* Redraw only the last line of a multi-line prompt. */
238021308Sache  t = strrchr (rl_display_prompt, '\n');
238121308Sache  if (t)
238258314Sache    redraw_prompt (++t);
238321308Sache  else
238421308Sache    rl_forced_update_display ();
238521308Sache}
238621308Sache
238721308Sachevoid
238821308Sache_rl_clean_up_for_exit ()
238921308Sache{
239021308Sache  if (readline_echoing_p)
239121308Sache    {
239221308Sache      _rl_move_vert (_rl_vis_botlin);
239321308Sache      _rl_vis_botlin = 0;
239421308Sache      fflush (rl_outstream);
239547563Sache      rl_restart_output (1, 0);
239621308Sache    }
239721308Sache}
239847563Sache
239947563Sachevoid
240047563Sache_rl_erase_entire_line ()
240147563Sache{
240247563Sache  cr ();
240347563Sache  _rl_clear_to_eol (0);
240447563Sache  cr ();
240547563Sache  fflush (rl_outstream);
240647563Sache}
240758314Sache
240858314Sache/* return the `current display line' of the cursor -- the number of lines to
240958314Sache   move up to get to the first screen line of the current readline line. */
241058314Sacheint
241158314Sache_rl_current_display_line ()
241258314Sache{
241358314Sache  int ret, nleft;
241458314Sache
241558314Sache  /* Find out whether or not there might be invisible characters in the
241658314Sache     editing buffer. */
241758314Sache  if (rl_display_prompt == rl_prompt)
241875409Sache    nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length;
241958314Sache  else
242075409Sache    nleft = _rl_last_c_pos - _rl_screenwidth;
242158314Sache
242258314Sache  if (nleft > 0)
242375409Sache    ret = 1 + nleft / _rl_screenwidth;
242458314Sache  else
242558314Sache    ret = 0;
242658314Sache
242758314Sache  return ret;
242858314Sache}
2429119614Sache
2430119614Sache#if defined (HANDLE_MULTIBYTE)
2431119614Sache/* Calculate the number of screen columns occupied by STR from START to END.
2432119614Sache   In the case of multibyte characters with stateful encoding, we have to
2433119614Sache   scan from the beginning of the string to take the state into account. */
2434119614Sachestatic int
2435119614Sache_rl_col_width (str, start, end)
2436136759Speter     const char *str;
2437119614Sache     int start, end;
2438119614Sache{
2439119614Sache  wchar_t wc;
2440165675Sache  mbstate_t ps;
2441119614Sache  int tmp, point, width, max;
2442119614Sache
2443119614Sache  if (end <= start)
2444119614Sache    return 0;
2445165680Sache  if (MB_CUR_MAX == 1 || rl_byte_oriented)
2446165680Sache    return (end - start);
2447119614Sache
2448165675Sache  memset (&ps, 0, sizeof (mbstate_t));
2449165675Sache
2450119614Sache  point = 0;
2451119614Sache  max = end;
2452119614Sache
2453119614Sache  while (point < start)
2454119614Sache    {
2455119614Sache      tmp = mbrlen (str + point, max, &ps);
2456136759Speter      if (MB_INVALIDCH ((size_t)tmp))
2457119614Sache	{
2458119614Sache	  /* In this case, the bytes are invalid or too short to compose a
2459119614Sache	     multibyte character, so we assume that the first byte represents
2460119614Sache	     a single character. */
2461119614Sache	  point++;
2462119614Sache	  max--;
2463119614Sache
2464119614Sache	  /* Clear the state of the byte sequence, because in this case the
2465119614Sache	     effect of mbstate is undefined. */
2466119614Sache	  memset (&ps, 0, sizeof (mbstate_t));
2467119614Sache	}
2468136759Speter      else if (MB_NULLWCH (tmp))
2469136759Speter	break;		/* Found '\0' */
2470119614Sache      else
2471119614Sache	{
2472119614Sache	  point += tmp;
2473119614Sache	  max -= tmp;
2474119614Sache	}
2475119614Sache    }
2476119614Sache
2477119614Sache  /* If START is not a byte that starts a character, then POINT will be
2478119614Sache     greater than START.  In this case, assume that (POINT - START) gives
2479119614Sache     a byte count that is the number of columns of difference. */
2480119614Sache  width = point - start;
2481119614Sache
2482119614Sache  while (point < end)
2483119614Sache    {
2484119614Sache      tmp = mbrtowc (&wc, str + point, max, &ps);
2485136759Speter      if (MB_INVALIDCH ((size_t)tmp))
2486119614Sache	{
2487119614Sache	  /* In this case, the bytes are invalid or too short to compose a
2488119614Sache	     multibyte character, so we assume that the first byte represents
2489119614Sache	     a single character. */
2490119614Sache	  point++;
2491119614Sache	  max--;
2492119614Sache
2493119614Sache	  /* and assume that the byte occupies a single column. */
2494119614Sache	  width++;
2495119614Sache
2496119614Sache	  /* Clear the state of the byte sequence, because in this case the
2497119614Sache	     effect of mbstate is undefined. */
2498119614Sache	  memset (&ps, 0, sizeof (mbstate_t));
2499119614Sache	}
2500136759Speter      else if (MB_NULLWCH (tmp))
2501136759Speter	break;			/* Found '\0' */
2502119614Sache      else
2503119614Sache	{
2504119614Sache	  point += tmp;
2505119614Sache	  max -= tmp;
2506119614Sache	  tmp = wcwidth(wc);
2507119614Sache	  width += (tmp >= 0) ? tmp : 1;
2508119614Sache	}
2509119614Sache    }
2510119614Sache
2511119614Sache  width += point - end;
2512119614Sache
2513119614Sache  return width;
2514119614Sache}
2515119614Sache#endif /* HANDLE_MULTIBYTE */
2516