display.c revision 168666
158314Sache/* $FreeBSD: head/contrib/libreadline/display.c 168666 2007-04-12 14:45:25Z ache $ */
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;
152221308Sache      /* Sometimes it is cheaper to print the characters rather than
152321308Sache	 use the terminal's capabilities.  If we're growing the number
152421308Sache	 of lines, make sure we actually cause the new line to wrap
152521308Sache	 around on auto-wrapping terminals. */
1526119614Sache      if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
152721308Sache	{
152875409Sache	  /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
152921308Sache	     _rl_horizontal_scroll_mode == 1, inserting the characters with
153075409Sache	     _rl_term_IC or _rl_term_ic will screw up the screen because of the
153121308Sache	     invisible characters.  We need to just draw them. */
153221308Sache	  if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 ||
153375409Sache			lendiff <= prompt_visible_length || !current_invis_chars))
153421308Sache	    {
1535119614Sache	      insert_some_chars (nfd, lendiff, col_lendiff);
1536119614Sache	      _rl_last_c_pos += col_lendiff;
153721308Sache	    }
1538157188Sache	  else if ((MB_CUR_MAX == 1 || rl_byte_oriented != 0) && *ols == 0 && lendiff > 0)
153921308Sache	    {
154021308Sache	      /* At the end of a line the characters do not have to
154121308Sache		 be "inserted".  They can just be placed on the screen. */
154221308Sache	      /* However, this screws up the rest of this block, which
154347563Sache		 assumes you've done the insert because you can. */
154421308Sache	      _rl_output_some_chars (nfd, lendiff);
1545119614Sache	      _rl_last_c_pos += col_lendiff;
154621308Sache	    }
154721308Sache	  else
154821308Sache	    {
154921308Sache	      /* We have horizontal scrolling and we are not inserting at
155021308Sache		 the end.  We have invisible characters in this line.  This
155121308Sache		 is a dumb update. */
155221308Sache	      _rl_output_some_chars (nfd, temp);
1553119614Sache	      _rl_last_c_pos += col_temp;
155421308Sache	      return;
155521308Sache	    }
155621308Sache	  /* Copy (new) chars to screen from first diff to last match. */
155721308Sache	  temp = nls - nfd;
155821308Sache	  if ((temp - lendiff) > 0)
155921308Sache	    {
156021308Sache	      _rl_output_some_chars (nfd + lendiff, temp - lendiff);
1561136759Speter#if 1
1562136759Speter	     /* XXX -- this bears closer inspection.  Fixes a redisplay bug
1563136759Speter		reported against bash-3.0-alpha by Andreas Schwab involving
1564136759Speter		multibyte characters and prompt strings with invisible
1565136759Speter		characters, but was previously disabled. */
1566136759Speter	      _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-col_lendiff);
1567119614Sache#else
1568136759Speter	      _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-lendiff);
1569119614Sache#endif
157021308Sache	    }
157121308Sache	}
157221308Sache      else
157321308Sache	{
157421308Sache	  /* cannot insert chars, write to EOL */
157521308Sache	  _rl_output_some_chars (nfd, temp);
1576119614Sache	  _rl_last_c_pos += col_temp;
1577157188Sache	  /* If we're in a multibyte locale and were before the last invisible
1578157188Sache	     char in the current line (which implies we just output some invisible
1579157188Sache	     characters) we need to adjust _rl_last_c_pos, since it represents
1580157188Sache	     a physical character position. */
158121308Sache	}
158221308Sache    }
158321308Sache  else				/* Delete characters from line. */
158421308Sache    {
158521308Sache      /* If possible and inexpensive to use terminal deletion, then do so. */
1586119614Sache      if (_rl_term_dc && (2 * col_temp) >= -col_lendiff)
158721308Sache	{
158821308Sache	  /* If all we're doing is erasing the invisible characters in the
158921308Sache	     prompt string, don't bother.  It screws up the assumptions
159021308Sache	     about what's on the screen. */
159121308Sache	  if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
159221308Sache	      -lendiff == visible_wrap_offset)
1593119614Sache	    col_lendiff = 0;
159421308Sache
1595119614Sache	  if (col_lendiff)
1596119614Sache	    delete_chars (-col_lendiff); /* delete (diff) characters */
159721308Sache
159821308Sache	  /* Copy (new) chars to screen from first diff to last match */
159921308Sache	  temp = nls - nfd;
160021308Sache	  if (temp > 0)
160121308Sache	    {
160221308Sache	      _rl_output_some_chars (nfd, temp);
1603119614Sache	      _rl_last_c_pos += _rl_col_width (nfd, 0, temp);;
160421308Sache	    }
160521308Sache	}
160621308Sache      /* Otherwise, print over the existing material. */
160721308Sache      else
160821308Sache	{
160921308Sache	  if (temp > 0)
161021308Sache	    {
161121308Sache	      _rl_output_some_chars (nfd, temp);
1612157188Sache	      _rl_last_c_pos += col_temp;		/* XXX */
161321308Sache	    }
161421308Sache	  lendiff = (oe - old) - (ne - new);
1615119614Sache	  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1616119614Sache	    col_lendiff = _rl_col_width (old, 0, oe - old) - _rl_col_width (new, 0, ne - new);
1617119614Sache	  else
1618119614Sache	    col_lendiff = lendiff;
1619119614Sache
1620119614Sache	  if (col_lendiff)
162147563Sache	    {
162247563Sache	      if (_rl_term_autowrap && current_line < inv_botlin)
1623119614Sache		space_to_eol (col_lendiff);
162447563Sache	      else
1625119614Sache		_rl_clear_to_eol (col_lendiff);
162647563Sache	    }
162721308Sache	}
162821308Sache    }
162921308Sache}
163021308Sache
163121308Sache/* Tell the update routines that we have moved onto a new (empty) line. */
163221308Sacheint
163321308Sacherl_on_new_line ()
163421308Sache{
163521308Sache  if (visible_line)
163621308Sache    visible_line[0] = '\0';
163721308Sache
163821308Sache  _rl_last_c_pos = _rl_last_v_pos = 0;
163921308Sache  _rl_vis_botlin = last_lmargin = 0;
164021308Sache  if (vis_lbreaks)
164121308Sache    vis_lbreaks[0] = vis_lbreaks[1] = 0;
164221308Sache  visible_wrap_offset = 0;
164321308Sache  return 0;
164421308Sache}
164521308Sache
164658314Sache/* Tell the update routines that we have moved onto a new line with the
164758314Sache   prompt already displayed.  Code originally from the version of readline
1648136759Speter   distributed with CLISP.  rl_expand_prompt must have already been called
1649136759Speter   (explicitly or implicitly).  This still doesn't work exactly right. */
165058314Sacheint
165158314Sacherl_on_new_line_with_prompt ()
165258314Sache{
165358314Sache  int prompt_size, i, l, real_screenwidth, newlines;
1654136759Speter  char *prompt_last_line, *lprompt;
165558314Sache
165658314Sache  /* Initialize visible_line and invisible_line to ensure that they can hold
165758314Sache     the already-displayed prompt. */
165858314Sache  prompt_size = strlen (rl_prompt) + 1;
165958314Sache  init_line_structures (prompt_size);
166058314Sache
166158314Sache  /* Make sure the line structures hold the already-displayed prompt for
166258314Sache     redisplay. */
1663136759Speter  lprompt = local_prompt ? local_prompt : rl_prompt;
1664136759Speter  strcpy (visible_line, lprompt);
1665136759Speter  strcpy (invisible_line, lprompt);
166658314Sache
166758314Sache  /* If the prompt contains newlines, take the last tail. */
166858314Sache  prompt_last_line = strrchr (rl_prompt, '\n');
166958314Sache  if (!prompt_last_line)
167058314Sache    prompt_last_line = rl_prompt;
167158314Sache
167258314Sache  l = strlen (prompt_last_line);
1673119614Sache  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1674157188Sache    _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l);	/* XXX */
1675119614Sache  else
1676119614Sache    _rl_last_c_pos = l;
167758314Sache
167858314Sache  /* Dissect prompt_last_line into screen lines. Note that here we have
167958314Sache     to use the real screenwidth. Readline's notion of screenwidth might be
168058314Sache     one less, see terminal.c. */
168175409Sache  real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1);
168258314Sache  _rl_last_v_pos = l / real_screenwidth;
168358314Sache  /* If the prompt length is a multiple of real_screenwidth, we don't know
168458314Sache     whether the cursor is at the end of the last line, or already at the
168558314Sache     beginning of the next line. Output a newline just to be safe. */
168658314Sache  if (l > 0 && (l % real_screenwidth) == 0)
168758314Sache    _rl_output_some_chars ("\n", 1);
168858314Sache  last_lmargin = 0;
168958314Sache
169058314Sache  newlines = 0; i = 0;
169158314Sache  while (i <= l)
169258314Sache    {
169358314Sache      _rl_vis_botlin = newlines;
169458314Sache      vis_lbreaks[newlines++] = i;
169558314Sache      i += real_screenwidth;
169658314Sache    }
169758314Sache  vis_lbreaks[newlines] = l;
169858314Sache  visible_wrap_offset = 0;
169958314Sache
1700136759Speter  rl_display_prompt = rl_prompt;	/* XXX - make sure it's set */
1701136759Speter
170258314Sache  return 0;
170358314Sache}
170458314Sache
170521308Sache/* Actually update the display, period. */
170621308Sacheint
170721308Sacherl_forced_update_display ()
170821308Sache{
1709165675Sache  register char *temp;
1710165675Sache
171121308Sache  if (visible_line)
171221308Sache    {
1713165675Sache      temp = visible_line;
171421308Sache      while (*temp)
171547563Sache	*temp++ = '\0';
171621308Sache    }
171721308Sache  rl_on_new_line ();
171821308Sache  forced_display++;
171921308Sache  (*rl_redisplay_function) ();
172021308Sache  return 0;
172121308Sache}
172221308Sache
172321308Sache/* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
1724157188Sache   (Well, when we don't have multibyte characters, _rl_last_c_pos is a
1725157188Sache   buffer index.)
172621308Sache   DATA is the contents of the screen line of interest; i.e., where
172721308Sache   the movement is being done. */
172821308Sachevoid
172921308Sache_rl_move_cursor_relative (new, data)
173021308Sache     int new;
173175409Sache     const char *data;
173221308Sache{
173321308Sache  register int i;
1734157188Sache  int woff;			/* number of invisible chars on current line */
1735157188Sache  int cpos, dpos;		/* current and desired cursor positions */
173621308Sache
1737157188Sache  woff = W_OFFSET (_rl_last_v_pos, wrap_offset);
1738157188Sache  cpos = _rl_last_c_pos;
1739119614Sache#if defined (HANDLE_MULTIBYTE)
1740119614Sache  /* If we have multibyte characters, NEW is indexed by the buffer point in
1741119614Sache     a multibyte string, but _rl_last_c_pos is the display position.  In
1742136759Speter     this case, NEW's display position is not obvious and must be
1743157188Sache     calculated.  We need to account for invisible characters in this line,
1744157188Sache     as long as we are past them and they are counted by _rl_col_width. */
1745157188Sache  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1746136759Speter    {
1747157188Sache      dpos = _rl_col_width (data, 0, new);
1748165675Sache      if (dpos > prompt_last_invisible)		/* XXX - don't use woff here */
1749165675Sache	{
1750165675Sache	  dpos -= woff;
1751165675Sache	  /* Since this will be assigned to _rl_last_c_pos at the end (more
1752165675Sache	     precisely, _rl_last_c_pos == dpos when this function returns),
1753165675Sache	     let the caller know. */
1754165675Sache	  cpos_adjusted = 1;
1755165675Sache	}
1756136759Speter    }
1757157188Sache  else
1758119614Sache#endif
1759157188Sache    dpos = new;
176021308Sache
1761157188Sache  /* If we don't have to do anything, then return. */
1762157188Sache  if (cpos == dpos)
1763157188Sache    return;
1764157188Sache
176521308Sache  /* It may be faster to output a CR, and then move forwards instead
176621308Sache     of moving backwards. */
176721308Sache  /* i == current physical cursor position. */
1768157188Sache#if defined (HANDLE_MULTIBYTE)
1769157188Sache  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1770157188Sache    i = _rl_last_c_pos;
1771157188Sache  else
1772157188Sache#endif
1773157188Sache  i = _rl_last_c_pos - woff;
1774165675Sache  if (dpos == 0 || CR_FASTER (dpos, _rl_last_c_pos) ||
177575409Sache      (_rl_term_autowrap && i == _rl_screenwidth))
177621308Sache    {
177721308Sache#if defined (__MSDOS__)
177821308Sache      putc ('\r', rl_outstream);
177921308Sache#else
178075409Sache      tputs (_rl_term_cr, 1, _rl_output_character_function);
178121308Sache#endif /* !__MSDOS__ */
1782157188Sache      cpos = _rl_last_c_pos = 0;
178321308Sache    }
178421308Sache
1785157188Sache  if (cpos < dpos)
178621308Sache    {
178721308Sache      /* Move the cursor forward.  We do it by printing the command
178821308Sache	 to move the cursor forward if there is one, else print that
178921308Sache	 portion of the output buffer again.  Which is cheaper? */
179021308Sache
179121308Sache      /* The above comment is left here for posterity.  It is faster
179221308Sache	 to print one character (non-control) than to print a control
179321308Sache	 sequence telling the terminal to move forward one character.
179421308Sache	 That kind of control is for people who don't know what the
179521308Sache	 data is underneath the cursor. */
1796165675Sache
1797165675Sache      /* However, we need a handle on where the current display position is
1798165675Sache	 in the buffer for the immediately preceding comment to be true.
1799165675Sache	 In multibyte locales, we don't currently have that info available.
1800165675Sache	 Without it, we don't know where the data we have to display begins
1801165675Sache	 in the buffer and we have to go back to the beginning of the screen
1802165675Sache	 line.  In this case, we can use the terminal sequence to move forward
1803165675Sache	 if it's available. */
1804119614Sache      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1805119614Sache	{
1806165675Sache	  if (_rl_term_forward_char)
1807165675Sache	    {
1808165675Sache	      for (i = cpos; i < dpos; i++)
1809165675Sache	        tputs (_rl_term_forward_char, 1, _rl_output_character_function);
1810165675Sache	    }
1811165675Sache	  else
1812165675Sache	    {
1813165675Sache	      tputs (_rl_term_cr, 1, _rl_output_character_function);
1814165675Sache	      for (i = 0; i < new; i++)
1815165675Sache		putc (data[i], rl_outstream);
1816165675Sache	    }
1817119614Sache	}
181821308Sache      else
1819157188Sache	for (i = cpos; i < new; i++)
182021308Sache	  putc (data[i], rl_outstream);
1821157188Sache    }
1822119614Sache
1823119614Sache#if defined (HANDLE_MULTIBYTE)
1824119614Sache  /* NEW points to the buffer point, but _rl_last_c_pos is the display point.
1825119614Sache     The byte length of the string is probably bigger than the column width
1826119614Sache     of the string, which means that if NEW == _rl_last_c_pos, then NEW's
1827119614Sache     display point is less than _rl_last_c_pos. */
1828119614Sache#endif
1829157188Sache  else if (cpos > dpos)
1830157188Sache    _rl_backspace (cpos - dpos);
1831119614Sache
1832157188Sache  _rl_last_c_pos = dpos;
183321308Sache}
183421308Sache
183521308Sache/* PWP: move the cursor up or down. */
183621308Sachevoid
183721308Sache_rl_move_vert (to)
183821308Sache     int to;
183921308Sache{
184021308Sache  register int delta, i;
184121308Sache
184275409Sache  if (_rl_last_v_pos == to || to > _rl_screenheight)
184321308Sache    return;
184421308Sache
184521308Sache  if ((delta = to - _rl_last_v_pos) > 0)
184621308Sache    {
184721308Sache      for (i = 0; i < delta; i++)
184821308Sache	putc ('\n', rl_outstream);
184958314Sache#if defined (__MSDOS__)
185058314Sache      putc ('\r', rl_outstream);
185158314Sache#else
185275409Sache      tputs (_rl_term_cr, 1, _rl_output_character_function);
185358314Sache#endif
185421308Sache      _rl_last_c_pos = 0;
185521308Sache    }
185621308Sache  else
185721308Sache    {			/* delta < 0 */
185875409Sache      if (_rl_term_up && *_rl_term_up)
185921308Sache	for (i = 0; i < -delta; i++)
186075409Sache	  tputs (_rl_term_up, 1, _rl_output_character_function);
186121308Sache    }
186258314Sache
186321308Sache  _rl_last_v_pos = to;		/* Now TO is here */
186421308Sache}
186521308Sache
186621308Sache/* Physically print C on rl_outstream.  This is for functions which know
186721308Sache   how to optimize the display.  Return the number of characters output. */
186821308Sacheint
186921308Sacherl_show_char (c)
187021308Sache     int c;
187121308Sache{
187221308Sache  int n = 1;
187321308Sache  if (META_CHAR (c) && (_rl_output_meta_chars == 0))
187421308Sache    {
187521308Sache      fprintf (rl_outstream, "M-");
187621308Sache      n += 2;
187721308Sache      c = UNMETA (c);
187821308Sache    }
187921308Sache
188021308Sache#if defined (DISPLAY_TABS)
188121308Sache  if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
188221308Sache#else
188321308Sache  if (CTRL_CHAR (c) || c == RUBOUT)
188421308Sache#endif /* !DISPLAY_TABS */
188521308Sache    {
188621308Sache      fprintf (rl_outstream, "C-");
188721308Sache      n += 2;
188821308Sache      c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
188921308Sache    }
189021308Sache
189121308Sache  putc (c, rl_outstream);
189221308Sache  fflush (rl_outstream);
189321308Sache  return n;
189421308Sache}
189521308Sache
189621308Sacheint
189721308Sacherl_character_len (c, pos)
189821308Sache     register int c, pos;
189921308Sache{
190021308Sache  unsigned char uc;
190121308Sache
190221308Sache  uc = (unsigned char)c;
190321308Sache
190421308Sache  if (META_CHAR (uc))
190521308Sache    return ((_rl_output_meta_chars == 0) ? 4 : 1);
190621308Sache
190721308Sache  if (uc == '\t')
190821308Sache    {
190921308Sache#if defined (DISPLAY_TABS)
191021308Sache      return (((pos | 7) + 1) - pos);
191121308Sache#else
191221308Sache      return (2);
191321308Sache#endif /* !DISPLAY_TABS */
191421308Sache    }
191521308Sache
191621308Sache  if (CTRL_CHAR (c) || c == RUBOUT)
191721308Sache    return (2);
191821308Sache
1919119614Sache  return ((ISPRINT (uc)) ? 1 : 2);
192021308Sache}
192121308Sache/* How to print things in the "echo-area".  The prompt is treated as a
192221308Sache   mini-modeline. */
1923157188Sachestatic int msg_saved_prompt = 0;
192421308Sache
192521308Sache#if defined (USE_VARARGS)
192621308Sacheint
192721308Sache#if defined (PREFER_STDARG)
192821308Sacherl_message (const char *format, ...)
192921308Sache#else
193021308Sacherl_message (va_alist)
193121308Sache     va_dcl
193221308Sache#endif
193321308Sache{
193421308Sache  va_list args;
193521308Sache#if defined (PREFER_VARARGS)
193621308Sache  char *format;
193721308Sache#endif
193821308Sache
193921308Sache#if defined (PREFER_STDARG)
194021308Sache  va_start (args, format);
194121308Sache#else
194221308Sache  va_start (args);
194321308Sache  format = va_arg (args, char *);
194421308Sache#endif
194521308Sache
1946119614Sache#if defined (HAVE_VSNPRINTF)
1947119614Sache  vsnprintf (msg_buf, sizeof (msg_buf) - 1, format, args);
1948119614Sache#else
194921308Sache  vsprintf (msg_buf, format, args);
1950119614Sache  msg_buf[sizeof(msg_buf) - 1] = '\0';	/* overflow? */
1951119614Sache#endif
195221308Sache  va_end (args);
195321308Sache
1954157188Sache  if (saved_local_prompt == 0)
1955157188Sache    {
1956157188Sache      rl_save_prompt ();
1957157188Sache      msg_saved_prompt = 1;
1958157188Sache    }
195921308Sache  rl_display_prompt = msg_buf;
1960157188Sache  local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
1961157188Sache					 &prompt_last_invisible,
1962157188Sache					 &prompt_invis_chars_first_line,
1963157188Sache					 &prompt_physical_chars);
1964157188Sache  local_prompt_prefix = (char *)NULL;
1965165675Sache  local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
196621308Sache  (*rl_redisplay_function) ();
1967157188Sache
196821308Sache  return 0;
196921308Sache}
197021308Sache#else /* !USE_VARARGS */
197121308Sacheint
197221308Sacherl_message (format, arg1, arg2)
197321308Sache     char *format;
197421308Sache{
197521308Sache  sprintf (msg_buf, format, arg1, arg2);
1976119614Sache  msg_buf[sizeof(msg_buf) - 1] = '\0';	/* overflow? */
1977157188Sache
197821308Sache  rl_display_prompt = msg_buf;
1979157188Sache  if (saved_local_prompt == 0)
1980157188Sache    {
1981157188Sache      rl_save_prompt ();
1982157188Sache      msg_saved_prompt = 1;
1983157188Sache    }
1984157188Sache  local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
1985157188Sache					 &prompt_last_invisible,
1986157188Sache					 &prompt_invis_chars_first_line,
1987157188Sache					 &prompt_physical_chars);
1988157188Sache  local_prompt_prefix = (char *)NULL;
1989165675Sache  local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
199021308Sache  (*rl_redisplay_function) ();
1991157188Sache
199221308Sache  return 0;
199321308Sache}
199421308Sache#endif /* !USE_VARARGS */
199521308Sache
199621308Sache/* How to clear things from the "echo-area". */
199721308Sacheint
199821308Sacherl_clear_message ()
199921308Sache{
200021308Sache  rl_display_prompt = rl_prompt;
2001157188Sache  if (msg_saved_prompt)
2002157188Sache    {
2003157188Sache      rl_restore_prompt ();
2004157188Sache      msg_saved_prompt = 0;
2005157188Sache    }
200621308Sache  (*rl_redisplay_function) ();
200721308Sache  return 0;
200821308Sache}
200921308Sache
201021308Sacheint
201121308Sacherl_reset_line_state ()
201221308Sache{
201321308Sache  rl_on_new_line ();
201421308Sache
201521308Sache  rl_display_prompt = rl_prompt ? rl_prompt : "";
201621308Sache  forced_display = 1;
201721308Sache  return 0;
201821308Sache}
201921308Sache
202021308Sachevoid
202147563Sacherl_save_prompt ()
202221308Sache{
202321308Sache  saved_local_prompt = local_prompt;
202421308Sache  saved_local_prefix = local_prompt_prefix;
2025157188Sache  saved_prefix_length = prompt_prefix_length;
2026165675Sache  saved_local_length = local_prompt_len;
202775409Sache  saved_last_invisible = prompt_last_invisible;
202875409Sache  saved_visible_length = prompt_visible_length;
2029136759Speter  saved_invis_chars_first_line = prompt_invis_chars_first_line;
2030136759Speter  saved_physical_chars = prompt_physical_chars;
203121308Sache
203221308Sache  local_prompt = local_prompt_prefix = (char *)0;
2033165675Sache  local_prompt_len = 0;
2034157188Sache  prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0;
2035136759Speter  prompt_invis_chars_first_line = prompt_physical_chars = 0;
203621308Sache}
203721308Sache
203821308Sachevoid
203947563Sacherl_restore_prompt ()
204021308Sache{
204175409Sache  FREE (local_prompt);
204275409Sache  FREE (local_prompt_prefix);
204321308Sache
204421308Sache  local_prompt = saved_local_prompt;
204521308Sache  local_prompt_prefix = saved_local_prefix;
2046165675Sache  local_prompt_len = saved_local_length;
2047157188Sache  prompt_prefix_length = saved_prefix_length;
204875409Sache  prompt_last_invisible = saved_last_invisible;
204975409Sache  prompt_visible_length = saved_visible_length;
2050136759Speter  prompt_invis_chars_first_line = saved_invis_chars_first_line;
2051136759Speter  prompt_physical_chars = saved_physical_chars;
2052157188Sache
2053157188Sache  /* can test saved_local_prompt to see if prompt info has been saved. */
2054157188Sache  saved_local_prompt = saved_local_prefix = (char *)0;
2055165675Sache  saved_local_length = 0;
2056157188Sache  saved_last_invisible = saved_visible_length = saved_prefix_length = 0;
2057157188Sache  saved_invis_chars_first_line = saved_physical_chars = 0;
205821308Sache}
205921308Sache
206021308Sachechar *
206121308Sache_rl_make_prompt_for_search (pchar)
206221308Sache     int pchar;
206321308Sache{
206421308Sache  int len;
2065157195Sache  char *pmt, *p;
206621308Sache
206747563Sache  rl_save_prompt ();
206821308Sache
2069157195Sache  /* We've saved the prompt, and can do anything with the various prompt
2070157195Sache     strings we need before they're restored.  We want the unexpanded
2071157195Sache     portion of the prompt string after any final newline. */
2072157195Sache  p = rl_prompt ? strrchr (rl_prompt, '\n') : 0;
2073157195Sache  if (p == 0)
207421308Sache    {
207521308Sache      len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
2076119614Sache      pmt = (char *)xmalloc (len + 2);
207721308Sache      if (len)
207847563Sache	strcpy (pmt, rl_prompt);
207921308Sache      pmt[len] = pchar;
208021308Sache      pmt[len+1] = '\0';
208121308Sache    }
208221308Sache  else
208321308Sache    {
2084157195Sache      p++;
2085157195Sache      len = strlen (p);
2086119614Sache      pmt = (char *)xmalloc (len + 2);
208721308Sache      if (len)
2088157195Sache	strcpy (pmt, p);
208921308Sache      pmt[len] = pchar;
209021308Sache      pmt[len+1] = '\0';
2091157195Sache    }
2092136759Speter
2093157195Sache  /* will be overwritten by expand_prompt, called from rl_message */
2094157188Sache  prompt_physical_chars = saved_physical_chars + 1;
209521308Sache  return pmt;
209621308Sache}
209721308Sache
209821308Sache/* Quick redisplay hack when erasing characters at the end of the line. */
209921308Sachevoid
210021308Sache_rl_erase_at_end_of_line (l)
210121308Sache     int l;
210221308Sache{
210321308Sache  register int i;
210421308Sache
210521308Sache  _rl_backspace (l);
210621308Sache  for (i = 0; i < l; i++)
210721308Sache    putc (' ', rl_outstream);
210821308Sache  _rl_backspace (l);
210921308Sache  for (i = 0; i < l; i++)
211021308Sache    visible_line[--_rl_last_c_pos] = '\0';
211121308Sache  rl_display_fixed++;
211221308Sache}
211321308Sache
211421308Sache/* Clear to the end of the line.  COUNT is the minimum
211521308Sache   number of character spaces to clear, */
211626497Sachevoid
211726497Sache_rl_clear_to_eol (count)
211821308Sache     int count;
211921308Sache{
212075409Sache  if (_rl_term_clreol)
212175409Sache    tputs (_rl_term_clreol, 1, _rl_output_character_function);
212226497Sache  else if (count)
212321308Sache    space_to_eol (count);
212421308Sache}
212521308Sache
212621308Sache/* Clear to the end of the line using spaces.  COUNT is the minimum
212721308Sache   number of character spaces to clear, */
212821308Sachestatic void
212921308Sachespace_to_eol (count)
213021308Sache     int count;
213121308Sache{
213221308Sache  register int i;
213321308Sache
213421308Sache  for (i = 0; i < count; i++)
213521308Sache   putc (' ', rl_outstream);
213621308Sache
213721308Sache  _rl_last_c_pos += count;
213821308Sache}
213921308Sache
214026497Sachevoid
214126497Sache_rl_clear_screen ()
214226497Sache{
214375409Sache  if (_rl_term_clrpag)
214475409Sache    tputs (_rl_term_clrpag, 1, _rl_output_character_function);
214526497Sache  else
214675409Sache    rl_crlf ();
214726497Sache}
214826497Sache
2149119614Sache/* Insert COUNT characters from STRING to the output stream at column COL. */
215021308Sachestatic void
2151119614Sacheinsert_some_chars (string, count, col)
215221308Sache     char *string;
2153119614Sache     int count, col;
215421308Sache{
2155157188Sache#if defined (__MSDOS__) || defined (__MINGW32__)
2156157188Sache  _rl_output_some_chars (string, count);
2157157188Sache#else
2158119614Sache  /* DEBUGGING */
2159119614Sache  if (MB_CUR_MAX == 1 || rl_byte_oriented)
2160119614Sache    if (count != col)
2161119614Sache      fprintf(stderr, "readline: debug: insert_some_chars: count (%d) != col (%d)\n", count, col);
2162119614Sache
216321308Sache  /* If IC is defined, then we do not have to "enter" insert mode. */
216475409Sache  if (_rl_term_IC)
216521308Sache    {
216621308Sache      char *buffer;
2167119614Sache
2168119614Sache      buffer = tgoto (_rl_term_IC, 0, col);
216921308Sache      tputs (buffer, 1, _rl_output_character_function);
217021308Sache      _rl_output_some_chars (string, count);
217121308Sache    }
217221308Sache  else
217321308Sache    {
217421308Sache      register int i;
217521308Sache
217621308Sache      /* If we have to turn on insert-mode, then do so. */
217775409Sache      if (_rl_term_im && *_rl_term_im)
217875409Sache	tputs (_rl_term_im, 1, _rl_output_character_function);
217921308Sache
218021308Sache      /* If there is a special command for inserting characters, then
218121308Sache	 use that first to open up the space. */
218275409Sache      if (_rl_term_ic && *_rl_term_ic)
218321308Sache	{
2184119614Sache	  for (i = col; i--; )
218575409Sache	    tputs (_rl_term_ic, 1, _rl_output_character_function);
218621308Sache	}
218721308Sache
218821308Sache      /* Print the text. */
218921308Sache      _rl_output_some_chars (string, count);
219021308Sache
219121308Sache      /* If there is a string to turn off insert mode, we had best use
219221308Sache	 it now. */
219375409Sache      if (_rl_term_ei && *_rl_term_ei)
219475409Sache	tputs (_rl_term_ei, 1, _rl_output_character_function);
219521308Sache    }
2196157188Sache#endif /* __MSDOS__ || __MINGW32__ */
219721308Sache}
219821308Sache
219921308Sache/* Delete COUNT characters from the display line. */
220021308Sachestatic void
220121308Sachedelete_chars (count)
220221308Sache     int count;
220321308Sache{
220475409Sache  if (count > _rl_screenwidth)	/* XXX */
220521308Sache    return;
220621308Sache
2207157188Sache#if !defined (__MSDOS__) && !defined (__MINGW32__)
220875409Sache  if (_rl_term_DC && *_rl_term_DC)
220921308Sache    {
221021308Sache      char *buffer;
221175409Sache      buffer = tgoto (_rl_term_DC, count, count);
221221308Sache      tputs (buffer, count, _rl_output_character_function);
221321308Sache    }
221421308Sache  else
221521308Sache    {
221675409Sache      if (_rl_term_dc && *_rl_term_dc)
221721308Sache	while (count--)
221875409Sache	  tputs (_rl_term_dc, 1, _rl_output_character_function);
221921308Sache    }
2220157188Sache#endif /* !__MSDOS__ && !__MINGW32__ */
222121308Sache}
222221308Sache
222321308Sachevoid
222421308Sache_rl_update_final ()
222521308Sache{
222621308Sache  int full_lines;
222721308Sache
222821308Sache  full_lines = 0;
222921308Sache  /* If the cursor is the only thing on an otherwise-blank last line,
223021308Sache     compensate so we don't print an extra CRLF. */
223121308Sache  if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
223226497Sache	visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
223321308Sache    {
223421308Sache      _rl_vis_botlin--;
223521308Sache      full_lines = 1;
223621308Sache    }
223721308Sache  _rl_move_vert (_rl_vis_botlin);
223821308Sache  /* If we've wrapped lines, remove the final xterm line-wrap flag. */
223975409Sache  if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth))
224021308Sache    {
224121308Sache      char *last_line;
2242119614Sache
224358314Sache      last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]];
2244165675Sache      cpos_buffer_position = -1;	/* don't know where we are in buffer */
2245165675Sache      _rl_move_cursor_relative (_rl_screenwidth - 1, last_line);	/* XXX */
224626497Sache      _rl_clear_to_eol (0);
224775409Sache      putc (last_line[_rl_screenwidth - 1], rl_outstream);
224821308Sache    }
224921308Sache  _rl_vis_botlin = 0;
225075409Sache  rl_crlf ();
225121308Sache  fflush (rl_outstream);
225221308Sache  rl_display_fixed++;
225321308Sache}
225421308Sache
225521308Sache/* Move to the start of the current line. */
225621308Sachestatic void
225721308Sachecr ()
225821308Sache{
225975409Sache  if (_rl_term_cr)
226021308Sache    {
226158314Sache#if defined (__MSDOS__)
226258314Sache      putc ('\r', rl_outstream);
226358314Sache#else
226475409Sache      tputs (_rl_term_cr, 1, _rl_output_character_function);
226558314Sache#endif
226621308Sache      _rl_last_c_pos = 0;
226721308Sache    }
226821308Sache}
226921308Sache
227058314Sache/* Redraw the last line of a multi-line prompt that may possibly contain
227158314Sache   terminal escape sequences.  Called with the cursor at column 0 of the
227258314Sache   line to draw the prompt on. */
227358314Sachestatic void
227458314Sacheredraw_prompt (t)
227558314Sache     char *t;
227658314Sache{
2277157188Sache  char *oldp;
227858314Sache
227958314Sache  oldp = rl_display_prompt;
2280157188Sache  rl_save_prompt ();
228158314Sache
228258314Sache  rl_display_prompt = t;
228375409Sache  local_prompt = expand_prompt (t, &prompt_visible_length,
228475409Sache				   &prompt_last_invisible,
2285136759Speter				   &prompt_invis_chars_first_line,
2286136759Speter				   &prompt_physical_chars);
228758314Sache  local_prompt_prefix = (char *)NULL;
2288165675Sache  local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
2289157188Sache
229058314Sache  rl_forced_update_display ();
229158314Sache
229258314Sache  rl_display_prompt = oldp;
2293157188Sache  rl_restore_prompt();
229458314Sache}
229558314Sache
229621308Sache/* Redisplay the current line after a SIGWINCH is received. */
229721308Sachevoid
229821308Sache_rl_redisplay_after_sigwinch ()
229921308Sache{
230058314Sache  char *t;
230121308Sache
230221308Sache  /* Clear the current line and put the cursor at column 0.  Make sure
230321308Sache     the right thing happens if we have wrapped to a new screen line. */
230475409Sache  if (_rl_term_cr)
230521308Sache    {
230658314Sache#if defined (__MSDOS__)
230758314Sache      putc ('\r', rl_outstream);
230858314Sache#else
230975409Sache      tputs (_rl_term_cr, 1, _rl_output_character_function);
231058314Sache#endif
231121308Sache      _rl_last_c_pos = 0;
231258314Sache#if defined (__MSDOS__)
231375409Sache      space_to_eol (_rl_screenwidth);
231458314Sache      putc ('\r', rl_outstream);
231558314Sache#else
231675409Sache      if (_rl_term_clreol)
231775409Sache	tputs (_rl_term_clreol, 1, _rl_output_character_function);
231821308Sache      else
231921308Sache	{
232075409Sache	  space_to_eol (_rl_screenwidth);
232175409Sache	  tputs (_rl_term_cr, 1, _rl_output_character_function);
232221308Sache	}
232358314Sache#endif
232421308Sache      if (_rl_last_v_pos > 0)
232521308Sache	_rl_move_vert (0);
232621308Sache    }
232721308Sache  else
232875409Sache    rl_crlf ();
232921308Sache
233021308Sache  /* Redraw only the last line of a multi-line prompt. */
233121308Sache  t = strrchr (rl_display_prompt, '\n');
233221308Sache  if (t)
233358314Sache    redraw_prompt (++t);
233421308Sache  else
233521308Sache    rl_forced_update_display ();
233621308Sache}
233721308Sache
233821308Sachevoid
233921308Sache_rl_clean_up_for_exit ()
234021308Sache{
234121308Sache  if (readline_echoing_p)
234221308Sache    {
234321308Sache      _rl_move_vert (_rl_vis_botlin);
234421308Sache      _rl_vis_botlin = 0;
234521308Sache      fflush (rl_outstream);
234647563Sache      rl_restart_output (1, 0);
234721308Sache    }
234821308Sache}
234947563Sache
235047563Sachevoid
235147563Sache_rl_erase_entire_line ()
235247563Sache{
235347563Sache  cr ();
235447563Sache  _rl_clear_to_eol (0);
235547563Sache  cr ();
235647563Sache  fflush (rl_outstream);
235747563Sache}
235858314Sache
235958314Sache/* return the `current display line' of the cursor -- the number of lines to
236058314Sache   move up to get to the first screen line of the current readline line. */
236158314Sacheint
236258314Sache_rl_current_display_line ()
236358314Sache{
236458314Sache  int ret, nleft;
236558314Sache
236658314Sache  /* Find out whether or not there might be invisible characters in the
236758314Sache     editing buffer. */
236858314Sache  if (rl_display_prompt == rl_prompt)
236975409Sache    nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length;
237058314Sache  else
237175409Sache    nleft = _rl_last_c_pos - _rl_screenwidth;
237258314Sache
237358314Sache  if (nleft > 0)
237475409Sache    ret = 1 + nleft / _rl_screenwidth;
237558314Sache  else
237658314Sache    ret = 0;
237758314Sache
237858314Sache  return ret;
237958314Sache}
2380119614Sache
2381119614Sache#if defined (HANDLE_MULTIBYTE)
2382119614Sache/* Calculate the number of screen columns occupied by STR from START to END.
2383119614Sache   In the case of multibyte characters with stateful encoding, we have to
2384119614Sache   scan from the beginning of the string to take the state into account. */
2385119614Sachestatic int
2386119614Sache_rl_col_width (str, start, end)
2387136759Speter     const char *str;
2388119614Sache     int start, end;
2389119614Sache{
2390119614Sache  wchar_t wc;
2391165675Sache  mbstate_t ps;
2392119614Sache  int tmp, point, width, max;
2393119614Sache
2394119614Sache  if (end <= start)
2395119614Sache    return 0;
2396165680Sache  if (MB_CUR_MAX == 1 || rl_byte_oriented)
2397165680Sache    return (end - start);
2398119614Sache
2399165675Sache  memset (&ps, 0, sizeof (mbstate_t));
2400165675Sache
2401119614Sache  point = 0;
2402119614Sache  max = end;
2403119614Sache
2404119614Sache  while (point < start)
2405119614Sache    {
2406119614Sache      tmp = mbrlen (str + point, max, &ps);
2407136759Speter      if (MB_INVALIDCH ((size_t)tmp))
2408119614Sache	{
2409119614Sache	  /* In this case, the bytes are invalid or too short to compose a
2410119614Sache	     multibyte character, so we assume that the first byte represents
2411119614Sache	     a single character. */
2412119614Sache	  point++;
2413119614Sache	  max--;
2414119614Sache
2415119614Sache	  /* Clear the state of the byte sequence, because in this case the
2416119614Sache	     effect of mbstate is undefined. */
2417119614Sache	  memset (&ps, 0, sizeof (mbstate_t));
2418119614Sache	}
2419136759Speter      else if (MB_NULLWCH (tmp))
2420136759Speter	break;		/* Found '\0' */
2421119614Sache      else
2422119614Sache	{
2423119614Sache	  point += tmp;
2424119614Sache	  max -= tmp;
2425119614Sache	}
2426119614Sache    }
2427119614Sache
2428119614Sache  /* If START is not a byte that starts a character, then POINT will be
2429119614Sache     greater than START.  In this case, assume that (POINT - START) gives
2430119614Sache     a byte count that is the number of columns of difference. */
2431119614Sache  width = point - start;
2432119614Sache
2433119614Sache  while (point < end)
2434119614Sache    {
2435119614Sache      tmp = mbrtowc (&wc, str + point, max, &ps);
2436136759Speter      if (MB_INVALIDCH ((size_t)tmp))
2437119614Sache	{
2438119614Sache	  /* In this case, the bytes are invalid or too short to compose a
2439119614Sache	     multibyte character, so we assume that the first byte represents
2440119614Sache	     a single character. */
2441119614Sache	  point++;
2442119614Sache	  max--;
2443119614Sache
2444119614Sache	  /* and assume that the byte occupies a single column. */
2445119614Sache	  width++;
2446119614Sache
2447119614Sache	  /* Clear the state of the byte sequence, because in this case the
2448119614Sache	     effect of mbstate is undefined. */
2449119614Sache	  memset (&ps, 0, sizeof (mbstate_t));
2450119614Sache	}
2451136759Speter      else if (MB_NULLWCH (tmp))
2452136759Speter	break;			/* Found '\0' */
2453119614Sache      else
2454119614Sache	{
2455119614Sache	  point += tmp;
2456119614Sache	  max -= tmp;
2457119614Sache	  tmp = wcwidth(wc);
2458119614Sache	  width += (tmp >= 0) ? tmp : 1;
2459119614Sache	}
2460119614Sache    }
2461119614Sache
2462119614Sache  width += point - end;
2463119614Sache
2464119614Sache  return width;
2465119614Sache}
2466119614Sache#endif /* HANDLE_MULTIBYTE */
2467