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