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