File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / readline / display.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 01:01:01 2021 UTC (3 years, 3 months ago) by misho
Branches: readline, MAIN
CVS tags: v8_2p0, v8_1p0, HEAD
readline 8.1

    1: /* display.c -- readline redisplay facility. */
    2: 
    3: /* Copyright (C) 1987-2020 Free Software Foundation, Inc.
    4: 
    5:    This file is part of the GNU Readline Library (Readline), a library    
    6:    for reading lines of text with interactive input and history editing.
    7: 
    8:    Readline is free software: you can redistribute it and/or modify
    9:    it under the terms of the GNU General Public License as published by
   10:    the Free Software Foundation, either version 3 of the License, or
   11:    (at your option) any later version.
   12: 
   13:    Readline is distributed in the hope that it will be useful,
   14:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   15:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16:    GNU General Public License for more details.
   17: 
   18:    You should have received a copy of the GNU General Public License
   19:    along with Readline.  If not, see <http://www.gnu.org/licenses/>.
   20: */
   21: 
   22: #define READLINE_LIBRARY
   23: 
   24: #if defined (HAVE_CONFIG_H)
   25: #  include <config.h>
   26: #endif
   27: 
   28: #include <sys/types.h>
   29: 
   30: #if defined (HAVE_UNISTD_H)
   31: #  include <unistd.h>
   32: #endif /* HAVE_UNISTD_H */
   33: 
   34: #include "posixstat.h"
   35: 
   36: #if defined (HAVE_STDLIB_H)
   37: #  include <stdlib.h>
   38: #else
   39: #  include "ansi_stdlib.h"
   40: #endif /* HAVE_STDLIB_H */
   41: 
   42: #include <stdio.h>
   43: 
   44: #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__)
   63: extern char *strchr (), *strrchr ();
   64: #endif /* !strchr && !__STDC__ */
   65: 
   66: static void putc_face PARAMS((int, int, char *));
   67: static void puts_face PARAMS((const char *, const char *, int));
   68: static void norm_face PARAMS((char *, int));
   69: 
   70: static void update_line PARAMS((char *, char *, char *, char *, int, int, int, int));
   71: static void space_to_eol PARAMS((int));
   72: static void delete_chars PARAMS((int));
   73: static void insert_some_chars PARAMS((char *, int, int));
   74: static void open_some_spaces PARAMS((int));
   75: static void cr PARAMS((void));
   76: static void redraw_prompt PARAMS((char *));
   77: static void _rl_move_cursor_relative PARAMS((int, const char *, const char *));
   78: 
   79: /* Values for FLAGS */
   80: #define PMT_MULTILINE	0x01
   81: 
   82: static char *expand_prompt PARAMS((char *, int, int *, int *, int *, int *));
   83: 
   84: #define DEFAULT_LINE_BUFFER_SIZE	1024
   85: 
   86: /* State of visible and invisible lines. */
   87: struct line_state
   88:   {
   89:     char *line;
   90:     char *lface;
   91:     int *lbreaks;
   92:     int lbsize;
   93: #if defined (HANDLE_MULTIBYTE)
   94:     int wbsize;
   95:     int *wrapped_line;
   96: #endif
   97:   };
   98: 
   99: /* The line display buffers.  One is the line currently displayed on
  100:    the screen.  The other is the line about to be displayed. */
  101: static struct line_state line_state_array[2];
  102: static struct line_state *line_state_visible = &line_state_array[0];
  103: static struct line_state *line_state_invisible = &line_state_array[1];
  104: static int line_structures_initialized = 0;
  105: 
  106: /* Backwards-compatible names. */
  107: #define inv_lbreaks	(line_state_invisible->lbreaks)
  108: #define inv_lbsize	(line_state_invisible->lbsize)
  109: #define vis_lbreaks	(line_state_visible->lbreaks)
  110: #define vis_lbsize	(line_state_visible->lbsize)
  111: 
  112: #define visible_line	(line_state_visible->line)
  113: #define vis_face	(line_state_visible->lface)
  114: #define invisible_line	(line_state_invisible->line)
  115: #define inv_face	(line_state_invisible->lface)
  116: 
  117: #if defined (HANDLE_MULTIBYTE)
  118: static int _rl_col_width PARAMS((const char *, int, int, int));
  119: #else
  120: #  define _rl_col_width(l, s, e, f)	(((e) <= (s)) ? 0 : (e) - (s))
  121: #endif
  122: 
  123: /* Heuristic used to decide whether it is faster to move from CUR to NEW
  124:    by backing up or outputting a carriage return and moving forward.  CUR
  125:    and NEW are either both buffer positions or absolute screen positions. */
  126: #define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new)))
  127: 
  128: /* _rl_last_c_pos is an absolute cursor position in multibyte locales and a
  129:    buffer index in others.  This macro is used when deciding whether the
  130:    current cursor position is in the middle of a prompt string containing
  131:    invisible characters.  XXX - might need to take `modmark' into account. */
  132: /* XXX - only valid when tested against _rl_last_c_pos; buffer indices need
  133:    to use prompt_last_invisible directly. */
  134: #define PROMPT_ENDING_INDEX \
  135:   ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) ? prompt_physical_chars : prompt_last_invisible+1)
  136: 
  137: #define FACE_NORMAL	'0'
  138: #define FACE_STANDOUT	'1'
  139: #define FACE_INVALID	((char)1)
  140:   
  141: /* **************************************************************** */
  142: /*								    */
  143: /*			Display stuff				    */
  144: /*								    */
  145: /* **************************************************************** */
  146: 
  147: /* This is the stuff that is hard for me.  I never seem to write good
  148:    display routines in C.  Let's see how I do this time. */
  149: 
  150: /* (PWP) Well... Good for a simple line updater, but totally ignores
  151:    the problems of input lines longer than the screen width.
  152: 
  153:    update_line and the code that calls it makes a multiple line,
  154:    automatically wrapping line update.  Careful attention needs
  155:    to be paid to the vertical position variables. */
  156: 
  157: /* Keep two buffers; one which reflects the current contents of the
  158:    screen, and the other to draw what we think the new contents should
  159:    be.  Then compare the buffers, and make whatever changes to the
  160:    screen itself that we should.  Finally, make the buffer that we
  161:    just drew into be the one which reflects the current contents of the
  162:    screen, and place the cursor where it belongs.
  163: 
  164:    Commands that want to can fix the display themselves, and then let
  165:    this function know that the display has been fixed by setting the
  166:    RL_DISPLAY_FIXED variable.  This is good for efficiency. */
  167: 
  168: /* Application-specific redisplay function. */
  169: rl_voidfunc_t *rl_redisplay_function = rl_redisplay;
  170: 
  171: /* Global variables declared here. */
  172: /* What YOU turn on when you have handled all redisplay yourself. */
  173: int rl_display_fixed = 0;
  174: 
  175: /* The stuff that gets printed out before the actual text of the line.
  176:    This is usually pointing to rl_prompt. */
  177: char *rl_display_prompt = (char *)NULL;
  178: 
  179: /* Variables used to include the editing mode in the prompt. */
  180: char *_rl_emacs_mode_str;
  181: int _rl_emacs_modestr_len;
  182: 
  183: char *_rl_vi_ins_mode_str;
  184: int _rl_vi_ins_modestr_len;
  185: 
  186: char *_rl_vi_cmd_mode_str;
  187: int _rl_vi_cmd_modestr_len;
  188: 
  189: /* Pseudo-global variables declared here. */
  190: 
  191: /* Hints for other parts of readline to give to the display engine. */
  192: int _rl_suppress_redisplay = 0;
  193: int _rl_want_redisplay = 0;
  194: 
  195: /* The visible cursor position.  If you print some text, adjust this. */
  196: /* NOTE: _rl_last_c_pos is used as a buffer index when not in a locale
  197:    supporting multibyte characters, and an absolute cursor position when
  198:    in such a locale.  This is an artifact of the donated multibyte support.
  199:    Care must be taken when modifying its value. */
  200: int _rl_last_c_pos = 0;
  201: int _rl_last_v_pos = 0;
  202: 
  203: /* Number of physical lines consumed by the current line buffer currently
  204:   on screen minus 1. */
  205: int _rl_vis_botlin = 0;
  206: 
  207: static int _rl_quick_redisplay = 0;
  208: 
  209: /* This is a hint update_line gives to rl_redisplay that it has adjusted the
  210:    value of _rl_last_c_pos *and* taken the presence of any invisible chars in
  211:    the prompt into account.  rl_redisplay notes this and does not do the
  212:    adjustment itself. */
  213: static int cpos_adjusted;
  214: 
  215: /* The index into the line buffer corresponding to the cursor position */
  216: static int cpos_buffer_position;
  217: 
  218: /* A flag to note when we're displaying the first line of the prompt */
  219: static int displaying_prompt_first_line;
  220: /* The number of multibyte characters in the prompt, if any */
  221: static int prompt_multibyte_chars;
  222: 
  223: static int _rl_inv_botlin = 0;
  224: 
  225: /* Variables used only in this file. */
  226: /* The last left edge of text that was displayed.  This is used when
  227:    doing horizontal scrolling.  It shifts in thirds of a screenwidth. */
  228: static int last_lmargin;
  229: 
  230: /* A buffer for `modeline' messages. */
  231: static char *msg_buf = 0;
  232: static int msg_bufsiz = 0;
  233: 
  234: /* Non-zero forces the redisplay even if we thought it was unnecessary. */
  235: static int forced_display;
  236: 
  237: /* Default and initial buffer size.  Can grow. */
  238: static int line_size  = 0;
  239: 
  240: /* Set to a non-zero value if horizontal scrolling has been enabled
  241:    automatically because the terminal was resized to height 1. */
  242: static int horizontal_scrolling_autoset = 0;	/* explicit initialization */
  243: 
  244: /* Variables to keep track of the expanded prompt string, which may
  245:    include invisible characters. */
  246: 
  247: static char *local_prompt, *local_prompt_prefix;
  248: static int local_prompt_len;
  249: static int prompt_prefix_length;
  250: /* Number of chars in the buffer that contribute to visible chars on the screen.
  251:    This might be different from the number of physical chars in the presence
  252:    of multibyte characters */
  253: static int prompt_visible_length;
  254: 
  255: /* The number of invisible characters in the line currently being
  256:    displayed on the screen. */
  257: static int visible_wrap_offset;
  258: 
  259: /* The number of invisible characters in the prompt string.  Static so it
  260:    can be shared between rl_redisplay and update_line */
  261: static int wrap_offset;
  262: 
  263: /* The index of the last invisible character in the prompt string. */
  264: static int prompt_last_invisible;
  265: 
  266: /* The length (buffer offset) of the first line of the last (possibly
  267:    multi-line) buffer displayed on the screen. */
  268: static int visible_first_line_len;
  269: 
  270: /* Number of invisible characters on the first physical line of the prompt.
  271:    Only valid when the number of physical characters in the prompt exceeds
  272:    (or is equal to) _rl_screenwidth. */
  273: static int prompt_invis_chars_first_line;
  274: 
  275: static int prompt_last_screen_line;
  276: 
  277: static int prompt_physical_chars;
  278: 
  279: /* An array of indexes into the prompt string where we will break physical
  280:    screen lines.  It's easier to compute in expand_prompt and use later in
  281:    rl_redisplay instead of having rl_redisplay try to guess about invisible
  282:    characters in the prompt or use heuristics about where they are. */
  283: static int *local_prompt_newlines;
  284: 
  285: /* set to a non-zero value by rl_redisplay if we are marking modified history
  286:    lines and the current line is so marked. */
  287: static int modmark;
  288: 
  289: static int line_totbytes;
  290: 
  291: /* Variables to save and restore prompt and display information. */
  292: 
  293: /* These are getting numerous enough that it's time to create a struct. */
  294: 
  295: static char *saved_local_prompt;
  296: static char *saved_local_prefix;
  297: static int *saved_local_prompt_newlines;
  298: 
  299: static int saved_last_invisible;
  300: static int saved_visible_length;
  301: static int saved_prefix_length;
  302: static int saved_local_length;
  303: static int saved_invis_chars_first_line;
  304: static int saved_physical_chars;
  305: 
  306: /* Return a string indicating the editing mode, for use in the prompt. */
  307: 
  308: static char *
  309: prompt_modestr (int *lenp)
  310: {
  311:   if (rl_editing_mode == emacs_mode)
  312:     {
  313:       if (lenp)
  314: 	*lenp = _rl_emacs_mode_str ? _rl_emacs_modestr_len : RL_EMACS_MODESTR_DEFLEN;
  315:       return _rl_emacs_mode_str ? _rl_emacs_mode_str : RL_EMACS_MODESTR_DEFAULT;
  316:     }
  317:   else if (_rl_keymap == vi_insertion_keymap)
  318:     {
  319:       if (lenp)
  320: 	*lenp = _rl_vi_ins_mode_str ? _rl_vi_ins_modestr_len : RL_VI_INS_MODESTR_DEFLEN;
  321:       return _rl_vi_ins_mode_str ? _rl_vi_ins_mode_str : RL_VI_INS_MODESTR_DEFAULT;		/* vi insert mode */
  322:     }
  323:   else
  324:     {
  325:       if (lenp)
  326: 	*lenp = _rl_vi_cmd_mode_str ? _rl_vi_cmd_modestr_len : RL_VI_CMD_MODESTR_DEFLEN;
  327:       return _rl_vi_cmd_mode_str ? _rl_vi_cmd_mode_str : RL_VI_CMD_MODESTR_DEFAULT;		/* vi command mode */
  328:     }
  329: }
  330: 
  331: /* Expand the prompt string S and return the number of visible
  332:    characters in *LP, if LP is not null.  This is currently more-or-less
  333:    a placeholder for expansion.  LIP, if non-null is a place to store the
  334:    index of the last invisible character in the returned string. NIFLP,
  335:    if non-zero, is a place to store the number of invisible characters in
  336:    the first prompt line.  The previous are used as byte counts -- indexes
  337:    into a character buffer.  *VLP gets the number of physical characters in
  338:    the expanded prompt (visible length) */
  339: 
  340: /* Current implementation:
  341: 	\001 (^A) start non-visible characters
  342: 	\002 (^B) end non-visible characters
  343:    all characters except \001 and \002 (following a \001) are copied to
  344:    the returned string; all characters except those between \001 and
  345:    \002 are assumed to be `visible'. */	
  346: 
  347: /* Possible values for FLAGS:
  348: 	PMT_MULTILINE	caller indicates that this is part of a multiline prompt
  349: */
  350: 
  351: /* This approximates the number of lines the prompt will take when displayed */
  352: #define APPROX_DIV(n, d)	(((n) < (d)) ? 1 : ((n) / (d)) + 1)
  353: 
  354: static char *
  355: expand_prompt (char *pmt, int flags, int *lp, int *lip, int *niflp, int *vlp)
  356: {
  357:   char *r, *ret, *p, *igstart, *nprompt, *ms;
  358:   int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars;
  359:   int mlen, newlines, newlines_guess, bound;
  360:   int mb_cur_max;
  361: 
  362:   /* We only expand the mode string for the last line of a multiline prompt
  363:      (a prompt with embedded newlines). */
  364:   ms = (((pmt == rl_prompt) ^ (flags & PMT_MULTILINE)) && _rl_show_mode_in_prompt) ? prompt_modestr (&mlen) : 0;
  365:   if (ms)
  366:     {
  367:       l = strlen (pmt);
  368:       nprompt = (char *)xmalloc (l + mlen + 1);
  369:       memcpy (nprompt, ms, mlen);
  370:       strcpy (nprompt + mlen, pmt);
  371:     }
  372:   else
  373:     nprompt = pmt;
  374: 
  375:   mb_cur_max = MB_CUR_MAX;
  376: 
  377:   if (_rl_screenwidth == 0)
  378:     _rl_get_screen_size (0, 0);	/* avoid division by zero */
  379: 
  380:   /* Short-circuit if we can.  We can do this if we are treating the prompt as
  381:      a sequence of bytes and there are no invisible characters in the prompt
  382:      to deal with. Since we populate local_prompt_newlines, we have to run
  383:      through the rest of the function if this prompt looks like it's going to
  384:      be longer than one screen line. */
  385:   if ((mb_cur_max <= 1 || rl_byte_oriented) && strchr (nprompt, RL_PROMPT_START_IGNORE) == 0)
  386:     {
  387:       l = strlen (nprompt);
  388:       if (l < (_rl_screenwidth > 0 ? _rl_screenwidth : 80))
  389:         {
  390: 	  r = (nprompt == pmt) ? savestring (pmt) : nprompt;
  391: 	  if (lp)
  392: 	    *lp = l;
  393: 	  if (lip)
  394: 	    *lip = 0;
  395: 	  if (niflp)
  396: 	    *niflp = 0;
  397: 	  if (vlp)
  398: 	    *vlp = l;
  399: 
  400: 	  local_prompt_newlines = (int *) xrealloc (local_prompt_newlines, sizeof (int) * 2);
  401: 	  local_prompt_newlines[0] = 0;
  402: 	  local_prompt_newlines[1] = -1;
  403: 
  404: 	  return r;
  405:         }
  406:     }
  407: 
  408:   l = strlen (nprompt);			/* XXX */
  409:   r = ret = (char *)xmalloc (l + 1);
  410: 
  411:   /* Guess at how many screen lines the prompt will take to size the array that
  412:      keeps track of where the line wraps happen */
  413:   newlines_guess = (_rl_screenwidth > 0) ? APPROX_DIV(l,  _rl_screenwidth) : APPROX_DIV(l, 80);
  414:   local_prompt_newlines = (int *) xrealloc (local_prompt_newlines, sizeof (int) * (newlines_guess + 1));
  415:   local_prompt_newlines[newlines = 0] = 0;
  416:   for (rl = 1; rl <= newlines_guess; rl++)
  417:     local_prompt_newlines[rl] = -1;
  418: 
  419:   rl = physchars = 0;	/* mode string now part of nprompt */
  420:   invfl = 0;		/* invisible chars in first line of prompt */
  421:   invflset = 0;		/* we only want to set invfl once */
  422:   igstart = 0;		/* we're not ignoring any characters yet */
  423: 
  424:   for (ignoring = last = ninvis = 0, p = nprompt; p && *p; p++)
  425:     {
  426:       /* This code strips the invisible character string markers
  427: 	 RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
  428:       if (ignoring == 0 && *p == RL_PROMPT_START_IGNORE)		/* XXX - check ignoring? */
  429: 	{
  430: 	  ignoring = 1;
  431: 	  igstart = p;
  432: 	  continue;
  433: 	}
  434:       else if (ignoring && *p == RL_PROMPT_END_IGNORE)
  435: 	{
  436: 	  ignoring = 0;
  437: 	  if (p != (igstart + 1))
  438: 	    last = r - ret - 1;
  439: 	  continue;
  440: 	}
  441:       else
  442: 	{
  443: #if defined (HANDLE_MULTIBYTE)
  444: 	  if (mb_cur_max > 1 && rl_byte_oriented == 0)
  445: 	    {
  446: 	      pind = p - nprompt;
  447: 	      ind = _rl_find_next_mbchar (nprompt, pind, 1, MB_FIND_NONZERO);
  448: 	      l = ind - pind;
  449: 	      while (l--)
  450: 	        *r++ = *p++;
  451: 	      if (!ignoring)
  452: 		{
  453: 		  /* rl ends up being assigned to prompt_visible_length,
  454: 		     which is the number of characters in the buffer that
  455: 		     contribute to characters on the screen, which might
  456: 		     not be the same as the number of physical characters
  457: 		     on the screen in the presence of multibyte characters */
  458: 		  rl += ind - pind;
  459: 		  physchars += _rl_col_width (nprompt, pind, ind, 0);
  460: 		}
  461: 	      else
  462: 		ninvis += ind - pind;
  463: 	      p--;			/* compensate for later increment */
  464: 	    }
  465: 	  else
  466: #endif
  467: 	    {
  468: 	      *r++ = *p;
  469: 	      if (!ignoring)
  470: 		{
  471: 		  rl++;			/* visible length byte counter */
  472: 		  physchars++;
  473: 		}
  474: 	      else
  475: 		ninvis++;		/* invisible chars byte counter */
  476: 	    }
  477: 
  478: 	  if (invflset == 0 && physchars >= _rl_screenwidth)
  479: 	    {
  480: 	      invfl = ninvis;
  481: 	      invflset = 1;
  482: 	    }
  483: 
  484: 	  if (physchars >= (bound = (newlines + 1) * _rl_screenwidth) && local_prompt_newlines[newlines+1] == -1)
  485: 	    {
  486: 	      int new;
  487: 	      if (physchars > bound)		/* should rarely happen */
  488: 		{
  489: #if defined (HANDLE_MULTIBYTE)
  490: 		  *r = '\0';	/* need null-termination for strlen */
  491: 		  if (mb_cur_max > 1 && rl_byte_oriented == 0)
  492: 		    new = _rl_find_prev_mbchar (ret, r - ret, MB_FIND_ANY);
  493: 		  else
  494: #endif
  495: 		    new = r - ret - (physchars - bound);	/* XXX */
  496: 		}
  497: 	      else
  498: 	        new = r - ret;
  499: 	      local_prompt_newlines[++newlines] = new;
  500: 	    }
  501: 	}
  502:     }
  503: 
  504:   if (rl < _rl_screenwidth)
  505:     invfl = ninvis;
  506: 
  507:   *r = '\0';
  508:   if (lp)
  509:     *lp = rl;
  510:   if (lip)
  511:     *lip = last;
  512:   if (niflp)
  513:     *niflp = invfl;
  514:   if  (vlp)
  515:     *vlp = physchars;
  516: 
  517:   if (nprompt != pmt)
  518:     free (nprompt);
  519: 
  520:   return ret;
  521: }
  522: 
  523: /* Just strip out RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE from
  524:    PMT and return the rest of PMT. */
  525: char *
  526: _rl_strip_prompt (char *pmt)
  527: {
  528:   char *ret;
  529: 
  530:   ret = expand_prompt (pmt, 0, (int *)NULL, (int *)NULL, (int *)NULL, (int *)NULL);
  531:   return ret;
  532: }
  533: 
  534: void
  535: _rl_reset_prompt (void)
  536: {
  537:   rl_visible_prompt_length = rl_expand_prompt (rl_prompt);
  538: }
  539: 
  540: /*
  541:  * Expand the prompt string into the various display components, if
  542:  * necessary.
  543:  *
  544:  * local_prompt = expanded last line of string in rl_display_prompt
  545:  *		  (portion after the final newline)
  546:  * local_prompt_prefix = portion before last newline of rl_display_prompt,
  547:  *			 expanded via expand_prompt
  548:  * prompt_visible_length = number of visible characters in local_prompt
  549:  * prompt_prefix_length = number of visible characters in local_prompt_prefix
  550:  *
  551:  * It also tries to keep track of the number of invisible characters in the
  552:  * prompt string, and where they are.
  553:  *
  554:  * This function is called once per call to readline().  It may also be
  555:  * called arbitrarily to expand the primary prompt.
  556:  *
  557:  * The return value is the number of visible characters on the last line
  558:  * of the (possibly multi-line) prompt.  In this case, multi-line means
  559:  * there are embedded newlines in the prompt string itself, not that the
  560:  * number of physical characters exceeds the screen width and the prompt
  561:  * wraps.
  562:  */
  563: int
  564: rl_expand_prompt (char *prompt)
  565: {
  566:   char *p, *t;
  567:   int c;
  568: 
  569:   /* Clear out any saved values. */
  570:   FREE (local_prompt);
  571:   FREE (local_prompt_prefix);
  572: 
  573:   local_prompt = local_prompt_prefix = (char *)0;
  574:   local_prompt_len = 0;
  575:   prompt_last_invisible = prompt_invis_chars_first_line = 0;
  576:   prompt_visible_length = prompt_physical_chars = 0;
  577: 
  578:   if (prompt == 0 || *prompt == 0)
  579:     return (0);
  580: 
  581:   p = strrchr (prompt, '\n');
  582:   if (p == 0)
  583:     {
  584:       /* The prompt is only one logical line, though it might wrap. */
  585:       local_prompt = expand_prompt (prompt, 0, &prompt_visible_length,
  586: 					       &prompt_last_invisible,
  587: 					       &prompt_invis_chars_first_line,
  588: 					       &prompt_physical_chars);
  589:       local_prompt_prefix = (char *)0;
  590:       local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
  591:       return (prompt_visible_length);
  592:     }
  593:   else
  594:     {
  595:       /* The prompt spans multiple lines. */
  596:       t = ++p;
  597:       c = *t; *t = '\0';
  598:       /* The portion of the prompt string up to and including the
  599: 	 final newline is now null-terminated. */
  600:       local_prompt_prefix = expand_prompt (prompt, PMT_MULTILINE,
  601: 						   &prompt_prefix_length,
  602: 						   (int *)NULL,
  603: 						   (int *)NULL,
  604: 						   (int *)NULL);
  605:       *t = c;
  606: 
  607:       local_prompt = expand_prompt (p, PMT_MULTILINE,
  608: 				       &prompt_visible_length,
  609: 				       &prompt_last_invisible,
  610: 				       &prompt_invis_chars_first_line,
  611: 				       &prompt_physical_chars);
  612:       local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
  613:       return (prompt_prefix_length);
  614:     }
  615: }
  616: 
  617: /* Allocate the various line structures, making sure they can hold MINSIZE
  618:    bytes. If the existing line size can accommodate MINSIZE bytes, don't do
  619:    anything. */
  620: static void
  621: realloc_line (int minsize)
  622: {
  623:   int minimum_size;
  624:   int newsize, delta;
  625: 
  626:   minimum_size = DEFAULT_LINE_BUFFER_SIZE;
  627:   if (minsize < minimum_size)
  628:     minsize = minimum_size;
  629:   if (minsize <= _rl_screenwidth)	/* XXX - for gdb */
  630:     minsize = _rl_screenwidth + 1;
  631:   if (line_size >= minsize)
  632:     return;
  633: 
  634:   newsize = minimum_size;
  635:   while (newsize < minsize)
  636:     newsize *= 2;
  637: 
  638:   visible_line = (char *)xrealloc (visible_line, newsize);
  639:   vis_face = (char *)xrealloc (vis_face, newsize);
  640: 
  641:   invisible_line = (char *)xrealloc (invisible_line, newsize);
  642:   inv_face = (char *)xrealloc (inv_face, newsize);
  643: 
  644:   delta = newsize - line_size;  
  645:   memset (visible_line + line_size, 0, delta);
  646:   memset (vis_face + line_size, FACE_NORMAL, delta);
  647:   memset (invisible_line + line_size, 1, delta);
  648:   memset (inv_face + line_size, FACE_INVALID, delta);
  649: 
  650:   line_size = newsize;
  651: }
  652: 
  653: /* Initialize the VISIBLE_LINE and INVISIBLE_LINE arrays, and their associated
  654:    arrays of line break markers.  MINSIZE is the minimum size of VISIBLE_LINE
  655:    and INVISIBLE_LINE; if it is greater than LINE_SIZE, LINE_SIZE is
  656:    increased.  If the lines have already been allocated, this ensures that
  657:    they can hold at least MINSIZE characters. */
  658: static void
  659: init_line_structures (int minsize)
  660: {
  661:   if (invisible_line == 0)	/* initialize it */
  662:     {
  663:       if (line_size > minsize)
  664: 	minsize = line_size;
  665:     }
  666:    realloc_line (minsize); 
  667: 
  668:   if (vis_lbreaks == 0)
  669:     {
  670:       /* should be enough. */
  671:       inv_lbsize = vis_lbsize = 256;
  672: 
  673: #if defined (HANDLE_MULTIBYTE)
  674:       line_state_visible->wbsize = vis_lbsize;
  675:       line_state_visible->wrapped_line = (int *)xmalloc (line_state_visible->wbsize * sizeof (int));
  676: 
  677:       line_state_invisible->wbsize = inv_lbsize;
  678:       line_state_invisible->wrapped_line = (int *)xmalloc (line_state_invisible->wbsize * sizeof (int));
  679: #endif
  680: 
  681:       inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int));
  682:       vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int));
  683:       inv_lbreaks[0] = vis_lbreaks[0] = 0;
  684:     }
  685: 
  686:   line_structures_initialized = 1;
  687: }
  688: 
  689: /* Convenience functions to add chars to the invisible line that update the
  690:    face information at the same time. */
  691: static void		/* XXX - change this */
  692: invis_addc (int *outp, char c, char face)
  693: {
  694:   realloc_line (*outp + 1);
  695:   invisible_line[*outp] = c;
  696:   inv_face[*outp] = face;
  697:   *outp += 1;
  698: }
  699: 
  700: static void
  701: invis_adds (int *outp, const char *str, int n, char face)
  702: {
  703:   int i;
  704: 
  705:   for (i = 0; i < n; i++)
  706:     invis_addc (outp, str[i], face);
  707: }
  708: 
  709: static void
  710: invis_nul (int *outp)
  711: {
  712:   invis_addc (outp, '\0', 0);
  713:   *outp -= 1;
  714: }
  715: 
  716: static void
  717: set_active_region (int *beg, int *end)
  718: {
  719:   if (rl_point >= 0 && rl_point <= rl_end && rl_mark >= 0 && rl_mark <= rl_end)
  720:     {
  721:       *beg = (rl_mark < rl_point) ? rl_mark : rl_point;
  722:       *end = (rl_mark < rl_point) ? rl_point : rl_mark;
  723:     }
  724: }
  725: 
  726: /* Do whatever tests are necessary and tell update_line that it can do a
  727:    quick, dumb redisplay on the assumption that there are so many
  728:    differences between the old and new lines that it would be a waste to
  729:    compute all the differences.
  730:    Right now, it just sets _rl_quick_redisplay if the current visible line
  731:    is a single line (so we don't have to move vertically or mess with line
  732:    wrapping). */
  733: void
  734: _rl_optimize_redisplay (void)
  735: {
  736:   if (_rl_vis_botlin == 0)
  737:     _rl_quick_redisplay = 1;
  738: }  
  739: 
  740: /* Basic redisplay algorithm.  See comments inline. */
  741: void
  742: rl_redisplay (void)
  743: {
  744:   int in, out, c, linenum, cursor_linenum;
  745:   int inv_botlin, lb_botlin, lb_linenum, o_cpos;
  746:   int newlines, lpos, temp, n0, num, prompt_lines_estimate;
  747:   char *prompt_this_line;
  748:   char cur_face;
  749:   int hl_begin, hl_end;
  750:   int mb_cur_max = MB_CUR_MAX;
  751: #if defined (HANDLE_MULTIBYTE)
  752:   wchar_t wc;
  753:   size_t wc_bytes;
  754:   int wc_width;
  755:   mbstate_t ps;
  756:   int _rl_wrapped_multicolumn = 0;
  757: #endif
  758: 
  759:   if (_rl_echoing_p == 0)
  760:     return;
  761: 
  762:   /* Block keyboard interrupts because this function manipulates global
  763:      data structures. */
  764:   _rl_block_sigint ();  
  765:   RL_SETSTATE (RL_STATE_REDISPLAYING);
  766: 
  767:   cur_face = FACE_NORMAL;
  768:   /* Can turn this into an array for multiple highlighted objects in addition
  769:      to the region */
  770:   hl_begin = hl_end = -1;
  771: 
  772:   if (rl_mark_active_p ())
  773:     set_active_region (&hl_begin, &hl_end);
  774: 
  775:   if (!rl_display_prompt)
  776:     rl_display_prompt = "";
  777: 
  778:   if (line_structures_initialized == 0)
  779:     {
  780:       init_line_structures (0);
  781:       rl_on_new_line ();
  782:     }
  783:   else if (line_size <= _rl_screenwidth)
  784:     init_line_structures (_rl_screenwidth + 1);
  785: 
  786:   /* Enable horizontal scrolling automatically for terminals of height 1
  787:      where wrapping lines doesn't work. Disable it as soon as the terminal
  788:      height is increased again if it was automatically enabled. */
  789:   if (_rl_screenheight <= 1)
  790:     {
  791:       if (_rl_horizontal_scroll_mode == 0)
  792: 	 horizontal_scrolling_autoset = 1;
  793:       _rl_horizontal_scroll_mode = 1;
  794:     }
  795:   else if (horizontal_scrolling_autoset)
  796:     _rl_horizontal_scroll_mode = 0;
  797: 
  798:   /* Draw the line into the buffer. */
  799:   cpos_buffer_position = -1;
  800: 
  801:   prompt_multibyte_chars = prompt_visible_length - prompt_physical_chars;
  802: 
  803:   out = inv_botlin = 0;
  804: 
  805:   /* Mark the line as modified or not.  We only do this for history
  806:      lines. */
  807:   modmark = 0;
  808:   if (_rl_mark_modified_lines && current_history () && rl_undo_list)
  809:     {
  810:       invis_addc (&out, '*', cur_face);
  811:       invis_nul (&out);
  812:       modmark = 1;
  813:     }
  814: 
  815:   /* If someone thought that the redisplay was handled, but the currently
  816:      visible line has a different modification state than the one about
  817:      to become visible, then correct the caller's misconception. */
  818:   if (visible_line[0] != invisible_line[0])
  819:     rl_display_fixed = 0;
  820: 
  821:   /* If the prompt to be displayed is the `primary' readline prompt (the
  822:      one passed to readline()), use the values we have already expanded.
  823:      If not, use what's already in rl_display_prompt.  WRAP_OFFSET is the
  824:      number of non-visible characters (bytes) in the prompt string. */
  825:   /* This is where we output the characters in the prompt before the last
  826:      newline, if any.  If there aren't any embedded newlines, we don't
  827:      write anything. Copy the last line of the prompt string into the line in
  828:      any case */
  829:   if (rl_display_prompt == rl_prompt || local_prompt)
  830:     {
  831:       if (local_prompt_prefix && forced_display)
  832: 	_rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix));
  833: 
  834:       if (local_prompt_len > 0)
  835: 	invis_adds (&out, local_prompt, local_prompt_len, cur_face);
  836:       invis_nul (&out);
  837:       wrap_offset = local_prompt_len - prompt_visible_length;
  838:     }
  839:   else
  840:     {
  841:       int pmtlen;
  842:       prompt_this_line = strrchr (rl_display_prompt, '\n');
  843:       if (!prompt_this_line)
  844: 	prompt_this_line = rl_display_prompt;
  845:       else
  846: 	{
  847: 	  prompt_this_line++;
  848: 	  pmtlen = prompt_this_line - rl_display_prompt;	/* temp var */
  849: 	  if (forced_display)
  850: 	    {
  851: 	      _rl_output_some_chars (rl_display_prompt, pmtlen);
  852: 	      /* Make sure we are at column zero even after a newline,
  853: 		 regardless of the state of terminal output processing. */
  854: 	      if (pmtlen < 2 || prompt_this_line[-2] != '\r')
  855: 		cr ();
  856: 	    }
  857: 	}
  858: 
  859:       prompt_physical_chars = pmtlen = strlen (prompt_this_line);	/* XXX */
  860:       invis_adds (&out, prompt_this_line, pmtlen, cur_face);
  861:       invis_nul (&out);
  862:       wrap_offset = prompt_invis_chars_first_line = 0;
  863:     }
  864: 
  865: #if defined (HANDLE_MULTIBYTE)
  866: #define CHECK_INV_LBREAKS() \
  867:       do { \
  868: 	if (newlines >= (inv_lbsize - 2)) \
  869: 	  { \
  870: 	    inv_lbsize *= 2; \
  871: 	    inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
  872: 	  } \
  873: 	if (newlines >= (line_state_invisible->wbsize - 2)) \
  874: 	  { \
  875: 	    line_state_invisible->wbsize *= 2; \
  876: 	    line_state_invisible->wrapped_line = (int *)xrealloc (line_state_invisible->wrapped_line, line_state_invisible->wbsize * sizeof(int)); \
  877: 	  } \
  878:       } while (0)
  879: #else
  880: #define CHECK_INV_LBREAKS() \
  881:       do { \
  882: 	if (newlines >= (inv_lbsize - 2)) \
  883: 	  { \
  884: 	    inv_lbsize *= 2; \
  885: 	    inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
  886: 	  } \
  887:       } while (0)
  888: #endif /* !HANDLE_MULTIBYTE */
  889: 
  890: #if defined (HANDLE_MULTIBYTE)	  
  891: #define CHECK_LPOS() \
  892:       do { \
  893: 	lpos++; \
  894: 	if (lpos >= _rl_screenwidth) \
  895: 	  { \
  896: 	    if (newlines >= (inv_lbsize - 2)) \
  897: 	      { \
  898: 		inv_lbsize *= 2; \
  899: 		inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
  900: 	      } \
  901: 	    inv_lbreaks[++newlines] = out; \
  902: 	    if (newlines >= (line_state_invisible->wbsize - 2)) \
  903: 	      { \
  904: 		line_state_invisible->wbsize *= 2; \
  905: 		line_state_invisible->wrapped_line = (int *)xrealloc (line_state_invisible->wrapped_line, line_state_invisible->wbsize * sizeof(int)); \
  906: 	      } \
  907: 	    line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn; \
  908: 	    lpos = 0; \
  909: 	  } \
  910:       } while (0)
  911: #else
  912: #define CHECK_LPOS() \
  913:       do { \
  914: 	lpos++; \
  915: 	if (lpos >= _rl_screenwidth) \
  916: 	  { \
  917: 	    if (newlines >= (inv_lbsize - 2)) \
  918: 	      { \
  919: 		inv_lbsize *= 2; \
  920: 		inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
  921: 	      } \
  922: 	    inv_lbreaks[++newlines] = out; \
  923: 	    lpos = 0; \
  924: 	  } \
  925:       } while (0)
  926: #endif
  927: 
  928:   /* inv_lbreaks[i] is where line i starts in the buffer. */
  929:   inv_lbreaks[newlines = 0] = 0;
  930:   /* lpos is a physical cursor position, so it needs to be adjusted by the
  931:      number of invisible characters in the prompt, per line.  We compute
  932:      the line breaks in the prompt string in expand_prompt, taking invisible
  933:      characters into account, and if lpos exceeds the screen width, we copy
  934:      the data in the loop below. */
  935:   lpos = prompt_physical_chars + modmark;
  936: 
  937: #if defined (HANDLE_MULTIBYTE)
  938:   memset (line_state_invisible->wrapped_line, 0, line_state_invisible->wbsize * sizeof (int));
  939:   num = 0;
  940: #endif
  941: 
  942:   /* prompt_invis_chars_first_line is the number of invisible characters (bytes)
  943:      in the first physical line of the prompt.
  944:      wrap_offset - prompt_invis_chars_first_line is usually the number of
  945:      invis chars on the second (or, more generally, last) line. */
  946: 
  947:   /* This is zero-based, used to set the newlines */
  948:   prompt_lines_estimate = lpos / _rl_screenwidth;
  949: 
  950:   /* what if lpos is already >= _rl_screenwidth before we start drawing the
  951:      contents of the command line? */
  952:   if (lpos >= _rl_screenwidth)
  953:     {
  954:       temp = 0;
  955: 
  956:       /* first copy the linebreaks array we computed in expand_prompt */
  957:       while (local_prompt_newlines[newlines+1] != -1)
  958: 	{
  959: 	  temp = local_prompt_newlines[newlines+1];
  960: 	  inv_lbreaks[++newlines] = temp;
  961: 	}  
  962: 
  963:       /* Now set lpos from the last newline */
  964:       if (mb_cur_max > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0)
  965:         lpos = _rl_col_width (local_prompt, temp, local_prompt_len, 1) - (wrap_offset - prompt_invis_chars_first_line);
  966:       else
  967:         lpos -= (_rl_screenwidth * newlines);
  968:     }
  969: 
  970:   prompt_last_screen_line = newlines;
  971: 
  972:   /* Draw the rest of the line (after the prompt) into invisible_line, keeping
  973:      track of where the cursor is (cpos_buffer_position), the number of the
  974:      line containing the cursor (lb_linenum), the last line number (lb_botlin
  975:      and inv_botlin).
  976:      It maintains an array of line breaks for display (inv_lbreaks).
  977:      This handles expanding tabs for display and displaying meta characters. */
  978:   lb_linenum = 0;
  979: #if defined (HANDLE_MULTIBYTE)
  980:   in = 0;
  981:   if (mb_cur_max > 1 && rl_byte_oriented == 0)
  982:     {
  983:       memset (&ps, 0, sizeof (mbstate_t));
  984:       if (_rl_utf8locale && UTF8_SINGLEBYTE(rl_line_buffer[0]))
  985: 	{
  986: 	  wc = (wchar_t)rl_line_buffer[0];
  987: 	  wc_bytes = 1;
  988: 	}
  989:       else
  990: 	wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps);
  991:     }
  992:   else
  993:     wc_bytes = 1;
  994:   while (in < rl_end)
  995: #else
  996:   for (in = 0; in < rl_end; in++)
  997: #endif
  998:     {
  999:       if (in == hl_begin)
 1000: 	cur_face = FACE_STANDOUT;
 1001:       else if (in == hl_end)
 1002: 	cur_face = FACE_NORMAL;
 1003: 
 1004:       c = (unsigned char)rl_line_buffer[in];
 1005: 
 1006: #if defined (HANDLE_MULTIBYTE)
 1007:       if (mb_cur_max > 1 && rl_byte_oriented == 0)
 1008: 	{
 1009: 	  if (MB_INVALIDCH (wc_bytes))
 1010: 	    {
 1011: 	      /* Byte sequence is invalid or shortened.  Assume that the
 1012: 	         first byte represents a character. */
 1013: 	      wc_bytes = 1;
 1014: 	      /* Assume that a character occupies a single column. */
 1015: 	      wc_width = 1;
 1016: 	      memset (&ps, 0, sizeof (mbstate_t));
 1017: 	    }
 1018: 	  else if (MB_NULLWCH (wc_bytes))
 1019: 	    break;			/* Found '\0' */
 1020: 	  else
 1021: 	    {
 1022: 	      temp = WCWIDTH (wc);
 1023: 	      wc_width = (temp >= 0) ? temp : 1;
 1024: 	    }
 1025: 	}
 1026: #endif
 1027: 
 1028:       if (in == rl_point)
 1029: 	{
 1030: 	  cpos_buffer_position = out;
 1031: 	  lb_linenum = newlines;
 1032: 	}
 1033: 
 1034: #if defined (HANDLE_MULTIBYTE)
 1035:       if (META_CHAR (c) && _rl_output_meta_chars == 0)	/* XXX - clean up */
 1036: #else
 1037:       if (META_CHAR (c))
 1038: #endif
 1039: 	{
 1040: 	  if (_rl_output_meta_chars == 0)
 1041: 	    {
 1042: 	      char obuf[5];
 1043: 	      int olen;
 1044: 
 1045: 	      olen = sprintf (obuf, "\\%o", c);
 1046: 	  
 1047: 	      if (lpos + olen >= _rl_screenwidth)
 1048: 		{
 1049: 		  temp = _rl_screenwidth - lpos;
 1050: 		  CHECK_INV_LBREAKS ();
 1051: 		  inv_lbreaks[++newlines] = out + temp;
 1052: #if defined (HANDLE_MULTIBYTE)
 1053: 		  line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn;
 1054: #endif
 1055: 		  lpos = olen - temp;
 1056: 		}
 1057: 	      else
 1058: 		lpos += olen;
 1059: 
 1060: 	      for (temp = 0; temp < olen; temp++)
 1061: 		{
 1062: 		  invis_addc (&out, obuf[temp], cur_face);
 1063: 		  CHECK_LPOS ();
 1064: 		}
 1065: 	    }
 1066: 	  else
 1067: 	    {
 1068: 	      invis_addc (&out, c, cur_face);
 1069: 	      CHECK_LPOS();
 1070: 	    }
 1071: 	}
 1072: #if defined (DISPLAY_TABS)
 1073:       else if (c == '\t')
 1074: 	{
 1075: 	  register int newout;
 1076: 
 1077: 	  newout = out + 8 - lpos % 8;
 1078: 	  temp = newout - out;
 1079: 	  if (lpos + temp >= _rl_screenwidth)
 1080: 	    {
 1081: 	      register int temp2;
 1082: 	      temp2 = _rl_screenwidth - lpos;
 1083: 	      CHECK_INV_LBREAKS ();
 1084: 	      inv_lbreaks[++newlines] = out + temp2;
 1085: #if defined (HANDLE_MULTIBYTE)
 1086: 	      line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn;
 1087: #endif
 1088: 	      lpos = temp - temp2;
 1089: 	      while (out < newout)
 1090: 		invis_addc (&out, ' ', cur_face);
 1091: 	    }
 1092: 	  else
 1093: 	    {
 1094: 	      while (out < newout)
 1095: 		invis_addc (&out, ' ', cur_face);
 1096: 	      lpos += temp;
 1097: 	    }
 1098: 	}
 1099: #endif
 1100:       else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
 1101: 	{
 1102: 	  invis_addc (&out, '\0', cur_face);
 1103: 	  CHECK_INV_LBREAKS ();
 1104: 	  inv_lbreaks[++newlines] = out;
 1105: #if defined (HANDLE_MULTIBYTE)
 1106: 	  line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn;
 1107: #endif
 1108: 	  lpos = 0;
 1109: 	}
 1110:       else if (CTRL_CHAR (c) || c == RUBOUT)
 1111: 	{
 1112: 	  invis_addc (&out, '^', cur_face);
 1113: 	  CHECK_LPOS();
 1114: 	  invis_addc (&out, CTRL_CHAR (c) ? UNCTRL (c) : '?', cur_face);
 1115: 	  CHECK_LPOS();
 1116: 	}
 1117:       else
 1118: 	{
 1119: #if defined (HANDLE_MULTIBYTE)
 1120: 	  if (mb_cur_max > 1 && rl_byte_oriented == 0)
 1121: 	    {
 1122: 	      register int i;
 1123: 
 1124: 	      _rl_wrapped_multicolumn = 0;
 1125: 
 1126: 	      if (_rl_screenwidth < lpos + wc_width)
 1127: 		for (i = lpos; i < _rl_screenwidth; i++)
 1128: 		  {
 1129: 		    /* The space will be removed in update_line() */
 1130: 		    invis_addc (&out, ' ', cur_face);
 1131: 		    _rl_wrapped_multicolumn++;
 1132: 		    CHECK_LPOS();
 1133: 		  }
 1134: 	      if (in == rl_point)
 1135: 		{
 1136: 		  cpos_buffer_position = out;
 1137: 		  lb_linenum = newlines;
 1138: 		}
 1139: 	      for (i = in; i < in+wc_bytes; i++)
 1140: 		invis_addc (&out, rl_line_buffer[i], cur_face);
 1141: 	      for (i = 0; i < wc_width; i++)
 1142: 		CHECK_LPOS();
 1143: 	    }
 1144: 	  else
 1145: 	    {
 1146: 	      invis_addc (&out, c, cur_face);
 1147: 	      CHECK_LPOS();
 1148: 	    }
 1149: #else
 1150: 	  invis_addc (&out, c, cur_face);
 1151: 	  CHECK_LPOS();
 1152: #endif
 1153: 	}
 1154: 
 1155: #if defined (HANDLE_MULTIBYTE)
 1156:       if (mb_cur_max > 1 && rl_byte_oriented == 0)
 1157: 	{
 1158: 	  in += wc_bytes;
 1159: 	  if (_rl_utf8locale && UTF8_SINGLEBYTE(rl_line_buffer[in]))
 1160: 	    {
 1161: 	      wc = (wchar_t)rl_line_buffer[in];
 1162: 	      wc_bytes = 1;
 1163: 	      memset (&ps, 0, sizeof (mbstate_t));	/* re-init state */
 1164: 	    }
 1165: 	  else
 1166: 	    wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps);
 1167: 	}
 1168:       else
 1169:         in++;
 1170: #endif
 1171:     }
 1172:   invis_nul (&out);
 1173:   line_totbytes = out;
 1174:   if (cpos_buffer_position < 0)
 1175:     {
 1176:       cpos_buffer_position = out;
 1177:       lb_linenum = newlines;
 1178:     }
 1179: 
 1180:   /* If we are switching from one line to multiple wrapped lines, we don't
 1181:      want to do a dumb update (or we want to make it smarter). */
 1182:   if (_rl_quick_redisplay && newlines > 0)
 1183:     _rl_quick_redisplay = 0;
 1184: 
 1185:   inv_botlin = lb_botlin = _rl_inv_botlin = newlines;
 1186:   CHECK_INV_LBREAKS ();
 1187:   inv_lbreaks[newlines+1] = out;
 1188: #if defined (HANDLE_MULTIBYTE)
 1189:   /* This should be 0 anyway */
 1190:   line_state_invisible->wrapped_line[newlines+1] = _rl_wrapped_multicolumn;
 1191: #endif
 1192:   cursor_linenum = lb_linenum;
 1193: 
 1194:   /* CPOS_BUFFER_POSITION == position in buffer where cursor should be placed.
 1195:      CURSOR_LINENUM == line number where the cursor should be placed. */
 1196: 
 1197:   /* PWP: now is when things get a bit hairy.  The visible and invisible
 1198:      line buffers are really multiple lines, which would wrap every
 1199:      (screenwidth - 1) characters.  Go through each in turn, finding
 1200:      the changed region and updating it.  The line order is top to bottom. */
 1201: 
 1202:   /* If we can move the cursor up and down, then use multiple lines,
 1203:      otherwise, let long lines display in a single terminal line, and
 1204:      horizontally scroll it. */
 1205:   displaying_prompt_first_line = 1;
 1206:   if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
 1207:     {
 1208:       int nleft, pos, changed_screen_line, tx;
 1209: 
 1210:       if (!rl_display_fixed || forced_display)
 1211: 	{
 1212: 	  forced_display = 0;
 1213: 
 1214: 	  /* If we have more than a screenful of material to display, then
 1215: 	     only display a screenful.  We should display the last screen,
 1216: 	     not the first.  */
 1217: 	  if (out >= _rl_screenchars)
 1218: 	    {
 1219: #if defined (HANDLE_MULTIBYTE)
 1220: 	      if (mb_cur_max > 1 && rl_byte_oriented == 0)
 1221: 		out = _rl_find_prev_mbchar (invisible_line, _rl_screenchars, MB_FIND_ANY);
 1222: 	      else
 1223: #endif
 1224: 		out = _rl_screenchars - 1;
 1225: 	    }
 1226: 
 1227: 	  /* The first line is at character position 0 in the buffer.  The
 1228: 	     second and subsequent lines start at inv_lbreaks[N], offset by
 1229: 	     OFFSET (which has already been calculated above).  */
 1230: 
 1231: #define INVIS_FIRST()	(prompt_physical_chars > _rl_screenwidth ? prompt_invis_chars_first_line : wrap_offset)
 1232: #define WRAP_OFFSET(line, offset)  ((line == 0) \
 1233: 					? (offset ? INVIS_FIRST() : 0) \
 1234: 					: ((line == prompt_last_screen_line) ? wrap_offset-prompt_invis_chars_first_line : 0))
 1235: #define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
 1236: #define VIS_LLEN(l)	((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
 1237: #define INV_LLEN(l)	(inv_lbreaks[l+1] - inv_lbreaks[l])
 1238: #define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
 1239: #define VIS_FACE(line) (vis_face + vis_lbreaks[line])
 1240: #define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
 1241: #define VIS_LINE_FACE(line) ((line) > _rl_vis_botlin) ? "" : VIS_FACE(line)
 1242: #define INV_LINE(line) (invisible_line + inv_lbreaks[line])
 1243: #define INV_LINE_FACE(line) (inv_face + inv_lbreaks[line])
 1244: 
 1245: #define OLD_CPOS_IN_PROMPT() (cpos_adjusted == 0 && \
 1246: 			_rl_last_c_pos != o_cpos && \
 1247: 			_rl_last_c_pos > wrap_offset && \
 1248: 			o_cpos < prompt_last_invisible)
 1249: 
 1250: 
 1251: 	  /* We don't want to highlight anything that's going to be off the top
 1252: 	     of the display; if the current line takes up more than an entire
 1253: 	    screen, just mark the lines that won't be displayed as having a
 1254: 	    `normal' face.
 1255: 	    It's imperfect, but better than display corruption. */
 1256: 	  if (rl_mark_active_p () && inv_botlin > _rl_screenheight)
 1257: 	    {
 1258: 	      int extra;
 1259: 
 1260: 	      extra = inv_botlin - _rl_screenheight;
 1261: 	      for (linenum = 0; linenum <= extra; linenum++)
 1262: 		norm_face (INV_LINE_FACE(linenum), INV_LLEN (linenum));
 1263: 	    }
 1264: 
 1265: 	  /* For each line in the buffer, do the updating display. */
 1266: 	  for (linenum = 0; linenum <= inv_botlin; linenum++)
 1267: 	    {
 1268: 	      /* This can lead us astray if we execute a program that changes
 1269: 		 the locale from a non-multibyte to a multibyte one. */
 1270: 	      o_cpos = _rl_last_c_pos;
 1271: 	      cpos_adjusted = 0;
 1272: 	      update_line (VIS_LINE(linenum), VIS_LINE_FACE(linenum),
 1273: 			   INV_LINE(linenum), INV_LINE_FACE(linenum),
 1274: 			   linenum,
 1275: 			   VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin);
 1276: 
 1277: 	      /* update_line potentially changes _rl_last_c_pos, but doesn't
 1278: 		 take invisible characters into account, since _rl_last_c_pos
 1279: 		 is an absolute cursor position in a multibyte locale.  We
 1280: 		 choose to (mostly) compensate for that here, rather than
 1281: 		 change update_line itself.  There are several cases in which
 1282: 		 update_line adjusts _rl_last_c_pos itself (so it can pass
 1283: 		 _rl_move_cursor_relative accurate values); it communicates
 1284: 		 this back by setting cpos_adjusted.  If we assume that
 1285: 		 _rl_last_c_pos is correct (an absolute cursor position) each
 1286: 		 time update_line is called, then we can assume in our
 1287: 		 calculations that o_cpos does not need to be adjusted by
 1288: 		 wrap_offset. */
 1289: 	      if (linenum == 0 && (mb_cur_max > 1 && rl_byte_oriented == 0) && OLD_CPOS_IN_PROMPT())
 1290: 		_rl_last_c_pos -= prompt_invis_chars_first_line;	/* XXX - was wrap_offset */
 1291: 	      else if (cpos_adjusted == 0 &&
 1292: 			linenum == prompt_last_screen_line &&
 1293: 			prompt_physical_chars > _rl_screenwidth &&
 1294: 			(mb_cur_max > 1 && rl_byte_oriented == 0) &&
 1295: 			_rl_last_c_pos != o_cpos &&
 1296: 			_rl_last_c_pos > (prompt_last_invisible - _rl_screenwidth - prompt_invis_chars_first_line))	/* XXX - rethink this last one */
 1297: 		/* This assumes that all the invisible characters are split
 1298: 		   between the first and last lines of the prompt, if the 
 1299: 		   prompt consumes more than two lines. It's usually right */
 1300: 		/* XXX - not sure this is ever executed */
 1301: 		_rl_last_c_pos -= (wrap_offset-prompt_invis_chars_first_line);
 1302: 
 1303: 	      /* If this is the line with the prompt, we might need to
 1304: 		 compensate for invisible characters in the new line. Do
 1305: 		 this only if there is not more than one new line (which
 1306: 		 implies that we completely overwrite the old visible line)
 1307: 		 and the new line is shorter than the old.  Make sure we are
 1308: 		 at the end of the new line before clearing. */
 1309: 	      if (linenum == 0 &&
 1310: 		  inv_botlin == 0 && _rl_last_c_pos == out &&
 1311: 		  (wrap_offset > visible_wrap_offset) &&
 1312: 		  (_rl_last_c_pos < visible_first_line_len))
 1313: 		{
 1314: 		  if (mb_cur_max > 1 && rl_byte_oriented == 0)
 1315: 		    nleft = _rl_screenwidth - _rl_last_c_pos;
 1316: 		  else
 1317: 		    nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos;
 1318: 		  if (nleft)
 1319: 		    _rl_clear_to_eol (nleft);
 1320: 		}
 1321: #if 0
 1322: 	      /* This segment is intended to handle the case where the old
 1323: 		 visible prompt has invisible characters and the new line
 1324: 		 to be displayed needs to clear the rest of the old characters
 1325: 		 out (e.g., when printing the i-search prompt): in general,
 1326: 		 the case of the new line being shorter than the old.  We need
 1327: 		 to be at the end of the new line and the old line needs to be
 1328: 		 longer than the current cursor position. It's not perfect,
 1329: 		 since it uses the byte length of the first line, but this will
 1330: 		 at worst result in some extra clear-to-end-of-lines. We can't
 1331: 		 use the prompt length variables because they may not
 1332: 		 correspond to the visible line (see printing the i-search
 1333: 		 prompt above). The tests for differing numbers of invisible
 1334: 		 characters may not matter and can probably be removed. */
 1335: 	      else if (linenum == 0 &&
 1336: 		       linenum == prompt_last_screen_line &&
 1337: 		       _rl_last_c_pos == out &&
 1338: 		       _rl_last_c_pos < visible_first_line_len &&
 1339: 		       visible_wrap_offset &&
 1340: 		       visible_wrap_offset != wrap_offset)
 1341: 		{
 1342: 		  if (mb_cur_max > 1 && rl_byte_oriented == 0)
 1343: 		    nleft = _rl_screenwidth - _rl_last_c_pos;
 1344: 		  else
 1345: 		    nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos;
 1346: 		  if (nleft)
 1347: 		    _rl_clear_to_eol (nleft);
 1348: 		}
 1349: #endif
 1350: 
 1351: 	      /* Since the new first line is now visible, save its length. */
 1352: 	      if (linenum == 0)
 1353: 		visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset;
 1354: 	    }
 1355: 
 1356: 	  /* We may have deleted some lines.  If so, clear the left over
 1357: 	     blank ones at the bottom out. */
 1358: 	  if (_rl_vis_botlin > inv_botlin)
 1359: 	    {
 1360: 	      char *tt;
 1361: 	      for (; linenum <= _rl_vis_botlin; linenum++)
 1362: 		{
 1363: 		  tt = VIS_CHARS (linenum);
 1364: 		  _rl_move_vert (linenum);
 1365: 		  _rl_move_cursor_relative (0, tt, VIS_FACE(linenum));
 1366: 		  _rl_clear_to_eol
 1367: 		    ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth);
 1368: 		}
 1369: 	    }
 1370: 	  _rl_vis_botlin = inv_botlin;
 1371: 
 1372: 	  /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
 1373: 	     different screen line during this redisplay. */
 1374: 	  changed_screen_line = _rl_last_v_pos != cursor_linenum;
 1375: 	  if (changed_screen_line)
 1376: 	    {
 1377: 	      _rl_move_vert (cursor_linenum);
 1378: 	      /* If we moved up to the line with the prompt using _rl_term_up,
 1379: 		 the physical cursor position on the screen stays the same,
 1380: 		 but the buffer position needs to be adjusted to account
 1381: 		 for invisible characters. */
 1382: 	      if ((mb_cur_max == 1 || rl_byte_oriented) && cursor_linenum == 0 && wrap_offset)
 1383: 		_rl_last_c_pos += wrap_offset;
 1384: 	    }
 1385: 
 1386: 	  /* Now we move the cursor to where it needs to be.  First, make
 1387: 	     sure we are on the correct line (cursor_linenum). */
 1388: 
 1389: 	  /* We have to reprint the prompt if it contains invisible
 1390: 	     characters, since it's not generally OK to just reprint
 1391: 	     the characters from the current cursor position.  But we
 1392: 	     only need to reprint it if the cursor is before the last
 1393: 	     invisible character in the prompt string. */
 1394: 	  /* XXX - why not use local_prompt_len? */
 1395: 	  nleft = prompt_visible_length + wrap_offset;
 1396: 	  if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
 1397: 	      _rl_last_c_pos < PROMPT_ENDING_INDEX && local_prompt)
 1398: 	    {
 1399: 	      _rl_cr ();
 1400: 	      if (modmark)
 1401: 		_rl_output_some_chars ("*", 1);
 1402: 
 1403: 	      _rl_output_some_chars (local_prompt, nleft);
 1404: 	      if (mb_cur_max > 1 && rl_byte_oriented == 0)
 1405: 		_rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft, 1) - wrap_offset + modmark;
 1406: 	      else
 1407: 		_rl_last_c_pos = nleft + modmark;
 1408: 	    }
 1409: 
 1410: 	  /* Where on that line?  And where does that line start
 1411: 	     in the buffer? */
 1412: 	  pos = inv_lbreaks[cursor_linenum];
 1413: 	  /* nleft == number of characters (bytes) in the line buffer between
 1414: 	     the start of the line and the desired cursor position. */
 1415: 	  nleft = cpos_buffer_position - pos;
 1416: 
 1417: 	  /* NLEFT is now a number of characters in a buffer.  When in a
 1418: 	     multibyte locale, however, _rl_last_c_pos is an absolute cursor
 1419: 	     position that doesn't take invisible characters in the prompt
 1420: 	     into account.  We use a fudge factor to compensate. */
 1421: 
 1422: 	  /* Since _rl_backspace() doesn't know about invisible characters in
 1423: 	     the prompt, and there's no good way to tell it, we compensate for
 1424: 	     those characters here and call _rl_backspace() directly if
 1425: 	     necessary */
 1426: 	  if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
 1427: 	    {
 1428: 	      /* TX == new physical cursor position in multibyte locale. */
 1429: 	      if (mb_cur_max > 1 && rl_byte_oriented == 0)
 1430: 		tx = _rl_col_width (&visible_line[pos], 0, nleft, 1) - visible_wrap_offset;
 1431: 	      else
 1432: 		tx = nleft;
 1433: 	      if (tx >= 0 && _rl_last_c_pos > tx)
 1434: 		{
 1435: 	          _rl_backspace (_rl_last_c_pos - tx);	/* XXX */
 1436: 	          _rl_last_c_pos = tx;
 1437: 		}
 1438: 	    }
 1439: 
 1440: 	  /* We need to note that in a multibyte locale we are dealing with
 1441: 	     _rl_last_c_pos as an absolute cursor position, but moving to a
 1442: 	     point specified by a buffer position (NLEFT) that doesn't take
 1443: 	     invisible characters into account. */
 1444: 	  if (mb_cur_max > 1 && rl_byte_oriented == 0)
 1445: 	    _rl_move_cursor_relative (nleft, &invisible_line[pos], &inv_face[pos]);
 1446: 	  else if (nleft != _rl_last_c_pos)
 1447: 	    _rl_move_cursor_relative (nleft, &invisible_line[pos], &inv_face[pos]);
 1448: 	}
 1449:     }
 1450:   else				/* Do horizontal scrolling. Much simpler */
 1451:     {
 1452: #define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
 1453:       int lmargin, ndisp, nleft, phys_c_pos, t;
 1454: 
 1455:       /* Always at top line. */
 1456:       _rl_last_v_pos = 0;
 1457: 
 1458:       /* Compute where in the buffer the displayed line should start.  This
 1459: 	 will be LMARGIN. */
 1460: 
 1461:       /* The number of characters that will be displayed before the cursor. */
 1462:       ndisp = cpos_buffer_position - wrap_offset;
 1463:       nleft  = prompt_visible_length + wrap_offset;
 1464:       /* Where the new cursor position will be on the screen.  This can be
 1465: 	 longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
 1466:       phys_c_pos = cpos_buffer_position - (last_lmargin ? last_lmargin : wrap_offset);
 1467:       t = _rl_screenwidth / 3;
 1468: 
 1469:       /* If the number of characters had already exceeded the screenwidth,
 1470: 	 last_lmargin will be > 0. */
 1471: 
 1472:       /* If the number of characters to be displayed is more than the screen
 1473: 	 width, compute the starting offset so that the cursor is about
 1474: 	 two-thirds of the way across the screen. */
 1475:       if (phys_c_pos > _rl_screenwidth - 2)
 1476: 	{
 1477: 	  lmargin = cpos_buffer_position - (2 * t);
 1478: 	  if (lmargin < 0)
 1479: 	    lmargin = 0;
 1480: 	  /* If the left margin would be in the middle of a prompt with
 1481: 	     invisible characters, don't display the prompt at all. */
 1482: 	  if (wrap_offset && lmargin > 0 && lmargin < nleft)
 1483: 	    lmargin = nleft;
 1484: 	}
 1485:       else if (ndisp < _rl_screenwidth - 2)		/* XXX - was -1 */
 1486: 	lmargin = 0;
 1487:       else if (phys_c_pos < 1)
 1488: 	{
 1489: 	  /* If we are moving back towards the beginning of the line and
 1490: 	     the last margin is no longer correct, compute a new one. */
 1491: 	  lmargin = ((cpos_buffer_position - 1) / t) * t;	/* XXX */
 1492: 	  if (wrap_offset && lmargin > 0 && lmargin < nleft)
 1493: 	    lmargin = nleft;
 1494: 	}
 1495:       else
 1496: 	lmargin = last_lmargin;
 1497: 
 1498:       displaying_prompt_first_line = lmargin < nleft;
 1499: 
 1500:       /* If the first character on the screen isn't the first character
 1501: 	 in the display line, indicate this with a special character. */
 1502:       if (lmargin > 0)
 1503: 	invisible_line[lmargin] = '<';
 1504: 
 1505:       /* If SCREENWIDTH characters starting at LMARGIN do not encompass
 1506: 	 the whole line, indicate that with a special character at the
 1507: 	 right edge of the screen.  If LMARGIN is 0, we need to take the
 1508: 	 wrap offset into account. */
 1509:       t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth;
 1510:       if (t > 0 && t < out)
 1511: 	invisible_line[t - 1] = '>';
 1512: 
 1513:       if (rl_display_fixed == 0 || forced_display || lmargin != last_lmargin)
 1514: 	{
 1515: 	  forced_display = 0;
 1516: 	  o_cpos = _rl_last_c_pos;
 1517: 	  cpos_adjusted = 0;
 1518: 	  update_line (&visible_line[last_lmargin], &vis_face[last_lmargin],
 1519: 		       &invisible_line[lmargin], &inv_face[lmargin],
 1520: 		       0,
 1521: 		       _rl_screenwidth + visible_wrap_offset,
 1522: 		       _rl_screenwidth + (lmargin ? 0 : wrap_offset),
 1523: 		       0);
 1524: 
 1525: 	  if ((mb_cur_max > 1 && rl_byte_oriented == 0) &&
 1526: 		displaying_prompt_first_line && OLD_CPOS_IN_PROMPT())
 1527: 	    _rl_last_c_pos -= prompt_invis_chars_first_line;	/* XXX - was wrap_offset */
 1528: 
 1529: 	  /* If the visible new line is shorter than the old, but the number
 1530: 	     of invisible characters is greater, and we are at the end of
 1531: 	     the new line, we need to clear to eol. */
 1532: 	  t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
 1533: 	  if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
 1534: 	      (_rl_last_c_pos == out) && displaying_prompt_first_line &&
 1535: 	      t < visible_first_line_len)
 1536: 	    {
 1537: 	      nleft = _rl_screenwidth - t;
 1538: 	      _rl_clear_to_eol (nleft);
 1539: 	    }
 1540: 	  visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
 1541: 	  if (visible_first_line_len > _rl_screenwidth)
 1542: 	    visible_first_line_len = _rl_screenwidth;
 1543: 
 1544: 	  _rl_move_cursor_relative (cpos_buffer_position - lmargin, &invisible_line[lmargin], &inv_face[lmargin]);
 1545: 	  last_lmargin = lmargin;
 1546: 	}
 1547:     }
 1548:   fflush (rl_outstream);
 1549: 
 1550:   /* Swap visible and non-visible lines. */
 1551:   {
 1552:     struct line_state *vtemp = line_state_visible;
 1553: 
 1554:     line_state_visible = line_state_invisible;
 1555:     line_state_invisible = vtemp;
 1556: 
 1557:     rl_display_fixed = 0;
 1558:     /* If we are displaying on a single line, and last_lmargin is > 0, we
 1559:        are not displaying any invisible characters, so set visible_wrap_offset
 1560:        to 0. */
 1561:     if (_rl_horizontal_scroll_mode && last_lmargin)
 1562:       visible_wrap_offset = 0;
 1563:     else
 1564:       visible_wrap_offset = wrap_offset;
 1565: 
 1566:     _rl_quick_redisplay = 0;
 1567:   }
 1568: 
 1569:   RL_UNSETSTATE (RL_STATE_REDISPLAYING);
 1570:   _rl_release_sigint ();
 1571: }
 1572: 
 1573: static void
 1574: putc_face (int c, int face, char *cur_face)
 1575: {
 1576:   char cf;
 1577:   cf = *cur_face;
 1578:   if (cf != face)
 1579:     {
 1580:       if (cf != FACE_NORMAL && cf != FACE_STANDOUT)
 1581: 	return;
 1582:       if (face != FACE_NORMAL && face != FACE_STANDOUT)
 1583: 	return;
 1584:       if (face == FACE_STANDOUT && cf == FACE_NORMAL)
 1585:         _rl_standout_on ();
 1586:       if (face == FACE_NORMAL && cf == FACE_STANDOUT)
 1587:         _rl_standout_off ();
 1588:       *cur_face = face;
 1589:     }
 1590:   if (c != EOF)
 1591:     putc (c, rl_outstream);
 1592: }
 1593: 
 1594: static void
 1595: puts_face (const char *str, const char *face, int n)
 1596: {
 1597:   int i;
 1598:   char cur_face;
 1599: 
 1600:   for (cur_face = FACE_NORMAL, i = 0; i < n; i++)
 1601:     putc_face (str[i], face[i], &cur_face);
 1602:   putc_face (EOF, FACE_NORMAL, &cur_face);
 1603: }
 1604: 
 1605: static void
 1606: norm_face (char *face, int n)
 1607: {
 1608:   memset (face, FACE_NORMAL, n);
 1609: }
 1610: 
 1611: #define ADJUST_CPOS(x) do { _rl_last_c_pos -= (x) ; cpos_adjusted = 1; } while (0)
 1612: 
 1613: /* PWP: update_line() is based on finding the middle difference of each
 1614:    line on the screen; vis:
 1615: 
 1616: 			     /old first difference
 1617: 	/beginning of line   |              /old last same       /old EOL
 1618: 	v 		     v              v                    v
 1619: old:	eddie> Oh, my little gruntle-buggy is to me, as lurgid as
 1620: new:	eddie> Oh, my little buggy says to me, as lurgid as
 1621: 	^		     ^        ^			   ^
 1622: 	\beginning of line   |	      \new last same	   \new end of line
 1623: 			     \new first difference
 1624: 
 1625:    All are character pointers for the sake of speed.  Special cases for
 1626:    no differences, as well as for end of line additions must be handled.
 1627: 
 1628:    Could be made even smarter, but this works well enough */
 1629: static void
 1630: update_line (char *old, char *old_face, char *new, char *new_face, int current_line, int omax, int nmax, int inv_botlin)
 1631: {
 1632:   char *ofd, *ols, *oe, *nfd, *nls, *ne;
 1633:   char *ofdf, *nfdf, *olsf, *nlsf;
 1634:   int temp, lendiff, wsatend, od, nd, twidth, o_cpos;
 1635:   int current_invis_chars;
 1636:   int col_lendiff, col_temp;
 1637:   int bytes_to_insert;
 1638:   int mb_cur_max = MB_CUR_MAX;
 1639: #if defined (HANDLE_MULTIBYTE)
 1640:   mbstate_t ps_new, ps_old;
 1641:   int new_offset, old_offset;
 1642: #endif
 1643: 
 1644:   /* If we're at the right edge of a terminal that supports xn, we're
 1645:      ready to wrap around, so do so.  This fixes problems with knowing
 1646:      the exact cursor position and cut-and-paste with certain terminal
 1647:      emulators.  In this calculation, TEMP is the physical screen
 1648:      position of the cursor. */
 1649:   if (mb_cur_max > 1 && rl_byte_oriented == 0)
 1650:     temp = _rl_last_c_pos;
 1651:   else
 1652:     temp = _rl_last_c_pos - WRAP_OFFSET (_rl_last_v_pos, visible_wrap_offset);
 1653:   if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
 1654: 	&& _rl_last_v_pos == current_line - 1)
 1655:     {
 1656:       /* We're going to wrap around by writing the first character of NEW to
 1657: 	 the screen and dealing with changes to what's visible by modifying
 1658: 	 OLD to match it.  Complicated by the presence of multi-width
 1659: 	 characters at the end of the line or beginning of the new one. */
 1660:       /* old is always somewhere in visible_line; new is always somewhere in
 1661:          invisible_line.  These should always be null-terminated. */
 1662: #if defined (HANDLE_MULTIBYTE)
 1663:       if (mb_cur_max > 1 && rl_byte_oriented == 0)
 1664: 	{
 1665: 	  wchar_t wc;
 1666: 	  mbstate_t ps;
 1667: 	  int oldwidth, newwidth;
 1668: 	  int oldbytes, newbytes;
 1669: 	  size_t ret;
 1670: 
 1671: 	  /* This fixes only double-column characters, but if the wrapped
 1672: 	     character consumes more than three columns, spaces will be
 1673: 	     inserted in the string buffer. */
 1674: 	  /* XXX remember that we are working on the invisible line right now;
 1675: 	     we don't swap visible and invisible until just before rl_redisplay
 1676: 	     returns */
 1677: 	  /* This will remove the extra placeholder space we added with
 1678: 	     _rl_wrapped_multicolumn */
 1679: 	  if (current_line < line_state_invisible->wbsize && line_state_invisible->wrapped_line[current_line] > 0)
 1680: 	    _rl_clear_to_eol (line_state_invisible->wrapped_line[current_line]);
 1681: 
 1682: 	  /* 1. how many screen positions does first char in old consume? */
 1683: 	  memset (&ps, 0, sizeof (mbstate_t));
 1684: 	  ret = mbrtowc (&wc, old, mb_cur_max, &ps);
 1685: 	  oldbytes = ret;
 1686: 	  if (MB_INVALIDCH (ret))
 1687: 	    {
 1688: 	      oldwidth = 1;
 1689: 	      oldbytes = 1;
 1690: 	    }
 1691: 	  else if (MB_NULLWCH (ret))
 1692: 	    oldwidth = 0;
 1693: 	  else
 1694: 	    oldwidth = WCWIDTH (wc);
 1695: 	  if (oldwidth < 0)
 1696: 	    oldwidth = 1;
 1697: 
 1698: 	  /* 2. how many screen positions does the first char in new consume? */
 1699: 	  memset (&ps, 0, sizeof (mbstate_t));
 1700: 	  ret = mbrtowc (&wc, new, mb_cur_max, &ps);
 1701: 	  newbytes = ret;
 1702: 	  if (MB_INVALIDCH (ret))
 1703: 	    {
 1704: 	      newwidth = 1;
 1705: 	      newbytes = 1;
 1706: 	    }
 1707: 	  else if (MB_NULLWCH (ret))
 1708: 	    newwidth = 0;
 1709: 	  else
 1710: 	    newwidth = WCWIDTH (wc);
 1711: 	  if (newwidth < 0)
 1712: 	    newwidth = 1;
 1713: 
 1714: 	  /* 3. if the new width is less than the old width, we need to keep
 1715: 	     going in new until we have consumed at least that many screen
 1716: 	     positions, and figure out how many bytes that will take */
 1717: 	  while (newbytes < nmax && newwidth < oldwidth)
 1718: 	    {
 1719: 	      int t;
 1720: 
 1721: 	      ret = mbrtowc (&wc, new+newbytes, mb_cur_max, &ps);
 1722: 	      if (MB_INVALIDCH (ret))
 1723: 		{
 1724: 		  newwidth += 1;
 1725: 		  newbytes += 1;
 1726: 		}
 1727: 	      else if (MB_NULLWCH (ret))
 1728: 	        break;
 1729: 	      else
 1730: 		{
 1731: 		  t = WCWIDTH (wc);
 1732: 		  newwidth += (t >= 0) ? t : 1;
 1733: 		  newbytes += ret;
 1734: 		}
 1735: 	    }
 1736: 	  /* 4. If the new width is more than the old width, keep going in old
 1737: 	     until we have consumed exactly that many screen positions, and
 1738: 	     figure out how many bytes that will take.  This is an optimization */
 1739: 	  while (oldbytes < omax && oldwidth < newwidth)
 1740: 	    {
 1741: 	      int t;
 1742: 
 1743: 	      ret = mbrtowc (&wc, old+oldbytes, mb_cur_max, &ps);
 1744: 	      if (MB_INVALIDCH (ret))
 1745: 		{
 1746: 		  oldwidth += 1;
 1747: 		  oldbytes += 1;
 1748: 		}
 1749: 	      else if (MB_NULLWCH (ret))
 1750: 	        break;
 1751: 	      else
 1752: 		{
 1753: 		  t = WCWIDTH (wc);
 1754: 		  oldwidth += (t >= 0) ? t : 1;
 1755: 		  oldbytes += ret;
 1756: 		}
 1757: 	    }
 1758: 	  /* 5. write the first newbytes of new, which takes newwidth.  This is
 1759: 	     where the screen wrapping takes place, and we are now writing
 1760: 	     characters onto the new line. We need to fix up old so it
 1761: 	     accurately reflects what is on the screen after the
 1762: 	     _rl_output_some_chars below. */
 1763: 	  if (newwidth > 0)
 1764: 	    {
 1765: 	      int count, i, j;
 1766: 	      char *optr;
 1767: 
 1768: 	      puts_face (new, new_face, newbytes);
 1769: 	      _rl_last_c_pos = newwidth;
 1770: 	      _rl_last_v_pos++;
 1771: 
 1772: 	      /* 5a. If the number of screen positions doesn't match, punt
 1773: 		 and do a dumb update.
 1774: 		 5b. If the number of bytes is greater in the new line than
 1775: 		 the old, do a dumb update, because there is no guarantee we
 1776: 		 can extend the old line enough to fit the new bytes. */
 1777: 	      if (newwidth != oldwidth || newbytes > oldbytes)
 1778: 		{
 1779: 		  oe = old + omax;
 1780: 		  ne = new + nmax;
 1781: 		  nd = newbytes;
 1782: 		  nfd = new + nd;
 1783: 		  ofdf = old_face + oldbytes;
 1784: 		  nfdf = new_face + newbytes;
 1785: 
 1786: 		  goto dumb_update;
 1787: 		}
 1788: 	      if (oldbytes != 0 && newbytes != 0)
 1789: 		{
 1790: 		  /* We have written as many bytes from new as we need to
 1791: 		     consume the first character of old. Fix up `old' so it
 1792: 		     reflects the new screen contents.  We use +1 in the
 1793: 		     memmove call to copy the trailing NUL. */
 1794: 		  /* (strlen(old+oldbytes) == (omax - oldbytes - 1)) */
 1795: 
 1796: 		  /* Don't bother trying to fit the bytes if the number of bytes
 1797: 		     doesn't change. */
 1798: 		  if (oldbytes != newbytes)
 1799: 		    {
 1800: 		      memmove (old+newbytes, old+oldbytes, strlen (old+oldbytes) + 1);
 1801: 		      memmove (old_face+newbytes, old_face+oldbytes, strlen (old+oldbytes) + 1);
 1802: 		    }
 1803: 		  memcpy (old, new, newbytes);
 1804: 		  memcpy (old_face, new_face, newbytes);
 1805: 		  j = newbytes - oldbytes;
 1806: 		  omax += j;
 1807: 		  /* Fix up indices if we copy data from one line to another */
 1808: 		  for (i = current_line+1; j != 0 && i <= inv_botlin+1 && i <=_rl_vis_botlin+1; i++)
 1809: 		    vis_lbreaks[i] += j;
 1810: 		}
 1811: 	    }
 1812: 	  else
 1813: 	    {
 1814: 	      putc (' ', rl_outstream);
 1815: 	      _rl_last_c_pos = 1;
 1816: 	      _rl_last_v_pos++;
 1817: 	      if (old[0] && new[0])
 1818: 		{
 1819: 		  old[0] = new[0];
 1820: 		  old_face[0] = new_face[0];
 1821: 		}
 1822: 	    }
 1823: 	}
 1824:       else
 1825: #endif
 1826: 	{
 1827: 	  if (new[0])
 1828: 	    puts_face (new, new_face, 1);
 1829: 	  else
 1830: 	    putc (' ', rl_outstream);
 1831: 	  _rl_last_c_pos = 1;
 1832: 	  _rl_last_v_pos++;
 1833: 	  if (old[0] && new[0])
 1834: 	    {
 1835: 	      old[0] = new[0];
 1836: 	      old_face[0] = new_face[0];
 1837: 	    }
 1838: 	}
 1839:     }
 1840: 
 1841:   /* We know that we are dealing with a single screen line here */
 1842:   if (_rl_quick_redisplay)
 1843:     {
 1844:       nfd = new;
 1845:       nfdf = new_face;
 1846:       ofd = old;
 1847:       ofdf = old_face;
 1848:       for (od = 0, oe = ofd; od < omax && *oe; oe++, od++);
 1849:       for (nd = 0, ne = nfd; nd < nmax && *ne; ne++, nd++);
 1850:       od = nd = 0;
 1851:       _rl_move_cursor_relative (0, old, old_face);
 1852: 
 1853:       bytes_to_insert = ne - nfd;
 1854:       if (bytes_to_insert < local_prompt_len)	/* ??? */
 1855: 	goto dumb_update;
 1856: 
 1857:       /* output the prompt, output the line contents, clear the rest */
 1858:       _rl_output_some_chars (nfd, local_prompt_len);
 1859:       if (mb_cur_max > 1 && rl_byte_oriented == 0)
 1860: 	_rl_last_c_pos = prompt_physical_chars;
 1861:       else
 1862: 	_rl_last_c_pos = local_prompt_len;
 1863: 
 1864:       bytes_to_insert -= local_prompt_len;
 1865:       if (bytes_to_insert > 0)
 1866: 	{
 1867: 	  puts_face (new+local_prompt_len, nfdf+local_prompt_len, bytes_to_insert);
 1868: 	  if (mb_cur_max > 1 && rl_byte_oriented)
 1869: 	    _rl_last_c_pos += _rl_col_width (new, local_prompt_len, ne-new, 1);
 1870: 	  else
 1871: 	    _rl_last_c_pos += bytes_to_insert;
 1872: 	}
 1873: 
 1874:       /* See comments at dumb_update: for an explanation of this heuristic */
 1875:       if (nmax < omax)
 1876: 	goto clear_rest_of_line;
 1877:       else if ((nmax - W_OFFSET(current_line, wrap_offset)) < (omax - W_OFFSET (current_line, visible_wrap_offset)))
 1878: 	goto clear_rest_of_line;
 1879:       else
 1880: 	return;
 1881:     }
 1882: 
 1883:   /* Find first difference. */
 1884: #if defined (HANDLE_MULTIBYTE)
 1885:   if (mb_cur_max > 1 && rl_byte_oriented == 0)
 1886:     {
 1887:       /* See if the old line is a subset of the new line, so that the
 1888: 	 only change is adding characters. */
 1889:       temp = (omax < nmax) ? omax : nmax;
 1890:       if (memcmp (old, new, temp) == 0 && memcmp (old_face, new_face, temp) == 0)
 1891: 	{
 1892: 	  new_offset = old_offset = temp;	/* adding at the end */
 1893: 	  ofd = old + temp;
 1894: 	  ofdf = old_face + temp;
 1895: 	  nfd = new + temp;
 1896: 	  nfdf = new_face + temp;
 1897: 	}
 1898:       else
 1899: 	{      
 1900: 	  memset (&ps_new, 0, sizeof(mbstate_t));
 1901: 	  memset (&ps_old, 0, sizeof(mbstate_t));
 1902: 
 1903: 	  /* Are the old and new lines the same? */
 1904: 	  if (omax == nmax && memcmp (new, old, omax) == 0 && memcmp (new_face, old_face, omax) == 0)
 1905: 	    {
 1906: 	      old_offset = omax;
 1907: 	      new_offset = nmax;
 1908: 	      ofd = old + omax;
 1909: 	      ofdf = old_face + omax;
 1910: 	      nfd = new + nmax;
 1911: 	      nfdf = new_face + nmax;
 1912: 	    }
 1913: 	  else
 1914: 	    {
 1915: 	      /* Go through the line from the beginning and find the first
 1916: 		 difference. We assume that faces change at (possibly multi-
 1917: 		 byte) character boundaries. */
 1918: 	      new_offset = old_offset = 0;
 1919: 	      for (ofd = old, ofdf = old_face, nfd = new, nfdf = new_face;
 1920: 		    (ofd - old < omax) && *ofd &&
 1921: 		    _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new) &&
 1922: 		    *ofdf == *nfdf; )
 1923: 		{
 1924: 		  old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY);
 1925: 		  new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY);
 1926: 
 1927: 		  ofd = old + old_offset;
 1928: 		  ofdf = old_face + old_offset;
 1929: 		  nfd = new + new_offset;
 1930: 		  nfdf = new_face + new_offset;
 1931: 		}
 1932: 	    }
 1933: 	}
 1934:     }
 1935:   else
 1936: #endif
 1937:   for (ofd = old, ofdf = old_face, nfd = new, nfdf = new_face;
 1938:        (ofd - old < omax) && *ofd && (*ofd == *nfd) && (*ofdf == *nfdf);
 1939:        ofd++, nfd++, ofdf++, nfdf++)
 1940:     ;
 1941: 
 1942:   /* Move to the end of the screen line.  ND and OD are used to keep track
 1943:      of the distance between ne and new and oe and old, respectively, to
 1944:      move a subtraction out of each loop. */
 1945:   for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
 1946:   for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
 1947: 
 1948:   /* If no difference, continue to next line. */
 1949:   if (ofd == oe && nfd == ne)
 1950:     return;
 1951: 
 1952: #if defined (HANDLE_MULTIBYTE)
 1953:   if (mb_cur_max > 1 && rl_byte_oriented == 0 && _rl_utf8locale)
 1954:     {
 1955:       wchar_t wc;
 1956:       mbstate_t ps = { 0 };
 1957:       int t;
 1958: 
 1959:       /* If the first character in the difference is a zero-width character,
 1960: 	 assume it's a combining character and back one up so the two base
 1961: 	 characters no longer compare equivalently. */
 1962:       t = mbrtowc (&wc, ofd, mb_cur_max, &ps);
 1963:       if (t > 0 && UNICODE_COMBINING_CHAR (wc) && WCWIDTH (wc) == 0)
 1964: 	{
 1965: 	  old_offset = _rl_find_prev_mbchar (old, ofd - old, MB_FIND_ANY);
 1966: 	  new_offset = _rl_find_prev_mbchar (new, nfd - new, MB_FIND_ANY);
 1967: 	  ofd = old + old_offset;	/* equal by definition */
 1968: 	  ofdf = old_face + old_offset;
 1969: 	  nfd = new + new_offset;
 1970: 	  nfdf = new_face + new_offset;
 1971: 	}
 1972:     }
 1973: #endif
 1974: 
 1975:   wsatend = 1;			/* flag for trailing whitespace */
 1976: 
 1977: #if defined (HANDLE_MULTIBYTE)
 1978:   /* Find the last character that is the same between the two lines.  This
 1979:      bounds the region that needs to change. */
 1980:   if (mb_cur_max > 1 && rl_byte_oriented == 0)
 1981:     {
 1982:       ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY);
 1983:       olsf = old_face + (ols - old);
 1984:       nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY);
 1985:       nlsf = new_face + (nls - new);
 1986: 
 1987:       while ((ols > ofd) && (nls > nfd))
 1988: 	{
 1989: 	  memset (&ps_old, 0, sizeof (mbstate_t));
 1990: 	  memset (&ps_new, 0, sizeof (mbstate_t));
 1991: 
 1992: 	  if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0 ||
 1993: 		*olsf != *nlsf)
 1994: 	    break;
 1995: 
 1996: 	  if (*ols == ' ')
 1997: 	    wsatend = 0;
 1998: 
 1999: 	  ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY);
 2000: 	  olsf = old_face + (ols - old);
 2001: 	  nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY);
 2002: 	  nlsf = new_face + (nls - new);
 2003: 	}
 2004:     }
 2005:   else
 2006:     {
 2007: #endif /* HANDLE_MULTIBYTE */
 2008:   ols = oe - 1;			/* find last same */
 2009:   olsf = old_face + (ols - old);
 2010:   nls = ne - 1;
 2011:   nlsf = new_face + (nls - new);
 2012:   while ((ols > ofd) && (nls > nfd) && (*ols == *nls) && (*olsf == *nlsf))
 2013:     {
 2014:       if (*ols != ' ')
 2015: 	wsatend = 0;
 2016:       ols--; olsf--;
 2017:       nls--; nlsf--;
 2018:     }
 2019: #if defined (HANDLE_MULTIBYTE)
 2020:     }
 2021: #endif
 2022: 
 2023:   if (wsatend)
 2024:     {
 2025:       ols = oe;
 2026:       olsf = old_face + (ols - old);
 2027:       nls = ne;
 2028:       nlsf = new_face + (nls - new);
 2029:     }
 2030: #if defined (HANDLE_MULTIBYTE)
 2031:   /* This may not work for stateful encoding, but who cares?  To handle
 2032:      stateful encoding properly, we have to scan each string from the
 2033:      beginning and compare. */
 2034:   else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0 || *olsf != *nlsf)
 2035: #else
 2036:   else if (*ols != *nls || *olsf != *nlsf)
 2037: #endif
 2038:     {
 2039:       if (*ols)			/* don't step past the NUL */
 2040: 	{
 2041: 	  if (mb_cur_max > 1 && rl_byte_oriented == 0)
 2042: 	    ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY);
 2043: 	  else
 2044: 	    ols++;
 2045: 	}
 2046:       if (*nls)
 2047: 	{
 2048: 	  if (mb_cur_max > 1 && rl_byte_oriented == 0)
 2049: 	    nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY);
 2050: 	  else
 2051: 	    nls++;
 2052: 	}
 2053:       olsf = old_face + (ols - old);
 2054:       nlsf = new_face + (nls - new);
 2055:     }
 2056: 
 2057:   /* count of invisible characters in the current invisible line. */
 2058:   current_invis_chars = W_OFFSET (current_line, wrap_offset);
 2059:   if (_rl_last_v_pos != current_line)
 2060:     {
 2061:       _rl_move_vert (current_line);
 2062:       /* We have moved up to a new screen line.  This line may or may not have
 2063:          invisible characters on it, but we do our best to recalculate
 2064:          visible_wrap_offset based on what we know. */
 2065:       if (current_line == 0)
 2066: 	visible_wrap_offset = prompt_invis_chars_first_line;	/* XXX */
 2067: #if 0		/* XXX - not yet */
 2068:       else if (current_line == prompt_last_screen_line && wrap_offset > prompt_invis_chars_first_line)
 2069: 	visible_wrap_offset = wrap_offset - prompt_invis_chars_first_line
 2070: #endif
 2071:       if ((mb_cur_max == 1 || rl_byte_oriented) && current_line == 0 && visible_wrap_offset)
 2072: 	_rl_last_c_pos += visible_wrap_offset;
 2073:     }
 2074: 
 2075:   /* If this is the first line and there are invisible characters in the
 2076:      prompt string, and the prompt string has not changed, and the current
 2077:      cursor position is before the last invisible character in the prompt,
 2078:      and the index of the character to move to is past the end of the prompt
 2079:      string, then redraw the entire prompt string.  We can only do this
 2080:      reliably if the terminal supports a `cr' capability.
 2081: 
 2082:      This can also happen if the prompt string has changed, and the first
 2083:      difference in the line is in the middle of the prompt string, after a
 2084:      sequence of invisible characters (worst case) and before the end of
 2085:      the prompt.  In this case, we have to redraw the entire prompt string
 2086:      so that the entire sequence of invisible characters is drawn.  We need
 2087:      to handle the worst case, when the difference is after (or in the middle
 2088:      of) a sequence of invisible characters that changes the text color and
 2089:      before the sequence that restores the text color to normal.  Then we have
 2090:      to make sure that the lines still differ -- if they don't, we can
 2091:      return immediately.
 2092: 
 2093:      This is not an efficiency hack -- there is a problem with redrawing
 2094:      portions of the prompt string if they contain terminal escape
 2095:      sequences (like drawing the `unbold' sequence without a corresponding
 2096:      `bold') that manifests itself on certain terminals. */
 2097: 
 2098:   lendiff = local_prompt_len;
 2099:   if (lendiff > nmax)
 2100:     lendiff = nmax;
 2101:   od = ofd - old;	/* index of first difference in visible line */
 2102:   nd = nfd - new;	/* nd, od are buffer indexes */
 2103:   if (current_line == 0 && !_rl_horizontal_scroll_mode &&
 2104:       _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 &&
 2105:       (((od > 0 || nd > 0) && (od <= prompt_last_invisible || nd <= prompt_last_invisible)) ||
 2106: 		((od >= lendiff) && _rl_last_c_pos < PROMPT_ENDING_INDEX)))
 2107:     {
 2108:       _rl_cr ();
 2109:       if (modmark)
 2110: 	_rl_output_some_chars ("*", 1);
 2111:       _rl_output_some_chars (local_prompt, lendiff);
 2112:       if (mb_cur_max > 1 && rl_byte_oriented == 0)
 2113: 	{
 2114: 	  /* If we just output the entire prompt string we can take advantage
 2115: 	     of knowing the number of physical characters in the prompt. If
 2116: 	     the prompt wraps lines (lendiff clamped at nmax), we can't. */
 2117: 	  if (lendiff == local_prompt_len)
 2118: 	    _rl_last_c_pos = prompt_physical_chars + modmark;
 2119: 	  else
 2120: 	    /* We take wrap_offset into account here so we can pass correct
 2121: 	       information to _rl_move_cursor_relative. */
 2122: 	    _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff, 1) - wrap_offset + modmark;
 2123: 	  cpos_adjusted = 1;
 2124: 	}
 2125:       else
 2126: 	_rl_last_c_pos = lendiff + modmark;
 2127: 
 2128:       /* Now if we have printed the prompt string because the first difference
 2129: 	 was within the prompt, see if we need to recompute where the lines
 2130: 	 differ.  Check whether where we are now is past the last place where
 2131: 	 the old and new lines are the same and short-circuit now if we are. */
 2132:       if ((od <= prompt_last_invisible || nd <= prompt_last_invisible) &&
 2133:           omax == nmax &&
 2134: 	  lendiff > (ols-old) && lendiff > (nls-new))
 2135: 	return;
 2136: 
 2137:       /* XXX - we need to fix up our calculations if we are now past the
 2138: 	 old ofd/nfd and the prompt length (or line length) has changed.
 2139: 	 We punt on the problem and do a dumb update.  We'd like to be able
 2140: 	 to just output the prompt from the beginning of the line up to the
 2141: 	 first difference, but you don't know the number of invisible
 2142: 	 characters in that case.
 2143: 	 This needs a lot of work to be efficient, but it usually doesn't matter. */
 2144:       if ((od <= prompt_last_invisible || nd <= prompt_last_invisible))
 2145: 	{
 2146: 	  nfd = new + lendiff;	/* number of characters we output above */
 2147: 	  nfdf = new_face + lendiff;
 2148: 	  nd = lendiff;
 2149: 
 2150: 	  /* Do a dumb update and return */
 2151: dumb_update:
 2152: 	  temp = ne - nfd;
 2153: 	  if (temp > 0)
 2154: 	    {
 2155: 	      puts_face (nfd, nfdf, temp);
 2156: 	      if (mb_cur_max > 1 && rl_byte_oriented == 0)
 2157: 		{
 2158: 		  _rl_last_c_pos += _rl_col_width (new, nd, ne - new, 1);
 2159: 		  /* Need to adjust here based on wrap_offset. Guess that if
 2160: 		     this is the line containing the last line of the prompt
 2161: 		     we need to adjust by
 2162: 		     	wrap_offset-prompt_invis_chars_first_line
 2163: 		     on the assumption that this is the number of invisible
 2164: 		     characters in the last line of the prompt. */
 2165: 		  if (wrap_offset > prompt_invis_chars_first_line &&
 2166: 		      current_line == prompt_last_screen_line &&
 2167: 		      prompt_physical_chars > _rl_screenwidth &&
 2168: 		      _rl_horizontal_scroll_mode == 0)
 2169: 		    ADJUST_CPOS (wrap_offset - prompt_invis_chars_first_line);
 2170: 
 2171: 		  /* If we just output a new line including the prompt, and
 2172: 		     the prompt includes invisible characters, we need to
 2173: 		     account for them in the _rl_last_c_pos calculation, since
 2174: 		     _rl_col_width does not. This happens when other code does
 2175: 		     a goto dumb_update; */
 2176: 		  else if (current_line == 0 &&
 2177: 			   nfd == new &&
 2178: 			   prompt_invis_chars_first_line &&
 2179: 			   local_prompt_len <= temp &&
 2180: 			   wrap_offset >= prompt_invis_chars_first_line &&
 2181: 			   _rl_horizontal_scroll_mode == 0)
 2182: 		    ADJUST_CPOS (prompt_invis_chars_first_line);
 2183: 		}
 2184: 	      else
 2185: 		_rl_last_c_pos += temp;
 2186: 	    }
 2187: 	  /* This is a useful heuristic, but what we really want is to clear
 2188: 	     if the new number of visible screen characters is less than the
 2189: 	     old number of visible screen characters. If the prompt has changed,
 2190: 	     we don't really have enough information about the visible line to
 2191: 	     know for sure, so we use another heuristic calclulation below. */
 2192: 	  if (nmax < omax)
 2193: 	    goto clear_rest_of_line;	/* XXX */
 2194: 	  else if ((nmax - W_OFFSET(current_line, wrap_offset)) < (omax - W_OFFSET (current_line, visible_wrap_offset)))
 2195: 	    goto clear_rest_of_line;
 2196: 	  else
 2197: 	    return;
 2198: 	}
 2199:     }
 2200: 
 2201:   o_cpos = _rl_last_c_pos;
 2202: 
 2203:   /* When this function returns, _rl_last_c_pos is correct, and an absolute
 2204:      cursor position in multibyte mode, but a buffer index when not in a
 2205:      multibyte locale. */
 2206:   _rl_move_cursor_relative (od, old, old_face);
 2207: 
 2208: #if defined (HANDLE_MULTIBYTE)
 2209:   /* We need to indicate that the cursor position is correct in the presence of
 2210:      invisible characters in the prompt string.  Let's see if setting this when
 2211:      we make sure we're at the end of the drawn prompt string works. */
 2212:   if (current_line == 0 && mb_cur_max > 1 && rl_byte_oriented == 0 &&
 2213:       (_rl_last_c_pos > 0 || o_cpos > 0) &&
 2214:       _rl_last_c_pos == prompt_physical_chars)
 2215:     cpos_adjusted = 1;
 2216: #endif
 2217: 
 2218:   /* if (len (new) > len (old))
 2219:      lendiff == difference in buffer (bytes)
 2220:      col_lendiff == difference on screen (columns)
 2221:      When not using multibyte characters, these are equal */
 2222:   lendiff = (nls - nfd) - (ols - ofd);
 2223:   if (mb_cur_max > 1 && rl_byte_oriented == 0)
 2224:     {
 2225:       int newchars, newwidth, newind;
 2226:       int oldchars, oldwidth, oldind;
 2227: 
 2228:       newchars = nls - new;
 2229:       oldchars = ols - old;
 2230: 
 2231:       /* If we can do it, try to adjust nls and ols so that nls-new will
 2232: 	 contain the entire new prompt string. That way we can use
 2233: 	 prompt_physical_chars and not have to recompute column widths.
 2234: 	 _rl_col_width adds wrap_offset and expects the caller to compensate,
 2235: 	 which we do below, so we do the same thing if we don't call
 2236: 	 _rl_col_width.
 2237: 	 We don't have to compare, since we know the characters are the same.
 2238: 	 The check of differing numbers of invisible chars may be extraneous.
 2239: 	 XXX - experimental */
 2240:       if (current_line == 0 && nfd == new && newchars > prompt_last_invisible &&
 2241: 	  newchars <= local_prompt_len &&
 2242: 	  local_prompt_len <= nmax &&
 2243: 	  current_invis_chars != visible_wrap_offset)
 2244: 	{
 2245: 	  while (newchars < nmax && oldchars < omax &&  newchars < local_prompt_len)
 2246: 	    {
 2247: #if defined (HANDLE_MULTIBYTE)
 2248: 	      newind = _rl_find_next_mbchar (new, newchars, 1, MB_FIND_NONZERO);
 2249: 	      oldind = _rl_find_next_mbchar (old, oldchars, 1, MB_FIND_NONZERO);
 2250: 
 2251: 	      nls += newind - newchars;
 2252: 	      ols += oldind - oldchars;
 2253: 
 2254: 	      newchars = newind;
 2255: 	      oldchars = oldind;
 2256: #else
 2257: 	      nls++; ols++;
 2258: 	      newchars++; oldchars++;
 2259: #endif
 2260: 	    }
 2261: 	  newwidth = (newchars == local_prompt_len) ? prompt_physical_chars + wrap_offset
 2262: 	  					    : _rl_col_width (new, 0, nls - new, 1);
 2263: 	  /* if we changed nls and ols, we need to recompute lendiff */
 2264: 	  lendiff = (nls - nfd) - (ols - ofd);
 2265: 
 2266: 	  nlsf = new_face + (nls - new);
 2267: 	  olsf = old_face + (ols - old);
 2268: 	}
 2269:       else
 2270: 	newwidth = _rl_col_width (new, nfd - new, nls - new, 1);
 2271: 
 2272:       oldwidth = _rl_col_width (old, ofd - old, ols - old, 1);
 2273: 
 2274:       col_lendiff = newwidth - oldwidth;
 2275:     }
 2276:   else
 2277:     col_lendiff = lendiff;
 2278: 
 2279:   /* col_lendiff uses _rl_col_width(), which doesn't know about whether or not
 2280:      the multibyte characters it counts are invisible, so unless we're printing
 2281:      the entire prompt string (in which case we can use prompt_physical_chars)
 2282:      the count is short by the number of bytes in the invisible multibyte
 2283:      characters - the number of multibyte characters.
 2284: 
 2285:      We don't have a good way to solve this without moving to something like
 2286:      a bitmap that indicates which characters are visible and which are
 2287:      invisible. We fix it up (imperfectly) in the caller and by trying to use
 2288:      the entire prompt string wherever we can. */
 2289:      
 2290:   /* If we are changing the number of invisible characters in a line, and
 2291:      the spot of first difference is before the end of the invisible chars,
 2292:      lendiff needs to be adjusted. */
 2293:   if (current_line == 0 && current_invis_chars != visible_wrap_offset)
 2294:     {
 2295:       if (mb_cur_max > 1 && rl_byte_oriented == 0)
 2296: 	{
 2297: 	  lendiff += visible_wrap_offset - current_invis_chars;
 2298: 	  col_lendiff += visible_wrap_offset - current_invis_chars;
 2299: 	}
 2300:       else
 2301: 	{
 2302: 	  lendiff += visible_wrap_offset - current_invis_chars;
 2303: 	  col_lendiff = lendiff;
 2304: 	}
 2305:     }
 2306: 
 2307:   /* We use temp as a count of the number of bytes from the first difference
 2308:      to the end of the new line.  col_temp is the corresponding number of
 2309:      screen columns.  A `dumb' update moves to the spot of first difference
 2310:      and writes TEMP bytes. */
 2311:   /* Insert (diff (len (old), len (new)) ch. */
 2312:   temp = ne - nfd;
 2313:   if (mb_cur_max > 1 && rl_byte_oriented == 0)
 2314:     col_temp = _rl_col_width (new, nfd - new, ne - new, 1);
 2315:   else
 2316:     col_temp = temp;
 2317: 
 2318:   /* how many bytes from the new line buffer to write to the display */
 2319:   bytes_to_insert = nls - nfd;
 2320: 
 2321:   /* col_lendiff > 0 if we are adding characters to the line */
 2322:   if (col_lendiff > 0)	/* XXX - was lendiff */
 2323:     {
 2324:       /* Non-zero if we're increasing the number of lines. */
 2325:       int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
 2326: 
 2327:       /* If col_lendiff is > 0, implying that the new string takes up more
 2328: 	 screen real estate than the old, but lendiff is < 0, meaning that it
 2329: 	 takes fewer bytes, we need to just output the characters starting
 2330: 	 from the first difference.  These will overwrite what is on the
 2331: 	 display, so there's no reason to do a smart update.  This can really
 2332: 	 only happen in a multibyte environment. */
 2333:       if (lendiff < 0)
 2334: 	{
 2335: 	  puts_face (nfd, nfdf, temp);
 2336: 	  _rl_last_c_pos += col_temp;
 2337: 	  /* If nfd begins before any invisible characters in the prompt,
 2338: 	     adjust _rl_last_c_pos to account for wrap_offset and set
 2339: 	     cpos_adjusted to let the caller know. */
 2340: 	  if (current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
 2341: 	    ADJUST_CPOS (wrap_offset);	/* XXX - prompt_invis_chars_first_line? */
 2342: 	  return;
 2343: 	}
 2344:       /* Sometimes it is cheaper to print the characters rather than
 2345: 	 use the terminal's capabilities.  If we're growing the number
 2346: 	 of lines, make sure we actually cause the new line to wrap
 2347: 	 around on auto-wrapping terminals. */
 2348:       else if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
 2349: 	{
 2350: 	  /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
 2351: 	     _rl_horizontal_scroll_mode == 1, inserting the characters with
 2352: 	     _rl_term_IC or _rl_term_ic will screw up the screen because of the
 2353: 	     invisible characters.  We need to just draw them. */
 2354: 	  /* The same thing happens if we're trying to draw before the last
 2355: 	     invisible character in the prompt string or we're increasing the
 2356: 	     number of invisible characters in the line and we're not drawing
 2357: 	     the entire prompt string. */
 2358: 	  if (*ols && ((_rl_horizontal_scroll_mode &&
 2359: 			_rl_last_c_pos == 0 &&
 2360: 			lendiff > prompt_visible_length &&
 2361: 			current_invis_chars > 0) == 0) &&
 2362: 		      (((mb_cur_max > 1 && rl_byte_oriented == 0) &&
 2363: 		        current_line == 0 && wrap_offset &&
 2364: 		        ((nfd - new) <= prompt_last_invisible) &&
 2365: 		        (col_lendiff < prompt_visible_length)) == 0) &&
 2366: 		      (visible_wrap_offset >= current_invis_chars))
 2367: 	    {
 2368: 	      open_some_spaces (col_lendiff);
 2369: 	      puts_face (nfd, nfdf, bytes_to_insert);
 2370: 	      if (mb_cur_max > 1 && rl_byte_oriented == 0)
 2371: 		_rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
 2372: 	      else
 2373: 		_rl_last_c_pos += bytes_to_insert;
 2374: 	    }
 2375: 	  else if ((mb_cur_max == 1 || rl_byte_oriented != 0) && *ols == 0 && lendiff > 0)
 2376: 	    {
 2377: 	      /* At the end of a line the characters do not have to
 2378: 		 be "inserted".  They can just be placed on the screen. */
 2379: 	      puts_face (nfd, nfdf, temp);
 2380: 	      _rl_last_c_pos += col_temp;
 2381: 	      return;
 2382: 	    }
 2383: 	  else	/* just write from first difference to end of new line */
 2384: 	    {
 2385: 	      puts_face (nfd, nfdf, temp);
 2386: 	      _rl_last_c_pos += col_temp;
 2387: 	      /* If nfd begins before the last invisible character in the
 2388: 		 prompt, adjust _rl_last_c_pos to account for wrap_offset
 2389: 		 and set cpos_adjusted to let the caller know. */
 2390: 	      if ((mb_cur_max > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
 2391: 		ADJUST_CPOS (wrap_offset);	/* XXX - prompt_invis_chars_first_line? */
 2392: 	      return;
 2393: 	    }
 2394: 
 2395: 	  if (bytes_to_insert > lendiff)
 2396: 	    {
 2397: 	      /* If nfd begins before the last invisible character in the
 2398: 		 prompt, adjust _rl_last_c_pos to account for wrap_offset
 2399: 		 and set cpos_adjusted to let the caller know. */
 2400: 	      if ((mb_cur_max > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
 2401: 		ADJUST_CPOS (wrap_offset);	/* XXX - prompt_invis_chars_first_line? */
 2402: 	    }
 2403: 	}
 2404:       else
 2405: 	{
 2406: 	  /* cannot insert chars, write to EOL */
 2407: 	  puts_face (nfd, nfdf, temp);
 2408: 	  _rl_last_c_pos += col_temp;
 2409: 	  /* If we're in a multibyte locale and were before the last invisible
 2410: 	     char in the current line (which implies we just output some invisible
 2411: 	     characters) we need to adjust _rl_last_c_pos, since it represents
 2412: 	     a physical character position. */
 2413: 	  /* The current_line*rl_screenwidth+prompt_invis_chars_first_line is a
 2414: 	     crude attempt to compute how far into the new line buffer we are.
 2415: 	     It doesn't work well in the face of multibyte characters and needs
 2416: 	     to be rethought. XXX */
 2417: 	  if ((mb_cur_max > 1 && rl_byte_oriented == 0) &&
 2418: 		current_line == prompt_last_screen_line && wrap_offset &&
 2419: 		displaying_prompt_first_line &&
 2420: 		wrap_offset != prompt_invis_chars_first_line &&
 2421: 		((nfd-new) < (prompt_last_invisible-(current_line*_rl_screenwidth+prompt_invis_chars_first_line))))
 2422: 	    ADJUST_CPOS (wrap_offset - prompt_invis_chars_first_line);
 2423: 
 2424: 	  /* XXX - what happens if wrap_offset == prompt_invis_chars_first_line
 2425: 	     and we are drawing the first line (current_line == 0)? We should
 2426: 	     adjust by _rl_last_c_pos -= prompt_invis_chars_first_line */
 2427: 	}
 2428:     }
 2429:   else				/* Delete characters from line. */
 2430:     {
 2431:       /* If possible and inexpensive to use terminal deletion, then do so. */
 2432:       if (_rl_term_dc && (2 * col_temp) >= -col_lendiff)
 2433: 	{
 2434: 	  /* If all we're doing is erasing the invisible characters in the
 2435: 	     prompt string, don't bother.  It screws up the assumptions
 2436: 	     about what's on the screen. */
 2437: 	  if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
 2438: 	      displaying_prompt_first_line &&
 2439: 	      -lendiff == visible_wrap_offset)
 2440: 	    col_lendiff = 0;
 2441: 
 2442: 	  /* If we have moved lmargin and we're shrinking the line, we've
 2443: 	     already moved the cursor to the first character of the new line,
 2444: 	     so deleting -col_lendiff characters will mess up the cursor
 2445: 	     position calculation */
 2446: 	  if (_rl_horizontal_scroll_mode && displaying_prompt_first_line == 0 &&
 2447: 		col_lendiff && _rl_last_c_pos < -col_lendiff)
 2448: 	    col_lendiff = 0;
 2449: 
 2450: 	  if (col_lendiff)
 2451: 	    delete_chars (-col_lendiff); /* delete (diff) characters */
 2452: 
 2453: 	  /* Copy (new) chars to screen from first diff to last match,
 2454: 	     overwriting what is there. */
 2455: 	  if (bytes_to_insert > 0)
 2456: 	    {
 2457: 	      /* If nfd begins at the prompt, or before the invisible
 2458: 		 characters in the prompt, we need to adjust _rl_last_c_pos
 2459: 		 in a multibyte locale to account for the wrap offset and
 2460: 		 set cpos_adjusted accordingly. */
 2461: 	      puts_face (nfd, nfdf, bytes_to_insert);
 2462: 	      if (mb_cur_max > 1 && rl_byte_oriented == 0)
 2463: 		{
 2464: 		  /* This still doesn't take into account whether or not the
 2465: 		     characters that this counts are invisible. */
 2466: 		  _rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
 2467: 		  if (current_line == 0 && wrap_offset &&
 2468: 			displaying_prompt_first_line &&
 2469: 			prompt_invis_chars_first_line &&
 2470: 			_rl_last_c_pos >= prompt_invis_chars_first_line &&
 2471: 			((nfd - new) <= prompt_last_invisible))
 2472: 		    ADJUST_CPOS (prompt_invis_chars_first_line);
 2473: 
 2474: #if 1
 2475: #ifdef HANDLE_MULTIBYTE
 2476: 		  /* If we write a non-space into the last screen column,
 2477: 		     remove the note that we added a space to compensate for
 2478: 		     a multibyte double-width character that didn't fit, since
 2479: 		     it's only valid for what was previously there. */
 2480: 		  /* XXX - watch this */
 2481: 		  if (_rl_last_c_pos == _rl_screenwidth &&
 2482: 			line_state_invisible->wrapped_line[current_line+1] &&
 2483: 			nfd[bytes_to_insert-1] != ' ')
 2484: 		    line_state_invisible->wrapped_line[current_line+1] = 0;
 2485: #endif
 2486: #endif
 2487: 		}
 2488: 	      else
 2489: 		_rl_last_c_pos += bytes_to_insert;
 2490: 
 2491: 	      /* XXX - we only want to do this if we are at the end of the line
 2492: 		 so we move there with _rl_move_cursor_relative */
 2493: 	      if (_rl_horizontal_scroll_mode && ((oe-old) > (ne-new)))
 2494: 		{
 2495: 		  _rl_move_cursor_relative (ne-new, new, new_face);
 2496: 		  goto clear_rest_of_line;
 2497: 		}
 2498: 	    }
 2499: 	}
 2500:       /* Otherwise, print over the existing material. */
 2501:       else
 2502: 	{
 2503: 	  if (temp > 0)
 2504: 	    {
 2505: 	      /* If nfd begins at the prompt, or before the invisible
 2506: 		 characters in the prompt, we need to adjust _rl_last_c_pos
 2507: 		 in a multibyte locale to account for the wrap offset and
 2508: 		 set cpos_adjusted accordingly. */
 2509: 	      puts_face (nfd, nfdf, temp);
 2510: 	      _rl_last_c_pos += col_temp;		/* XXX */
 2511: 	      if (mb_cur_max > 1 && rl_byte_oriented == 0)
 2512: 		{
 2513: 		  if (current_line == 0 && wrap_offset &&
 2514: 			displaying_prompt_first_line &&
 2515: 			_rl_last_c_pos > wrap_offset &&
 2516: 			((nfd - new) <= prompt_last_invisible))
 2517: 		    ADJUST_CPOS (wrap_offset);	/* XXX - prompt_invis_chars_first_line? */
 2518: 		}
 2519: 	    }
 2520: clear_rest_of_line:
 2521: 	  lendiff = (oe - old) - (ne - new);
 2522: 	  if (mb_cur_max > 1 && rl_byte_oriented == 0)
 2523: 	    col_lendiff = _rl_col_width (old, 0, oe - old, 1) - _rl_col_width (new, 0, ne - new, 1);
 2524: 	  else
 2525: 	    col_lendiff = lendiff;
 2526: 
 2527: 	  /* If we've already printed over the entire width of the screen,
 2528: 	     including the old material, then col_lendiff doesn't matter and
 2529: 	     space_to_eol will insert too many spaces.  XXX - maybe we should
 2530: 	     adjust col_lendiff based on the difference between _rl_last_c_pos
 2531: 	     and _rl_screenwidth */
 2532: 	  if (col_lendiff && ((mb_cur_max == 1 || rl_byte_oriented) || (_rl_last_c_pos < _rl_screenwidth)))
 2533: 	    {	  
 2534: 	      if (_rl_term_autowrap && current_line < inv_botlin)
 2535: 		space_to_eol (col_lendiff);
 2536: 	      else
 2537: 		_rl_clear_to_eol (col_lendiff);
 2538: 	    }
 2539: 	}
 2540:     }
 2541: }
 2542: 
 2543: /* Tell the update routines that we have moved onto a new (empty) line. */
 2544: int
 2545: rl_on_new_line (void)
 2546: {
 2547:   if (visible_line)
 2548:     visible_line[0] = '\0';
 2549: 
 2550:   _rl_last_c_pos = _rl_last_v_pos = 0;
 2551:   _rl_vis_botlin = last_lmargin = 0;
 2552:   if (vis_lbreaks)
 2553:     vis_lbreaks[0] = vis_lbreaks[1] = 0;
 2554:   visible_wrap_offset = 0;
 2555:   return 0;
 2556: }
 2557: 
 2558: /* Clear all screen lines occupied by the current readline line buffer
 2559:    (visible line) */
 2560: int
 2561: rl_clear_visible_line (void)
 2562: {
 2563:   int curr_line;
 2564: 
 2565:   /* Make sure we move to column 0 so we clear the entire line */
 2566:   _rl_cr ();
 2567:   _rl_last_c_pos = 0;
 2568: 
 2569:   /* Move to the last screen line of the current visible line */
 2570:   _rl_move_vert (_rl_vis_botlin);
 2571: 
 2572:   /* And erase screen lines going up to line 0 (first visible line) */
 2573:   for (curr_line = _rl_last_v_pos; curr_line >= 0; curr_line--)
 2574:     {
 2575:       _rl_move_vert (curr_line);
 2576:       _rl_clear_to_eol (0);
 2577:     }
 2578: 
 2579:   return 0;
 2580: }
 2581: 
 2582: /* Tell the update routines that we have moved onto a new line with the
 2583:    prompt already displayed.  Code originally from the version of readline
 2584:    distributed with CLISP.  rl_expand_prompt must have already been called
 2585:    (explicitly or implicitly).  This still doesn't work exactly right; it
 2586:    should use expand_prompt() */
 2587: int
 2588: rl_on_new_line_with_prompt (void)
 2589: {
 2590:   int prompt_size, i, l, real_screenwidth, newlines;
 2591:   char *prompt_last_line, *lprompt;
 2592: 
 2593:   /* Initialize visible_line and invisible_line to ensure that they can hold
 2594:      the already-displayed prompt. */
 2595:   prompt_size = strlen (rl_prompt) + 1;
 2596:   init_line_structures (prompt_size);
 2597: 
 2598:   /* Make sure the line structures hold the already-displayed prompt for
 2599:      redisplay. */
 2600:   lprompt = local_prompt ? local_prompt : rl_prompt;
 2601:   strcpy (visible_line, lprompt);
 2602:   strcpy (invisible_line, lprompt);
 2603: 
 2604:   /* If the prompt contains newlines, take the last tail. */
 2605:   prompt_last_line = strrchr (rl_prompt, '\n');
 2606:   if (!prompt_last_line)
 2607:     prompt_last_line = rl_prompt;
 2608: 
 2609:   l = strlen (prompt_last_line);
 2610:   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
 2611:     _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l, 1);	/* XXX */
 2612:   else
 2613:     _rl_last_c_pos = l;
 2614: 
 2615:   /* Dissect prompt_last_line into screen lines. Note that here we have
 2616:      to use the real screenwidth. Readline's notion of screenwidth might be
 2617:      one less, see terminal.c. */
 2618:   real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1);
 2619:   _rl_last_v_pos = l / real_screenwidth;
 2620:   /* If the prompt length is a multiple of real_screenwidth, we don't know
 2621:      whether the cursor is at the end of the last line, or already at the
 2622:      beginning of the next line. Output a newline just to be safe. */
 2623:   if (l > 0 && (l % real_screenwidth) == 0)
 2624:     _rl_output_some_chars ("\n", 1);
 2625:   last_lmargin = 0;
 2626: 
 2627:   newlines = 0; i = 0;
 2628:   while (i <= l)
 2629:     {
 2630:       _rl_vis_botlin = newlines;
 2631:       vis_lbreaks[newlines++] = i;
 2632:       i += real_screenwidth;
 2633:     }
 2634:   vis_lbreaks[newlines] = l;
 2635:   visible_wrap_offset = 0;
 2636: 
 2637:   rl_display_prompt = rl_prompt;	/* XXX - make sure it's set */
 2638: 
 2639:   return 0;
 2640: }
 2641: 
 2642: /* Actually update the display, period. */
 2643: int
 2644: rl_forced_update_display (void)
 2645: {
 2646:   register char *temp;
 2647: 
 2648:   if (visible_line)
 2649:     {
 2650:       temp = visible_line;
 2651:       while (*temp)
 2652: 	*temp++ = '\0';
 2653:     }
 2654:   rl_on_new_line ();
 2655:   forced_display++;
 2656:   (*rl_redisplay_function) ();
 2657:   return 0;
 2658: }
 2659: 
 2660: /* Redraw only the last line of a multi-line prompt. */
 2661: void
 2662: rl_redraw_prompt_last_line (void)
 2663: {
 2664:   char *t;
 2665: 
 2666:   t = strrchr (rl_display_prompt, '\n');
 2667:   if (t)
 2668:     redraw_prompt (++t);
 2669:   else
 2670:     rl_forced_update_display ();
 2671: }
 2672: 
 2673: /* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
 2674:    (Well, when we don't have multibyte characters, _rl_last_c_pos is a
 2675:    buffer index.)
 2676:    DATA is the contents of the screen line of interest; i.e., where
 2677:    the movement is being done.
 2678:    DATA is always the visible line or the invisible line */
 2679: static void
 2680: _rl_move_cursor_relative (int new, const char *data, const char *dataf)
 2681: {
 2682:   register int i;
 2683:   int woff;			/* number of invisible chars on current line */
 2684:   int cpos, dpos;		/* current and desired cursor positions */
 2685:   int adjust;
 2686:   int in_invisline;
 2687:   int mb_cur_max = MB_CUR_MAX;
 2688: 
 2689:   woff = WRAP_OFFSET (_rl_last_v_pos, wrap_offset);
 2690:   cpos = _rl_last_c_pos;
 2691: 
 2692:   if (cpos == 0 && cpos == new)
 2693:     return;
 2694: 
 2695: #if defined (HANDLE_MULTIBYTE)
 2696:   /* If we have multibyte characters, NEW is indexed by the buffer point in
 2697:      a multibyte string, but _rl_last_c_pos is the display position.  In
 2698:      this case, NEW's display position is not obvious and must be
 2699:      calculated.  We need to account for invisible characters in this line,
 2700:      as long as we are past them and they are counted by _rl_col_width. */
 2701:   if (mb_cur_max > 1 && rl_byte_oriented == 0)
 2702:     {
 2703:       adjust = 1;
 2704:       /* Try to short-circuit common cases and eliminate a bunch of multibyte
 2705: 	 character function calls. */
 2706:       /* 1.  prompt string */
 2707:       if (new == local_prompt_len && memcmp (data, local_prompt, new) == 0)
 2708: 	{
 2709: 	  dpos = prompt_physical_chars;
 2710: 	  cpos_adjusted = 1;
 2711: 	  adjust = 0;
 2712: 	}
 2713:       /* 2.  prompt_string + line contents */
 2714:       else if (new > local_prompt_len && local_prompt && memcmp (data, local_prompt, local_prompt_len) == 0)
 2715: 	{
 2716: 	  dpos = prompt_physical_chars + _rl_col_width (data, local_prompt_len, new, 1);
 2717: 	  cpos_adjusted = 1;
 2718: 	  adjust = 0;
 2719: 	}
 2720:       else
 2721:         dpos = _rl_col_width (data, 0, new, 1);
 2722: 
 2723:       if (displaying_prompt_first_line == 0)
 2724: 	adjust = 0;
 2725: 
 2726:       /* yet another special case: printing the last line of a prompt with
 2727: 	 multibyte characters and invisible characters whose printable length
 2728: 	 exceeds the screen width with the last invisible character
 2729: 	 (prompt_last_invisible) in the last line.  IN_INVISLINE is the
 2730: 	 offset of DATA in invisible_line */
 2731:       in_invisline = 0;
 2732:       if (data > invisible_line && data < invisible_line+inv_lbreaks[_rl_inv_botlin+1])
 2733: 	in_invisline = data - invisible_line;
 2734: 
 2735:       /* Use NEW when comparing against the last invisible character in the
 2736: 	 prompt string, since they're both buffer indices and DPOS is a
 2737: 	 desired display position. */
 2738:       /* NEW is relative to the current displayed line, while
 2739: 	 PROMPT_LAST_INVISIBLE is relative to the entire (wrapped) line.
 2740: 	 Need a way to reconcile these two variables by turning NEW into a
 2741: 	 buffer position relative to the start of the line */
 2742:       if (adjust && ((new > prompt_last_invisible) ||		/* XXX - don't use woff here */
 2743: 		     (new+in_invisline > prompt_last_invisible) ||	/* invisible line */
 2744: 	  (prompt_physical_chars >= _rl_screenwidth &&		/* visible line */
 2745: 	   _rl_last_v_pos == prompt_last_screen_line &&
 2746: 	   wrap_offset >= woff && dpos >= woff &&
 2747: 	   new > (prompt_last_invisible-(vis_lbreaks[_rl_last_v_pos])-wrap_offset))))
 2748: 	   /* XXX last comparison might need to be >= */
 2749: 	{
 2750: 	  dpos -= woff;
 2751: 	  /* Since this will be assigned to _rl_last_c_pos at the end (more
 2752: 	     precisely, _rl_last_c_pos == dpos when this function returns),
 2753: 	     let the caller know. */
 2754: 	  cpos_adjusted = 1;
 2755: 	}
 2756:     }
 2757:   else
 2758: #endif
 2759:     dpos = new;
 2760: 
 2761:   /* If we don't have to do anything, then return. */
 2762:   if (cpos == dpos)
 2763:     return;
 2764: 
 2765:   /* It may be faster to output a CR, and then move forwards instead
 2766:      of moving backwards. */
 2767:   /* i == current physical cursor position. */
 2768: #if defined (HANDLE_MULTIBYTE)
 2769:   if (mb_cur_max > 1 && rl_byte_oriented == 0)
 2770:     i = _rl_last_c_pos;
 2771:   else
 2772: #endif
 2773:   i = _rl_last_c_pos - woff;
 2774:   if (dpos == 0 || CR_FASTER (dpos, _rl_last_c_pos) ||
 2775:       (_rl_term_autowrap && i == _rl_screenwidth))
 2776:     {
 2777:       _rl_cr ();
 2778:       cpos = _rl_last_c_pos = 0;
 2779:     }
 2780: 
 2781:   if (cpos < dpos)
 2782:     {
 2783:       /* Move the cursor forward.  We do it by printing the command
 2784: 	 to move the cursor forward if there is one, else print that
 2785: 	 portion of the output buffer again.  Which is cheaper? */
 2786: 
 2787:       /* The above comment is left here for posterity.  It is faster
 2788: 	 to print one character (non-control) than to print a control
 2789: 	 sequence telling the terminal to move forward one character.
 2790: 	 That kind of control is for people who don't know what the
 2791: 	 data is underneath the cursor. */
 2792: 
 2793:       /* However, we need a handle on where the current display position is
 2794: 	 in the buffer for the immediately preceding comment to be true.
 2795: 	 In multibyte locales, we don't currently have that info available.
 2796: 	 Without it, we don't know where the data we have to display begins
 2797: 	 in the buffer and we have to go back to the beginning of the screen
 2798: 	 line.  In this case, we can use the terminal sequence to move forward
 2799: 	 if it's available. */
 2800:       if (mb_cur_max > 1 && rl_byte_oriented == 0)
 2801: 	{
 2802: 	  if (_rl_term_forward_char)
 2803: 	    {
 2804: 	      for (i = cpos; i < dpos; i++)
 2805: 	        tputs (_rl_term_forward_char, 1, _rl_output_character_function);
 2806: 	    }
 2807: 	  else
 2808: 	    {
 2809: 	      _rl_cr ();
 2810: 	      puts_face (data, dataf, new);
 2811: 	    }
 2812: 	}
 2813:       else
 2814: 	puts_face (data + cpos, dataf + cpos, new - cpos);
 2815:     }
 2816: 
 2817: #if defined (HANDLE_MULTIBYTE)
 2818:   /* NEW points to the buffer point, but _rl_last_c_pos is the display point.
 2819:      The byte length of the string is probably bigger than the column width
 2820:      of the string, which means that if NEW == _rl_last_c_pos, then NEW's
 2821:      display point is less than _rl_last_c_pos. */
 2822: #endif
 2823:   else if (cpos > dpos)
 2824:     _rl_backspace (cpos - dpos);
 2825: 
 2826:   _rl_last_c_pos = dpos;
 2827: }
 2828: 
 2829: /* PWP: move the cursor up or down. */
 2830: void
 2831: _rl_move_vert (int to)
 2832: {
 2833:   register int delta, i;
 2834: 
 2835:   if (_rl_last_v_pos == to || to > _rl_screenheight)
 2836:     return;
 2837: 
 2838:   if ((delta = to - _rl_last_v_pos) > 0)
 2839:     {
 2840:       for (i = 0; i < delta; i++)
 2841: 	putc ('\n', rl_outstream);
 2842:       _rl_cr ();
 2843:       _rl_last_c_pos = 0;
 2844:     }
 2845:   else
 2846:     {			/* delta < 0 */
 2847: #ifdef __DJGPP__
 2848:       int row, col;
 2849: 
 2850:       fflush (rl_outstream);
 2851:       ScreenGetCursor (&row, &col);
 2852:       ScreenSetCursor (row + delta, col);
 2853:       i = -delta;
 2854: #else
 2855:       if (_rl_term_up && *_rl_term_up)
 2856: 	for (i = 0; i < -delta; i++)
 2857: 	  tputs (_rl_term_up, 1, _rl_output_character_function);
 2858: #endif /* !__DJGPP__ */
 2859:     }
 2860: 
 2861:   _rl_last_v_pos = to;		/* Now TO is here */
 2862: }
 2863: 
 2864: /* Physically print C on rl_outstream.  This is for functions which know
 2865:    how to optimize the display.  Return the number of characters output. */
 2866: int
 2867: rl_show_char (int c)
 2868: {
 2869:   int n = 1;
 2870:   if (META_CHAR (c) && (_rl_output_meta_chars == 0))
 2871:     {
 2872:       fprintf (rl_outstream, "M-");
 2873:       n += 2;
 2874:       c = UNMETA (c);
 2875:     }
 2876: 
 2877: #if defined (DISPLAY_TABS)
 2878:   if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
 2879: #else
 2880:   if (CTRL_CHAR (c) || c == RUBOUT)
 2881: #endif /* !DISPLAY_TABS */
 2882:     {
 2883:       fprintf (rl_outstream, "C-");
 2884:       n += 2;
 2885:       c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
 2886:     }
 2887: 
 2888:   putc (c, rl_outstream);
 2889:   fflush (rl_outstream);
 2890:   return n;
 2891: }
 2892: 
 2893: int
 2894: rl_character_len (int c, int pos)
 2895: {
 2896:   unsigned char uc;
 2897: 
 2898:   uc = (unsigned char)c;
 2899: 
 2900:   if (META_CHAR (uc))
 2901:     return ((_rl_output_meta_chars == 0) ? 4 : 1);
 2902: 
 2903:   if (uc == '\t')
 2904:     {
 2905: #if defined (DISPLAY_TABS)
 2906:       return (((pos | 7) + 1) - pos);
 2907: #else
 2908:       return (2);
 2909: #endif /* !DISPLAY_TABS */
 2910:     }
 2911: 
 2912:   if (CTRL_CHAR (c) || c == RUBOUT)
 2913:     return (2);
 2914: 
 2915:   return ((ISPRINT (uc)) ? 1 : 2);
 2916: }
 2917: /* How to print things in the "echo-area".  The prompt is treated as a
 2918:    mini-modeline. */
 2919: static int msg_saved_prompt = 0;
 2920: 
 2921: #if defined (USE_VARARGS)
 2922: int
 2923: #if defined (PREFER_STDARG)
 2924: rl_message (const char *format, ...)
 2925: #else
 2926: rl_message (va_alist)
 2927:      va_dcl
 2928: #endif
 2929: {
 2930:   va_list args;
 2931: #if defined (PREFER_VARARGS)
 2932:   char *format;
 2933: #endif
 2934: #if defined (HAVE_VSNPRINTF)
 2935:   int bneed;
 2936: #endif
 2937: 
 2938: #if defined (PREFER_STDARG)
 2939:   va_start (args, format);
 2940: #else
 2941:   va_start (args);
 2942:   format = va_arg (args, char *);
 2943: #endif
 2944: 
 2945:   if (msg_buf == 0)
 2946:     msg_buf = xmalloc (msg_bufsiz = 128);
 2947: 
 2948: #if defined (HAVE_VSNPRINTF)
 2949:   bneed = vsnprintf (msg_buf, msg_bufsiz, format, args);
 2950:   if (bneed >= msg_bufsiz - 1)
 2951:     {
 2952:       msg_bufsiz = bneed + 1;
 2953:       msg_buf = xrealloc (msg_buf, msg_bufsiz);
 2954:       va_end (args);
 2955: 
 2956: #if defined (PREFER_STDARG)
 2957:       va_start (args, format);
 2958: #else
 2959:       va_start (args);
 2960:       format = va_arg (args, char *);
 2961: #endif
 2962:       vsnprintf (msg_buf, msg_bufsiz - 1, format, args);
 2963:     }
 2964: #else
 2965:   vsprintf (msg_buf, format, args);
 2966:   msg_buf[msg_bufsiz - 1] = '\0';	/* overflow? */
 2967: #endif
 2968:   va_end (args);
 2969: 
 2970:   if (saved_local_prompt == 0)
 2971:     {
 2972:       rl_save_prompt ();
 2973:       msg_saved_prompt = 1;
 2974:     }
 2975:   else if (local_prompt != saved_local_prompt)
 2976:     {
 2977:       FREE (local_prompt);
 2978:       FREE (local_prompt_prefix);
 2979:       local_prompt = (char *)NULL;
 2980:     }
 2981:   rl_display_prompt = msg_buf;
 2982:   local_prompt = expand_prompt (msg_buf, 0, &prompt_visible_length,
 2983: 					    &prompt_last_invisible,
 2984: 					    &prompt_invis_chars_first_line,
 2985: 					    &prompt_physical_chars);
 2986:   local_prompt_prefix = (char *)NULL;
 2987:   local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
 2988:   (*rl_redisplay_function) ();
 2989: 
 2990:   return 0;
 2991: }
 2992: #else /* !USE_VARARGS */
 2993: int
 2994: rl_message (format, arg1, arg2)
 2995:      char *format;
 2996: {
 2997:   if (msg_buf == 0)
 2998:     msg_buf = xmalloc (msg_bufsiz = 128);
 2999: 
 3000:   sprintf (msg_buf, format, arg1, arg2);
 3001:   msg_buf[msg_bufsiz - 1] = '\0';	/* overflow? */
 3002: 
 3003:   rl_display_prompt = msg_buf;
 3004:   if (saved_local_prompt == 0)
 3005:     {
 3006:       rl_save_prompt ();
 3007:       msg_saved_prompt = 1;
 3008:     }
 3009:   else if (local_prompt != saved_local_prompt)
 3010:     {
 3011:       FREE (local_prompt);
 3012:       FREE (local_prompt_prefix);
 3013:       local_prompt = (char *)NULL;
 3014:     }
 3015:   local_prompt = expand_prompt (msg_buf, 0, &prompt_visible_length,
 3016: 					    &prompt_last_invisible,
 3017: 					    &prompt_invis_chars_first_line,
 3018: 					    &prompt_physical_chars);
 3019:   local_prompt_prefix = (char *)NULL;
 3020:   local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
 3021:   (*rl_redisplay_function) ();
 3022:       
 3023:   return 0;
 3024: }
 3025: #endif /* !USE_VARARGS */
 3026: 
 3027: /* How to clear things from the "echo-area". */
 3028: int
 3029: rl_clear_message (void)
 3030: {
 3031:   rl_display_prompt = rl_prompt;
 3032:   if (msg_saved_prompt)
 3033:     {
 3034:       rl_restore_prompt ();
 3035:       msg_saved_prompt = 0;
 3036:     }
 3037:   (*rl_redisplay_function) ();
 3038:   return 0;
 3039: }
 3040: 
 3041: int
 3042: rl_reset_line_state (void)
 3043: {
 3044:   rl_on_new_line ();
 3045: 
 3046:   rl_display_prompt = rl_prompt ? rl_prompt : "";
 3047:   forced_display = 1;
 3048:   return 0;
 3049: }
 3050: 
 3051: /* Save all of the variables associated with the prompt and its display. Most
 3052:    of the complexity is dealing with the invisible characters in the prompt
 3053:    string and where they are. There are enough of these that I should consider
 3054:    a struct. */
 3055: void
 3056: rl_save_prompt (void)
 3057: {
 3058:   saved_local_prompt = local_prompt;
 3059:   saved_local_prefix = local_prompt_prefix;
 3060:   saved_prefix_length = prompt_prefix_length;
 3061:   saved_local_length = local_prompt_len;
 3062:   saved_last_invisible = prompt_last_invisible;
 3063:   saved_visible_length = prompt_visible_length;
 3064:   saved_invis_chars_first_line = prompt_invis_chars_first_line;
 3065:   saved_physical_chars = prompt_physical_chars;
 3066:   saved_local_prompt_newlines = local_prompt_newlines;
 3067: 
 3068:   local_prompt = local_prompt_prefix = (char *)0;
 3069:   local_prompt_len = 0;
 3070:   local_prompt_newlines = (int *)0;
 3071: 
 3072:   prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0;
 3073:   prompt_invis_chars_first_line = prompt_physical_chars = 0;
 3074: }
 3075: 
 3076: void
 3077: rl_restore_prompt (void)
 3078: {
 3079:   FREE (local_prompt);
 3080:   FREE (local_prompt_prefix);
 3081:   FREE (local_prompt_newlines);
 3082: 
 3083:   local_prompt = saved_local_prompt;
 3084:   local_prompt_prefix = saved_local_prefix;
 3085:   local_prompt_len = saved_local_length;
 3086:   local_prompt_newlines = saved_local_prompt_newlines;
 3087: 
 3088:   prompt_prefix_length = saved_prefix_length;
 3089:   prompt_last_invisible = saved_last_invisible;
 3090:   prompt_visible_length = saved_visible_length;
 3091:   prompt_invis_chars_first_line = saved_invis_chars_first_line;
 3092:   prompt_physical_chars = saved_physical_chars;
 3093: 
 3094:   /* can test saved_local_prompt to see if prompt info has been saved. */
 3095:   saved_local_prompt = saved_local_prefix = (char *)0;
 3096:   saved_local_length = 0;
 3097:   saved_last_invisible = saved_visible_length = saved_prefix_length = 0;
 3098:   saved_invis_chars_first_line = saved_physical_chars = 0;
 3099:   saved_local_prompt_newlines = 0;
 3100: }
 3101: 
 3102: char *
 3103: _rl_make_prompt_for_search (int pchar)
 3104: {
 3105:   int len;
 3106:   char *pmt, *p;
 3107: 
 3108:   rl_save_prompt ();
 3109: 
 3110:   /* We've saved the prompt, and can do anything with the various prompt
 3111:      strings we need before they're restored.  We want the unexpanded
 3112:      portion of the prompt string after any final newline. */
 3113:   p = rl_prompt ? strrchr (rl_prompt, '\n') : 0;
 3114:   if (p == 0)
 3115:     {
 3116:       len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
 3117:       pmt = (char *)xmalloc (len + 2);
 3118:       if (len)
 3119: 	strcpy (pmt, rl_prompt);
 3120:       pmt[len] = pchar;
 3121:       pmt[len+1] = '\0';
 3122:     }
 3123:   else
 3124:     {
 3125:       p++;
 3126:       len = strlen (p);
 3127:       pmt = (char *)xmalloc (len + 2);
 3128:       if (len)
 3129: 	strcpy (pmt, p);
 3130:       pmt[len] = pchar;
 3131:       pmt[len+1] = '\0';
 3132:     }  
 3133: 
 3134:   /* will be overwritten by expand_prompt, called from rl_message */
 3135:   prompt_physical_chars = saved_physical_chars + 1;
 3136:   return pmt;
 3137: }
 3138: 
 3139: /* Quick redisplay hack when erasing characters at the end of the line. */
 3140: void
 3141: _rl_erase_at_end_of_line (int l)
 3142: {
 3143:   register int i;
 3144: 
 3145:   _rl_backspace (l);
 3146:   for (i = 0; i < l; i++)
 3147:     putc (' ', rl_outstream);
 3148:   _rl_backspace (l);
 3149:   for (i = 0; i < l; i++)
 3150:     visible_line[--_rl_last_c_pos] = '\0';
 3151:   rl_display_fixed++;
 3152: }
 3153: 
 3154: /* Clear to the end of the line.  COUNT is the minimum
 3155:    number of character spaces to clear, but we use a terminal escape
 3156:    sequence if available. */
 3157: void
 3158: _rl_clear_to_eol (int count)
 3159: {
 3160: #ifndef __MSDOS__
 3161:   if (_rl_term_clreol)
 3162:     tputs (_rl_term_clreol, 1, _rl_output_character_function);
 3163:   else
 3164: #endif
 3165:     if (count)
 3166:       space_to_eol (count);
 3167: }
 3168: 
 3169: /* Clear to the end of the line using spaces.  COUNT is the minimum
 3170:    number of character spaces to clear, */
 3171: static void
 3172: space_to_eol (int count)
 3173: {
 3174:   register int i;
 3175: 
 3176:   for (i = 0; i < count; i++)
 3177:     putc (' ', rl_outstream);
 3178: 
 3179:   _rl_last_c_pos += count;
 3180: }
 3181: 
 3182: void
 3183: _rl_clear_screen (int clrscr)
 3184: {
 3185: #if defined (__DJGPP__)
 3186:   ScreenClear ();
 3187:   ScreenSetCursor (0, 0);
 3188: #else
 3189:   if (_rl_term_clrpag)
 3190:     {
 3191:       tputs (_rl_term_clrpag, 1, _rl_output_character_function);
 3192:       if (clrscr && _rl_term_clrscroll)
 3193: 	tputs (_rl_term_clrscroll, 1, _rl_output_character_function);
 3194:     }
 3195:   else
 3196:     rl_crlf ();
 3197: #endif /* __DJGPP__ */
 3198: }
 3199: 
 3200: /* Insert COUNT characters from STRING to the output stream at column COL. */
 3201: static void
 3202: insert_some_chars (char *string, int count, int col)
 3203: {
 3204:   open_some_spaces (col);
 3205:   _rl_output_some_chars (string, count);
 3206: }
 3207: 
 3208: /* Insert COL spaces, keeping the cursor at the same position.  We follow the
 3209:    ncurses documentation and use either im/ei with explicit spaces, or IC/ic
 3210:    by itself.  We assume there will either be ei or we don't need to use it. */
 3211: static void
 3212: open_some_spaces (int col)
 3213: {
 3214: #if !defined (__MSDOS__) && (!defined (__MINGW32__) || defined (NCURSES_VERSION))
 3215:   char *buffer;
 3216:   register int i;
 3217: 
 3218:   /* If IC is defined, then we do not have to "enter" insert mode. */
 3219:   if (_rl_term_IC)
 3220:     {
 3221:       buffer = tgoto (_rl_term_IC, 0, col);
 3222:       tputs (buffer, 1, _rl_output_character_function);
 3223:     }
 3224:   else if (_rl_term_im && *_rl_term_im)
 3225:     {
 3226:       tputs (_rl_term_im, 1, _rl_output_character_function);
 3227:       /* just output the desired number of spaces */
 3228:       for (i = col; i--; )
 3229: 	_rl_output_character_function (' ');
 3230:       /* If there is a string to turn off insert mode, use it now. */
 3231:       if (_rl_term_ei && *_rl_term_ei)
 3232: 	tputs (_rl_term_ei, 1, _rl_output_character_function);
 3233:       /* and move back the right number of spaces */
 3234:       _rl_backspace (col);
 3235:     }
 3236:   else if (_rl_term_ic && *_rl_term_ic)
 3237:     {
 3238:       /* If there is a special command for inserting characters, then
 3239: 	 use that first to open up the space. */
 3240:       for (i = col; i--; )
 3241: 	tputs (_rl_term_ic, 1, _rl_output_character_function);
 3242:     }
 3243: #endif /* !__MSDOS__ && (!__MINGW32__ || NCURSES_VERSION)*/
 3244: }
 3245: 
 3246: /* Delete COUNT characters from the display line. */
 3247: static void
 3248: delete_chars (int count)
 3249: {
 3250:   if (count > _rl_screenwidth)	/* XXX */
 3251:     return;
 3252: 
 3253: #if !defined (__MSDOS__) && (!defined (__MINGW32__) || defined (NCURSES_VERSION))
 3254:   if (_rl_term_DC && *_rl_term_DC)
 3255:     {
 3256:       char *buffer;
 3257:       buffer = tgoto (_rl_term_DC, count, count);
 3258:       tputs (buffer, count, _rl_output_character_function);
 3259:     }
 3260:   else
 3261:     {
 3262:       if (_rl_term_dc && *_rl_term_dc)
 3263: 	while (count--)
 3264: 	  tputs (_rl_term_dc, 1, _rl_output_character_function);
 3265:     }
 3266: #endif /* !__MSDOS__ && (!__MINGW32__ || NCURSES_VERSION)*/
 3267: }
 3268: 
 3269: void
 3270: _rl_update_final (void)
 3271: {
 3272:   int full_lines, woff, botline_length;
 3273: 
 3274:   if (line_structures_initialized == 0)
 3275:     return;
 3276: 
 3277:   full_lines = 0;
 3278:   /* If the cursor is the only thing on an otherwise-blank last line,
 3279:      compensate so we don't print an extra CRLF. */
 3280:   if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
 3281: 	visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
 3282:     {
 3283:       _rl_vis_botlin--;
 3284:       full_lines = 1;
 3285:     }
 3286:   _rl_move_vert (_rl_vis_botlin);
 3287:   woff = W_OFFSET(_rl_vis_botlin, wrap_offset);
 3288:   botline_length = VIS_LLEN(_rl_vis_botlin) - woff;
 3289:   /* If we've wrapped lines, remove the final xterm line-wrap flag. */
 3290:   if (full_lines && _rl_term_autowrap && botline_length == _rl_screenwidth)
 3291:     {
 3292:       char *last_line, *last_face;
 3293: 
 3294:       /* LAST_LINE includes invisible characters, so if you want to get the
 3295: 	 last character of the first line, you have to take WOFF into account.
 3296: 	 This needs to be done for both calls to _rl_move_cursor_relative,
 3297: 	 which takes a buffer position as the first argument, and any direct
 3298: 	 subscripts of LAST_LINE. */
 3299:       last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]]; /* = VIS_CHARS(_rl_vis_botlin); */
 3300:       last_face = &vis_face[vis_lbreaks[_rl_vis_botlin]]; /* = VIS_CHARS(_rl_vis_botlin); */
 3301:       cpos_buffer_position = -1;	/* don't know where we are in buffer */
 3302:       _rl_move_cursor_relative (_rl_screenwidth - 1 + woff, last_line, last_face);	/* XXX */
 3303:       _rl_clear_to_eol (0);
 3304:       puts_face (&last_line[_rl_screenwidth - 1 + woff],
 3305: 		 &last_face[_rl_screenwidth - 1 + woff], 1);
 3306:     }
 3307:   _rl_vis_botlin = 0;
 3308:   if (botline_length > 0 || _rl_last_c_pos > 0)
 3309:     rl_crlf ();
 3310:   fflush (rl_outstream);
 3311:   rl_display_fixed++;
 3312: }
 3313: 
 3314: /* Move to the start of the current line. */
 3315: static void
 3316: cr (void)
 3317: {
 3318:   _rl_cr ();
 3319:   _rl_last_c_pos = 0;
 3320: }
 3321: 
 3322: /* Redraw the last line of a multi-line prompt that may possibly contain
 3323:    terminal escape sequences.  Called with the cursor at column 0 of the
 3324:    line to draw the prompt on. */
 3325: static void
 3326: redraw_prompt (char *t)
 3327: {
 3328:   char *oldp;
 3329: 
 3330:   oldp = rl_display_prompt;
 3331:   rl_save_prompt ();
 3332: 
 3333:   rl_display_prompt = t;
 3334:   local_prompt = expand_prompt (t, PMT_MULTILINE,
 3335: 				   &prompt_visible_length,
 3336: 				   &prompt_last_invisible,
 3337: 				   &prompt_invis_chars_first_line,
 3338: 				   &prompt_physical_chars);
 3339:   local_prompt_prefix = (char *)NULL;
 3340:   local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
 3341: 
 3342:   rl_forced_update_display ();
 3343: 
 3344:   rl_display_prompt = oldp;
 3345:   rl_restore_prompt();
 3346: }
 3347:       
 3348: /* Redisplay the current line after a SIGWINCH is received. */
 3349: void
 3350: _rl_redisplay_after_sigwinch (void)
 3351: {
 3352:   char *t;
 3353: 
 3354:   /* Clear the last line (assuming that the screen size change will result in
 3355:      either more or fewer characters on that line only) and put the cursor at
 3356:      column 0.  Make sure the right thing happens if we have wrapped to a new
 3357:      screen line. */
 3358:   if (_rl_term_cr)
 3359:     {
 3360:       _rl_move_vert (_rl_vis_botlin);
 3361: 
 3362:       _rl_cr ();
 3363:       _rl_last_c_pos = 0;
 3364: 
 3365: #if !defined (__MSDOS__)
 3366:       if (_rl_term_clreol)
 3367: 	tputs (_rl_term_clreol, 1, _rl_output_character_function);
 3368:       else
 3369: #endif
 3370: 	{
 3371: 	  space_to_eol (_rl_screenwidth);
 3372: 	  _rl_cr ();
 3373: 	}
 3374: 
 3375:       if (_rl_last_v_pos > 0)
 3376: 	_rl_move_vert (0);
 3377:     }
 3378:   else
 3379:     rl_crlf ();
 3380: 
 3381:   /* Redraw only the last line of a multi-line prompt. */
 3382:   t = strrchr (rl_display_prompt, '\n');
 3383:   if (t)
 3384:     redraw_prompt (++t);
 3385:   else
 3386:     rl_forced_update_display ();
 3387: }
 3388: 
 3389: void
 3390: _rl_clean_up_for_exit (void)
 3391: {
 3392:   if (_rl_echoing_p)
 3393:     {
 3394:       if (_rl_vis_botlin > 0)	/* minor optimization plus bug fix */
 3395: 	_rl_move_vert (_rl_vis_botlin);
 3396:       _rl_vis_botlin = 0;
 3397:       fflush (rl_outstream);
 3398:       rl_restart_output (1, 0);
 3399:     }
 3400: }
 3401: 
 3402: void
 3403: _rl_erase_entire_line (void)
 3404: {
 3405:   cr ();
 3406:   _rl_clear_to_eol (0);
 3407:   cr ();
 3408:   fflush (rl_outstream);
 3409: }
 3410: 
 3411: void
 3412: _rl_ttyflush (void)
 3413: {
 3414:   fflush (rl_outstream);
 3415: }
 3416: 
 3417: /* return the `current display line' of the cursor -- the number of lines to
 3418:    move up to get to the first screen line of the current readline line. */
 3419: int
 3420: _rl_current_display_line (void)
 3421: {
 3422:   int ret, nleft;
 3423: 
 3424:   /* Find out whether or not there might be invisible characters in the
 3425:      editing buffer. */
 3426:   if (rl_display_prompt == rl_prompt)
 3427:     nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length;
 3428:   else
 3429:     nleft = _rl_last_c_pos - _rl_screenwidth;
 3430: 
 3431:   if (nleft > 0)
 3432:     ret = 1 + nleft / _rl_screenwidth;
 3433:   else
 3434:     ret = 0;
 3435: 
 3436:   return ret;
 3437: }
 3438: 
 3439: void
 3440: _rl_refresh_line (void)
 3441: {
 3442:   rl_clear_visible_line ();
 3443:   rl_redraw_prompt_last_line ();
 3444:   rl_keep_mark_active ();
 3445: }
 3446: 
 3447: #if defined (HANDLE_MULTIBYTE)
 3448: /* Calculate the number of screen columns occupied by STR from START to END.
 3449:    In the case of multibyte characters with stateful encoding, we have to
 3450:    scan from the beginning of the string to take the state into account. */
 3451: static int
 3452: _rl_col_width (const char *str, int start, int end, int flags)
 3453: {
 3454:   wchar_t wc;
 3455:   mbstate_t ps;
 3456:   int tmp, point, width, max;
 3457: 
 3458:   if (end <= start)
 3459:     return 0;
 3460:   if (MB_CUR_MAX == 1 || rl_byte_oriented)
 3461:     /* this can happen in some cases where it's inconvenient to check */
 3462:     return (end - start);
 3463: 
 3464:   memset (&ps, 0, sizeof (mbstate_t));
 3465: 
 3466:   point = 0;
 3467:   max = end;
 3468: 
 3469:   /* Try to short-circuit common cases.  The adjustment to remove wrap_offset
 3470:      is done by the caller. */
 3471:   /* 1.  prompt string */
 3472:   if (flags && start == 0 && end == local_prompt_len && memcmp (str, local_prompt, local_prompt_len) == 0)
 3473:     return (prompt_physical_chars + wrap_offset);
 3474:   /* 2.  prompt string + line contents */
 3475:   else if (flags && start == 0 && local_prompt_len > 0 && end > local_prompt_len && local_prompt && memcmp (str, local_prompt, local_prompt_len) == 0)
 3476:     {
 3477:       tmp = prompt_physical_chars + wrap_offset;
 3478:       /* XXX - try to call ourselves recursively with non-prompt portion */
 3479:       tmp += _rl_col_width (str, local_prompt_len, end, flags);
 3480:       return (tmp);
 3481:     }
 3482: 
 3483:   while (point < start)
 3484:     {
 3485:       if (_rl_utf8locale && UTF8_SINGLEBYTE(str[point]))
 3486: 	{
 3487: 	  memset (&ps, 0, sizeof (mbstate_t));
 3488: 	  tmp = 1;
 3489: 	}
 3490:       else
 3491: 	tmp = mbrlen (str + point, max, &ps);
 3492:       if (MB_INVALIDCH ((size_t)tmp))
 3493: 	{
 3494: 	  /* In this case, the bytes are invalid or too short to compose a
 3495: 	     multibyte character, so we assume that the first byte represents
 3496: 	     a single character. */
 3497: 	  point++;
 3498: 	  max--;
 3499: 
 3500: 	  /* Clear the state of the byte sequence, because in this case the
 3501: 	     effect of mbstate is undefined. */
 3502: 	  memset (&ps, 0, sizeof (mbstate_t));
 3503: 	}
 3504:       else if (MB_NULLWCH (tmp))
 3505: 	break;		/* Found '\0' */
 3506:       else
 3507: 	{
 3508: 	  point += tmp;
 3509: 	  max -= tmp;
 3510: 	}
 3511:     }
 3512: 
 3513:   /* If START is not a byte that starts a character, then POINT will be
 3514:      greater than START.  In this case, assume that (POINT - START) gives
 3515:      a byte count that is the number of columns of difference. */
 3516:   width = point - start;
 3517: 
 3518:   while (point < end)
 3519:     {
 3520:       if (_rl_utf8locale && UTF8_SINGLEBYTE(str[point]))
 3521: 	{
 3522: 	  tmp = 1;
 3523: 	  wc = (wchar_t) str[point];
 3524: 	}
 3525:       else
 3526: 	tmp = mbrtowc (&wc, str + point, max, &ps);
 3527:       if (MB_INVALIDCH ((size_t)tmp))
 3528: 	{
 3529: 	  /* In this case, the bytes are invalid or too short to compose a
 3530: 	     multibyte character, so we assume that the first byte represents
 3531: 	     a single character. */
 3532: 	  point++;
 3533: 	  max--;
 3534: 
 3535: 	  /* and assume that the byte occupies a single column. */
 3536: 	  width++;
 3537: 
 3538: 	  /* Clear the state of the byte sequence, because in this case the
 3539: 	     effect of mbstate is undefined. */
 3540: 	  memset (&ps, 0, sizeof (mbstate_t));
 3541: 	}
 3542:       else if (MB_NULLWCH (tmp))
 3543: 	break;			/* Found '\0' */
 3544:       else
 3545: 	{
 3546: 	  point += tmp;
 3547: 	  max -= tmp;
 3548: 	  tmp = WCWIDTH(wc);
 3549: 	  width += (tmp >= 0) ? tmp : 1;
 3550: 	}
 3551:     }
 3552: 
 3553:   width += point - end;
 3554: 
 3555:   return width;
 3556: }
 3557: #endif /* HANDLE_MULTIBYTE */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>