display.c revision 136759
150276Speter/* $FreeBSD: head/contrib/libreadline/display.c 136759 2004-10-21 20:10:14Z peter $ */
2184989Srafan
350276Speter/* display.c -- readline redisplay facility. */
450276Speter
550276Speter/* Copyright (C) 1987-2004 Free Software Foundation, Inc.
650276Speter
750276Speter   This file is part of the GNU Readline Library, a library for
850276Speter   reading lines of text with interactive input and history editing.
950276Speter
1050276Speter   The GNU Readline Library is free software; you can redistribute it
1150276Speter   and/or modify it under the terms of the GNU General Public License
1250276Speter   as published by the Free Software Foundation; either version 2, or
1350276Speter   (at your option) any later version.
1450276Speter
1550276Speter   The GNU Readline Library is distributed in the hope that it will be
1650276Speter   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
1750276Speter   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1850276Speter   GNU General Public License for more details.
1950276Speter
2050276Speter   The GNU General Public License is often shipped with GNU software, and
2150276Speter   is generally kept in a file called COPYING or LICENSE.  If you do not
2250276Speter   have a copy of the license, write to the Free Software Foundation,
2350276Speter   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
2450276Speter#define READLINE_LIBRARY
2550276Speter
2650276Speter#if defined (HAVE_CONFIG_H)
2750276Speter#  include <config.h>
2850276Speter#endif
2950276Speter
3050276Speter#include <sys/types.h>
3150276Speter
32166124Srafan#if defined (HAVE_UNISTD_H)
3350276Speter#  include <unistd.h>
3450276Speter#endif /* HAVE_UNISTD_H */
3550276Speter
3650276Speter#include "posixstat.h"
3750276Speter
3850276Speter#if defined (HAVE_STDLIB_H)
3950276Speter#  include <stdlib.h>
4050276Speter#else
4150276Speter#  include "ansi_stdlib.h"
4250276Speter#endif /* HAVE_STDLIB_H */
43166124Srafan
4450276Speter#include <stdio.h>
4550276Speter
4650276Speter/* System-specific feature definitions and include files. */
4750276Speter#include "rldefs.h"
4850276Speter#include "rlmbutil.h"
4950276Speter
5050276Speter/* Termcap library stuff. */
5150276Speter#include "tcap.h"
5250276Speter
5350276Speter/* Some standard library routines. */
5450276Speter#include "readline.h"
5550276Speter#include "history.h"
5650276Speter
5750276Speter#include "rlprivate.h"
5850276Speter#include "xmalloc.h"
5950276Speter
6050276Speter#if !defined (strchr) && !defined (__STDC__)
6150276Speterextern char *strchr (), *strrchr ();
6250276Speter#endif /* !strchr && !__STDC__ */
6350276Speter
6450276Speter#if defined (HACK_TERMCAP_MOTION)
6550276Speterextern char *_rl_term_forward_char;
6650276Speter#endif
6750276Speter
6850276Speterstatic void update_line PARAMS((char *, char *, int, int, int, int));
6950276Speterstatic void space_to_eol PARAMS((int));
7050276Speterstatic void delete_chars PARAMS((int));
7150276Speterstatic void insert_some_chars PARAMS((char *, int, int));
7250276Speterstatic void cr PARAMS((void));
7350276Speter
7450276Speter#if defined (HANDLE_MULTIBYTE)
7550276Speterstatic int _rl_col_width PARAMS((const char *, int, int));
7650276Speterstatic int *_rl_wrapped_line;
7750276Speter#else
7850276Speter#  define _rl_col_width(l, s, e)	(((e) <= (s)) ? 0 : (e) - (s))
7950276Speter#endif
8050276Speter
8150276Speterstatic int *inv_lbreaks, *vis_lbreaks;
8250276Speterstatic int inv_lbsize, vis_lbsize;
8350276Speter
8450276Speter/* Heuristic used to decide whether it is faster to move from CUR to NEW
8550276Speter   by backing up or outputting a carriage return and moving forward. */
8650276Speter#define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new)))
8750276Speter
8850276Speter/* **************************************************************** */
8950276Speter/*								    */
9050276Speter/*			Display stuff				    */
9150276Speter/*								    */
9250276Speter/* **************************************************************** */
9350276Speter
9450276Speter/* This is the stuff that is hard for me.  I never seem to write good
9550276Speter   display routines in C.  Let's see how I do this time. */
96184989Srafan
9750276Speter/* (PWP) Well... Good for a simple line updater, but totally ignores
9850276Speter   the problems of input lines longer than the screen width.
9950276Speter
10050276Speter   update_line and the code that calls it makes a multiple line,
10150276Speter   automatically wrapping line update.  Careful attention needs
10250276Speter   to be paid to the vertical position variables. */
10350276Speter
10450276Speter/* Keep two buffers; one which reflects the current contents of the
10550276Speter   screen, and the other to draw what we think the new contents should
10650276Speter   be.  Then compare the buffers, and make whatever changes to the
10750276Speter   screen itself that we should.  Finally, make the buffer that we
10850276Speter   just drew into be the one which reflects the current contents of the
10962449Speter   screen, and place the cursor where it belongs.
11050276Speter
11150276Speter   Commands that want to can fix the display themselves, and then let
11262449Speter   this function know that the display has been fixed by setting the
11362449Speter   RL_DISPLAY_FIXED variable.  This is good for efficiency. */
11450276Speter
11550276Speter/* Application-specific redisplay function. */
11662449Speterrl_voidfunc_t *rl_redisplay_function = rl_redisplay;
11762449Speter
11862449Speter/* Global variables declared here. */
119166124Srafan/* What YOU turn on when you have handled all redisplay yourself. */
12050276Speterint rl_display_fixed = 0;
12162449Speter
12262449Speterint _rl_suppress_redisplay = 0;
12350276Speter
12450276Speter/* The stuff that gets printed out before the actual text of the line.
12562449Speter   This is usually pointing to rl_prompt. */
12662449Speterchar *rl_display_prompt = (char *)NULL;
12750276Speter
12862449Speter/* Pseudo-global variables declared here. */
12962449Speter/* The visible cursor position.  If you print some text, adjust this. */
13062449Speterint _rl_last_c_pos = 0;
13162449Speterint _rl_last_v_pos = 0;
13262449Speter
133166124Srafan/* Number of lines currently on screen minus 1. */
13462449Speterint _rl_vis_botlin = 0;
13562449Speter
13662449Speter/* Variables used only in this file. */
13762449Speter/* The last left edge of text that was displayed.  This is used when
13850276Speter   doing horizontal scrolling.  It shifts in thirds of a screenwidth. */
13950276Speterstatic int last_lmargin;
140166124Srafan
141166124Srafan/* The line display buffers.  One is the line currently displayed on
14250276Speter   the screen.  The other is the line about to be displayed. */
14362449Speterstatic char *visible_line = (char *)NULL;
144166124Srafanstatic char *invisible_line = (char *)NULL;
14562449Speter
14650276Speter/* A buffer for `modeline' messages. */
14750276Speterstatic char msg_buf[128];
14862449Speter
14962449Speter/* Non-zero forces the redisplay even if we thought it was unnecessary. */
15050276Speterstatic int forced_display;
15150276Speter
152184989Srafan/* Default and initial buffer size.  Can grow. */
15350276Speterstatic int line_size = 1024;
15450276Speter
15550276Speter/* Variables to keep track of the expanded prompt string, which may
15650276Speter   include invisible characters. */
15750276Speter
15862449Speterstatic char *local_prompt, *local_prompt_prefix;
15962449Speterstatic int prompt_visible_length, prompt_prefix_length;
16050276Speter
16150276Speter/* The number of invisible characters in the line currently being
16250276Speter   displayed on the screen. */
16350276Speterstatic int visible_wrap_offset;
16450276Speter
16550276Speter/* The number of invisible characters in the prompt string.  Static so it
16650276Speter   can be shared between rl_redisplay and update_line */
16762449Speterstatic int wrap_offset;
16850276Speter
16950276Speter/* The index of the last invisible character in the prompt string. */
17050276Speterstatic int prompt_last_invisible;
17150276Speter
17262449Speter/* The length (buffer offset) of the first line of the last (possibly
17362449Speter   multi-line) buffer displayed on the screen. */
17450276Speterstatic int visible_first_line_len;
17550276Speter
17650276Speter/* Number of invisible characters on the first physical line of the prompt.
17750276Speter   Only valid when the number of physical characters in the prompt exceeds
17850276Speter   (or is equal to) _rl_screenwidth. */
17962449Speterstatic int prompt_invis_chars_first_line;
18050276Speter
18162449Speterstatic int prompt_last_screen_line;
18250276Speter
18350276Speterstatic int prompt_physical_chars;
18450276Speter
18550276Speter/* Expand the prompt string S and return the number of visible
186184989Srafan   characters in *LP, if LP is not null.  This is currently more-or-less
18750276Speter   a placeholder for expansion.  LIP, if non-null is a place to store the
18850276Speter   index of the last invisible character in the returned string. NIFLP,
18950276Speter   if non-zero, is a place to store the number of invisible characters in
19050276Speter   the first prompt line.  The previous are used as byte counts -- indexes
19150276Speter   into a character buffer. */
19250276Speter
19350276Speter/* Current implementation:
19450276Speter	\001 (^A) start non-visible characters
19550276Speter	\002 (^B) end non-visible characters
19650276Speter   all characters except \001 and \002 (following a \001) are copied to
19750276Speter   the returned string; all characters except those between \001 and
19897049Speter   \002 are assumed to be `visible'. */
19950276Speter
20050276Speterstatic char *
20150276Speterexpand_prompt (pmt, lp, lip, niflp, vlp)
20250276Speter     char *pmt;
20350276Speter     int *lp, *lip, *niflp, *vlp;
204184989Srafan{
20550276Speter  char *r, *ret, *p;
20650276Speter  int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars;
20750276Speter
20850276Speter  /* Short-circuit if we can. */
20950276Speter  if ((MB_CUR_MAX <= 1 || rl_byte_oriented) && strchr (pmt, RL_PROMPT_START_IGNORE) == 0)
21050276Speter    {
21150276Speter      r = savestring (pmt);
21250276Speter      if (lp)
21350276Speter	*lp = strlen (r);
214184989Srafan      if (lip)
21550276Speter	*lip = 0;
21650276Speter      if (niflp)
21750276Speter	*niflp = 0;
21862449Speter      if (vlp)
21962449Speter	*vlp = lp ? *lp : strlen (r);
22062449Speter      return r;
22150276Speter    }
22262449Speter
22350276Speter  l = strlen (pmt);
22462449Speter  r = ret = (char *)xmalloc (l + 1);
22550276Speter
22662449Speter  invfl = 0;	/* invisible chars in first line of prompt */
22762449Speter  invflset = 0;	/* we only want to set invfl once */
22862449Speter
22950276Speter  for (rl = ignoring = last = ninvis = physchars = 0, p = pmt; p && *p; p++)
23050276Speter    {
23150276Speter      /* This code strips the invisible character string markers
23250276Speter	 RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
23362449Speter      if (*p == RL_PROMPT_START_IGNORE)
23462449Speter	{
23550276Speter	  ignoring++;
23650276Speter	  continue;
23762449Speter	}
23862449Speter      else if (ignoring && *p == RL_PROMPT_END_IGNORE)
23962449Speter	{
24062449Speter	  ignoring = 0;
24162449Speter	  last = r - ret - 1;
24262449Speter	  continue;
24362449Speter	}
24462449Speter      else
24562449Speter	{
24662449Speter#if defined (HANDLE_MULTIBYTE)
24762449Speter	  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
24862449Speter	    {
24962449Speter	      pind = p - pmt;
25050276Speter	      ind = _rl_find_next_mbchar (pmt, pind, 1, MB_FIND_NONZERO);
25162449Speter	      l = ind - pind;
25262449Speter	      while (l--)
25362449Speter	        *r++ = *p++;
25462449Speter	      if (!ignoring)
25550276Speter		{
25662449Speter		  rl += ind - pind;
25750276Speter		  physchars += _rl_col_width (pmt, pind, ind);
25862449Speter		}
25962449Speter	      else
26062449Speter		ninvis += ind - pind;
26162449Speter	      p--;			/* compensate for later increment */
26250276Speter	    }
26362449Speter	  else
26462449Speter#endif
26562449Speter	    {
26650276Speter	      *r++ = *p;
26762449Speter	      if (!ignoring)
26862449Speter		{
26962449Speter		  rl++;			/* visible length byte counter */
27050276Speter		  physchars++;
27150276Speter		}
27276726Speter	      else
27376726Speter		ninvis++;		/* invisible chars byte counter */
27476726Speter	    }
27576726Speter
276166124Srafan	  if (invflset == 0 && rl >= _rl_screenwidth)
27776726Speter	    {
27876726Speter	      invfl = ninvis;
27976726Speter	      invflset = 1;
280166124Srafan	    }
281166124Srafan	}
28250276Speter    }
28350276Speter
28450276Speter  if (rl < _rl_screenwidth)
28550276Speter    invfl = ninvis;
28650276Speter
28750276Speter  *r = '\0';
28850276Speter  if (lp)
28950276Speter    *lp = rl;
29050276Speter  if (lip)
29150276Speter    *lip = last;
29262449Speter  if (niflp)
29350276Speter    *niflp = invfl;
29450276Speter  if  (vlp)
29550276Speter    *vlp = physchars;
29650276Speter  return ret;
29750276Speter}
298166124Srafan
29962449Speter/* Just strip out RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE from
30097049Speter   PMT and return the rest of PMT. */
30150276Speterchar *
30250276Speter_rl_strip_prompt (pmt)
30362449Speter     char *pmt;
30462449Speter{
30550276Speter  char *ret;
30650276Speter
307166124Srafan  ret = expand_prompt (pmt, (int *)NULL, (int *)NULL, (int *)NULL, (int *)NULL);
30862449Speter  return ret;
30950276Speter}
31050276Speter
31162449Speter/*
31262449Speter * Expand the prompt string into the various display components, if
31362449Speter * necessary.
31462449Speter *
31550276Speter * local_prompt = expanded last line of string in rl_display_prompt
31650276Speter *		  (portion after the final newline)
31750276Speter * local_prompt_prefix = portion before last newline of rl_display_prompt,
31850276Speter *			 expanded via expand_prompt
31950276Speter * prompt_visible_length = number of visible characters in local_prompt
32050276Speter * prompt_prefix_length = number of visible characters in local_prompt_prefix
32150276Speter *
32250276Speter * This function is called once per call to readline().  It may also be
32350276Speter * called arbitrarily to expand the primary prompt.
32450276Speter *
32550276Speter * The return value is the number of visible characters on the last line
32650276Speter * of the (possibly multi-line) prompt.
32750276Speter */
32850276Speterint
32950276Speterrl_expand_prompt (prompt)
33062449Speter     char *prompt;
33162449Speter{
33262449Speter  char *p, *t;
33350276Speter  int c;
33450276Speter
33562449Speter  /* Clear out any saved values. */
33662449Speter  FREE (local_prompt);
33762449Speter  FREE (local_prompt_prefix);
33862449Speter
33950276Speter  local_prompt = local_prompt_prefix = (char *)0;
34050276Speter  prompt_last_invisible = prompt_visible_length = 0;
34150276Speter
34250276Speter  if (prompt == 0 || *prompt == 0)
34362449Speter    return (0);
34450276Speter
34550276Speter  p = strrchr (prompt, '\n');
34650276Speter  if (!p)
34750276Speter    {
34862449Speter      /* The prompt is only one logical line, though it might wrap. */
34950276Speter      local_prompt = expand_prompt (prompt, &prompt_visible_length,
35062449Speter					    &prompt_last_invisible,
35150276Speter					    &prompt_invis_chars_first_line,
35262449Speter					    &prompt_physical_chars);
35350276Speter      local_prompt_prefix = (char *)0;
35450276Speter      return (prompt_visible_length);
35550276Speter    }
35676726Speter  else
35750276Speter    {
35850276Speter      /* The prompt spans multiple lines. */
35950276Speter      t = ++p;
36050276Speter      local_prompt = expand_prompt (p, &prompt_visible_length,
36150276Speter				       &prompt_last_invisible,
36250276Speter				       (int *)NULL,
36350276Speter				       &prompt_physical_chars);
36450276Speter      c = *t; *t = '\0';
36550276Speter      /* The portion of the prompt string up to and including the
36650276Speter	 final newline is now null-terminated. */
36750276Speter      local_prompt_prefix = expand_prompt (prompt, &prompt_prefix_length,
36850276Speter						   (int *)NULL,
36950276Speter						   &prompt_invis_chars_first_line,
37050276Speter						   (int *)NULL);
37150276Speter      *t = c;
37262449Speter      return (prompt_prefix_length);
37350276Speter    }
37462449Speter}
37550276Speter
37650276Speter/* Initialize the VISIBLE_LINE and INVISIBLE_LINE arrays, and their associated
37762449Speter   arrays of line break markers.  MINSIZE is the minimum size of VISIBLE_LINE
37850276Speter   and INVISIBLE_LINE; if it is greater than LINE_SIZE, LINE_SIZE is
37950276Speter   increased.  If the lines have already been allocated, this ensures that
38062449Speter   they can hold at least MINSIZE characters. */
38150276Speterstatic void
38250276Speterinit_line_structures (minsize)
38362449Speter      int minsize;
38450276Speter{
38550276Speter  register int n;
38650276Speter
38750276Speter  if (invisible_line == 0)	/* initialize it */
38850276Speter    {
38950276Speter      if (line_size < minsize)
39050276Speter	line_size = minsize;
39150276Speter      visible_line = (char *)xmalloc (line_size);
39250276Speter      invisible_line = (char *)xmalloc (line_size);
39362449Speter    }
39450276Speter  else if (line_size < minsize)	/* ensure it can hold MINSIZE chars */
39550276Speter    {
39650276Speter      line_size *= 2;
39750276Speter      if (line_size < minsize)
39850276Speter	line_size = minsize;
39950276Speter      visible_line = (char *)xrealloc (visible_line, line_size);
40050276Speter      invisible_line = (char *)xrealloc (invisible_line, line_size);
40150276Speter    }
40262449Speter
40350276Speter  for (n = minsize; n < line_size; n++)
40450276Speter    {
40550276Speter      visible_line[n] = 0;
40650276Speter      invisible_line[n] = 1;
40762449Speter    }
40850276Speter
40950276Speter  if (vis_lbreaks == 0)
41050276Speter    {
41150276Speter      /* should be enough. */
41250276Speter      inv_lbsize = vis_lbsize = 256;
41350276Speter      inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int));
41462449Speter      vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int));
41550276Speter#if defined (HANDLE_MULTIBYTE)
41650276Speter      _rl_wrapped_line = (int *)xmalloc (vis_lbsize * sizeof (int));
41762449Speter#endif
41850276Speter      inv_lbreaks[0] = vis_lbreaks[0] = 0;
41950276Speter    }
42050276Speter}
42150276Speter
42250276Speter/* Basic redisplay algorithm. */
42350276Spetervoid
42462449Speterrl_redisplay ()
42550276Speter{
42650276Speter  register int in, out, c, linenum, cursor_linenum;
42750276Speter  register char *line;
42850276Speter  int c_pos, inv_botlin, lb_botlin, lb_linenum;
42962449Speter  int newlines, lpos, temp, modmark, n0, num;
43050276Speter  char *prompt_this_line;
43150276Speter#if defined (HANDLE_MULTIBYTE)
43262449Speter  wchar_t wc;
43350276Speter  size_t wc_bytes;
43450276Speter  int wc_width;
43550276Speter  mbstate_t ps;
43650276Speter  int _rl_wrapped_multicolumn = 0;
43750276Speter#endif
43850276Speter
43950276Speter  if (!readline_echoing_p)
44062449Speter    return;
44150276Speter
44250276Speter  if (!rl_display_prompt)
44362449Speter    rl_display_prompt = "";
44462449Speter
44550276Speter  if (invisible_line == 0)
44662449Speter    {
44750276Speter      init_line_structures (0);
44850276Speter      rl_on_new_line ();
44950276Speter    }
45050276Speter
45162449Speter  /* Draw the line into the buffer. */
45250276Speter  c_pos = -1;
45350276Speter
45450276Speter  line = invisible_line;
45550276Speter  out = inv_botlin = 0;
45650276Speter
45750276Speter  /* Mark the line as modified or not.  We only do this for history
45850276Speter     lines. */
45950276Speter  modmark = 0;
46050276Speter  if (_rl_mark_modified_lines && current_history () && rl_undo_list)
46162449Speter    {
46250276Speter      line[out++] = '*';
46362449Speter      line[out] = '\0';
46462449Speter      modmark = 1;
46562449Speter    }
46650276Speter
46762449Speter  /* If someone thought that the redisplay was handled, but the currently
468166124Srafan     visible line has a different modification state than the one about
46950276Speter     to become visible, then correct the caller's misconception. */
47050276Speter  if (visible_line[0] != invisible_line[0])
47150276Speter    rl_display_fixed = 0;
47250276Speter
47350276Speter  /* If the prompt to be displayed is the `primary' readline prompt (the
47462449Speter     one passed to readline()), use the values we have already expanded.
47562449Speter     If not, use what's already in rl_display_prompt.  WRAP_OFFSET is the
47662449Speter     number of non-visible characters in the prompt string. */
47750276Speter  if (rl_display_prompt == rl_prompt || local_prompt)
47862449Speter    {
47962449Speter      int local_len = local_prompt ? strlen (local_prompt) : 0;
48062449Speter      if (local_prompt_prefix && forced_display)
48150276Speter	_rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix));
48262449Speter
48362449Speter      if (local_len > 0)
48462449Speter	{
48550276Speter	  temp = local_len + out + 2;
48662449Speter	  if (temp >= line_size)
48762449Speter	    {
48862449Speter	      line_size = (temp + 1024) - (temp % 1024);
48950276Speter	      visible_line = (char *)xrealloc (visible_line, line_size);
49062449Speter	      line = invisible_line = (char *)xrealloc (invisible_line, line_size);
49162449Speter	    }
49262449Speter	  strncpy (line + out, local_prompt, local_len);
49350276Speter	  out += local_len;
49462449Speter	}
49562449Speter      line[out] = '\0';
49662449Speter      wrap_offset = local_len - prompt_visible_length;
49750276Speter    }
49862449Speter  else
49962449Speter    {
50062449Speter      int pmtlen;
50150276Speter      prompt_this_line = strrchr (rl_display_prompt, '\n');
50262449Speter      if (!prompt_this_line)
50362449Speter	prompt_this_line = rl_display_prompt;
50462449Speter      else
50550276Speter	{
50662449Speter	  prompt_this_line++;
50762449Speter	  pmtlen = prompt_this_line - rl_display_prompt;	/* temp var */
50862449Speter	  if (forced_display)
50950276Speter	    {
51062449Speter	      _rl_output_some_chars (rl_display_prompt, pmtlen);
51162449Speter	      /* Make sure we are at column zero even after a newline,
51262449Speter		 regardless of the state of terminal output processing. */
51350276Speter	      if (pmtlen < 2 || prompt_this_line[-2] != '\r')
51462449Speter		cr ();
51562449Speter	    }
51662449Speter	}
51750276Speter
51850276Speter      prompt_physical_chars = pmtlen = strlen (prompt_this_line);
51962449Speter      temp = pmtlen + out + 2;
52050276Speter      if (temp >= line_size)
52150276Speter	{
52262449Speter	  line_size = (temp + 1024) - (temp % 1024);
52362449Speter	  visible_line = (char *)xrealloc (visible_line, line_size);
52450276Speter	  line = invisible_line = (char *)xrealloc (invisible_line, line_size);
52550276Speter	}
52662449Speter      strncpy (line + out,  prompt_this_line, pmtlen);
52762449Speter      out += pmtlen;
52862449Speter      line[out] = '\0';
52962449Speter      wrap_offset = prompt_invis_chars_first_line = 0;
53050276Speter    }
53150276Speter
53262449Speter#define CHECK_INV_LBREAKS() \
53350276Speter      do { \
53450276Speter	if (newlines >= (inv_lbsize - 2)) \
53550276Speter	  { \
53662449Speter	    inv_lbsize *= 2; \
53750276Speter	    inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
53850276Speter	  } \
53950276Speter      } while (0)
54050276Speter
54150276Speter#if defined (HANDLE_MULTIBYTE)
54250276Speter#define CHECK_LPOS() \
54350276Speter      do { \
54450276Speter	lpos++; \
54550276Speter	if (lpos >= _rl_screenwidth) \
54662449Speter	  { \
54762449Speter	    if (newlines >= (inv_lbsize - 2)) \
54862449Speter	      { \
54997049Speter		inv_lbsize *= 2; \
55062449Speter		inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
55150276Speter		_rl_wrapped_line = (int *)xrealloc (_rl_wrapped_line, inv_lbsize * sizeof (int)); \
55250276Speter	      } \
55362449Speter	    inv_lbreaks[++newlines] = out; \
55450276Speter	    _rl_wrapped_line[newlines] = _rl_wrapped_multicolumn; \
55550276Speter	    lpos = 0; \
55662449Speter	  } \
55762449Speter      } while (0)
55850276Speter#else
55950276Speter#define CHECK_LPOS() \
56050276Speter      do { \
56162449Speter	lpos++; \
56262449Speter	if (lpos >= _rl_screenwidth) \
56362449Speter	  { \
56462449Speter	    if (newlines >= (inv_lbsize - 2)) \
56562449Speter	      { \
56662449Speter		inv_lbsize *= 2; \
56762449Speter		inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
56862449Speter	      } \
56962449Speter	    inv_lbreaks[++newlines] = out; \
57062449Speter	    lpos = 0; \
57162449Speter	  } \
57262449Speter      } while (0)
57397049Speter#endif
57497049Speter
57562449Speter  /* inv_lbreaks[i] is where line i starts in the buffer. */
57662449Speter  inv_lbreaks[newlines = 0] = 0;
57762449Speter#if 0
57862449Speter  lpos = out - wrap_offset;
57962449Speter#else
58062449Speter  lpos = prompt_physical_chars + modmark;
58162449Speter#endif
58262449Speter
58362449Speter#if defined (HANDLE_MULTIBYTE)
58462449Speter  memset (_rl_wrapped_line, 0, vis_lbsize);
58562449Speter  num = 0;
58662449Speter#endif
58762449Speter
58862449Speter  /* prompt_invis_chars_first_line is the number of invisible characters in
58962449Speter     the first physical line of the prompt.
59062449Speter     wrap_offset - prompt_invis_chars_first_line is the number of invis
59162449Speter     chars on the second line. */
59262449Speter
59362449Speter  /* what if lpos is already >= _rl_screenwidth before we start drawing the
59462449Speter     contents of the command line? */
59562449Speter  while (lpos >= _rl_screenwidth)
59662449Speter    {
59762449Speter      /* fix from Darin Johnson <darin@acuson.com> for prompt string with
59862449Speter         invisible characters that is longer than the screen width.  The
59962449Speter         prompt_invis_chars_first_line variable could be made into an array
60062449Speter         saying how many invisible characters there are per line, but that's
60176726Speter         probably too much work for the benefit gained.  How many people have
60262449Speter         prompts that exceed two physical lines?
60362449Speter         Additional logic fix from Edward Catmur <ed@catmur.co.uk> */
60462449Speter#if defined (HANDLE_MULTIBYTE)
60562449Speter      n0 = num;
60662449Speter      temp = local_prompt ? strlen (local_prompt) : 0;
60762449Speter      while (num < temp)
60862449Speter	{
60962449Speter	  if (_rl_col_width  (local_prompt, n0, num) > _rl_screenwidth)
61062449Speter	    {
61162449Speter	      num = _rl_find_prev_mbchar (local_prompt, num, MB_FIND_ANY);
61262449Speter	      break;
61362449Speter	    }
61462449Speter	  num++;
61562449Speter	}
61662449Speter      temp = num +
61762449Speter#else
61862449Speter      temp = ((newlines + 1) * _rl_screenwidth) +
61950276Speter#endif /* !HANDLE_MULTIBYTE */
62050276Speter             ((local_prompt_prefix == 0) ? ((newlines == 0) ? prompt_invis_chars_first_line
62150276Speter							    : ((newlines == 1) ? wrap_offset : 0))
62250276Speter					 : ((newlines == 0) ? wrap_offset :0));
62350276Speter
62450276Speter      inv_lbreaks[++newlines] = temp;
62550276Speter#if defined (HANDLE_MULTIBYTE)
62650276Speter      lpos -= _rl_col_width (local_prompt, n0, num);
62750276Speter#else
62850276Speter      lpos -= _rl_screenwidth;
62950276Speter#endif
63050276Speter    }
63150276Speter
63250276Speter  prompt_last_screen_line = newlines;
63350276Speter
63450276Speter  /* Draw the rest of the line (after the prompt) into invisible_line, keeping
63550276Speter     track of where the cursor is (c_pos), the number of the line containing
63676726Speter     the cursor (lb_linenum), the last line number (lb_botlin and inv_botlin).
63776726Speter     It maintains an array of line breaks for display (inv_lbreaks).
63876726Speter     This handles expanding tabs for display and displaying meta characters. */
63976726Speter  lb_linenum = 0;
640166124Srafan#if defined (HANDLE_MULTIBYTE)
641166124Srafan  in = 0;
64250276Speter  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
64362449Speter    {
64450276Speter      memset (&ps, 0, sizeof (mbstate_t));
64550276Speter      wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps);
64650276Speter    }
64750276Speter  else
64862449Speter    wc_bytes = 1;
64962449Speter  while (in < rl_end)
65050276Speter#else
65150276Speter  for (in = 0; in < rl_end; in++)
65250276Speter#endif
653166124Srafan    {
65450276Speter      c = (unsigned char)rl_line_buffer[in];
65597049Speter
65650276Speter#if defined (HANDLE_MULTIBYTE)
657166124Srafan      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
65850276Speter	{
65950276Speter	  if (MB_INVALIDCH (wc_bytes))
66050276Speter	    {
66197049Speter	      /* Byte sequence is invalid or shortened.  Assume that the
66250276Speter	         first byte represents a character. */
66350276Speter	      wc_bytes = 1;
66450276Speter	      /* Assume that a character occupies a single column. */
66562449Speter	      wc_width = 1;
66662449Speter	      memset (&ps, 0, sizeof (mbstate_t));
66762449Speter	    }
66850276Speter	  else if (MB_NULLWCH (wc_bytes))
66962449Speter	    break;			/* Found '\0' */
67050276Speter	  else
67162449Speter	    {
67250276Speter	      temp = wcwidth (wc);
67397049Speter	      wc_width = (temp >= 0) ? temp : 1;
67476726Speter	    }
67576726Speter	}
67676726Speter#endif
67776726Speter
67850276Speter      if (out + 8 >= line_size)		/* XXX - 8 for \t */
67950276Speter	{
68062449Speter	  line_size *= 2;
68162449Speter	  visible_line = (char *)xrealloc (visible_line, line_size);
682166124Srafan	  invisible_line = (char *)xrealloc (invisible_line, line_size);
683166124Srafan	  line = invisible_line;
68450276Speter	}
68562449Speter
68650276Speter      if (in == rl_point)
68762449Speter	{
68862449Speter	  c_pos = out;
68950276Speter	  lb_linenum = newlines;
69062449Speter	}
69162449Speter
69250276Speter#if defined (HANDLE_MULTIBYTE)
69362449Speter      if (META_CHAR (c) && _rl_output_meta_chars == 0)	/* XXX - clean up */
69462449Speter#else
69550276Speter      if (META_CHAR (c))
69662449Speter#endif
69762449Speter	{
69862449Speter	  if (_rl_output_meta_chars == 0)
69962449Speter	    {
70062449Speter	      sprintf (line + out, "\\%o", c);
70162449Speter
70276726Speter	      if (lpos + 4 >= _rl_screenwidth)
70350276Speter		{
70462449Speter		  temp = _rl_screenwidth - lpos;
70550276Speter		  CHECK_INV_LBREAKS ();
70650276Speter		  inv_lbreaks[++newlines] = out + temp;
70750276Speter		  lpos = 4 - temp;
70862449Speter		}
70950276Speter	      else
71062449Speter		lpos += 4;
71162449Speter
71250276Speter	      out += 4;
71362449Speter	    }
71462449Speter	  else
71550276Speter	    {
71662449Speter	      line[out++] = c;
71762449Speter	      CHECK_LPOS();
71850276Speter	    }
71962449Speter	}
72050276Speter#if defined (DISPLAY_TABS)
72162449Speter      else if (c == '\t')
72262449Speter	{
72350276Speter	  register int newout;
72462449Speter
72550276Speter#if 0
72650276Speter	  newout = (out | (int)7) + 1;
72750276Speter#else
72850276Speter	  newout = out + 8 - lpos % 8;
72950276Speter#endif
73050276Speter	  temp = newout - out;
73150276Speter	  if (lpos + temp >= _rl_screenwidth)
73250276Speter	    {
73350276Speter	      register int temp2;
73450276Speter	      temp2 = _rl_screenwidth - lpos;
73550276Speter	      CHECK_INV_LBREAKS ();
73650276Speter	      inv_lbreaks[++newlines] = out + temp2;
73750276Speter	      lpos = temp - temp2;
73850276Speter	      while (out < newout)
73950276Speter		line[out++] = ' ';
74050276Speter	    }
74150276Speter	  else
74297049Speter	    {
74350276Speter	      while (out < newout)
74462449Speter		line[out++] = ' ';
74562449Speter	      lpos += temp;
74662449Speter	    }
74762449Speter	}
74850276Speter#endif
74950276Speter      else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
75050276Speter	{
75162449Speter	  line[out++] = '\0';	/* XXX - sentinel */
75250276Speter	  CHECK_INV_LBREAKS ();
75350276Speter	  inv_lbreaks[++newlines] = out;
75450276Speter	  lpos = 0;
75562449Speter	}
75650276Speter      else if (CTRL_CHAR (c) || c == RUBOUT)
75750276Speter	{
75862449Speter	  line[out++] = '^';
75962449Speter	  CHECK_LPOS();
76062449Speter	  line[out++] = CTRL_CHAR (c) ? UNCTRL (c) : '?';
76162449Speter	  CHECK_LPOS();
76262449Speter	}
76350276Speter      else
76462449Speter	{
76550276Speter#if defined (HANDLE_MULTIBYTE)
76650276Speter	  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
76750276Speter	    {
76850276Speter	      register int i;
76950276Speter
77050276Speter	      _rl_wrapped_multicolumn = 0;
77162449Speter
77262449Speter	      if (_rl_screenwidth < lpos + wc_width)
77362449Speter		for (i = lpos; i < _rl_screenwidth; i++)
77450276Speter		  {
77550276Speter		    /* The space will be removed in update_line() */
77662449Speter		    line[out++] = ' ';
77762449Speter		    _rl_wrapped_multicolumn++;
77850276Speter		    CHECK_LPOS();
77950276Speter		  }
78050276Speter	      if (in == rl_point)
78162449Speter		{
78250276Speter		  c_pos = out;
78350276Speter		  lb_linenum = newlines;
78450276Speter		}
78562449Speter	      for (i = in; i < in+wc_bytes; i++)
78662449Speter		line[out++] = rl_line_buffer[i];
78762449Speter	      for (i = 0; i < wc_width; i++)
78862449Speter		CHECK_LPOS();
78962449Speter	    }
79050276Speter	  else
791184989Srafan	    {
792184989Srafan	      line[out++] = c;
793184989Srafan	      CHECK_LPOS();
794184989Srafan	    }
795184989Srafan#else
79650276Speter	  line[out++] = c;
79750276Speter	  CHECK_LPOS();
79850276Speter#endif
79962449Speter	}
80050276Speter
80162449Speter#if defined (HANDLE_MULTIBYTE)
80250276Speter      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
80350276Speter	{
80450276Speter	  in += wc_bytes;
80550276Speter	  wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps);
80650276Speter	}
80750276Speter      else
80862449Speter        in++;
80962449Speter#endif
81050276Speter
81150276Speter    }
81250276Speter  line[out] = '\0';
81350276Speter  if (c_pos < 0)
81462449Speter    {
81550276Speter      c_pos = out;
81650276Speter      lb_linenum = newlines;
81750276Speter    }
81850276Speter
81950276Speter  inv_botlin = lb_botlin = newlines;
82050276Speter  CHECK_INV_LBREAKS ();
82162449Speter  inv_lbreaks[newlines+1] = out;
82262449Speter  cursor_linenum = lb_linenum;
82350276Speter
82450276Speter  /* C_POS == position in buffer where cursor should be placed.
82550276Speter     CURSOR_LINENUM == line number where the cursor should be placed. */
82650276Speter
82750276Speter  /* PWP: now is when things get a bit hairy.  The visible and invisible
82850276Speter     line buffers are really multiple lines, which would wrap every
82950276Speter     (screenwidth - 1) characters.  Go through each in turn, finding
83062449Speter     the changed region and updating it.  The line order is top to bottom. */
83162449Speter
83250276Speter  /* If we can move the cursor up and down, then use multiple lines,
83350276Speter     otherwise, let long lines display in a single terminal line, and
83450276Speter     horizontally scroll it. */
83562449Speter
83650276Speter  if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
83750276Speter    {
83850276Speter      int nleft, pos, changed_screen_line;
83962449Speter
84050276Speter      if (!rl_display_fixed || forced_display)
84150276Speter	{
84250276Speter	  forced_display = 0;
843166124Srafan
844166124Srafan	  /* If we have more than a screenful of material to display, then
845166124Srafan	     only display a screenful.  We should display the last screen,
846166124Srafan	     not the first.  */
847166124Srafan	  if (out >= _rl_screenchars)
848166124Srafan	    {
849166124Srafan	      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
850166124Srafan		out = _rl_find_prev_mbchar (line, _rl_screenchars, MB_FIND_ANY);
851166124Srafan	      else
852166124Srafan		out = _rl_screenchars - 1;
853	    }
854
855	  /* The first line is at character position 0 in the buffer.  The
856	     second and subsequent lines start at inv_lbreaks[N], offset by
857	     OFFSET (which has already been calculated above).  */
858
859#define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
860#define VIS_LLEN(l)	((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
861#define INV_LLEN(l)	(inv_lbreaks[l+1] - inv_lbreaks[l])
862#define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
863#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
864#define INV_LINE(line) (invisible_line + inv_lbreaks[line])
865
866	  /* For each line in the buffer, do the updating display. */
867	  for (linenum = 0; linenum <= inv_botlin; linenum++)
868	    {
869	      update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum,
870			   VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin);
871
872	      /* If this is the line with the prompt, we might need to
873		 compensate for invisible characters in the new line. Do
874		 this only if there is not more than one new line (which
875		 implies that we completely overwrite the old visible line)
876		 and the new line is shorter than the old.  Make sure we are
877		 at the end of the new line before clearing. */
878	      if (linenum == 0 &&
879		  inv_botlin == 0 && _rl_last_c_pos == out &&
880		  (wrap_offset > visible_wrap_offset) &&
881		  (_rl_last_c_pos < visible_first_line_len))
882		{
883		  nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos;
884		  if (nleft)
885		    _rl_clear_to_eol (nleft);
886		}
887
888	      /* Since the new first line is now visible, save its length. */
889	      if (linenum == 0)
890		visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset;
891	    }
892
893	  /* We may have deleted some lines.  If so, clear the left over
894	     blank ones at the bottom out. */
895	  if (_rl_vis_botlin > inv_botlin)
896	    {
897	      char *tt;
898	      for (; linenum <= _rl_vis_botlin; linenum++)
899		{
900		  tt = VIS_CHARS (linenum);
901		  _rl_move_vert (linenum);
902		  _rl_move_cursor_relative (0, tt);
903		  _rl_clear_to_eol
904		    ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth);
905		}
906	    }
907	  _rl_vis_botlin = inv_botlin;
908
909	  /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
910	     different screen line during this redisplay. */
911	  changed_screen_line = _rl_last_v_pos != cursor_linenum;
912	  if (changed_screen_line)
913	    {
914	      _rl_move_vert (cursor_linenum);
915	      /* If we moved up to the line with the prompt using _rl_term_up,
916		 the physical cursor position on the screen stays the same,
917		 but the buffer position needs to be adjusted to account
918		 for invisible characters. */
919	      if (cursor_linenum == 0 && wrap_offset)
920		_rl_last_c_pos += wrap_offset;
921	    }
922
923	  /* We have to reprint the prompt if it contains invisible
924	     characters, since it's not generally OK to just reprint
925	     the characters from the current cursor position.  But we
926	     only need to reprint it if the cursor is before the last
927	     invisible character in the prompt string. */
928	  nleft = prompt_visible_length + wrap_offset;
929	  if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
930	      _rl_last_c_pos <= prompt_last_invisible && local_prompt)
931	    {
932#if defined (__MSDOS__)
933	      putc ('\r', rl_outstream);
934#else
935	      if (_rl_term_cr)
936		tputs (_rl_term_cr, 1, _rl_output_character_function);
937#endif
938	      _rl_output_some_chars (local_prompt, nleft);
939	      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
940		_rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft);
941	      else
942		_rl_last_c_pos = nleft;
943	    }
944
945	  /* Where on that line?  And where does that line start
946	     in the buffer? */
947	  pos = inv_lbreaks[cursor_linenum];
948	  /* nleft == number of characters in the line buffer between the
949	     start of the line and the cursor position. */
950	  nleft = c_pos - pos;
951
952	  /* Since _rl_backspace() doesn't know about invisible characters in the
953	     prompt, and there's no good way to tell it, we compensate for
954	     those characters here and call _rl_backspace() directly. */
955	  if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
956	    {
957	      _rl_backspace (_rl_last_c_pos - nleft);
958	      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
959		_rl_last_c_pos = _rl_col_width (&visible_line[pos], 0, nleft);
960	      else
961		_rl_last_c_pos = nleft;
962	    }
963
964	  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
965	    _rl_move_cursor_relative (nleft, &invisible_line[pos]);
966	  else if (nleft != _rl_last_c_pos)
967	    _rl_move_cursor_relative (nleft, &invisible_line[pos]);
968	}
969    }
970  else				/* Do horizontal scrolling. */
971    {
972#define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
973      int lmargin, ndisp, nleft, phys_c_pos, t;
974
975      /* Always at top line. */
976      _rl_last_v_pos = 0;
977
978      /* Compute where in the buffer the displayed line should start.  This
979	 will be LMARGIN. */
980
981      /* The number of characters that will be displayed before the cursor. */
982      ndisp = c_pos - wrap_offset;
983      nleft  = prompt_visible_length + wrap_offset;
984      /* Where the new cursor position will be on the screen.  This can be
985	 longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
986      phys_c_pos = c_pos - (last_lmargin ? last_lmargin : wrap_offset);
987      t = _rl_screenwidth / 3;
988
989      /* If the number of characters had already exceeded the screenwidth,
990	 last_lmargin will be > 0. */
991
992      /* If the number of characters to be displayed is more than the screen
993	 width, compute the starting offset so that the cursor is about
994	 two-thirds of the way across the screen. */
995      if (phys_c_pos > _rl_screenwidth - 2)
996	{
997	  lmargin = c_pos - (2 * t);
998	  if (lmargin < 0)
999	    lmargin = 0;
1000	  /* If the left margin would be in the middle of a prompt with
1001	     invisible characters, don't display the prompt at all. */
1002	  if (wrap_offset && lmargin > 0 && lmargin < nleft)
1003	    lmargin = nleft;
1004	}
1005      else if (ndisp < _rl_screenwidth - 2)		/* XXX - was -1 */
1006	lmargin = 0;
1007      else if (phys_c_pos < 1)
1008	{
1009	  /* If we are moving back towards the beginning of the line and
1010	     the last margin is no longer correct, compute a new one. */
1011	  lmargin = ((c_pos - 1) / t) * t;	/* XXX */
1012	  if (wrap_offset && lmargin > 0 && lmargin < nleft)
1013	    lmargin = nleft;
1014	}
1015      else
1016	lmargin = last_lmargin;
1017
1018      /* If the first character on the screen isn't the first character
1019	 in the display line, indicate this with a special character. */
1020      if (lmargin > 0)
1021	line[lmargin] = '<';
1022
1023      /* If SCREENWIDTH characters starting at LMARGIN do not encompass
1024	 the whole line, indicate that with a special character at the
1025	 right edge of the screen.  If LMARGIN is 0, we need to take the
1026	 wrap offset into account. */
1027      t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth;
1028      if (t < out)
1029	line[t - 1] = '>';
1030
1031      if (!rl_display_fixed || forced_display || lmargin != last_lmargin)
1032	{
1033	  forced_display = 0;
1034	  update_line (&visible_line[last_lmargin],
1035		       &invisible_line[lmargin],
1036		       0,
1037		       _rl_screenwidth + visible_wrap_offset,
1038		       _rl_screenwidth + (lmargin ? 0 : wrap_offset),
1039		       0);
1040
1041	  /* If the visible new line is shorter than the old, but the number
1042	     of invisible characters is greater, and we are at the end of
1043	     the new line, we need to clear to eol. */
1044	  t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
1045	  if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
1046	      (_rl_last_c_pos == out) &&
1047	      t < visible_first_line_len)
1048	    {
1049	      nleft = _rl_screenwidth - t;
1050	      _rl_clear_to_eol (nleft);
1051	    }
1052	  visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
1053	  if (visible_first_line_len > _rl_screenwidth)
1054	    visible_first_line_len = _rl_screenwidth;
1055
1056	  _rl_move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]);
1057	  last_lmargin = lmargin;
1058	}
1059    }
1060  fflush (rl_outstream);
1061
1062  /* Swap visible and non-visible lines. */
1063  {
1064    char *vtemp = visible_line;
1065    int *itemp = vis_lbreaks, ntemp = vis_lbsize;
1066
1067    visible_line = invisible_line;
1068    invisible_line = vtemp;
1069
1070    vis_lbreaks = inv_lbreaks;
1071    inv_lbreaks = itemp;
1072
1073    vis_lbsize = inv_lbsize;
1074    inv_lbsize = ntemp;
1075
1076    rl_display_fixed = 0;
1077    /* If we are displaying on a single line, and last_lmargin is > 0, we
1078       are not displaying any invisible characters, so set visible_wrap_offset
1079       to 0. */
1080    if (_rl_horizontal_scroll_mode && last_lmargin)
1081      visible_wrap_offset = 0;
1082    else
1083      visible_wrap_offset = wrap_offset;
1084  }
1085}
1086
1087/* PWP: update_line() is based on finding the middle difference of each
1088   line on the screen; vis:
1089
1090			     /old first difference
1091	/beginning of line   |	      /old last same       /old EOL
1092	v		     v	      v		    v
1093old:	eddie> Oh, my little gruntle-buggy is to me, as lurgid as
1094new:	eddie> Oh, my little buggy says to me, as lurgid as
1095	^		     ^	^			   ^
1096	\beginning of line   |	\new last same	   \new end of line
1097			     \new first difference
1098
1099   All are character pointers for the sake of speed.  Special cases for
1100   no differences, as well as for end of line additions must be handled.
1101
1102   Could be made even smarter, but this works well enough */
1103static void
1104update_line (old, new, current_line, omax, nmax, inv_botlin)
1105     register char *old, *new;
1106     int current_line, omax, nmax, inv_botlin;
1107{
1108  register char *ofd, *ols, *oe, *nfd, *nls, *ne;
1109  int temp, lendiff, wsatend, od, nd;
1110  int current_invis_chars;
1111  int col_lendiff, col_temp;
1112#if defined (HANDLE_MULTIBYTE)
1113  mbstate_t ps_new, ps_old;
1114  int new_offset, old_offset, tmp;
1115#endif
1116
1117  /* If we're at the right edge of a terminal that supports xn, we're
1118     ready to wrap around, so do so.  This fixes problems with knowing
1119     the exact cursor position and cut-and-paste with certain terminal
1120     emulators.  In this calculation, TEMP is the physical screen
1121     position of the cursor. */
1122  temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
1123  if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
1124	&& _rl_last_v_pos == current_line - 1)
1125    {
1126#if defined (HANDLE_MULTIBYTE)
1127      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1128	{
1129	  wchar_t wc;
1130	  mbstate_t ps;
1131	  int tempwidth, bytes;
1132	  size_t ret;
1133
1134	  /* This fixes only double-column characters, but if the wrapped
1135	     character comsumes more than three columns, spaces will be
1136	     inserted in the string buffer. */
1137	  if (_rl_wrapped_line[current_line] > 0)
1138	    _rl_clear_to_eol (_rl_wrapped_line[current_line]);
1139
1140	  memset (&ps, 0, sizeof (mbstate_t));
1141	  ret = mbrtowc (&wc, new, MB_CUR_MAX, &ps);
1142	  if (MB_INVALIDCH (ret))
1143	    {
1144	      tempwidth = 1;
1145	      ret = 1;
1146	    }
1147	  else if (MB_NULLWCH (ret))
1148	    tempwidth = 0;
1149	  else
1150	    tempwidth = wcwidth (wc);
1151
1152	  if (tempwidth > 0)
1153	    {
1154	      int count;
1155	      bytes = ret;
1156	      for (count = 0; count < bytes; count++)
1157		putc (new[count], rl_outstream);
1158	      _rl_last_c_pos = tempwidth;
1159	      _rl_last_v_pos++;
1160	      memset (&ps, 0, sizeof (mbstate_t));
1161	      ret = mbrtowc (&wc, old, MB_CUR_MAX, &ps);
1162	      if (ret != 0 && bytes != 0)
1163		{
1164		  if (MB_INVALIDCH (ret))
1165		    memmove (old+bytes, old+1, strlen (old+1));
1166		  else
1167		    memmove (old+bytes, old+ret, strlen (old+ret));
1168		  memcpy (old, new, bytes);
1169		}
1170	    }
1171	  else
1172	    {
1173	      putc (' ', rl_outstream);
1174	      _rl_last_c_pos = 1;
1175	      _rl_last_v_pos++;
1176	      if (old[0] && new[0])
1177		old[0] = new[0];
1178	    }
1179	}
1180      else
1181#endif
1182	{
1183	  if (new[0])
1184	    putc (new[0], rl_outstream);
1185	  else
1186	    putc (' ', rl_outstream);
1187	  _rl_last_c_pos = 1;		/* XXX */
1188	  _rl_last_v_pos++;
1189	  if (old[0] && new[0])
1190	    old[0] = new[0];
1191	}
1192    }
1193
1194
1195  /* Find first difference. */
1196#if defined (HANDLE_MULTIBYTE)
1197  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1198    {
1199      /* See if the old line is a subset of the new line, so that the
1200	 only change is adding characters. */
1201      temp = (omax < nmax) ? omax : nmax;
1202      if (memcmp (old, new, temp) == 0)
1203	{
1204	  ofd = old + temp;
1205	  nfd = new + temp;
1206	}
1207      else
1208	{
1209	  memset (&ps_new, 0, sizeof(mbstate_t));
1210	  memset (&ps_old, 0, sizeof(mbstate_t));
1211
1212	  if (omax == nmax && STREQN (new, old, omax))
1213	    {
1214	      ofd = old + omax;
1215	      nfd = new + nmax;
1216	    }
1217	  else
1218	    {
1219	      new_offset = old_offset = 0;
1220	      for (ofd = old, nfd = new;
1221		    (ofd - old < omax) && *ofd &&
1222		    _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new); )
1223		{
1224		  old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY);
1225		  new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY);
1226		  ofd = old + old_offset;
1227		  nfd = new + new_offset;
1228		}
1229	    }
1230	}
1231    }
1232  else
1233#endif
1234  for (ofd = old, nfd = new;
1235       (ofd - old < omax) && *ofd && (*ofd == *nfd);
1236       ofd++, nfd++)
1237    ;
1238
1239  /* Move to the end of the screen line.  ND and OD are used to keep track
1240     of the distance between ne and new and oe and old, respectively, to
1241     move a subtraction out of each loop. */
1242  for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
1243  for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
1244
1245  /* If no difference, continue to next line. */
1246  if (ofd == oe && nfd == ne)
1247    return;
1248
1249  wsatend = 1;			/* flag for trailing whitespace */
1250
1251#if defined (HANDLE_MULTIBYTE)
1252  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1253    {
1254      ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY);
1255      nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY);
1256      while ((ols > ofd) && (nls > nfd))
1257	{
1258	  memset (&ps_old, 0, sizeof (mbstate_t));
1259	  memset (&ps_new, 0, sizeof (mbstate_t));
1260
1261#if 0
1262	  /* On advice from jir@yamato.ibm.com */
1263	  _rl_adjust_point (old, ols - old, &ps_old);
1264	  _rl_adjust_point (new, nls - new, &ps_new);
1265#endif
1266
1267	  if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0)
1268	    break;
1269
1270	  if (*ols == ' ')
1271	    wsatend = 0;
1272
1273	  ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY);
1274	  nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY);
1275	}
1276    }
1277  else
1278    {
1279#endif /* HANDLE_MULTIBYTE */
1280  ols = oe - 1;			/* find last same */
1281  nls = ne - 1;
1282  while ((ols > ofd) && (nls > nfd) && (*ols == *nls))
1283    {
1284      if (*ols != ' ')
1285	wsatend = 0;
1286      ols--;
1287      nls--;
1288    }
1289#if defined (HANDLE_MULTIBYTE)
1290    }
1291#endif
1292
1293  if (wsatend)
1294    {
1295      ols = oe;
1296      nls = ne;
1297    }
1298#if defined (HANDLE_MULTIBYTE)
1299  /* This may not work for stateful encoding, but who cares?  To handle
1300     stateful encoding properly, we have to scan each string from the
1301     beginning and compare. */
1302  else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0)
1303#else
1304  else if (*ols != *nls)
1305#endif
1306    {
1307      if (*ols)			/* don't step past the NUL */
1308	{
1309	  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1310	    ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY);
1311	  else
1312	    ols++;
1313	}
1314      if (*nls)
1315	{
1316	  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1317	    nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY);
1318	  else
1319	    nls++;
1320	}
1321    }
1322
1323  /* count of invisible characters in the current invisible line. */
1324  current_invis_chars = W_OFFSET (current_line, wrap_offset);
1325  if (_rl_last_v_pos != current_line)
1326    {
1327      _rl_move_vert (current_line);
1328      if (current_line == 0 && visible_wrap_offset)
1329	_rl_last_c_pos += visible_wrap_offset;
1330    }
1331
1332  /* If this is the first line and there are invisible characters in the
1333     prompt string, and the prompt string has not changed, and the current
1334     cursor position is before the last invisible character in the prompt,
1335     and the index of the character to move to is past the end of the prompt
1336     string, then redraw the entire prompt string.  We can only do this
1337     reliably if the terminal supports a `cr' capability.
1338
1339     This is not an efficiency hack -- there is a problem with redrawing
1340     portions of the prompt string if they contain terminal escape
1341     sequences (like drawing the `unbold' sequence without a corresponding
1342     `bold') that manifests itself on certain terminals. */
1343
1344  lendiff = local_prompt ? strlen (local_prompt) : 0;
1345  od = ofd - old;	/* index of first difference in visible line */
1346  if (current_line == 0 && !_rl_horizontal_scroll_mode &&
1347      _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 &&
1348      od >= lendiff && _rl_last_c_pos <= prompt_last_invisible)
1349    {
1350#if defined (__MSDOS__)
1351      putc ('\r', rl_outstream);
1352#else
1353      tputs (_rl_term_cr, 1, _rl_output_character_function);
1354#endif
1355      _rl_output_some_chars (local_prompt, lendiff);
1356      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1357	_rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff);
1358      else
1359	_rl_last_c_pos = lendiff;
1360    }
1361
1362  _rl_move_cursor_relative (od, old);
1363
1364  /* if (len (new) > len (old))
1365     lendiff == difference in buffer
1366     col_lendiff == difference on screen
1367     When not using multibyte characters, these are equal */
1368  lendiff = (nls - nfd) - (ols - ofd);
1369  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1370    col_lendiff = _rl_col_width (new, nfd - new, nls - new) - _rl_col_width (old, ofd - old, ols - old);
1371  else
1372    col_lendiff = lendiff;
1373
1374  /* If we are changing the number of invisible characters in a line, and
1375     the spot of first difference is before the end of the invisible chars,
1376     lendiff needs to be adjusted. */
1377  if (current_line == 0 && !_rl_horizontal_scroll_mode &&
1378      current_invis_chars != visible_wrap_offset)
1379    {
1380      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1381	{
1382	  lendiff += visible_wrap_offset - current_invis_chars;
1383	  col_lendiff += visible_wrap_offset - current_invis_chars;
1384	}
1385      else
1386	{
1387	  lendiff += visible_wrap_offset - current_invis_chars;
1388	  col_lendiff = lendiff;
1389	}
1390    }
1391
1392  /* Insert (diff (len (old), len (new)) ch. */
1393  temp = ne - nfd;
1394  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1395    col_temp = _rl_col_width (new, nfd - new, ne - new);
1396  else
1397    col_temp = temp;
1398
1399  if (col_lendiff > 0)	/* XXX - was lendiff */
1400    {
1401      /* Non-zero if we're increasing the number of lines. */
1402      int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
1403      /* Sometimes it is cheaper to print the characters rather than
1404	 use the terminal's capabilities.  If we're growing the number
1405	 of lines, make sure we actually cause the new line to wrap
1406	 around on auto-wrapping terminals. */
1407      if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
1408	{
1409	  /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
1410	     _rl_horizontal_scroll_mode == 1, inserting the characters with
1411	     _rl_term_IC or _rl_term_ic will screw up the screen because of the
1412	     invisible characters.  We need to just draw them. */
1413	  if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 ||
1414			lendiff <= prompt_visible_length || !current_invis_chars))
1415	    {
1416	      insert_some_chars (nfd, lendiff, col_lendiff);
1417	      _rl_last_c_pos += col_lendiff;
1418	    }
1419	  else if (*ols == 0 && lendiff > 0)
1420	    {
1421	      /* At the end of a line the characters do not have to
1422		 be "inserted".  They can just be placed on the screen. */
1423	      /* However, this screws up the rest of this block, which
1424		 assumes you've done the insert because you can. */
1425	      _rl_output_some_chars (nfd, lendiff);
1426	      _rl_last_c_pos += col_lendiff;
1427	    }
1428	  else
1429	    {
1430	      /* We have horizontal scrolling and we are not inserting at
1431		 the end.  We have invisible characters in this line.  This
1432		 is a dumb update. */
1433	      _rl_output_some_chars (nfd, temp);
1434	      _rl_last_c_pos += col_temp;
1435	      return;
1436	    }
1437	  /* Copy (new) chars to screen from first diff to last match. */
1438	  temp = nls - nfd;
1439	  if ((temp - lendiff) > 0)
1440	    {
1441	      _rl_output_some_chars (nfd + lendiff, temp - lendiff);
1442#if 1
1443	     /* XXX -- this bears closer inspection.  Fixes a redisplay bug
1444		reported against bash-3.0-alpha by Andreas Schwab involving
1445		multibyte characters and prompt strings with invisible
1446		characters, but was previously disabled. */
1447	      _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-col_lendiff);
1448#else
1449	      _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-lendiff);
1450#endif
1451	    }
1452	}
1453      else
1454	{
1455	  /* cannot insert chars, write to EOL */
1456	  _rl_output_some_chars (nfd, temp);
1457	  _rl_last_c_pos += col_temp;
1458	}
1459    }
1460  else				/* Delete characters from line. */
1461    {
1462      /* If possible and inexpensive to use terminal deletion, then do so. */
1463      if (_rl_term_dc && (2 * col_temp) >= -col_lendiff)
1464	{
1465	  /* If all we're doing is erasing the invisible characters in the
1466	     prompt string, don't bother.  It screws up the assumptions
1467	     about what's on the screen. */
1468	  if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
1469	      -lendiff == visible_wrap_offset)
1470	    col_lendiff = 0;
1471
1472	  if (col_lendiff)
1473	    delete_chars (-col_lendiff); /* delete (diff) characters */
1474
1475	  /* Copy (new) chars to screen from first diff to last match */
1476	  temp = nls - nfd;
1477	  if (temp > 0)
1478	    {
1479	      _rl_output_some_chars (nfd, temp);
1480	      _rl_last_c_pos += _rl_col_width (nfd, 0, temp);;
1481	    }
1482	}
1483      /* Otherwise, print over the existing material. */
1484      else
1485	{
1486	  if (temp > 0)
1487	    {
1488	      _rl_output_some_chars (nfd, temp);
1489	      _rl_last_c_pos += col_temp;
1490	    }
1491	  lendiff = (oe - old) - (ne - new);
1492	  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1493	    col_lendiff = _rl_col_width (old, 0, oe - old) - _rl_col_width (new, 0, ne - new);
1494	  else
1495	    col_lendiff = lendiff;
1496
1497	  if (col_lendiff)
1498	    {
1499	      if (_rl_term_autowrap && current_line < inv_botlin)
1500		space_to_eol (col_lendiff);
1501	      else
1502		_rl_clear_to_eol (col_lendiff);
1503	    }
1504	}
1505    }
1506}
1507
1508/* Tell the update routines that we have moved onto a new (empty) line. */
1509int
1510rl_on_new_line ()
1511{
1512  if (visible_line)
1513    visible_line[0] = '\0';
1514
1515  _rl_last_c_pos = _rl_last_v_pos = 0;
1516  _rl_vis_botlin = last_lmargin = 0;
1517  if (vis_lbreaks)
1518    vis_lbreaks[0] = vis_lbreaks[1] = 0;
1519  visible_wrap_offset = 0;
1520  return 0;
1521}
1522
1523/* Tell the update routines that we have moved onto a new line with the
1524   prompt already displayed.  Code originally from the version of readline
1525   distributed with CLISP.  rl_expand_prompt must have already been called
1526   (explicitly or implicitly).  This still doesn't work exactly right. */
1527int
1528rl_on_new_line_with_prompt ()
1529{
1530  int prompt_size, i, l, real_screenwidth, newlines;
1531  char *prompt_last_line, *lprompt;
1532
1533  /* Initialize visible_line and invisible_line to ensure that they can hold
1534     the already-displayed prompt. */
1535  prompt_size = strlen (rl_prompt) + 1;
1536  init_line_structures (prompt_size);
1537
1538  /* Make sure the line structures hold the already-displayed prompt for
1539     redisplay. */
1540  lprompt = local_prompt ? local_prompt : rl_prompt;
1541  strcpy (visible_line, lprompt);
1542  strcpy (invisible_line, lprompt);
1543
1544  /* If the prompt contains newlines, take the last tail. */
1545  prompt_last_line = strrchr (rl_prompt, '\n');
1546  if (!prompt_last_line)
1547    prompt_last_line = rl_prompt;
1548
1549  l = strlen (prompt_last_line);
1550  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1551    _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l);
1552  else
1553    _rl_last_c_pos = l;
1554
1555  /* Dissect prompt_last_line into screen lines. Note that here we have
1556     to use the real screenwidth. Readline's notion of screenwidth might be
1557     one less, see terminal.c. */
1558  real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1);
1559  _rl_last_v_pos = l / real_screenwidth;
1560  /* If the prompt length is a multiple of real_screenwidth, we don't know
1561     whether the cursor is at the end of the last line, or already at the
1562     beginning of the next line. Output a newline just to be safe. */
1563  if (l > 0 && (l % real_screenwidth) == 0)
1564    _rl_output_some_chars ("\n", 1);
1565  last_lmargin = 0;
1566
1567  newlines = 0; i = 0;
1568  while (i <= l)
1569    {
1570      _rl_vis_botlin = newlines;
1571      vis_lbreaks[newlines++] = i;
1572      i += real_screenwidth;
1573    }
1574  vis_lbreaks[newlines] = l;
1575  visible_wrap_offset = 0;
1576
1577  rl_display_prompt = rl_prompt;	/* XXX - make sure it's set */
1578
1579  return 0;
1580}
1581
1582/* Actually update the display, period. */
1583int
1584rl_forced_update_display ()
1585{
1586  if (visible_line)
1587    {
1588      register char *temp = visible_line;
1589
1590      while (*temp)
1591	*temp++ = '\0';
1592    }
1593  rl_on_new_line ();
1594  forced_display++;
1595  (*rl_redisplay_function) ();
1596  return 0;
1597}
1598
1599/* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
1600   DATA is the contents of the screen line of interest; i.e., where
1601   the movement is being done. */
1602void
1603_rl_move_cursor_relative (new, data)
1604     int new;
1605     const char *data;
1606{
1607  register int i;
1608
1609  /* If we don't have to do anything, then return. */
1610#if defined (HANDLE_MULTIBYTE)
1611  /* If we have multibyte characters, NEW is indexed by the buffer point in
1612     a multibyte string, but _rl_last_c_pos is the display position.  In
1613     this case, NEW's display position is not obvious and must be
1614     calculated. */
1615  if (MB_CUR_MAX == 1 || rl_byte_oriented)
1616    {
1617      if (_rl_last_c_pos == new)
1618	return;
1619    }
1620  else if (_rl_last_c_pos == _rl_col_width (data, 0, new))
1621    return;
1622#else
1623  if (_rl_last_c_pos == new) return;
1624#endif
1625
1626  /* It may be faster to output a CR, and then move forwards instead
1627     of moving backwards. */
1628  /* i == current physical cursor position. */
1629  i = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
1630  if (new == 0 || CR_FASTER (new, _rl_last_c_pos) ||
1631      (_rl_term_autowrap && i == _rl_screenwidth))
1632    {
1633#if defined (__MSDOS__)
1634      putc ('\r', rl_outstream);
1635#else
1636      tputs (_rl_term_cr, 1, _rl_output_character_function);
1637#endif /* !__MSDOS__ */
1638      _rl_last_c_pos = 0;
1639    }
1640
1641  if (_rl_last_c_pos < new)
1642    {
1643      /* Move the cursor forward.  We do it by printing the command
1644	 to move the cursor forward if there is one, else print that
1645	 portion of the output buffer again.  Which is cheaper? */
1646
1647      /* The above comment is left here for posterity.  It is faster
1648	 to print one character (non-control) than to print a control
1649	 sequence telling the terminal to move forward one character.
1650	 That kind of control is for people who don't know what the
1651	 data is underneath the cursor. */
1652#if defined (HACK_TERMCAP_MOTION)
1653      if (_rl_term_forward_char)
1654	{
1655	  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1656	    {
1657	      int width;
1658	      width = _rl_col_width (data, _rl_last_c_pos, new);
1659	      for (i = 0; i < width; i++)
1660		tputs (_rl_term_forward_char, 1, _rl_output_character_function);
1661	    }
1662	  else
1663	    {
1664	      for (i = _rl_last_c_pos; i < new; i++)
1665		tputs (_rl_term_forward_char, 1, _rl_output_character_function);
1666	    }
1667	}
1668      else if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1669	{
1670	  tputs (_rl_term_cr, 1, _rl_output_character_function);
1671	  for (i = 0; i < new; i++)
1672	    putc (data[i], rl_outstream);
1673	}
1674      else
1675	for (i = _rl_last_c_pos; i < new; i++)
1676	  putc (data[i], rl_outstream);
1677
1678#else /* !HACK_TERMCAP_MOTION */
1679
1680      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1681	{
1682	  tputs (_rl_term_cr, 1, _rl_output_character_function);
1683	  for (i = 0; i < new; i++)
1684	    putc (data[i], rl_outstream);
1685	}
1686      else
1687	for (i = _rl_last_c_pos; i < new; i++)
1688	  putc (data[i], rl_outstream);
1689
1690#endif /* !HACK_TERMCAP_MOTION */
1691
1692    }
1693#if defined (HANDLE_MULTIBYTE)
1694  /* NEW points to the buffer point, but _rl_last_c_pos is the display point.
1695     The byte length of the string is probably bigger than the column width
1696     of the string, which means that if NEW == _rl_last_c_pos, then NEW's
1697     display point is less than _rl_last_c_pos. */
1698  else if (_rl_last_c_pos >= new)
1699#else
1700  else if (_rl_last_c_pos > new)
1701#endif
1702    {
1703      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1704	_rl_backspace (_rl_last_c_pos - _rl_col_width (data, 0, new));
1705      else
1706	_rl_backspace (_rl_last_c_pos - new);
1707    }
1708
1709  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1710    _rl_last_c_pos =  _rl_col_width (data, 0, new);
1711  else
1712    _rl_last_c_pos = new;
1713}
1714
1715/* PWP: move the cursor up or down. */
1716void
1717_rl_move_vert (to)
1718     int to;
1719{
1720  register int delta, i;
1721
1722  if (_rl_last_v_pos == to || to > _rl_screenheight)
1723    return;
1724
1725  if ((delta = to - _rl_last_v_pos) > 0)
1726    {
1727      for (i = 0; i < delta; i++)
1728	putc ('\n', rl_outstream);
1729#if defined (__MSDOS__)
1730      putc ('\r', rl_outstream);
1731#else
1732      tputs (_rl_term_cr, 1, _rl_output_character_function);
1733#endif
1734      _rl_last_c_pos = 0;
1735    }
1736  else
1737    {			/* delta < 0 */
1738      if (_rl_term_up && *_rl_term_up)
1739	for (i = 0; i < -delta; i++)
1740	  tputs (_rl_term_up, 1, _rl_output_character_function);
1741    }
1742
1743  _rl_last_v_pos = to;		/* Now TO is here */
1744}
1745
1746/* Physically print C on rl_outstream.  This is for functions which know
1747   how to optimize the display.  Return the number of characters output. */
1748int
1749rl_show_char (c)
1750     int c;
1751{
1752  int n = 1;
1753  if (META_CHAR (c) && (_rl_output_meta_chars == 0))
1754    {
1755      fprintf (rl_outstream, "M-");
1756      n += 2;
1757      c = UNMETA (c);
1758    }
1759
1760#if defined (DISPLAY_TABS)
1761  if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
1762#else
1763  if (CTRL_CHAR (c) || c == RUBOUT)
1764#endif /* !DISPLAY_TABS */
1765    {
1766      fprintf (rl_outstream, "C-");
1767      n += 2;
1768      c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
1769    }
1770
1771  putc (c, rl_outstream);
1772  fflush (rl_outstream);
1773  return n;
1774}
1775
1776int
1777rl_character_len (c, pos)
1778     register int c, pos;
1779{
1780  unsigned char uc;
1781
1782  uc = (unsigned char)c;
1783
1784  if (META_CHAR (uc))
1785    return ((_rl_output_meta_chars == 0) ? 4 : 1);
1786
1787  if (uc == '\t')
1788    {
1789#if defined (DISPLAY_TABS)
1790      return (((pos | 7) + 1) - pos);
1791#else
1792      return (2);
1793#endif /* !DISPLAY_TABS */
1794    }
1795
1796  if (CTRL_CHAR (c) || c == RUBOUT)
1797    return (2);
1798
1799  return ((ISPRINT (uc)) ? 1 : 2);
1800}
1801
1802/* How to print things in the "echo-area".  The prompt is treated as a
1803   mini-modeline. */
1804
1805#if defined (USE_VARARGS)
1806int
1807#if defined (PREFER_STDARG)
1808rl_message (const char *format, ...)
1809#else
1810rl_message (va_alist)
1811     va_dcl
1812#endif
1813{
1814  va_list args;
1815#if defined (PREFER_VARARGS)
1816  char *format;
1817#endif
1818
1819#if defined (PREFER_STDARG)
1820  va_start (args, format);
1821#else
1822  va_start (args);
1823  format = va_arg (args, char *);
1824#endif
1825
1826#if defined (HAVE_VSNPRINTF)
1827  vsnprintf (msg_buf, sizeof (msg_buf) - 1, format, args);
1828#else
1829  vsprintf (msg_buf, format, args);
1830  msg_buf[sizeof(msg_buf) - 1] = '\0';	/* overflow? */
1831#endif
1832  va_end (args);
1833
1834  rl_display_prompt = msg_buf;
1835  (*rl_redisplay_function) ();
1836  return 0;
1837}
1838#else /* !USE_VARARGS */
1839int
1840rl_message (format, arg1, arg2)
1841     char *format;
1842{
1843  sprintf (msg_buf, format, arg1, arg2);
1844  msg_buf[sizeof(msg_buf) - 1] = '\0';	/* overflow? */
1845  rl_display_prompt = msg_buf;
1846  (*rl_redisplay_function) ();
1847  return 0;
1848}
1849#endif /* !USE_VARARGS */
1850
1851/* How to clear things from the "echo-area". */
1852int
1853rl_clear_message ()
1854{
1855  rl_display_prompt = rl_prompt;
1856  (*rl_redisplay_function) ();
1857  return 0;
1858}
1859
1860int
1861rl_reset_line_state ()
1862{
1863  rl_on_new_line ();
1864
1865  rl_display_prompt = rl_prompt ? rl_prompt : "";
1866  forced_display = 1;
1867  return 0;
1868}
1869
1870/* These are getting numerous enough that it's time to create a struct. */
1871
1872static char *saved_local_prompt;
1873static char *saved_local_prefix;
1874static int saved_last_invisible;
1875static int saved_visible_length;
1876static int saved_invis_chars_first_line;
1877static int saved_physical_chars;
1878
1879void
1880rl_save_prompt ()
1881{
1882  saved_local_prompt = local_prompt;
1883  saved_local_prefix = local_prompt_prefix;
1884  saved_last_invisible = prompt_last_invisible;
1885  saved_visible_length = prompt_visible_length;
1886  saved_invis_chars_first_line = prompt_invis_chars_first_line;
1887  saved_physical_chars = prompt_physical_chars;
1888
1889  local_prompt = local_prompt_prefix = (char *)0;
1890  prompt_last_invisible = prompt_visible_length = 0;
1891  prompt_invis_chars_first_line = prompt_physical_chars = 0;
1892}
1893
1894void
1895rl_restore_prompt ()
1896{
1897  FREE (local_prompt);
1898  FREE (local_prompt_prefix);
1899
1900  local_prompt = saved_local_prompt;
1901  local_prompt_prefix = saved_local_prefix;
1902  prompt_last_invisible = saved_last_invisible;
1903  prompt_visible_length = saved_visible_length;
1904  prompt_invis_chars_first_line = saved_invis_chars_first_line;
1905  prompt_physical_chars = saved_physical_chars;
1906}
1907
1908char *
1909_rl_make_prompt_for_search (pchar)
1910     int pchar;
1911{
1912  int len;
1913  char *pmt;
1914
1915  rl_save_prompt ();
1916
1917  if (saved_local_prompt == 0)
1918    {
1919      len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
1920      pmt = (char *)xmalloc (len + 2);
1921      if (len)
1922	strcpy (pmt, rl_prompt);
1923      pmt[len] = pchar;
1924      pmt[len+1] = '\0';
1925    }
1926  else
1927    {
1928      len = *saved_local_prompt ? strlen (saved_local_prompt) : 0;
1929      pmt = (char *)xmalloc (len + 2);
1930      if (len)
1931	strcpy (pmt, saved_local_prompt);
1932      pmt[len] = pchar;
1933      pmt[len+1] = '\0';
1934      local_prompt = savestring (pmt);
1935      prompt_last_invisible = saved_last_invisible;
1936      prompt_visible_length = saved_visible_length + 1;
1937    }
1938
1939  return pmt;
1940}
1941
1942/* Quick redisplay hack when erasing characters at the end of the line. */
1943void
1944_rl_erase_at_end_of_line (l)
1945     int l;
1946{
1947  register int i;
1948
1949  _rl_backspace (l);
1950  for (i = 0; i < l; i++)
1951    putc (' ', rl_outstream);
1952  _rl_backspace (l);
1953  for (i = 0; i < l; i++)
1954    visible_line[--_rl_last_c_pos] = '\0';
1955  rl_display_fixed++;
1956}
1957
1958/* Clear to the end of the line.  COUNT is the minimum
1959   number of character spaces to clear, */
1960void
1961_rl_clear_to_eol (count)
1962     int count;
1963{
1964  if (_rl_term_clreol)
1965    tputs (_rl_term_clreol, 1, _rl_output_character_function);
1966  else if (count)
1967    space_to_eol (count);
1968}
1969
1970/* Clear to the end of the line using spaces.  COUNT is the minimum
1971   number of character spaces to clear, */
1972static void
1973space_to_eol (count)
1974     int count;
1975{
1976  register int i;
1977
1978  for (i = 0; i < count; i++)
1979   putc (' ', rl_outstream);
1980
1981  _rl_last_c_pos += count;
1982}
1983
1984void
1985_rl_clear_screen ()
1986{
1987  if (_rl_term_clrpag)
1988    tputs (_rl_term_clrpag, 1, _rl_output_character_function);
1989  else
1990    rl_crlf ();
1991}
1992
1993/* Insert COUNT characters from STRING to the output stream at column COL. */
1994static void
1995insert_some_chars (string, count, col)
1996     char *string;
1997     int count, col;
1998{
1999  /* DEBUGGING */
2000  if (MB_CUR_MAX == 1 || rl_byte_oriented)
2001    if (count != col)
2002      fprintf(stderr, "readline: debug: insert_some_chars: count (%d) != col (%d)\n", count, col);
2003
2004  /* If IC is defined, then we do not have to "enter" insert mode. */
2005  if (_rl_term_IC)
2006    {
2007      char *buffer;
2008
2009      buffer = tgoto (_rl_term_IC, 0, col);
2010      tputs (buffer, 1, _rl_output_character_function);
2011      _rl_output_some_chars (string, count);
2012    }
2013  else
2014    {
2015      register int i;
2016
2017      /* If we have to turn on insert-mode, then do so. */
2018      if (_rl_term_im && *_rl_term_im)
2019	tputs (_rl_term_im, 1, _rl_output_character_function);
2020
2021      /* If there is a special command for inserting characters, then
2022	 use that first to open up the space. */
2023      if (_rl_term_ic && *_rl_term_ic)
2024	{
2025	  for (i = col; i--; )
2026	    tputs (_rl_term_ic, 1, _rl_output_character_function);
2027	}
2028
2029      /* Print the text. */
2030      _rl_output_some_chars (string, count);
2031
2032      /* If there is a string to turn off insert mode, we had best use
2033	 it now. */
2034      if (_rl_term_ei && *_rl_term_ei)
2035	tputs (_rl_term_ei, 1, _rl_output_character_function);
2036    }
2037}
2038
2039/* Delete COUNT characters from the display line. */
2040static void
2041delete_chars (count)
2042     int count;
2043{
2044  if (count > _rl_screenwidth)	/* XXX */
2045    return;
2046
2047  if (_rl_term_DC && *_rl_term_DC)
2048    {
2049      char *buffer;
2050      buffer = tgoto (_rl_term_DC, count, count);
2051      tputs (buffer, count, _rl_output_character_function);
2052    }
2053  else
2054    {
2055      if (_rl_term_dc && *_rl_term_dc)
2056	while (count--)
2057	  tputs (_rl_term_dc, 1, _rl_output_character_function);
2058    }
2059}
2060
2061void
2062_rl_update_final ()
2063{
2064  int full_lines;
2065
2066  full_lines = 0;
2067  /* If the cursor is the only thing on an otherwise-blank last line,
2068     compensate so we don't print an extra CRLF. */
2069  if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
2070	visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
2071    {
2072      _rl_vis_botlin--;
2073      full_lines = 1;
2074    }
2075  _rl_move_vert (_rl_vis_botlin);
2076  /* If we've wrapped lines, remove the final xterm line-wrap flag. */
2077  if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth))
2078    {
2079      char *last_line;
2080
2081      last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]];
2082      _rl_move_cursor_relative (_rl_screenwidth - 1, last_line);
2083      _rl_clear_to_eol (0);
2084      putc (last_line[_rl_screenwidth - 1], rl_outstream);
2085    }
2086  _rl_vis_botlin = 0;
2087  rl_crlf ();
2088  fflush (rl_outstream);
2089  rl_display_fixed++;
2090}
2091
2092/* Move to the start of the current line. */
2093static void
2094cr ()
2095{
2096  if (_rl_term_cr)
2097    {
2098#if defined (__MSDOS__)
2099      putc ('\r', rl_outstream);
2100#else
2101      tputs (_rl_term_cr, 1, _rl_output_character_function);
2102#endif
2103      _rl_last_c_pos = 0;
2104    }
2105}
2106
2107/* Redraw the last line of a multi-line prompt that may possibly contain
2108   terminal escape sequences.  Called with the cursor at column 0 of the
2109   line to draw the prompt on. */
2110static void
2111redraw_prompt (t)
2112     char *t;
2113{
2114  char *oldp, *oldl, *oldlprefix;
2115  int oldlen, oldlast, oldplen, oldninvis, oldphyschars;
2116
2117  /* Geez, I should make this a struct. */
2118  oldp = rl_display_prompt;
2119  oldl = local_prompt;
2120  oldlprefix = local_prompt_prefix;
2121  oldlen = prompt_visible_length;
2122  oldplen = prompt_prefix_length;
2123  oldlast = prompt_last_invisible;
2124  oldninvis = prompt_invis_chars_first_line;
2125  oldphyschars = prompt_physical_chars;
2126
2127  rl_display_prompt = t;
2128  local_prompt = expand_prompt (t, &prompt_visible_length,
2129				   &prompt_last_invisible,
2130				   &prompt_invis_chars_first_line,
2131				   &prompt_physical_chars);
2132  local_prompt_prefix = (char *)NULL;
2133  rl_forced_update_display ();
2134
2135  rl_display_prompt = oldp;
2136  local_prompt = oldl;
2137  local_prompt_prefix = oldlprefix;
2138  prompt_visible_length = oldlen;
2139  prompt_prefix_length = oldplen;
2140  prompt_last_invisible = oldlast;
2141  prompt_invis_chars_first_line = oldninvis;
2142  prompt_physical_chars = oldphyschars;
2143}
2144
2145/* Redisplay the current line after a SIGWINCH is received. */
2146void
2147_rl_redisplay_after_sigwinch ()
2148{
2149  char *t;
2150
2151  /* Clear the current line and put the cursor at column 0.  Make sure
2152     the right thing happens if we have wrapped to a new screen line. */
2153  if (_rl_term_cr)
2154    {
2155#if defined (__MSDOS__)
2156      putc ('\r', rl_outstream);
2157#else
2158      tputs (_rl_term_cr, 1, _rl_output_character_function);
2159#endif
2160      _rl_last_c_pos = 0;
2161#if defined (__MSDOS__)
2162      space_to_eol (_rl_screenwidth);
2163      putc ('\r', rl_outstream);
2164#else
2165      if (_rl_term_clreol)
2166	tputs (_rl_term_clreol, 1, _rl_output_character_function);
2167      else
2168	{
2169	  space_to_eol (_rl_screenwidth);
2170	  tputs (_rl_term_cr, 1, _rl_output_character_function);
2171	}
2172#endif
2173      if (_rl_last_v_pos > 0)
2174	_rl_move_vert (0);
2175    }
2176  else
2177    rl_crlf ();
2178
2179  /* Redraw only the last line of a multi-line prompt. */
2180  t = strrchr (rl_display_prompt, '\n');
2181  if (t)
2182    redraw_prompt (++t);
2183  else
2184    rl_forced_update_display ();
2185}
2186
2187void
2188_rl_clean_up_for_exit ()
2189{
2190  if (readline_echoing_p)
2191    {
2192      _rl_move_vert (_rl_vis_botlin);
2193      _rl_vis_botlin = 0;
2194      fflush (rl_outstream);
2195      rl_restart_output (1, 0);
2196    }
2197}
2198
2199void
2200_rl_erase_entire_line ()
2201{
2202  cr ();
2203  _rl_clear_to_eol (0);
2204  cr ();
2205  fflush (rl_outstream);
2206}
2207
2208/* return the `current display line' of the cursor -- the number of lines to
2209   move up to get to the first screen line of the current readline line. */
2210int
2211_rl_current_display_line ()
2212{
2213  int ret, nleft;
2214
2215  /* Find out whether or not there might be invisible characters in the
2216     editing buffer. */
2217  if (rl_display_prompt == rl_prompt)
2218    nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length;
2219  else
2220    nleft = _rl_last_c_pos - _rl_screenwidth;
2221
2222  if (nleft > 0)
2223    ret = 1 + nleft / _rl_screenwidth;
2224  else
2225    ret = 0;
2226
2227  return ret;
2228}
2229
2230#if defined (HANDLE_MULTIBYTE)
2231/* Calculate the number of screen columns occupied by STR from START to END.
2232   In the case of multibyte characters with stateful encoding, we have to
2233   scan from the beginning of the string to take the state into account. */
2234static int
2235_rl_col_width (str, start, end)
2236     const char *str;
2237     int start, end;
2238{
2239  wchar_t wc;
2240  mbstate_t ps = {0};
2241  int tmp, point, width, max;
2242
2243  if (end <= start)
2244    return 0;
2245
2246  point = 0;
2247  max = end;
2248
2249  while (point < start)
2250    {
2251      tmp = mbrlen (str + point, max, &ps);
2252      if (MB_INVALIDCH ((size_t)tmp))
2253	{
2254	  /* In this case, the bytes are invalid or too short to compose a
2255	     multibyte character, so we assume that the first byte represents
2256	     a single character. */
2257	  point++;
2258	  max--;
2259
2260	  /* Clear the state of the byte sequence, because in this case the
2261	     effect of mbstate is undefined. */
2262	  memset (&ps, 0, sizeof (mbstate_t));
2263	}
2264      else if (MB_NULLWCH (tmp))
2265	break;		/* Found '\0' */
2266      else
2267	{
2268	  point += tmp;
2269	  max -= tmp;
2270	}
2271    }
2272
2273  /* If START is not a byte that starts a character, then POINT will be
2274     greater than START.  In this case, assume that (POINT - START) gives
2275     a byte count that is the number of columns of difference. */
2276  width = point - start;
2277
2278  while (point < end)
2279    {
2280      tmp = mbrtowc (&wc, str + point, max, &ps);
2281      if (MB_INVALIDCH ((size_t)tmp))
2282	{
2283	  /* In this case, the bytes are invalid or too short to compose a
2284	     multibyte character, so we assume that the first byte represents
2285	     a single character. */
2286	  point++;
2287	  max--;
2288
2289	  /* and assume that the byte occupies a single column. */
2290	  width++;
2291
2292	  /* Clear the state of the byte sequence, because in this case the
2293	     effect of mbstate is undefined. */
2294	  memset (&ps, 0, sizeof (mbstate_t));
2295	}
2296      else if (MB_NULLWCH (tmp))
2297	break;			/* Found '\0' */
2298      else
2299	{
2300	  point += tmp;
2301	  max -= tmp;
2302	  tmp = wcwidth(wc);
2303	  width += (tmp >= 0) ? tmp : 1;
2304	}
2305    }
2306
2307  width += point - end;
2308
2309  return width;
2310}
2311#endif /* HANDLE_MULTIBYTE */
2312