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