display.c revision 47563
121308Sache/* display.c -- readline redisplay facility. */
221308Sache
321308Sache/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
421308Sache
521308Sache   This file is part of the GNU Readline Library, a library for
621308Sache   reading lines of text with interactive input and history editing.
721308Sache
821308Sache   The GNU Readline Library is free software; you can redistribute it
921308Sache   and/or modify it under the terms of the GNU General Public License
1021308Sache   as published by the Free Software Foundation; either version 1, or
1121308Sache   (at your option) any later version.
1221308Sache
1321308Sache   The GNU Readline Library is distributed in the hope that it will be
1421308Sache   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
1521308Sache   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1621308Sache   GNU General Public License for more details.
1721308Sache
1821308Sache   The GNU General Public License is often shipped with GNU software, and
1921308Sache   is generally kept in a file called COPYING or LICENSE.  If you do not
2021308Sache   have a copy of the license, write to the Free Software Foundation,
2121308Sache   675 Mass Ave, Cambridge, MA 02139, USA. */
2221308Sache#define READLINE_LIBRARY
2321308Sache
2421308Sache#if defined (HAVE_CONFIG_H)
2521308Sache#  include <config.h>
2621308Sache#endif
2721308Sache
2821308Sache#include <sys/types.h>
2921308Sache
3021308Sache#if defined (HAVE_UNISTD_H)
3121308Sache#  include <unistd.h>
3221308Sache#endif /* HAVE_UNISTD_H */
3321308Sache
3426497Sache#include "posixstat.h"
3526497Sache
3621308Sache#if defined (HAVE_STDLIB_H)
3721308Sache#  include <stdlib.h>
3821308Sache#else
3921308Sache#  include "ansi_stdlib.h"
4021308Sache#endif /* HAVE_STDLIB_H */
4121308Sache
4226497Sache#include <stdio.h>
4321308Sache
4426497Sache#if defined (__GO32__)
4526497Sache#  include <go32.h>
4626497Sache#  include <pc.h>
4726497Sache#endif /* __GO32__ */
4826497Sache
4921308Sache/* System-specific feature definitions and include files. */
5021308Sache#include "rldefs.h"
5121308Sache
5221308Sache/* Termcap library stuff. */
5321308Sache#include "tcap.h"
5421308Sache
5521308Sache/* Some standard library routines. */
5621308Sache#include "readline.h"
5721308Sache#include "history.h"
5821308Sache
5921308Sache#if !defined (strchr) && !defined (__STDC__)
6021308Sacheextern char *strchr (), *strrchr ();
6121308Sache#endif /* !strchr && !__STDC__ */
6221308Sache
6321308Sache/* Global and pseudo-global variables and functions
6421308Sache   imported from readline.c. */
6521308Sacheextern char *rl_prompt;
6621308Sacheextern int readline_echoing_p;
6721308Sache
6821308Sacheextern int _rl_output_meta_chars;
6921308Sacheextern int _rl_horizontal_scroll_mode;
7021308Sacheextern int _rl_mark_modified_lines;
7121308Sacheextern int _rl_prefer_visible_bell;
7221308Sache
7321308Sache/* Variables and functions imported from terminal.c */
7421308Sacheextern void _rl_output_some_chars ();
7535486Sache#ifdef _MINIX
7635486Sacheextern void _rl_output_character_function ();
7735486Sache#else
7821308Sacheextern int _rl_output_character_function ();
7935486Sache#endif
8021308Sacheextern int _rl_backspace ();
8121308Sache
8226497Sacheextern char *term_clreol, *term_clrpag;
8326497Sacheextern char *term_im, *term_ic,  *term_ei, *term_DC;
8421308Sacheextern char *term_up, *term_dc, *term_cr, *term_IC;
8521308Sacheextern int screenheight, screenwidth, screenchars;
8621308Sacheextern int terminal_can_insert, _rl_term_autowrap;
8721308Sache
8821308Sache/* Pseudo-global functions (local to the readline library) exported
8921308Sache   by this file. */
9021308Sachevoid _rl_move_cursor_relative (), _rl_output_some_chars ();
9121308Sachevoid _rl_move_vert ();
9226497Sachevoid _rl_clear_to_eol (), _rl_clear_screen ();
9321308Sache
9426497Sachestatic void update_line (), space_to_eol ();
9521308Sachestatic void delete_chars (), insert_some_chars ();
9621308Sachestatic void cr ();
9721308Sache
9821308Sachestatic int *inv_lbreaks, *vis_lbreaks;
9921308Sache
10021308Sacheextern char *xmalloc (), *xrealloc ();
10121308Sache
10221308Sache/* Heuristic used to decide whether it is faster to move from CUR to NEW
10321308Sache   by backing up or outputting a carriage return and moving forward. */
10421308Sache#define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new)))
10521308Sache
10621308Sache/* **************************************************************** */
10721308Sache/*								    */
10821308Sache/*			Display stuff				    */
10921308Sache/*								    */
11021308Sache/* **************************************************************** */
11121308Sache
11221308Sache/* This is the stuff that is hard for me.  I never seem to write good
11321308Sache   display routines in C.  Let's see how I do this time. */
11421308Sache
11521308Sache/* (PWP) Well... Good for a simple line updater, but totally ignores
11621308Sache   the problems of input lines longer than the screen width.
11721308Sache
11821308Sache   update_line and the code that calls it makes a multiple line,
11921308Sache   automatically wrapping line update.  Careful attention needs
12021308Sache   to be paid to the vertical position variables. */
12121308Sache
12221308Sache/* Keep two buffers; one which reflects the current contents of the
12321308Sache   screen, and the other to draw what we think the new contents should
12421308Sache   be.  Then compare the buffers, and make whatever changes to the
12521308Sache   screen itself that we should.  Finally, make the buffer that we
12621308Sache   just drew into be the one which reflects the current contents of the
12721308Sache   screen, and place the cursor where it belongs.
12821308Sache
12921308Sache   Commands that want to can fix the display themselves, and then let
13021308Sache   this function know that the display has been fixed by setting the
13121308Sache   RL_DISPLAY_FIXED variable.  This is good for efficiency. */
13221308Sache
13321308Sache/* Application-specific redisplay function. */
13421308SacheVFunction *rl_redisplay_function = rl_redisplay;
13521308Sache
13621308Sache/* Global variables declared here. */
13721308Sache/* What YOU turn on when you have handled all redisplay yourself. */
13821308Sacheint rl_display_fixed = 0;
13921308Sache
14021308Sacheint _rl_suppress_redisplay = 0;
14121308Sache
14221308Sache/* The stuff that gets printed out before the actual text of the line.
14321308Sache   This is usually pointing to rl_prompt. */
14421308Sachechar *rl_display_prompt = (char *)NULL;
14521308Sache
14621308Sache/* Pseudo-global variables declared here. */
14721308Sache/* The visible cursor position.  If you print some text, adjust this. */
14821308Sacheint _rl_last_c_pos = 0;
14921308Sacheint _rl_last_v_pos = 0;
15021308Sache
15121308Sache/* Number of lines currently on screen minus 1. */
15221308Sacheint _rl_vis_botlin = 0;
15321308Sache
15421308Sache/* Variables used only in this file. */
15521308Sache/* The last left edge of text that was displayed.  This is used when
15621308Sache   doing horizontal scrolling.  It shifts in thirds of a screenwidth. */
15721308Sachestatic int last_lmargin;
15821308Sache
15921308Sache/* The line display buffers.  One is the line currently displayed on
16021308Sache   the screen.  The other is the line about to be displayed. */
16121308Sachestatic char *visible_line = (char *)NULL;
16221308Sachestatic char *invisible_line = (char *)NULL;
16321308Sache
16421308Sache/* A buffer for `modeline' messages. */
16521308Sachestatic char msg_buf[128];
16621308Sache
16721308Sache/* Non-zero forces the redisplay even if we thought it was unnecessary. */
16821308Sachestatic int forced_display;
16921308Sache
17021308Sache/* Default and initial buffer size.  Can grow. */
17121308Sachestatic int line_size = 1024;
17221308Sache
17321308Sachestatic char *local_prompt, *local_prompt_prefix;
17421308Sachestatic int visible_length, prefix_length;
17521308Sache
17621308Sache/* The number of invisible characters in the line currently being
17721308Sache   displayed on the screen. */
17821308Sachestatic int visible_wrap_offset;
17921308Sache
18021308Sache/* static so it can be shared between rl_redisplay and update_line */
18121308Sachestatic int wrap_offset;
18221308Sache
18321308Sache/* The index of the last invisible_character in the prompt string. */
18421308Sachestatic int last_invisible;
18521308Sache
18621308Sache/* The length (buffer offset) of the first line of the last (possibly
18721308Sache   multi-line) buffer displayed on the screen. */
18821308Sachestatic int visible_first_line_len;
18921308Sache
19021308Sache/* Expand the prompt string S and return the number of visible
19121308Sache   characters in *LP, if LP is not null.  This is currently more-or-less
19221308Sache   a placeholder for expansion.  LIP, if non-null is a place to store the
19321308Sache   index of the last invisible character in ther eturned string. */
19421308Sache
19521308Sache/* Current implementation:
19621308Sache	\001 (^A) start non-visible characters
19721308Sache	\002 (^B) end non-visible characters
19821308Sache   all characters except \001 and \002 (following a \001) are copied to
19921308Sache   the returned string; all characters except those between \001 and
20021308Sache   \002 are assumed to be `visible'. */
20121308Sache
20221308Sachestatic char *
20321308Sacheexpand_prompt (pmt, lp, lip)
20421308Sache     char *pmt;
20521308Sache     int *lp, *lip;
20621308Sache{
20721308Sache  char *r, *ret, *p;
20821308Sache  int l, rl, last, ignoring;
20921308Sache
21021308Sache  /* Short-circuit if we can. */
21121308Sache  if (strchr (pmt, RL_PROMPT_START_IGNORE) == 0)
21221308Sache    {
21321308Sache      r = savestring (pmt);
21421308Sache      if (lp)
21521308Sache	*lp = strlen (r);
21621308Sache      return r;
21721308Sache    }
21821308Sache
21921308Sache  l = strlen (pmt);
22021308Sache  r = ret = xmalloc (l + 1);
22121308Sache
22221308Sache  for (rl = ignoring = last = 0, p = pmt; p && *p; p++)
22321308Sache    {
22421308Sache      /* This code strips the invisible character string markers
22521308Sache	 RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
22621308Sache      if (*p == RL_PROMPT_START_IGNORE)
22721308Sache	{
22821308Sache	  ignoring++;
22921308Sache	  continue;
23021308Sache	}
23121308Sache      else if (ignoring && *p == RL_PROMPT_END_IGNORE)
23221308Sache	{
23321308Sache	  ignoring = 0;
23421308Sache	  last = r - ret - 1;
23521308Sache	  continue;
23621308Sache	}
23721308Sache      else
23821308Sache	{
23921308Sache	  *r++ = *p;
24021308Sache	  if (!ignoring)
24121308Sache	    rl++;
24221308Sache	}
24321308Sache    }
24421308Sache
24521308Sache  *r = '\0';
24621308Sache  if (lp)
24721308Sache    *lp = rl;
24821308Sache  if (lip)
24921308Sache    *lip = last;
25021308Sache  return ret;
25121308Sache}
25221308Sache
25321308Sache/*
25421308Sache * Expand the prompt string into the various display components, if
25521308Sache * necessary.
25621308Sache *
25721308Sache * local_prompt = expanded last line of string in rl_display_prompt
25821308Sache *		  (portion after the final newline)
25921308Sache * local_prompt_prefix = portion before last newline of rl_display_prompt,
26021308Sache *			 expanded via expand_prompt
26121308Sache * visible_length = number of visible characters in local_prompt
26221308Sache * prefix_length = number of visible characters in local_prompt_prefix
26321308Sache *
26421308Sache * This function is called once per call to readline().  It may also be
26521308Sache * called arbitrarily to expand the primary prompt.
26621308Sache *
26721308Sache * The return value is the number of visible characters on the last line
26821308Sache * of the (possibly multi-line) prompt.
26921308Sache */
27021308Sacheint
27121308Sacherl_expand_prompt (prompt)
27221308Sache     char *prompt;
27321308Sache{
27421308Sache  char *p, *t;
27521308Sache  int c;
27621308Sache
27721308Sache  /* Clear out any saved values. */
27821308Sache  if (local_prompt)
27921308Sache    free (local_prompt);
28021308Sache  if (local_prompt_prefix)
28121308Sache    free (local_prompt_prefix);
28221308Sache  local_prompt = local_prompt_prefix = (char *)0;
28347563Sache  last_invisible = visible_length = 0;
28421308Sache
28521308Sache  if (prompt == 0 || *prompt == 0)
28621308Sache    return (0);
28721308Sache
28821308Sache  p = strrchr (prompt, '\n');
28921308Sache  if (!p)
29021308Sache    {
29121308Sache      /* The prompt is only one line. */
29221308Sache      local_prompt = expand_prompt (prompt, &visible_length, &last_invisible);
29321308Sache      local_prompt_prefix = (char *)0;
29421308Sache      return (visible_length);
29521308Sache    }
29621308Sache  else
29721308Sache    {
29821308Sache      /* The prompt spans multiple lines. */
29921308Sache      t = ++p;
30021308Sache      local_prompt = expand_prompt (p, &visible_length, &last_invisible);
30121308Sache      c = *t; *t = '\0';
30221308Sache      /* The portion of the prompt string up to and including the
30321308Sache	 final newline is now null-terminated. */
30421308Sache      local_prompt_prefix = expand_prompt (prompt, &prefix_length, (int *)NULL);
30521308Sache      *t = c;
30621308Sache      return (prefix_length);
30721308Sache    }
30821308Sache}
30921308Sache
31021308Sache/* Basic redisplay algorithm. */
31121308Sachevoid
31221308Sacherl_redisplay ()
31321308Sache{
31421308Sache  register int in, out, c, linenum, cursor_linenum;
31521308Sache  register char *line;
31621308Sache  int c_pos, inv_botlin, lb_botlin, lb_linenum;
31726497Sache  int newlines, lpos, temp;
31821308Sache  char *prompt_this_line;
31921308Sache
32021308Sache  if (!readline_echoing_p)
32121308Sache    return;
32221308Sache
32321308Sache  if (!rl_display_prompt)
32421308Sache    rl_display_prompt = "";
32521308Sache
32621308Sache  if (invisible_line == 0)
32721308Sache    {
32821308Sache      visible_line = xmalloc (line_size);
32921308Sache      invisible_line = xmalloc (line_size);
33021308Sache      for (in = 0; in < line_size; in++)
33121308Sache	{
33221308Sache	  visible_line[in] = 0;
33321308Sache	  invisible_line[in] = 1;
33421308Sache	}
33521308Sache
33621308Sache      /* should be enough, but then again, this is just for testing. */
33721308Sache      inv_lbreaks = (int *)malloc (256 * sizeof (int));
33821308Sache      vis_lbreaks = (int *)malloc (256 * sizeof (int));
33921308Sache      inv_lbreaks[0] = vis_lbreaks[0] = 0;
34021308Sache
34121308Sache      rl_on_new_line ();
34221308Sache    }
34321308Sache
34421308Sache  /* Draw the line into the buffer. */
34521308Sache  c_pos = -1;
34621308Sache
34721308Sache  line = invisible_line;
34821308Sache  out = inv_botlin = 0;
34921308Sache
35021308Sache  /* Mark the line as modified or not.  We only do this for history
35121308Sache     lines. */
35221308Sache  if (_rl_mark_modified_lines && current_history () && rl_undo_list)
35321308Sache    {
35421308Sache      line[out++] = '*';
35521308Sache      line[out] = '\0';
35621308Sache    }
35721308Sache
35821308Sache  /* If someone thought that the redisplay was handled, but the currently
35921308Sache     visible line has a different modification state than the one about
36021308Sache     to become visible, then correct the caller's misconception. */
36121308Sache  if (visible_line[0] != invisible_line[0])
36221308Sache    rl_display_fixed = 0;
36321308Sache
36421308Sache  /* If the prompt to be displayed is the `primary' readline prompt (the
36521308Sache     one passed to readline()), use the values we have already expanded.
36621308Sache     If not, use what's already in rl_display_prompt.  WRAP_OFFSET is the
36721308Sache     number of non-visible characters in the prompt string. */
36821308Sache  if (rl_display_prompt == rl_prompt || local_prompt)
36921308Sache    {
37021308Sache      int local_len = local_prompt ? strlen (local_prompt) : 0;
37121308Sache      if (local_prompt_prefix && forced_display)
37221308Sache	_rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix));
37321308Sache
37421308Sache      if (local_len > 0)
37521308Sache	{
37647563Sache	  temp = local_len + out + 2;
37747563Sache	  if (temp >= line_size)
37847563Sache	    {
37947563Sache	      line_size = (temp + 1024) - (temp % 1024);
38047563Sache	      visible_line = xrealloc (visible_line, line_size);
38147563Sache	      line = invisible_line = xrealloc (invisible_line, line_size);
38247563Sache	    }
38321308Sache	  strncpy (line + out, local_prompt, local_len);
38421308Sache	  out += local_len;
38521308Sache	}
38621308Sache      line[out] = '\0';
38721308Sache      wrap_offset = local_len - visible_length;
38821308Sache    }
38921308Sache  else
39021308Sache    {
39121308Sache      int pmtlen;
39221308Sache      prompt_this_line = strrchr (rl_display_prompt, '\n');
39321308Sache      if (!prompt_this_line)
39421308Sache	prompt_this_line = rl_display_prompt;
39521308Sache      else
39621308Sache	{
39721308Sache	  prompt_this_line++;
39821308Sache	  if (forced_display)
39921308Sache	    {
40021308Sache	      _rl_output_some_chars (rl_display_prompt, prompt_this_line - rl_display_prompt);
40121308Sache	      /* Make sure we are at column zero even after a newline,
40221308Sache		 regardless of the state of terminal output processing. */
40321308Sache	      if (prompt_this_line[-2] != '\r')
40421308Sache		cr ();
40521308Sache	    }
40621308Sache	}
40721308Sache
40821308Sache      pmtlen = strlen (prompt_this_line);
40947563Sache      temp = pmtlen + out + 2;
41047563Sache      if (temp >= line_size)
41147563Sache	{
41247563Sache	  line_size = (temp + 1024) - (temp % 1024);
41347563Sache	  visible_line = xrealloc (visible_line, line_size);
41447563Sache	  line = invisible_line = xrealloc (invisible_line, line_size);
41547563Sache	}
41621308Sache      strncpy (line + out,  prompt_this_line, pmtlen);
41721308Sache      out += pmtlen;
41821308Sache      line[out] = '\0';
41921308Sache      wrap_offset = 0;
42021308Sache    }
42121308Sache
42221308Sache#define CHECK_LPOS() \
42321308Sache      do { \
42447563Sache	lpos++; \
42547563Sache	if (lpos >= screenwidth) \
42647563Sache	  { \
42747563Sache	    inv_lbreaks[++newlines] = out; \
42847563Sache	    lpos = 0; \
42947563Sache	  } \
43021308Sache      } while (0)
43121308Sache
43221308Sache  /* inv_lbreaks[i] is where line i starts in the buffer. */
43321308Sache  inv_lbreaks[newlines = 0] = 0;
43426497Sache  lpos = out - wrap_offset;
43521308Sache
43626497Sache  /* XXX - what if lpos is already >= screenwidth before we start drawing the
43726497Sache     contents of the command line? */
43826497Sache  while (lpos >= screenwidth)
43921308Sache    {
44036328Sdes#if 0
44126497Sache      temp = ((newlines + 1) * screenwidth) - ((newlines == 0) ? wrap_offset : 0);
44236328Sdes#else
44336328Sdes      /* XXX - possible fix from Darin Johnson <darin@acuson.com> for prompt
44447563Sache	 string with invisible characters that is longer than the screen
44547563Sache	 width. */
44636328Sdes      temp = ((newlines + 1) * screenwidth) + ((newlines == 0) ? wrap_offset : 0);
44736328Sdes#endif
44826497Sache      inv_lbreaks[++newlines] = temp;
44926497Sache      lpos -= screenwidth;
45026497Sache    }
45126497Sache
45226497Sache  lb_linenum = 0;
45326497Sache  for (in = 0; in < rl_end; in++)
45426497Sache    {
45521308Sache      c = (unsigned char)rl_line_buffer[in];
45621308Sache
45721308Sache      if (out + 8 >= line_size)		/* XXX - 8 for \t */
45821308Sache	{
45921308Sache	  line_size *= 2;
46021308Sache	  visible_line = xrealloc (visible_line, line_size);
46121308Sache	  invisible_line = xrealloc (invisible_line, line_size);
46221308Sache	  line = invisible_line;
46321308Sache	}
46421308Sache
46521308Sache      if (in == rl_point)
46621308Sache	{
46721308Sache	  c_pos = out;
46821308Sache	  lb_linenum = newlines;
46921308Sache	}
47021308Sache
47121308Sache      if (META_CHAR (c))
47221308Sache	{
47321308Sache	  if (_rl_output_meta_chars == 0)
47421308Sache	    {
47521308Sache	      sprintf (line + out, "\\%o", c);
47621308Sache
47721308Sache	      if (lpos + 4 >= screenwidth)
47821308Sache		{
47921308Sache		  temp = screenwidth - lpos;
48021308Sache		  inv_lbreaks[++newlines] = out + temp;
48121308Sache		  lpos = 4 - temp;
48221308Sache		}
48321308Sache	      else
48421308Sache		lpos += 4;
48521308Sache
48621308Sache	      out += 4;
48721308Sache	    }
48821308Sache	  else
48921308Sache	    {
49021308Sache	      line[out++] = c;
49121308Sache	      CHECK_LPOS();
49221308Sache	    }
49321308Sache	}
49421308Sache#if defined (DISPLAY_TABS)
49521308Sache      else if (c == '\t')
49621308Sache	{
49721308Sache	  register int temp, newout;
49847563Sache
49947563Sache#if 0
50021308Sache	  newout = (out | (int)7) + 1;
50147563Sache#else
50247563Sache	  newout = out + 8 - lpos % 8;
50347563Sache#endif
50421308Sache	  temp = newout - out;
50521308Sache	  if (lpos + temp >= screenwidth)
50621308Sache	    {
50721308Sache	      register int temp2;
50821308Sache	      temp2 = screenwidth - lpos;
50921308Sache	      inv_lbreaks[++newlines] = out + temp2;
51021308Sache	      lpos = temp - temp2;
51121308Sache	      while (out < newout)
51221308Sache		line[out++] = ' ';
51321308Sache	    }
51421308Sache	  else
51521308Sache	    {
51621308Sache	      while (out < newout)
51721308Sache		line[out++] = ' ';
51821308Sache	      lpos += temp;
51921308Sache	    }
52021308Sache	}
52121308Sache#endif
52221308Sache      else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && term_up && *term_up)
52347563Sache	{
52447563Sache	  line[out++] = '\0';	/* XXX - sentinel */
52547563Sache	  inv_lbreaks[++newlines] = out;
52647563Sache	  lpos = 0;
52747563Sache	}
52821308Sache      else if (CTRL_CHAR (c) || c == RUBOUT)
52921308Sache	{
53021308Sache	  line[out++] = '^';
53121308Sache	  CHECK_LPOS();
53221308Sache	  line[out++] = CTRL_CHAR (c) ? UNCTRL (c) : '?';
53321308Sache	  CHECK_LPOS();
53421308Sache	}
53521308Sache      else
53621308Sache	{
53721308Sache	  line[out++] = c;
53821308Sache	  CHECK_LPOS();
53921308Sache	}
54021308Sache    }
54121308Sache  line[out] = '\0';
54221308Sache  if (c_pos < 0)
54321308Sache    {
54421308Sache      c_pos = out;
54521308Sache      lb_linenum = newlines;
54621308Sache    }
54721308Sache
54821308Sache  inv_botlin = lb_botlin = newlines;
54921308Sache  inv_lbreaks[newlines+1] = out;
55021308Sache  cursor_linenum = lb_linenum;
55121308Sache
55221308Sache  /* C_POS == position in buffer where cursor should be placed. */
55321308Sache
55421308Sache  /* PWP: now is when things get a bit hairy.  The visible and invisible
55521308Sache     line buffers are really multiple lines, which would wrap every
55621308Sache     (screenwidth - 1) characters.  Go through each in turn, finding
55721308Sache     the changed region and updating it.  The line order is top to bottom. */
55821308Sache
55921308Sache  /* If we can move the cursor up and down, then use multiple lines,
56021308Sache     otherwise, let long lines display in a single terminal line, and
56121308Sache     horizontally scroll it. */
56221308Sache
56321308Sache  if (_rl_horizontal_scroll_mode == 0 && term_up && *term_up)
56421308Sache    {
56521308Sache      int nleft, pos, changed_screen_line;
56621308Sache
56721308Sache      if (!rl_display_fixed || forced_display)
56821308Sache	{
56921308Sache	  forced_display = 0;
57021308Sache
57121308Sache	  /* If we have more than a screenful of material to display, then
57221308Sache	     only display a screenful.  We should display the last screen,
57321308Sache	     not the first.  */
57421308Sache	  if (out >= screenchars)
57521308Sache	    out = screenchars - 1;
57621308Sache
57721308Sache	  /* The first line is at character position 0 in the buffer.  The
57821308Sache	     second and subsequent lines start at inv_lbreaks[N], offset by
57921308Sache	     OFFSET (which has already been calculated above).  */
58021308Sache
58121308Sache#define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
58221308Sache#define VIS_LLEN(l)	((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
58321308Sache#define INV_LLEN(l)	(inv_lbreaks[l+1] - inv_lbreaks[l])
58421308Sache#define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
58521308Sache#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
58621308Sache#define INV_LINE(line) (invisible_line + inv_lbreaks[line])
58721308Sache
58821308Sache	  /* For each line in the buffer, do the updating display. */
58921308Sache	  for (linenum = 0; linenum <= inv_botlin; linenum++)
59021308Sache	    {
59121308Sache	      update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum,
59221308Sache			   VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin);
59321308Sache
59421308Sache	      /* If this is the line with the prompt, we might need to
59521308Sache		 compensate for invisible characters in the new line. Do
59621308Sache		 this only if there is not more than one new line (which
59721308Sache		 implies that we completely overwrite the old visible line)
59821308Sache		 and the new line is shorter than the old.  Make sure we are
59921308Sache		 at the end of the new line before clearing. */
60021308Sache	      if (linenum == 0 &&
60121308Sache		  inv_botlin == 0 && _rl_last_c_pos == out &&
60221308Sache		  (wrap_offset > visible_wrap_offset) &&
60321308Sache		  (_rl_last_c_pos < visible_first_line_len))
60421308Sache		{
60521308Sache		  nleft = screenwidth + wrap_offset - _rl_last_c_pos;
60621308Sache		  if (nleft)
60726497Sache		    _rl_clear_to_eol (nleft);
60821308Sache		}
60921308Sache
61021308Sache	      /* Since the new first line is now visible, save its length. */
61121308Sache	      if (linenum == 0)
61221308Sache		visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset;
61321308Sache	    }
61421308Sache
61521308Sache	  /* We may have deleted some lines.  If so, clear the left over
61621308Sache	     blank ones at the bottom out. */
61721308Sache	  if (_rl_vis_botlin > inv_botlin)
61821308Sache	    {
61921308Sache	      char *tt;
62021308Sache	      for (; linenum <= _rl_vis_botlin; linenum++)
62121308Sache		{
62221308Sache		  tt = VIS_CHARS (linenum);
62321308Sache		  _rl_move_vert (linenum);
62421308Sache		  _rl_move_cursor_relative (0, tt);
62526497Sache		  _rl_clear_to_eol
62621308Sache		    ((linenum == _rl_vis_botlin) ? strlen (tt) : screenwidth);
62721308Sache		}
62821308Sache	    }
62921308Sache	  _rl_vis_botlin = inv_botlin;
63021308Sache
63121308Sache	  /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
63221308Sache	     different screen line during this redisplay. */
63321308Sache	  changed_screen_line = _rl_last_v_pos != cursor_linenum;
63421308Sache	  if (changed_screen_line)
63521308Sache	    {
63621308Sache	      _rl_move_vert (cursor_linenum);
63721308Sache	      /* If we moved up to the line with the prompt using term_up,
63847563Sache		 the physical cursor position on the screen stays the same,
63947563Sache		 but the buffer position needs to be adjusted to account
64047563Sache		 for invisible characters. */
64121308Sache	      if (cursor_linenum == 0 && wrap_offset)
64247563Sache		_rl_last_c_pos += wrap_offset;
64321308Sache	    }
64421308Sache
64521308Sache	  /* We have to reprint the prompt if it contains invisible
64621308Sache	     characters, since it's not generally OK to just reprint
64721308Sache	     the characters from the current cursor position.  But we
64821308Sache	     only need to reprint it if the cursor is before the last
64921308Sache	     invisible character in the prompt string. */
65021308Sache	  nleft = visible_length + wrap_offset;
65121308Sache	  if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
65221308Sache	      _rl_last_c_pos <= last_invisible && local_prompt)
65321308Sache	    {
65421308Sache	      if (term_cr)
65521308Sache		tputs (term_cr, 1, _rl_output_character_function);
65621308Sache	      _rl_output_some_chars (local_prompt, nleft);
65721308Sache	      _rl_last_c_pos = nleft;
65821308Sache	    }
65921308Sache
66021308Sache	  /* Where on that line?  And where does that line start
66121308Sache	     in the buffer? */
66221308Sache	  pos = inv_lbreaks[cursor_linenum];
66321308Sache	  /* nleft == number of characters in the line buffer between the
66421308Sache	     start of the line and the cursor position. */
66521308Sache	  nleft = c_pos - pos;
66621308Sache
66721308Sache	  /* Since _rl_backspace() doesn't know about invisible characters in the
66821308Sache	     prompt, and there's no good way to tell it, we compensate for
66921308Sache	     those characters here and call _rl_backspace() directly. */
67021308Sache	  if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
67121308Sache	    {
67221308Sache	      _rl_backspace (_rl_last_c_pos - nleft);
67321308Sache	      _rl_last_c_pos = nleft;
67421308Sache	    }
67521308Sache
67621308Sache	  if (nleft != _rl_last_c_pos)
67721308Sache	    _rl_move_cursor_relative (nleft, &invisible_line[pos]);
67821308Sache	}
67921308Sache    }
68021308Sache  else				/* Do horizontal scrolling. */
68121308Sache    {
68221308Sache#define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
68321308Sache      int lmargin, ndisp, nleft, phys_c_pos, t;
68421308Sache
68521308Sache      /* Always at top line. */
68621308Sache      _rl_last_v_pos = 0;
68721308Sache
68821308Sache      /* Compute where in the buffer the displayed line should start.  This
68921308Sache	 will be LMARGIN. */
69021308Sache
69121308Sache      /* The number of characters that will be displayed before the cursor. */
69221308Sache      ndisp = c_pos - wrap_offset;
69321308Sache      nleft  = visible_length + wrap_offset;
69421308Sache      /* Where the new cursor position will be on the screen.  This can be
69547563Sache	 longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
69621308Sache      phys_c_pos = c_pos - (last_lmargin ? last_lmargin : wrap_offset);
69721308Sache      t = screenwidth / 3;
69821308Sache
69921308Sache      /* If the number of characters had already exceeded the screenwidth,
70047563Sache	 last_lmargin will be > 0. */
70121308Sache
70221308Sache      /* If the number of characters to be displayed is more than the screen
70347563Sache	 width, compute the starting offset so that the cursor is about
70447563Sache	 two-thirds of the way across the screen. */
70521308Sache      if (phys_c_pos > screenwidth - 2)
70621308Sache	{
70721308Sache	  lmargin = c_pos - (2 * t);
70821308Sache	  if (lmargin < 0)
70921308Sache	    lmargin = 0;
71021308Sache	  /* If the left margin would be in the middle of a prompt with
71121308Sache	     invisible characters, don't display the prompt at all. */
71221308Sache	  if (wrap_offset && lmargin > 0 && lmargin < nleft)
71321308Sache	    lmargin = nleft;
71421308Sache	}
71521308Sache      else if (ndisp < screenwidth - 2)		/* XXX - was -1 */
71647563Sache	lmargin = 0;
71721308Sache      else if (phys_c_pos < 1)
71821308Sache	{
71921308Sache	  /* If we are moving back towards the beginning of the line and
72021308Sache	     the last margin is no longer correct, compute a new one. */
72121308Sache	  lmargin = ((c_pos - 1) / t) * t;	/* XXX */
72221308Sache	  if (wrap_offset && lmargin > 0 && lmargin < nleft)
72321308Sache	    lmargin = nleft;
72421308Sache	}
72521308Sache      else
72647563Sache	lmargin = last_lmargin;
72721308Sache
72821308Sache      /* If the first character on the screen isn't the first character
72921308Sache	 in the display line, indicate this with a special character. */
73021308Sache      if (lmargin > 0)
73121308Sache	line[lmargin] = '<';
73221308Sache
73321308Sache      /* If SCREENWIDTH characters starting at LMARGIN do not encompass
73447563Sache	 the whole line, indicate that with a special character at the
73547563Sache	 right edge of the screen.  If LMARGIN is 0, we need to take the
73647563Sache	 wrap offset into account. */
73721308Sache      t = lmargin + M_OFFSET (lmargin, wrap_offset) + screenwidth;
73821308Sache      if (t < out)
73947563Sache	line[t - 1] = '>';
74021308Sache
74121308Sache      if (!rl_display_fixed || forced_display || lmargin != last_lmargin)
74221308Sache	{
74321308Sache	  forced_display = 0;
74421308Sache	  update_line (&visible_line[last_lmargin],
74521308Sache		       &invisible_line[lmargin],
74621308Sache		       0,
74721308Sache		       screenwidth + visible_wrap_offset,
74821308Sache		       screenwidth + (lmargin ? 0 : wrap_offset),
74921308Sache		       0);
75021308Sache
75121308Sache	  /* If the visible new line is shorter than the old, but the number
75221308Sache	     of invisible characters is greater, and we are at the end of
75321308Sache	     the new line, we need to clear to eol. */
75421308Sache	  t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
75521308Sache	  if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
75621308Sache	      (_rl_last_c_pos == out) &&
75721308Sache	      t < visible_first_line_len)
75821308Sache	    {
75921308Sache	      nleft = screenwidth - t;
76026497Sache	      _rl_clear_to_eol (nleft);
76121308Sache	    }
76221308Sache	  visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
76321308Sache	  if (visible_first_line_len > screenwidth)
76421308Sache	    visible_first_line_len = screenwidth;
76521308Sache
76621308Sache	  _rl_move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]);
76721308Sache	  last_lmargin = lmargin;
76821308Sache	}
76921308Sache    }
77021308Sache  fflush (rl_outstream);
77121308Sache
77221308Sache  /* Swap visible and non-visible lines. */
77321308Sache  {
77421308Sache    char *temp = visible_line;
77521308Sache    int *itemp = vis_lbreaks;
77621308Sache    visible_line = invisible_line;
77721308Sache    invisible_line = temp;
77821308Sache    vis_lbreaks = inv_lbreaks;
77921308Sache    inv_lbreaks = itemp;
78021308Sache    rl_display_fixed = 0;
78121308Sache    /* If we are displaying on a single line, and last_lmargin is > 0, we
78221308Sache       are not displaying any invisible characters, so set visible_wrap_offset
78321308Sache       to 0. */
78421308Sache    if (_rl_horizontal_scroll_mode && last_lmargin)
78521308Sache      visible_wrap_offset = 0;
78621308Sache    else
78721308Sache      visible_wrap_offset = wrap_offset;
78821308Sache  }
78921308Sache}
79021308Sache
79121308Sache/* PWP: update_line() is based on finding the middle difference of each
79221308Sache   line on the screen; vis:
79321308Sache
79421308Sache			     /old first difference
79521308Sache	/beginning of line   |	      /old last same       /old EOL
79621308Sache	v		     v	      v		    v
79721308Sacheold:	eddie> Oh, my little gruntle-buggy is to me, as lurgid as
79821308Sachenew:	eddie> Oh, my little buggy says to me, as lurgid as
79921308Sache	^		     ^	^			   ^
80021308Sache	\beginning of line   |	\new last same	   \new end of line
80121308Sache			     \new first difference
80221308Sache
80321308Sache   All are character pointers for the sake of speed.  Special cases for
80447563Sache   no differences, as well as for end of line additions must be handled.
80521308Sache
80621308Sache   Could be made even smarter, but this works well enough */
80721308Sachestatic void
80821308Sacheupdate_line (old, new, current_line, omax, nmax, inv_botlin)
80921308Sache     register char *old, *new;
81021308Sache     int current_line, omax, nmax, inv_botlin;
81121308Sache{
81221308Sache  register char *ofd, *ols, *oe, *nfd, *nls, *ne;
81321308Sache  int temp, lendiff, wsatend, od, nd;
81421308Sache  int current_invis_chars;
81521308Sache
81621308Sache  /* If we're at the right edge of a terminal that supports xn, we're
81721308Sache     ready to wrap around, so do so.  This fixes problems with knowing
81821308Sache     the exact cursor position and cut-and-paste with certain terminal
81921308Sache     emulators.  In this calculation, TEMP is the physical screen
82021308Sache     position of the cursor. */
82121308Sache  temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
82221308Sache  if (temp == screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
82321308Sache      && _rl_last_v_pos == current_line - 1)
82421308Sache    {
82521308Sache      if (new[0])
82621308Sache	putc (new[0], rl_outstream);
82721308Sache      else
82821308Sache	putc (' ', rl_outstream);
82921308Sache      _rl_last_c_pos = 1;		/* XXX */
83021308Sache      _rl_last_v_pos++;
83121308Sache      if (old[0] && new[0])
83247563Sache	old[0] = new[0];
83321308Sache    }
83421308Sache
83521308Sache  /* Find first difference. */
83621308Sache  for (ofd = old, nfd = new;
83721308Sache       (ofd - old < omax) && *ofd && (*ofd == *nfd);
83821308Sache       ofd++, nfd++)
83921308Sache    ;
84021308Sache
84121308Sache  /* Move to the end of the screen line.  ND and OD are used to keep track
84221308Sache     of the distance between ne and new and oe and old, respectively, to
84321308Sache     move a subtraction out of each loop. */
84421308Sache  for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
84521308Sache  for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
84621308Sache
84721308Sache  /* If no difference, continue to next line. */
84821308Sache  if (ofd == oe && nfd == ne)
84921308Sache    return;
85021308Sache
85121308Sache  wsatend = 1;			/* flag for trailing whitespace */
85221308Sache  ols = oe - 1;			/* find last same */
85321308Sache  nls = ne - 1;
85421308Sache  while ((ols > ofd) && (nls > nfd) && (*ols == *nls))
85521308Sache    {
85621308Sache      if (*ols != ' ')
85721308Sache	wsatend = 0;
85821308Sache      ols--;
85921308Sache      nls--;
86021308Sache    }
86121308Sache
86221308Sache  if (wsatend)
86321308Sache    {
86421308Sache      ols = oe;
86521308Sache      nls = ne;
86621308Sache    }
86721308Sache  else if (*ols != *nls)
86821308Sache    {
86921308Sache      if (*ols)			/* don't step past the NUL */
87021308Sache	ols++;
87121308Sache      if (*nls)
87221308Sache	nls++;
87321308Sache    }
87421308Sache
87521308Sache  /* count of invisible characters in the current invisible line. */
87621308Sache  current_invis_chars = W_OFFSET (current_line, wrap_offset);
87721308Sache  if (_rl_last_v_pos != current_line)
87821308Sache    {
87921308Sache      _rl_move_vert (current_line);
88021308Sache      if (current_line == 0 && visible_wrap_offset)
88121308Sache	_rl_last_c_pos += visible_wrap_offset;
88221308Sache    }
88321308Sache
88421308Sache  /* If this is the first line and there are invisible characters in the
88521308Sache     prompt string, and the prompt string has not changed, and the current
88621308Sache     cursor position is before the last invisible character in the prompt,
88721308Sache     and the index of the character to move to is past the end of the prompt
88821308Sache     string, then redraw the entire prompt string.  We can only do this
88921308Sache     reliably if the terminal supports a `cr' capability.
89021308Sache
89121308Sache     This is not an efficiency hack -- there is a problem with redrawing
89221308Sache     portions of the prompt string if they contain terminal escape
89321308Sache     sequences (like drawing the `unbold' sequence without a corresponding
89421308Sache     `bold') that manifests itself on certain terminals. */
89521308Sache
89621308Sache  lendiff = local_prompt ? strlen (local_prompt) : 0;
89721308Sache  od = ofd - old;	/* index of first difference in visible line */
89821308Sache  if (current_line == 0 && !_rl_horizontal_scroll_mode &&
89921308Sache      term_cr && lendiff > visible_length && _rl_last_c_pos > 0 &&
90021308Sache      od > lendiff && _rl_last_c_pos < last_invisible)
90121308Sache    {
90221308Sache      tputs (term_cr, 1, _rl_output_character_function);
90321308Sache      _rl_output_some_chars (local_prompt, lendiff);
90421308Sache      _rl_last_c_pos = lendiff;
90521308Sache    }
90621308Sache
90721308Sache  _rl_move_cursor_relative (od, old);
90821308Sache
90921308Sache  /* if (len (new) > len (old)) */
91021308Sache  lendiff = (nls - nfd) - (ols - ofd);
91121308Sache
91221308Sache  /* If we are changing the number of invisible characters in a line, and
91321308Sache     the spot of first difference is before the end of the invisible chars,
91421308Sache     lendiff needs to be adjusted. */
91521308Sache  if (current_line == 0 && !_rl_horizontal_scroll_mode &&
91621308Sache      current_invis_chars != visible_wrap_offset)
91747563Sache    lendiff += visible_wrap_offset - current_invis_chars;
91821308Sache
91921308Sache  /* Insert (diff (len (old), len (new)) ch. */
92021308Sache  temp = ne - nfd;
92121308Sache  if (lendiff > 0)
92221308Sache    {
92321308Sache      /* Non-zero if we're increasing the number of lines. */
92421308Sache      int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
92521308Sache      /* Sometimes it is cheaper to print the characters rather than
92621308Sache	 use the terminal's capabilities.  If we're growing the number
92721308Sache	 of lines, make sure we actually cause the new line to wrap
92821308Sache	 around on auto-wrapping terminals. */
92921308Sache      if (terminal_can_insert && ((2 * temp) >= lendiff || term_IC) && (!_rl_term_autowrap || !gl))
93021308Sache	{
93121308Sache	  /* If lendiff > visible_length and _rl_last_c_pos == 0 and
93221308Sache	     _rl_horizontal_scroll_mode == 1, inserting the characters with
93321308Sache	     term_IC or term_ic will screw up the screen because of the
93421308Sache	     invisible characters.  We need to just draw them. */
93521308Sache	  if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 ||
93621308Sache			lendiff <= visible_length || !current_invis_chars))
93721308Sache	    {
93821308Sache	      insert_some_chars (nfd, lendiff);
93921308Sache	      _rl_last_c_pos += lendiff;
94021308Sache	    }
94121308Sache	  else if (*ols == 0)
94221308Sache	    {
94321308Sache	      /* At the end of a line the characters do not have to
94421308Sache		 be "inserted".  They can just be placed on the screen. */
94521308Sache	      /* However, this screws up the rest of this block, which
94647563Sache		 assumes you've done the insert because you can. */
94721308Sache	      _rl_output_some_chars (nfd, lendiff);
94821308Sache	      _rl_last_c_pos += lendiff;
94921308Sache	    }
95021308Sache	  else
95121308Sache	    {
95221308Sache	      /* We have horizontal scrolling and we are not inserting at
95321308Sache		 the end.  We have invisible characters in this line.  This
95421308Sache		 is a dumb update. */
95521308Sache	      _rl_output_some_chars (nfd, temp);
95621308Sache	      _rl_last_c_pos += temp;
95721308Sache	      return;
95821308Sache	    }
95921308Sache	  /* Copy (new) chars to screen from first diff to last match. */
96021308Sache	  temp = nls - nfd;
96121308Sache	  if ((temp - lendiff) > 0)
96221308Sache	    {
96321308Sache	      _rl_output_some_chars (nfd + lendiff, temp - lendiff);
96421308Sache	      _rl_last_c_pos += temp - lendiff;
96521308Sache	    }
96621308Sache	}
96721308Sache      else
96821308Sache	{
96921308Sache	  /* cannot insert chars, write to EOL */
97021308Sache	  _rl_output_some_chars (nfd, temp);
97121308Sache	  _rl_last_c_pos += temp;
97221308Sache	}
97321308Sache    }
97421308Sache  else				/* Delete characters from line. */
97521308Sache    {
97621308Sache      /* If possible and inexpensive to use terminal deletion, then do so. */
97721308Sache      if (term_dc && (2 * temp) >= -lendiff)
97821308Sache	{
97921308Sache	  /* If all we're doing is erasing the invisible characters in the
98021308Sache	     prompt string, don't bother.  It screws up the assumptions
98121308Sache	     about what's on the screen. */
98221308Sache	  if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
98321308Sache	      -lendiff == visible_wrap_offset)
98421308Sache	    lendiff = 0;
98521308Sache
98621308Sache	  if (lendiff)
98721308Sache	    delete_chars (-lendiff); /* delete (diff) characters */
98821308Sache
98921308Sache	  /* Copy (new) chars to screen from first diff to last match */
99021308Sache	  temp = nls - nfd;
99121308Sache	  if (temp > 0)
99221308Sache	    {
99321308Sache	      _rl_output_some_chars (nfd, temp);
99421308Sache	      _rl_last_c_pos += temp;
99521308Sache	    }
99621308Sache	}
99721308Sache      /* Otherwise, print over the existing material. */
99821308Sache      else
99921308Sache	{
100021308Sache	  if (temp > 0)
100121308Sache	    {
100221308Sache	      _rl_output_some_chars (nfd, temp);
100321308Sache	      _rl_last_c_pos += temp;
100421308Sache	    }
100521308Sache	  lendiff = (oe - old) - (ne - new);
100647563Sache	  if (lendiff)
100747563Sache	    {
100847563Sache	      if (_rl_term_autowrap && current_line < inv_botlin)
100947563Sache		space_to_eol (lendiff);
101047563Sache	      else
101147563Sache		_rl_clear_to_eol (lendiff);
101247563Sache	    }
101321308Sache	}
101421308Sache    }
101521308Sache}
101621308Sache
101721308Sache/* Tell the update routines that we have moved onto a new (empty) line. */
101821308Sacheint
101921308Sacherl_on_new_line ()
102021308Sache{
102121308Sache  if (visible_line)
102221308Sache    visible_line[0] = '\0';
102321308Sache
102421308Sache  _rl_last_c_pos = _rl_last_v_pos = 0;
102521308Sache  _rl_vis_botlin = last_lmargin = 0;
102621308Sache  if (vis_lbreaks)
102721308Sache    vis_lbreaks[0] = vis_lbreaks[1] = 0;
102821308Sache  visible_wrap_offset = 0;
102921308Sache  return 0;
103021308Sache}
103121308Sache
103221308Sache/* Actually update the display, period. */
103321308Sacheint
103421308Sacherl_forced_update_display ()
103521308Sache{
103621308Sache  if (visible_line)
103721308Sache    {
103821308Sache      register char *temp = visible_line;
103921308Sache
104021308Sache      while (*temp)
104147563Sache	*temp++ = '\0';
104221308Sache    }
104321308Sache  rl_on_new_line ();
104421308Sache  forced_display++;
104521308Sache  (*rl_redisplay_function) ();
104621308Sache  return 0;
104721308Sache}
104821308Sache
104921308Sache/* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
105021308Sache   DATA is the contents of the screen line of interest; i.e., where
105121308Sache   the movement is being done. */
105221308Sachevoid
105321308Sache_rl_move_cursor_relative (new, data)
105421308Sache     int new;
105521308Sache     char *data;
105621308Sache{
105721308Sache  register int i;
105821308Sache
105921308Sache  /* If we don't have to do anything, then return. */
106021308Sache  if (_rl_last_c_pos == new) return;
106121308Sache
106221308Sache  /* It may be faster to output a CR, and then move forwards instead
106321308Sache     of moving backwards. */
106421308Sache  /* i == current physical cursor position. */
106521308Sache  i = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
106621308Sache  if (new == 0 || CR_FASTER (new, _rl_last_c_pos) ||
106721308Sache      (_rl_term_autowrap && i == screenwidth))
106821308Sache    {
106921308Sache#if defined (__MSDOS__)
107021308Sache      putc ('\r', rl_outstream);
107121308Sache#else
107221308Sache      tputs (term_cr, 1, _rl_output_character_function);
107321308Sache#endif /* !__MSDOS__ */
107421308Sache      _rl_last_c_pos = 0;
107521308Sache    }
107621308Sache
107721308Sache  if (_rl_last_c_pos < new)
107821308Sache    {
107921308Sache      /* Move the cursor forward.  We do it by printing the command
108021308Sache	 to move the cursor forward if there is one, else print that
108121308Sache	 portion of the output buffer again.  Which is cheaper? */
108221308Sache
108321308Sache      /* The above comment is left here for posterity.  It is faster
108421308Sache	 to print one character (non-control) than to print a control
108521308Sache	 sequence telling the terminal to move forward one character.
108621308Sache	 That kind of control is for people who don't know what the
108721308Sache	 data is underneath the cursor. */
108821308Sache#if defined (HACK_TERMCAP_MOTION)
108921308Sache      extern char *term_forward_char;
109021308Sache
109121308Sache      if (term_forward_char)
109221308Sache	for (i = _rl_last_c_pos; i < new; i++)
109321308Sache	  tputs (term_forward_char, 1, _rl_output_character_function);
109421308Sache      else
109521308Sache	for (i = _rl_last_c_pos; i < new; i++)
109621308Sache	  putc (data[i], rl_outstream);
109721308Sache#else
109821308Sache      for (i = _rl_last_c_pos; i < new; i++)
109921308Sache	putc (data[i], rl_outstream);
110021308Sache#endif /* HACK_TERMCAP_MOTION */
110121308Sache    }
110247563Sache  else if (_rl_last_c_pos > new)
110321308Sache    _rl_backspace (_rl_last_c_pos - new);
110421308Sache  _rl_last_c_pos = new;
110521308Sache}
110621308Sache
110721308Sache/* PWP: move the cursor up or down. */
110821308Sachevoid
110921308Sache_rl_move_vert (to)
111021308Sache     int to;
111121308Sache{
111221308Sache  register int delta, i;
111321308Sache
111421308Sache  if (_rl_last_v_pos == to || to > screenheight)
111521308Sache    return;
111621308Sache
111721308Sache#if defined (__GO32__)
111821308Sache  {
111921308Sache    int row, col;
112021308Sache
112121308Sache    ScreenGetCursor (&row, &col);
112221308Sache    ScreenSetCursor ((row + to - _rl_last_v_pos), col);
112321308Sache  }
112421308Sache#else /* !__GO32__ */
112521308Sache
112621308Sache  if ((delta = to - _rl_last_v_pos) > 0)
112721308Sache    {
112821308Sache      for (i = 0; i < delta; i++)
112921308Sache	putc ('\n', rl_outstream);
113021308Sache      tputs (term_cr, 1, _rl_output_character_function);
113121308Sache      _rl_last_c_pos = 0;
113221308Sache    }
113321308Sache  else
113421308Sache    {			/* delta < 0 */
113521308Sache      if (term_up && *term_up)
113621308Sache	for (i = 0; i < -delta; i++)
113721308Sache	  tputs (term_up, 1, _rl_output_character_function);
113821308Sache    }
113921308Sache#endif /* !__GO32__ */
114021308Sache  _rl_last_v_pos = to;		/* Now TO is here */
114121308Sache}
114221308Sache
114321308Sache/* Physically print C on rl_outstream.  This is for functions which know
114421308Sache   how to optimize the display.  Return the number of characters output. */
114521308Sacheint
114621308Sacherl_show_char (c)
114721308Sache     int c;
114821308Sache{
114921308Sache  int n = 1;
115021308Sache  if (META_CHAR (c) && (_rl_output_meta_chars == 0))
115121308Sache    {
115221308Sache      fprintf (rl_outstream, "M-");
115321308Sache      n += 2;
115421308Sache      c = UNMETA (c);
115521308Sache    }
115621308Sache
115721308Sache#if defined (DISPLAY_TABS)
115821308Sache  if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
115921308Sache#else
116021308Sache  if (CTRL_CHAR (c) || c == RUBOUT)
116121308Sache#endif /* !DISPLAY_TABS */
116221308Sache    {
116321308Sache      fprintf (rl_outstream, "C-");
116421308Sache      n += 2;
116521308Sache      c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
116621308Sache    }
116721308Sache
116821308Sache  putc (c, rl_outstream);
116921308Sache  fflush (rl_outstream);
117021308Sache  return n;
117121308Sache}
117221308Sache
117321308Sacheint
117421308Sacherl_character_len (c, pos)
117521308Sache     register int c, pos;
117621308Sache{
117721308Sache  unsigned char uc;
117821308Sache
117921308Sache  uc = (unsigned char)c;
118021308Sache
118121308Sache  if (META_CHAR (uc))
118221308Sache    return ((_rl_output_meta_chars == 0) ? 4 : 1);
118321308Sache
118421308Sache  if (uc == '\t')
118521308Sache    {
118621308Sache#if defined (DISPLAY_TABS)
118721308Sache      return (((pos | 7) + 1) - pos);
118821308Sache#else
118921308Sache      return (2);
119021308Sache#endif /* !DISPLAY_TABS */
119121308Sache    }
119221308Sache
119321308Sache  if (CTRL_CHAR (c) || c == RUBOUT)
119421308Sache    return (2);
119521308Sache
119621308Sache  return ((isprint (uc)) ? 1 : 2);
119721308Sache}
119821308Sache
119921308Sache/* How to print things in the "echo-area".  The prompt is treated as a
120021308Sache   mini-modeline. */
120121308Sache
120221308Sache#if defined (USE_VARARGS)
120321308Sacheint
120421308Sache#if defined (PREFER_STDARG)
120521308Sacherl_message (const char *format, ...)
120621308Sache#else
120721308Sacherl_message (va_alist)
120821308Sache     va_dcl
120921308Sache#endif
121021308Sache{
121121308Sache  va_list args;
121221308Sache#if defined (PREFER_VARARGS)
121321308Sache  char *format;
121421308Sache#endif
121521308Sache
121621308Sache#if defined (PREFER_STDARG)
121721308Sache  va_start (args, format);
121821308Sache#else
121921308Sache  va_start (args);
122021308Sache  format = va_arg (args, char *);
122121308Sache#endif
122221308Sache
122321308Sache  vsprintf (msg_buf, format, args);
122421308Sache  va_end (args);
122521308Sache
122621308Sache  rl_display_prompt = msg_buf;
122721308Sache  (*rl_redisplay_function) ();
122821308Sache  return 0;
122921308Sache}
123021308Sache#else /* !USE_VARARGS */
123121308Sacheint
123221308Sacherl_message (format, arg1, arg2)
123321308Sache     char *format;
123421308Sache{
123521308Sache  sprintf (msg_buf, format, arg1, arg2);
123621308Sache  rl_display_prompt = msg_buf;
123721308Sache  (*rl_redisplay_function) ();
123821308Sache  return 0;
123921308Sache}
124021308Sache#endif /* !USE_VARARGS */
124121308Sache
124221308Sache/* How to clear things from the "echo-area". */
124321308Sacheint
124421308Sacherl_clear_message ()
124521308Sache{
124621308Sache  rl_display_prompt = rl_prompt;
124721308Sache  (*rl_redisplay_function) ();
124821308Sache  return 0;
124921308Sache}
125021308Sache
125121308Sacheint
125221308Sacherl_reset_line_state ()
125321308Sache{
125421308Sache  rl_on_new_line ();
125521308Sache
125621308Sache  rl_display_prompt = rl_prompt ? rl_prompt : "";
125721308Sache  forced_display = 1;
125821308Sache  return 0;
125921308Sache}
126021308Sache
126121308Sachestatic char *saved_local_prompt;
126221308Sachestatic char *saved_local_prefix;
126321308Sachestatic int saved_last_invisible;
126421308Sachestatic int saved_visible_length;
126521308Sache
126621308Sachevoid
126747563Sacherl_save_prompt ()
126821308Sache{
126921308Sache  saved_local_prompt = local_prompt;
127021308Sache  saved_local_prefix = local_prompt_prefix;
127121308Sache  saved_last_invisible = last_invisible;
127221308Sache  saved_visible_length = visible_length;
127321308Sache
127421308Sache  local_prompt = local_prompt_prefix = (char *)0;
127521308Sache  last_invisible = visible_length = 0;
127621308Sache}
127721308Sache
127821308Sachevoid
127947563Sacherl_restore_prompt ()
128021308Sache{
128121308Sache  if (local_prompt)
128221308Sache    free (local_prompt);
128321308Sache  if (local_prompt_prefix)
128421308Sache    free (local_prompt_prefix);
128521308Sache
128621308Sache  local_prompt = saved_local_prompt;
128721308Sache  local_prompt_prefix = saved_local_prefix;
128821308Sache  last_invisible = saved_last_invisible;
128921308Sache  visible_length = saved_visible_length;
129021308Sache}
129121308Sache
129221308Sachechar *
129321308Sache_rl_make_prompt_for_search (pchar)
129421308Sache     int pchar;
129521308Sache{
129621308Sache  int len;
129721308Sache  char *pmt;
129821308Sache
129947563Sache  rl_save_prompt ();
130021308Sache
130121308Sache  if (saved_local_prompt == 0)
130221308Sache    {
130321308Sache      len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
130421308Sache      pmt = xmalloc (len + 2);
130521308Sache      if (len)
130647563Sache	strcpy (pmt, rl_prompt);
130721308Sache      pmt[len] = pchar;
130821308Sache      pmt[len+1] = '\0';
130921308Sache    }
131021308Sache  else
131121308Sache    {
131221308Sache      len = *saved_local_prompt ? strlen (saved_local_prompt) : 0;
131321308Sache      pmt = xmalloc (len + 2);
131421308Sache      if (len)
131547563Sache	strcpy (pmt, saved_local_prompt);
131621308Sache      pmt[len] = pchar;
131721308Sache      pmt[len+1] = '\0';
131821308Sache      local_prompt = savestring (pmt);
131921308Sache      last_invisible = saved_last_invisible;
132021308Sache      visible_length = saved_visible_length + 1;
132121308Sache    }
132221308Sache  return pmt;
132321308Sache}
132421308Sache
132521308Sache/* Quick redisplay hack when erasing characters at the end of the line. */
132621308Sachevoid
132721308Sache_rl_erase_at_end_of_line (l)
132821308Sache     int l;
132921308Sache{
133021308Sache  register int i;
133121308Sache
133221308Sache  _rl_backspace (l);
133321308Sache  for (i = 0; i < l; i++)
133421308Sache    putc (' ', rl_outstream);
133521308Sache  _rl_backspace (l);
133621308Sache  for (i = 0; i < l; i++)
133721308Sache    visible_line[--_rl_last_c_pos] = '\0';
133821308Sache  rl_display_fixed++;
133921308Sache}
134021308Sache
134121308Sache/* Clear to the end of the line.  COUNT is the minimum
134221308Sache   number of character spaces to clear, */
134326497Sachevoid
134426497Sache_rl_clear_to_eol (count)
134521308Sache     int count;
134621308Sache{
134721308Sache#if !defined (__GO32__)
134821308Sache  if (term_clreol)
134926497Sache    tputs (term_clreol, 1, _rl_output_character_function);
135026497Sache  else if (count)
135121308Sache#endif /* !__GO32__ */
135221308Sache    space_to_eol (count);
135321308Sache}
135421308Sache
135521308Sache/* Clear to the end of the line using spaces.  COUNT is the minimum
135621308Sache   number of character spaces to clear, */
135721308Sachestatic void
135821308Sachespace_to_eol (count)
135921308Sache     int count;
136021308Sache{
136121308Sache  register int i;
136221308Sache
136321308Sache  for (i = 0; i < count; i++)
136421308Sache   putc (' ', rl_outstream);
136521308Sache
136621308Sache  _rl_last_c_pos += count;
136721308Sache}
136821308Sache
136926497Sachevoid
137026497Sache_rl_clear_screen ()
137126497Sache{
137226497Sache#if !defined (__GO32__)
137326497Sache  if (term_clrpag)
137426497Sache    tputs (term_clrpag, 1, _rl_output_character_function);
137526497Sache  else
137626497Sache#endif /* !__GO32__ */
137726497Sache    crlf ();
137826497Sache}
137926497Sache
138021308Sache/* Insert COUNT characters from STRING to the output stream. */
138121308Sachestatic void
138221308Sacheinsert_some_chars (string, count)
138321308Sache     char *string;
138421308Sache     int count;
138521308Sache{
138621308Sache#if defined (__GO32__)
138721308Sache  int row, col, width;
138821308Sache  char *row_start;
138921308Sache
139021308Sache  ScreenGetCursor (&row, &col);
139121308Sache  width = ScreenCols ();
139221308Sache  row_start = ScreenPrimary + (row * width);
139321308Sache
139421308Sache  memcpy (row_start + col + count, row_start + col, width - col - count);
139521308Sache
139621308Sache  /* Place the text on the screen. */
139721308Sache  _rl_output_some_chars (string, count);
139821308Sache#else /* !_GO32 */
139921308Sache
140021308Sache  /* If IC is defined, then we do not have to "enter" insert mode. */
140121308Sache  if (term_IC)
140221308Sache    {
140321308Sache      char *buffer;
140421308Sache      buffer = tgoto (term_IC, 0, count);
140521308Sache      tputs (buffer, 1, _rl_output_character_function);
140621308Sache      _rl_output_some_chars (string, count);
140721308Sache    }
140821308Sache  else
140921308Sache    {
141021308Sache      register int i;
141121308Sache
141221308Sache      /* If we have to turn on insert-mode, then do so. */
141321308Sache      if (term_im && *term_im)
141421308Sache	tputs (term_im, 1, _rl_output_character_function);
141521308Sache
141621308Sache      /* If there is a special command for inserting characters, then
141721308Sache	 use that first to open up the space. */
141821308Sache      if (term_ic && *term_ic)
141921308Sache	{
142021308Sache	  for (i = count; i--; )
142121308Sache	    tputs (term_ic, 1, _rl_output_character_function);
142221308Sache	}
142321308Sache
142421308Sache      /* Print the text. */
142521308Sache      _rl_output_some_chars (string, count);
142621308Sache
142721308Sache      /* If there is a string to turn off insert mode, we had best use
142821308Sache	 it now. */
142921308Sache      if (term_ei && *term_ei)
143021308Sache	tputs (term_ei, 1, _rl_output_character_function);
143121308Sache    }
143221308Sache#endif /* !__GO32__ */
143321308Sache}
143421308Sache
143521308Sache/* Delete COUNT characters from the display line. */
143621308Sachestatic void
143721308Sachedelete_chars (count)
143821308Sache     int count;
143921308Sache{
144021308Sache#if defined (__GO32__)
144121308Sache  int row, col, width;
144221308Sache  char *row_start;
144321308Sache
144421308Sache  ScreenGetCursor (&row, &col);
144521308Sache  width = ScreenCols ();
144621308Sache  row_start = ScreenPrimary + (row * width);
144721308Sache
144821308Sache  memcpy (row_start + col, row_start + col + count, width - col - count);
144921308Sache  memset (row_start + width - count, 0, count * 2);
145021308Sache#else /* !_GO32 */
145121308Sache
145221308Sache  if (count > screenwidth)	/* XXX */
145321308Sache    return;
145421308Sache
145521308Sache  if (term_DC && *term_DC)
145621308Sache    {
145721308Sache      char *buffer;
145821308Sache      buffer = tgoto (term_DC, count, count);
145921308Sache      tputs (buffer, count, _rl_output_character_function);
146021308Sache    }
146121308Sache  else
146221308Sache    {
146321308Sache      if (term_dc && *term_dc)
146421308Sache	while (count--)
146521308Sache	  tputs (term_dc, 1, _rl_output_character_function);
146621308Sache    }
146721308Sache#endif /* !__GO32__ */
146821308Sache}
146921308Sache
147021308Sachevoid
147121308Sache_rl_update_final ()
147221308Sache{
147321308Sache  int full_lines;
147421308Sache
147521308Sache  full_lines = 0;
147621308Sache  /* If the cursor is the only thing on an otherwise-blank last line,
147721308Sache     compensate so we don't print an extra CRLF. */
147821308Sache  if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
147926497Sache	visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
148021308Sache    {
148121308Sache      _rl_vis_botlin--;
148221308Sache      full_lines = 1;
148321308Sache    }
148421308Sache  _rl_move_vert (_rl_vis_botlin);
148521308Sache  /* If we've wrapped lines, remove the final xterm line-wrap flag. */
148621308Sache  if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == screenwidth))
148721308Sache    {
148821308Sache      char *last_line;
148921308Sache      last_line = &visible_line[inv_lbreaks[_rl_vis_botlin]];
149021308Sache      _rl_move_cursor_relative (screenwidth - 1, last_line);
149126497Sache      _rl_clear_to_eol (0);
149221308Sache      putc (last_line[screenwidth - 1], rl_outstream);
149321308Sache    }
149421308Sache  _rl_vis_botlin = 0;
149521308Sache  crlf ();
149621308Sache  fflush (rl_outstream);
149721308Sache  rl_display_fixed++;
149821308Sache}
149921308Sache
150021308Sache/* Move to the start of the current line. */
150121308Sachestatic void
150221308Sachecr ()
150321308Sache{
150421308Sache  if (term_cr)
150521308Sache    {
150621308Sache      tputs (term_cr, 1, _rl_output_character_function);
150721308Sache      _rl_last_c_pos = 0;
150821308Sache    }
150921308Sache}
151021308Sache
151121308Sache/* Redisplay the current line after a SIGWINCH is received. */
151221308Sachevoid
151321308Sache_rl_redisplay_after_sigwinch ()
151421308Sache{
151530971Sache  char *t, *oldp, *oldl, *oldlprefix;
151621308Sache
151721308Sache  /* Clear the current line and put the cursor at column 0.  Make sure
151821308Sache     the right thing happens if we have wrapped to a new screen line. */
151921308Sache  if (term_cr)
152021308Sache    {
152121308Sache      tputs (term_cr, 1, _rl_output_character_function);
152221308Sache      _rl_last_c_pos = 0;
152321308Sache      if (term_clreol)
152421308Sache	tputs (term_clreol, 1, _rl_output_character_function);
152521308Sache      else
152621308Sache	{
152721308Sache	  space_to_eol (screenwidth);
152821308Sache	  tputs (term_cr, 1, _rl_output_character_function);
152921308Sache	}
153021308Sache      if (_rl_last_v_pos > 0)
153121308Sache	_rl_move_vert (0);
153221308Sache    }
153321308Sache  else
153421308Sache    crlf ();
153521308Sache
153621308Sache  /* Redraw only the last line of a multi-line prompt. */
153721308Sache  t = strrchr (rl_display_prompt, '\n');
153821308Sache  if (t)
153921308Sache    {
154021308Sache      oldp = rl_display_prompt;
154130971Sache      oldl = local_prompt;
154230971Sache      oldlprefix = local_prompt_prefix;
154321308Sache      rl_display_prompt = ++t;
154430971Sache      local_prompt = local_prompt_prefix = (char *)NULL;
154521308Sache      rl_forced_update_display ();
154621308Sache      rl_display_prompt = oldp;
154730971Sache      local_prompt = oldl;
154830971Sache      local_prompt_prefix = oldlprefix;
154921308Sache    }
155021308Sache  else
155121308Sache    rl_forced_update_display ();
155221308Sache}
155321308Sache
155421308Sachevoid
155521308Sache_rl_clean_up_for_exit ()
155621308Sache{
155721308Sache  if (readline_echoing_p)
155821308Sache    {
155921308Sache      _rl_move_vert (_rl_vis_botlin);
156021308Sache      _rl_vis_botlin = 0;
156121308Sache      fflush (rl_outstream);
156247563Sache      rl_restart_output (1, 0);
156321308Sache    }
156421308Sache}
156547563Sache
156647563Sachevoid
156747563Sache_rl_erase_entire_line ()
156847563Sache{
156947563Sache  cr ();
157047563Sache  _rl_clear_to_eol (0);
157147563Sache  cr ();
157247563Sache  fflush (rl_outstream);
157347563Sache}
1574