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