158314Sache/* $FreeBSD$ */ 221308Sache/* display.c -- readline redisplay facility. */ 321308Sache 4165675Sache/* Copyright (C) 1987-2006 Free Software Foundation, Inc. 521308Sache 621308Sache This file is part of the GNU Readline Library, a library for 721308Sache reading lines of text with interactive input and history editing. 821308Sache 921308Sache The GNU Readline Library is free software; you can redistribute it 1021308Sache and/or modify it under the terms of the GNU General Public License 1158314Sache as published by the Free Software Foundation; either version 2, or 1221308Sache (at your option) any later version. 1321308Sache 1421308Sache The GNU Readline Library is distributed in the hope that it will be 1521308Sache useful, but WITHOUT ANY WARRANTY; without even the implied warranty 1621308Sache of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1721308Sache GNU General Public License for more details. 1821308Sache 1921308Sache The GNU General Public License is often shipped with GNU software, and 2021308Sache is generally kept in a file called COPYING or LICENSE. If you do not 2121308Sache have a copy of the license, write to the Free Software Foundation, 2258314Sache 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ 2321308Sache#define READLINE_LIBRARY 2421308Sache 2521308Sache#if defined (HAVE_CONFIG_H) 2621308Sache# include <config.h> 2721308Sache#endif 2821308Sache 2921308Sache#include <sys/types.h> 3021308Sache 3121308Sache#if defined (HAVE_UNISTD_H) 3221308Sache# include <unistd.h> 3321308Sache#endif /* HAVE_UNISTD_H */ 3421308Sache 3526497Sache#include "posixstat.h" 3626497Sache 3721308Sache#if defined (HAVE_STDLIB_H) 3821308Sache# include <stdlib.h> 3921308Sache#else 4021308Sache# include "ansi_stdlib.h" 4121308Sache#endif /* HAVE_STDLIB_H */ 4221308Sache 4326497Sache#include <stdio.h> 4421308Sache 4521308Sache/* System-specific feature definitions and include files. */ 4621308Sache#include "rldefs.h" 47119614Sache#include "rlmbutil.h" 4821308Sache 4921308Sache/* Termcap library stuff. */ 5021308Sache#include "tcap.h" 5121308Sache 5221308Sache/* Some standard library routines. */ 5321308Sache#include "readline.h" 5421308Sache#include "history.h" 5521308Sache 5658314Sache#include "rlprivate.h" 5758314Sache#include "xmalloc.h" 5858314Sache 5921308Sache#if !defined (strchr) && !defined (__STDC__) 6021308Sacheextern char *strchr (), *strrchr (); 6121308Sache#endif /* !strchr && !__STDC__ */ 6221308Sache 63119614Sachestatic void update_line PARAMS((char *, char *, int, int, int, int)); 64119614Sachestatic void space_to_eol PARAMS((int)); 65119614Sachestatic void delete_chars PARAMS((int)); 66119614Sachestatic void insert_some_chars PARAMS((char *, int, int)); 67119614Sachestatic void cr PARAMS((void)); 6821308Sache 69119614Sache#if defined (HANDLE_MULTIBYTE) 70136759Speterstatic int _rl_col_width PARAMS((const char *, int, int)); 71119614Sachestatic int *_rl_wrapped_line; 72119614Sache#else 73119614Sache# define _rl_col_width(l, s, e) (((e) <= (s)) ? 0 : (e) - (s)) 74119614Sache#endif 75119614Sache 7621308Sachestatic int *inv_lbreaks, *vis_lbreaks; 7758314Sachestatic int inv_lbsize, vis_lbsize; 7821308Sache 7921308Sache/* Heuristic used to decide whether it is faster to move from CUR to NEW 80165675Sache by backing up or outputting a carriage return and moving forward. CUR 81165675Sache and NEW are either both buffer positions or absolute screen positions. */ 8221308Sache#define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new))) 8321308Sache 84165675Sache/* _rl_last_c_pos is an absolute cursor position in multibyte locales and a 85165675Sache buffer index in others. This macro is used when deciding whether the 86165675Sache current cursor position is in the middle of a prompt string containing 87165675Sache invisible characters. */ 88165675Sache#define PROMPT_ENDING_INDEX \ 89165675Sache ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) ? prompt_physical_chars : prompt_last_invisible+1) 90165675Sache 91165675Sache 9221308Sache/* **************************************************************** */ 9321308Sache/* */ 9421308Sache/* Display stuff */ 9521308Sache/* */ 9621308Sache/* **************************************************************** */ 9721308Sache 9821308Sache/* This is the stuff that is hard for me. I never seem to write good 9921308Sache display routines in C. Let's see how I do this time. */ 10021308Sache 10121308Sache/* (PWP) Well... Good for a simple line updater, but totally ignores 10221308Sache the problems of input lines longer than the screen width. 10321308Sache 10421308Sache update_line and the code that calls it makes a multiple line, 10521308Sache automatically wrapping line update. Careful attention needs 10621308Sache to be paid to the vertical position variables. */ 10721308Sache 10821308Sache/* Keep two buffers; one which reflects the current contents of the 10921308Sache screen, and the other to draw what we think the new contents should 11021308Sache be. Then compare the buffers, and make whatever changes to the 11121308Sache screen itself that we should. Finally, make the buffer that we 11221308Sache just drew into be the one which reflects the current contents of the 11321308Sache screen, and place the cursor where it belongs. 11421308Sache 11521308Sache Commands that want to can fix the display themselves, and then let 11621308Sache this function know that the display has been fixed by setting the 11721308Sache RL_DISPLAY_FIXED variable. This is good for efficiency. */ 11821308Sache 11921308Sache/* Application-specific redisplay function. */ 12075409Sacherl_voidfunc_t *rl_redisplay_function = rl_redisplay; 12121308Sache 12221308Sache/* Global variables declared here. */ 12321308Sache/* What YOU turn on when you have handled all redisplay yourself. */ 12421308Sacheint rl_display_fixed = 0; 12521308Sache 12621308Sacheint _rl_suppress_redisplay = 0; 127157188Sacheint _rl_want_redisplay = 0; 12821308Sache 12921308Sache/* The stuff that gets printed out before the actual text of the line. 13021308Sache This is usually pointing to rl_prompt. */ 13121308Sachechar *rl_display_prompt = (char *)NULL; 13221308Sache 13321308Sache/* Pseudo-global variables declared here. */ 134157188Sache 13521308Sache/* The visible cursor position. If you print some text, adjust this. */ 136157188Sache/* NOTE: _rl_last_c_pos is used as a buffer index when not in a locale 137157188Sache supporting multibyte characters, and an absolute cursor position when 138157188Sache in such a locale. This is an artifact of the donated multibyte support. 139157188Sache Care must be taken when modifying its value. */ 14021308Sacheint _rl_last_c_pos = 0; 14121308Sacheint _rl_last_v_pos = 0; 14221308Sache 143157188Sachestatic int cpos_adjusted; 144165675Sachestatic int cpos_buffer_position; 145157188Sache 14621308Sache/* Number of lines currently on screen minus 1. */ 14721308Sacheint _rl_vis_botlin = 0; 14821308Sache 14921308Sache/* Variables used only in this file. */ 15021308Sache/* The last left edge of text that was displayed. This is used when 15121308Sache doing horizontal scrolling. It shifts in thirds of a screenwidth. */ 15221308Sachestatic int last_lmargin; 15321308Sache 15421308Sache/* The line display buffers. One is the line currently displayed on 15521308Sache the screen. The other is the line about to be displayed. */ 15621308Sachestatic char *visible_line = (char *)NULL; 15721308Sachestatic char *invisible_line = (char *)NULL; 15821308Sache 15921308Sache/* A buffer for `modeline' messages. */ 16021308Sachestatic char msg_buf[128]; 16121308Sache 16221308Sache/* Non-zero forces the redisplay even if we thought it was unnecessary. */ 16321308Sachestatic int forced_display; 16421308Sache 16521308Sache/* Default and initial buffer size. Can grow. */ 16621308Sachestatic int line_size = 1024; 16721308Sache 16875409Sache/* Variables to keep track of the expanded prompt string, which may 16975409Sache include invisible characters. */ 17075409Sache 17121308Sachestatic char *local_prompt, *local_prompt_prefix; 172165675Sachestatic int local_prompt_len; 17375409Sachestatic int prompt_visible_length, prompt_prefix_length; 17421308Sache 17521308Sache/* The number of invisible characters in the line currently being 17621308Sache displayed on the screen. */ 17721308Sachestatic int visible_wrap_offset; 17821308Sache 17975409Sache/* The number of invisible characters in the prompt string. Static so it 18075409Sache can be shared between rl_redisplay and update_line */ 18121308Sachestatic int wrap_offset; 18221308Sache 18375409Sache/* The index of the last invisible character in the prompt string. */ 18475409Sachestatic int prompt_last_invisible; 18521308Sache 18621308Sache/* The length (buffer offset) of the first line of the last (possibly 18721308Sache multi-line) buffer displayed on the screen. */ 18821308Sachestatic int visible_first_line_len; 18921308Sache 19075409Sache/* Number of invisible characters on the first physical line of the prompt. 19175409Sache Only valid when the number of physical characters in the prompt exceeds 19275409Sache (or is equal to) _rl_screenwidth. */ 19375409Sachestatic int prompt_invis_chars_first_line; 19475409Sache 19575409Sachestatic int prompt_last_screen_line; 19675409Sache 197136759Speterstatic int prompt_physical_chars; 198136759Speter 199157188Sache/* Variables to save and restore prompt and display information. */ 200157188Sache 201157188Sache/* These are getting numerous enough that it's time to create a struct. */ 202157188Sache 203157188Sachestatic char *saved_local_prompt; 204157188Sachestatic char *saved_local_prefix; 205157188Sachestatic int saved_last_invisible; 206157188Sachestatic int saved_visible_length; 207157188Sachestatic int saved_prefix_length; 208165675Sachestatic int saved_local_length; 209157188Sachestatic int saved_invis_chars_first_line; 210157188Sachestatic int saved_physical_chars; 211157188Sache 21221308Sache/* Expand the prompt string S and return the number of visible 21321308Sache characters in *LP, if LP is not null. This is currently more-or-less 21421308Sache a placeholder for expansion. LIP, if non-null is a place to store the 21575409Sache index of the last invisible character in the returned string. NIFLP, 21675409Sache if non-zero, is a place to store the number of invisible characters in 217136759Speter the first prompt line. The previous are used as byte counts -- indexes 218136759Speter into a character buffer. */ 21921308Sache 22021308Sache/* Current implementation: 22121308Sache \001 (^A) start non-visible characters 22221308Sache \002 (^B) end non-visible characters 22321308Sache all characters except \001 and \002 (following a \001) are copied to 22421308Sache the returned string; all characters except those between \001 and 22521308Sache \002 are assumed to be `visible'. */ 22621308Sache 22721308Sachestatic char * 228136759Speterexpand_prompt (pmt, lp, lip, niflp, vlp) 22921308Sache char *pmt; 230136759Speter int *lp, *lip, *niflp, *vlp; 23121308Sache{ 232165675Sache char *r, *ret, *p, *igstart; 233136759Speter int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars; 23421308Sache 23521308Sache /* Short-circuit if we can. */ 236136759Speter if ((MB_CUR_MAX <= 1 || rl_byte_oriented) && strchr (pmt, RL_PROMPT_START_IGNORE) == 0) 23721308Sache { 23821308Sache r = savestring (pmt); 23921308Sache if (lp) 24021308Sache *lp = strlen (r); 241136759Speter if (lip) 242136759Speter *lip = 0; 243136759Speter if (niflp) 244136759Speter *niflp = 0; 245136759Speter if (vlp) 246136759Speter *vlp = lp ? *lp : strlen (r); 24721308Sache return r; 24821308Sache } 24921308Sache 25021308Sache l = strlen (pmt); 251119614Sache r = ret = (char *)xmalloc (l + 1); 25275409Sache 25375409Sache invfl = 0; /* invisible chars in first line of prompt */ 254136759Speter invflset = 0; /* we only want to set invfl once */ 25575409Sache 256165675Sache igstart = 0; 257136759Speter for (rl = ignoring = last = ninvis = physchars = 0, p = pmt; p && *p; p++) 25821308Sache { 25921308Sache /* This code strips the invisible character string markers 26021308Sache RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */ 261165675Sache if (ignoring == 0 && *p == RL_PROMPT_START_IGNORE) /* XXX - check ignoring? */ 26221308Sache { 263165675Sache ignoring = 1; 264165675Sache igstart = p; 26521308Sache continue; 26621308Sache } 26721308Sache else if (ignoring && *p == RL_PROMPT_END_IGNORE) 26821308Sache { 26921308Sache ignoring = 0; 270165675Sache if (p != (igstart + 1)) 271157188Sache last = r - ret - 1; 27221308Sache continue; 27321308Sache } 27421308Sache else 27521308Sache { 276136759Speter#if defined (HANDLE_MULTIBYTE) 277136759Speter if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 278136759Speter { 279136759Speter pind = p - pmt; 280136759Speter ind = _rl_find_next_mbchar (pmt, pind, 1, MB_FIND_NONZERO); 281136759Speter l = ind - pind; 282136759Speter while (l--) 283136759Speter *r++ = *p++; 284136759Speter if (!ignoring) 285136759Speter { 286136759Speter rl += ind - pind; 287136759Speter physchars += _rl_col_width (pmt, pind, ind); 288136759Speter } 289136759Speter else 290136759Speter ninvis += ind - pind; 291136759Speter p--; /* compensate for later increment */ 292136759Speter } 29375409Sache else 294136759Speter#endif 295136759Speter { 296136759Speter *r++ = *p; 297136759Speter if (!ignoring) 298136759Speter { 299136759Speter rl++; /* visible length byte counter */ 300136759Speter physchars++; 301136759Speter } 302136759Speter else 303136759Speter ninvis++; /* invisible chars byte counter */ 304136759Speter } 305136759Speter 306136759Speter if (invflset == 0 && rl >= _rl_screenwidth) 307136759Speter { 308136759Speter invfl = ninvis; 309136759Speter invflset = 1; 310136759Speter } 31121308Sache } 31221308Sache } 31321308Sache 31475409Sache if (rl < _rl_screenwidth) 31575409Sache invfl = ninvis; 31675409Sache 31721308Sache *r = '\0'; 31821308Sache if (lp) 31921308Sache *lp = rl; 32021308Sache if (lip) 32121308Sache *lip = last; 32275409Sache if (niflp) 32375409Sache *niflp = invfl; 324136759Speter if (vlp) 325136759Speter *vlp = physchars; 32621308Sache return ret; 32721308Sache} 32821308Sache 32958314Sache/* Just strip out RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE from 33058314Sache PMT and return the rest of PMT. */ 33158314Sachechar * 33258314Sache_rl_strip_prompt (pmt) 33358314Sache char *pmt; 33458314Sache{ 33558314Sache char *ret; 33658314Sache 337136759Speter ret = expand_prompt (pmt, (int *)NULL, (int *)NULL, (int *)NULL, (int *)NULL); 33858314Sache return ret; 33958314Sache} 34058314Sache 34121308Sache/* 34221308Sache * Expand the prompt string into the various display components, if 34321308Sache * necessary. 34421308Sache * 34521308Sache * local_prompt = expanded last line of string in rl_display_prompt 34621308Sache * (portion after the final newline) 34721308Sache * local_prompt_prefix = portion before last newline of rl_display_prompt, 34821308Sache * expanded via expand_prompt 34975409Sache * prompt_visible_length = number of visible characters in local_prompt 35075409Sache * prompt_prefix_length = number of visible characters in local_prompt_prefix 35121308Sache * 35221308Sache * This function is called once per call to readline(). It may also be 35321308Sache * called arbitrarily to expand the primary prompt. 35421308Sache * 35521308Sache * The return value is the number of visible characters on the last line 35621308Sache * of the (possibly multi-line) prompt. 35721308Sache */ 35821308Sacheint 35921308Sacherl_expand_prompt (prompt) 36021308Sache char *prompt; 36121308Sache{ 36221308Sache char *p, *t; 36321308Sache int c; 36421308Sache 36521308Sache /* Clear out any saved values. */ 36675409Sache FREE (local_prompt); 36775409Sache FREE (local_prompt_prefix); 36875409Sache 36921308Sache local_prompt = local_prompt_prefix = (char *)0; 370165675Sache local_prompt_len = 0; 371157188Sache prompt_last_invisible = prompt_invis_chars_first_line = 0; 372157188Sache prompt_visible_length = prompt_physical_chars = 0; 37321308Sache 37421308Sache if (prompt == 0 || *prompt == 0) 37521308Sache return (0); 37621308Sache 37721308Sache p = strrchr (prompt, '\n'); 37821308Sache if (!p) 37921308Sache { 38075409Sache /* The prompt is only one logical line, though it might wrap. */ 38175409Sache local_prompt = expand_prompt (prompt, &prompt_visible_length, 38275409Sache &prompt_last_invisible, 383136759Speter &prompt_invis_chars_first_line, 384136759Speter &prompt_physical_chars); 38521308Sache local_prompt_prefix = (char *)0; 386165675Sache local_prompt_len = local_prompt ? strlen (local_prompt) : 0; 38775409Sache return (prompt_visible_length); 38821308Sache } 38921308Sache else 39021308Sache { 39121308Sache /* The prompt spans multiple lines. */ 39221308Sache t = ++p; 39375409Sache local_prompt = expand_prompt (p, &prompt_visible_length, 39475409Sache &prompt_last_invisible, 395257586Ssbruno &prompt_invis_chars_first_line, 396136759Speter &prompt_physical_chars); 39721308Sache c = *t; *t = '\0'; 39821308Sache /* The portion of the prompt string up to and including the 39921308Sache final newline is now null-terminated. */ 40075409Sache local_prompt_prefix = expand_prompt (prompt, &prompt_prefix_length, 40175409Sache (int *)NULL, 402257586Ssbruno (int *)NULL, 403136759Speter (int *)NULL); 40421308Sache *t = c; 405165675Sache local_prompt_len = local_prompt ? strlen (local_prompt) : 0; 40675409Sache return (prompt_prefix_length); 40721308Sache } 40821308Sache} 40921308Sache 41058314Sache/* Initialize the VISIBLE_LINE and INVISIBLE_LINE arrays, and their associated 41158314Sache arrays of line break markers. MINSIZE is the minimum size of VISIBLE_LINE 41258314Sache and INVISIBLE_LINE; if it is greater than LINE_SIZE, LINE_SIZE is 41358314Sache increased. If the lines have already been allocated, this ensures that 41458314Sache they can hold at least MINSIZE characters. */ 41558314Sachestatic void 41658314Sacheinit_line_structures (minsize) 41758314Sache int minsize; 41858314Sache{ 41958314Sache register int n; 42058314Sache 42158314Sache if (invisible_line == 0) /* initialize it */ 42258314Sache { 42358314Sache if (line_size < minsize) 42458314Sache line_size = minsize; 425119614Sache visible_line = (char *)xmalloc (line_size); 426119614Sache invisible_line = (char *)xmalloc (line_size); 42758314Sache } 42858314Sache else if (line_size < minsize) /* ensure it can hold MINSIZE chars */ 42958314Sache { 43058314Sache line_size *= 2; 43158314Sache if (line_size < minsize) 43258314Sache line_size = minsize; 433119614Sache visible_line = (char *)xrealloc (visible_line, line_size); 434119614Sache invisible_line = (char *)xrealloc (invisible_line, line_size); 43558314Sache } 43658314Sache 43758314Sache for (n = minsize; n < line_size; n++) 43858314Sache { 43958314Sache visible_line[n] = 0; 44058314Sache invisible_line[n] = 1; 44158314Sache } 44258314Sache 44358314Sache if (vis_lbreaks == 0) 44458314Sache { 44558314Sache /* should be enough. */ 44658314Sache inv_lbsize = vis_lbsize = 256; 44758314Sache inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int)); 44858314Sache vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int)); 449119614Sache#if defined (HANDLE_MULTIBYTE) 450119614Sache _rl_wrapped_line = (int *)xmalloc (vis_lbsize * sizeof (int)); 451119614Sache#endif 45258314Sache inv_lbreaks[0] = vis_lbreaks[0] = 0; 45358314Sache } 45458314Sache} 45558314Sache 45621308Sache/* Basic redisplay algorithm. */ 45721308Sachevoid 45821308Sacherl_redisplay () 45921308Sache{ 46021308Sache register int in, out, c, linenum, cursor_linenum; 46121308Sache register char *line; 462165675Sache int inv_botlin, lb_botlin, lb_linenum, o_cpos; 463136759Speter int newlines, lpos, temp, modmark, n0, num; 46421308Sache char *prompt_this_line; 465119614Sache#if defined (HANDLE_MULTIBYTE) 466119614Sache wchar_t wc; 467119614Sache size_t wc_bytes; 468119614Sache int wc_width; 469119614Sache mbstate_t ps; 470119614Sache int _rl_wrapped_multicolumn = 0; 471119614Sache#endif 47221308Sache 47321308Sache if (!readline_echoing_p) 47421308Sache return; 47521308Sache 47621308Sache if (!rl_display_prompt) 47721308Sache rl_display_prompt = ""; 47821308Sache 479157188Sache if (invisible_line == 0 || vis_lbreaks == 0) 48021308Sache { 48158314Sache init_line_structures (0); 48221308Sache rl_on_new_line (); 48321308Sache } 48421308Sache 48521308Sache /* Draw the line into the buffer. */ 486165675Sache cpos_buffer_position = -1; 48721308Sache 48821308Sache line = invisible_line; 48921308Sache out = inv_botlin = 0; 49021308Sache 49121308Sache /* Mark the line as modified or not. We only do this for history 49221308Sache lines. */ 493136759Speter modmark = 0; 49421308Sache if (_rl_mark_modified_lines && current_history () && rl_undo_list) 49521308Sache { 49621308Sache line[out++] = '*'; 49721308Sache line[out] = '\0'; 498136759Speter modmark = 1; 49921308Sache } 50021308Sache 50121308Sache /* If someone thought that the redisplay was handled, but the currently 50221308Sache visible line has a different modification state than the one about 50321308Sache to become visible, then correct the caller's misconception. */ 50421308Sache if (visible_line[0] != invisible_line[0]) 50521308Sache rl_display_fixed = 0; 50621308Sache 50721308Sache /* If the prompt to be displayed is the `primary' readline prompt (the 50821308Sache one passed to readline()), use the values we have already expanded. 50921308Sache If not, use what's already in rl_display_prompt. WRAP_OFFSET is the 51021308Sache number of non-visible characters in the prompt string. */ 51121308Sache if (rl_display_prompt == rl_prompt || local_prompt) 51221308Sache { 51321308Sache if (local_prompt_prefix && forced_display) 51421308Sache _rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix)); 51521308Sache 516165675Sache if (local_prompt_len > 0) 51721308Sache { 518165675Sache temp = local_prompt_len + out + 2; 51947563Sache if (temp >= line_size) 52047563Sache { 52147563Sache line_size = (temp + 1024) - (temp % 1024); 522119614Sache visible_line = (char *)xrealloc (visible_line, line_size); 523119614Sache line = invisible_line = (char *)xrealloc (invisible_line, line_size); 52447563Sache } 525165675Sache strncpy (line + out, local_prompt, local_prompt_len); 526165675Sache out += local_prompt_len; 52721308Sache } 52821308Sache line[out] = '\0'; 529165675Sache wrap_offset = local_prompt_len - prompt_visible_length; 53021308Sache } 53121308Sache else 53221308Sache { 53321308Sache int pmtlen; 53421308Sache prompt_this_line = strrchr (rl_display_prompt, '\n'); 53521308Sache if (!prompt_this_line) 53621308Sache prompt_this_line = rl_display_prompt; 53721308Sache else 53821308Sache { 53921308Sache prompt_this_line++; 54058314Sache pmtlen = prompt_this_line - rl_display_prompt; /* temp var */ 54121308Sache if (forced_display) 54221308Sache { 54358314Sache _rl_output_some_chars (rl_display_prompt, pmtlen); 54421308Sache /* Make sure we are at column zero even after a newline, 54521308Sache regardless of the state of terminal output processing. */ 54658314Sache if (pmtlen < 2 || prompt_this_line[-2] != '\r') 54721308Sache cr (); 54821308Sache } 54921308Sache } 55021308Sache 551136759Speter prompt_physical_chars = pmtlen = strlen (prompt_this_line); 55247563Sache temp = pmtlen + out + 2; 55347563Sache if (temp >= line_size) 55447563Sache { 55547563Sache line_size = (temp + 1024) - (temp % 1024); 556119614Sache visible_line = (char *)xrealloc (visible_line, line_size); 557119614Sache line = invisible_line = (char *)xrealloc (invisible_line, line_size); 55847563Sache } 55921308Sache strncpy (line + out, prompt_this_line, pmtlen); 56021308Sache out += pmtlen; 56121308Sache line[out] = '\0'; 56275409Sache wrap_offset = prompt_invis_chars_first_line = 0; 56321308Sache } 56421308Sache 565168666Sache#if defined (HANDLE_MULTIBYTE) 56658314Sache#define CHECK_INV_LBREAKS() \ 56758314Sache do { \ 56858314Sache if (newlines >= (inv_lbsize - 2)) \ 56958314Sache { \ 57058314Sache inv_lbsize *= 2; \ 57158314Sache inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \ 572168666Sache _rl_wrapped_line = (int *)xrealloc (_rl_wrapped_line, inv_lbsize * sizeof (int)); \ 57358314Sache } \ 57458314Sache } while (0) 575168666Sache#else 576168666Sache#define CHECK_INV_LBREAKS() \ 577168666Sache do { \ 578168666Sache if (newlines >= (inv_lbsize - 2)) \ 579168666Sache { \ 580168666Sache inv_lbsize *= 2; \ 581168666Sache inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \ 582168666Sache } \ 583168666Sache } while (0) 584168666Sache#endif /* HANDLE_MULTIBYTE */ 585119614Sache 586119614Sache#if defined (HANDLE_MULTIBYTE) 58721308Sache#define CHECK_LPOS() \ 58821308Sache do { \ 58947563Sache lpos++; \ 59075409Sache if (lpos >= _rl_screenwidth) \ 59147563Sache { \ 59258314Sache if (newlines >= (inv_lbsize - 2)) \ 59358314Sache { \ 59458314Sache inv_lbsize *= 2; \ 59558314Sache inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \ 596119614Sache _rl_wrapped_line = (int *)xrealloc (_rl_wrapped_line, inv_lbsize * sizeof (int)); \ 59758314Sache } \ 59847563Sache inv_lbreaks[++newlines] = out; \ 599119614Sache _rl_wrapped_line[newlines] = _rl_wrapped_multicolumn; \ 60047563Sache lpos = 0; \ 60147563Sache } \ 60221308Sache } while (0) 603119614Sache#else 604119614Sache#define CHECK_LPOS() \ 605119614Sache do { \ 606119614Sache lpos++; \ 607119614Sache if (lpos >= _rl_screenwidth) \ 608119614Sache { \ 609119614Sache if (newlines >= (inv_lbsize - 2)) \ 610119614Sache { \ 611119614Sache inv_lbsize *= 2; \ 612119614Sache inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \ 613119614Sache } \ 614119614Sache inv_lbreaks[++newlines] = out; \ 615119614Sache lpos = 0; \ 616119614Sache } \ 617119614Sache } while (0) 618119614Sache#endif 61921308Sache 62021308Sache /* inv_lbreaks[i] is where line i starts in the buffer. */ 62121308Sache inv_lbreaks[newlines = 0] = 0; 622136759Speter#if 0 62326497Sache lpos = out - wrap_offset; 624136759Speter#else 625136759Speter lpos = prompt_physical_chars + modmark; 626136759Speter#endif 627136759Speter 628119614Sache#if defined (HANDLE_MULTIBYTE) 629119614Sache memset (_rl_wrapped_line, 0, vis_lbsize); 630136759Speter num = 0; 631119614Sache#endif 63221308Sache 63375409Sache /* prompt_invis_chars_first_line is the number of invisible characters in 63475409Sache the first physical line of the prompt. 63575409Sache wrap_offset - prompt_invis_chars_first_line is the number of invis 63675409Sache chars on the second line. */ 63775409Sache 63875409Sache /* what if lpos is already >= _rl_screenwidth before we start drawing the 63926497Sache contents of the command line? */ 64075409Sache while (lpos >= _rl_screenwidth) 64121308Sache { 642165675Sache int z; 64375409Sache /* fix from Darin Johnson <darin@acuson.com> for prompt string with 64475409Sache invisible characters that is longer than the screen width. The 64575409Sache prompt_invis_chars_first_line variable could be made into an array 64675409Sache saying how many invisible characters there are per line, but that's 64775409Sache probably too much work for the benefit gained. How many people have 648136759Speter prompts that exceed two physical lines? 649136759Speter Additional logic fix from Edward Catmur <ed@catmur.co.uk> */ 650136759Speter#if defined (HANDLE_MULTIBYTE) 651165675Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 652136759Speter { 653165675Sache n0 = num; 654165675Sache temp = local_prompt_len; 655165675Sache while (num < temp) 656136759Speter { 657165675Sache z = _rl_col_width (local_prompt, n0, num); 658165675Sache if (z > _rl_screenwidth) 659165675Sache { 660165675Sache num = _rl_find_prev_mbchar (local_prompt, num, MB_FIND_ANY); 661165675Sache break; 662165675Sache } 663165675Sache else if (z == _rl_screenwidth) 664165675Sache break; 665165675Sache num++; 666136759Speter } 667165675Sache temp = num; 668136759Speter } 669165675Sache else 670136759Speter#endif /* !HANDLE_MULTIBYTE */ 671165675Sache temp = ((newlines + 1) * _rl_screenwidth); 672165675Sache 673165675Sache /* Now account for invisible characters in the current line. */ 674165675Sache temp += ((local_prompt_prefix == 0) ? ((newlines == 0) ? prompt_invis_chars_first_line 675165675Sache : ((newlines == 1) ? wrap_offset : 0)) 676165675Sache : ((newlines == 0) ? wrap_offset :0)); 677136759Speter 678136759Speter inv_lbreaks[++newlines] = temp; 679136759Speter#if defined (HANDLE_MULTIBYTE) 680165675Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 681165675Sache lpos -= _rl_col_width (local_prompt, n0, num); 682165675Sache else 683119614Sache#endif 684165675Sache lpos -= _rl_screenwidth; 68526497Sache } 68626497Sache 68775409Sache prompt_last_screen_line = newlines; 68875409Sache 68975409Sache /* Draw the rest of the line (after the prompt) into invisible_line, keeping 690165675Sache track of where the cursor is (cpos_buffer_position), the number of the line containing 69175409Sache the cursor (lb_linenum), the last line number (lb_botlin and inv_botlin). 69275409Sache It maintains an array of line breaks for display (inv_lbreaks). 69375409Sache This handles expanding tabs for display and displaying meta characters. */ 69426497Sache lb_linenum = 0; 695119614Sache#if defined (HANDLE_MULTIBYTE) 696119614Sache in = 0; 697119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 698119614Sache { 699119614Sache memset (&ps, 0, sizeof (mbstate_t)); 700119614Sache wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps); 701119614Sache } 702119614Sache else 703119614Sache wc_bytes = 1; 704119614Sache while (in < rl_end) 705119614Sache#else 70626497Sache for (in = 0; in < rl_end; in++) 707119614Sache#endif 70826497Sache { 70921308Sache c = (unsigned char)rl_line_buffer[in]; 71021308Sache 711119614Sache#if defined (HANDLE_MULTIBYTE) 712119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 713119614Sache { 714136759Speter if (MB_INVALIDCH (wc_bytes)) 715119614Sache { 716119614Sache /* Byte sequence is invalid or shortened. Assume that the 717119614Sache first byte represents a character. */ 718119614Sache wc_bytes = 1; 719119614Sache /* Assume that a character occupies a single column. */ 720119614Sache wc_width = 1; 721119614Sache memset (&ps, 0, sizeof (mbstate_t)); 722119614Sache } 723136759Speter else if (MB_NULLWCH (wc_bytes)) 724119614Sache break; /* Found '\0' */ 725119614Sache else 726119614Sache { 727119614Sache temp = wcwidth (wc); 728136759Speter wc_width = (temp >= 0) ? temp : 1; 729119614Sache } 730119614Sache } 731119614Sache#endif 732119614Sache 73321308Sache if (out + 8 >= line_size) /* XXX - 8 for \t */ 73421308Sache { 73521308Sache line_size *= 2; 736119614Sache visible_line = (char *)xrealloc (visible_line, line_size); 737119614Sache invisible_line = (char *)xrealloc (invisible_line, line_size); 73821308Sache line = invisible_line; 73921308Sache } 74021308Sache 74121308Sache if (in == rl_point) 74221308Sache { 743165675Sache cpos_buffer_position = out; 74421308Sache lb_linenum = newlines; 74521308Sache } 74621308Sache 747119614Sache#if defined (HANDLE_MULTIBYTE) 748119614Sache if (META_CHAR (c) && _rl_output_meta_chars == 0) /* XXX - clean up */ 749119614Sache#else 75021308Sache if (META_CHAR (c)) 751119614Sache#endif 75221308Sache { 75321308Sache if (_rl_output_meta_chars == 0) 75421308Sache { 75521308Sache sprintf (line + out, "\\%o", c); 75621308Sache 75775409Sache if (lpos + 4 >= _rl_screenwidth) 75821308Sache { 75975409Sache temp = _rl_screenwidth - lpos; 76058314Sache CHECK_INV_LBREAKS (); 76121308Sache inv_lbreaks[++newlines] = out + temp; 76221308Sache lpos = 4 - temp; 76321308Sache } 76421308Sache else 76521308Sache lpos += 4; 76621308Sache 76721308Sache out += 4; 76821308Sache } 76921308Sache else 77021308Sache { 77121308Sache line[out++] = c; 77221308Sache CHECK_LPOS(); 77321308Sache } 77421308Sache } 77521308Sache#if defined (DISPLAY_TABS) 77621308Sache else if (c == '\t') 77721308Sache { 77875409Sache register int newout; 77947563Sache 78047563Sache#if 0 78121308Sache newout = (out | (int)7) + 1; 78247563Sache#else 78347563Sache newout = out + 8 - lpos % 8; 78447563Sache#endif 78521308Sache temp = newout - out; 78675409Sache if (lpos + temp >= _rl_screenwidth) 78721308Sache { 78821308Sache register int temp2; 78975409Sache temp2 = _rl_screenwidth - lpos; 79058314Sache CHECK_INV_LBREAKS (); 79121308Sache inv_lbreaks[++newlines] = out + temp2; 79221308Sache lpos = temp - temp2; 79321308Sache while (out < newout) 79421308Sache line[out++] = ' '; 79521308Sache } 79621308Sache else 79721308Sache { 79821308Sache while (out < newout) 79921308Sache line[out++] = ' '; 80021308Sache lpos += temp; 80121308Sache } 80221308Sache } 80321308Sache#endif 80475409Sache else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up) 80547563Sache { 80647563Sache line[out++] = '\0'; /* XXX - sentinel */ 80758314Sache CHECK_INV_LBREAKS (); 80847563Sache inv_lbreaks[++newlines] = out; 80947563Sache lpos = 0; 81047563Sache } 81121308Sache else if (CTRL_CHAR (c) || c == RUBOUT) 81221308Sache { 81321308Sache line[out++] = '^'; 81421308Sache CHECK_LPOS(); 81521308Sache line[out++] = CTRL_CHAR (c) ? UNCTRL (c) : '?'; 81621308Sache CHECK_LPOS(); 81721308Sache } 81821308Sache else 81921308Sache { 820119614Sache#if defined (HANDLE_MULTIBYTE) 821119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 822119614Sache { 823119614Sache register int i; 824119614Sache 825119614Sache _rl_wrapped_multicolumn = 0; 826119614Sache 827119614Sache if (_rl_screenwidth < lpos + wc_width) 828119614Sache for (i = lpos; i < _rl_screenwidth; i++) 829119614Sache { 830119614Sache /* The space will be removed in update_line() */ 831119614Sache line[out++] = ' '; 832119614Sache _rl_wrapped_multicolumn++; 833119614Sache CHECK_LPOS(); 834119614Sache } 835119614Sache if (in == rl_point) 836119614Sache { 837165675Sache cpos_buffer_position = out; 838119614Sache lb_linenum = newlines; 839119614Sache } 840119614Sache for (i = in; i < in+wc_bytes; i++) 841119614Sache line[out++] = rl_line_buffer[i]; 842119614Sache for (i = 0; i < wc_width; i++) 843119614Sache CHECK_LPOS(); 844119614Sache } 845119614Sache else 846119614Sache { 847119614Sache line[out++] = c; 848119614Sache CHECK_LPOS(); 849119614Sache } 850119614Sache#else 85121308Sache line[out++] = c; 85221308Sache CHECK_LPOS(); 853119614Sache#endif 85421308Sache } 855119614Sache 856119614Sache#if defined (HANDLE_MULTIBYTE) 857119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 858119614Sache { 859119614Sache in += wc_bytes; 860119614Sache wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps); 861119614Sache } 862119614Sache else 863119614Sache in++; 864119614Sache#endif 865119614Sache 86621308Sache } 86721308Sache line[out] = '\0'; 868165675Sache if (cpos_buffer_position < 0) 86921308Sache { 870165675Sache cpos_buffer_position = out; 87121308Sache lb_linenum = newlines; 87221308Sache } 87321308Sache 87421308Sache inv_botlin = lb_botlin = newlines; 87558314Sache CHECK_INV_LBREAKS (); 87621308Sache inv_lbreaks[newlines+1] = out; 87721308Sache cursor_linenum = lb_linenum; 87821308Sache 879165675Sache /* CPOS_BUFFER_POSITION == position in buffer where cursor should be placed. 88075409Sache CURSOR_LINENUM == line number where the cursor should be placed. */ 88121308Sache 88221308Sache /* PWP: now is when things get a bit hairy. The visible and invisible 88321308Sache line buffers are really multiple lines, which would wrap every 88421308Sache (screenwidth - 1) characters. Go through each in turn, finding 88521308Sache the changed region and updating it. The line order is top to bottom. */ 88621308Sache 88721308Sache /* If we can move the cursor up and down, then use multiple lines, 88821308Sache otherwise, let long lines display in a single terminal line, and 88921308Sache horizontally scroll it. */ 89021308Sache 89175409Sache if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up) 89221308Sache { 893157188Sache int nleft, pos, changed_screen_line, tx; 89421308Sache 89521308Sache if (!rl_display_fixed || forced_display) 89621308Sache { 89721308Sache forced_display = 0; 89821308Sache 89921308Sache /* If we have more than a screenful of material to display, then 90021308Sache only display a screenful. We should display the last screen, 90121308Sache not the first. */ 90275409Sache if (out >= _rl_screenchars) 903119614Sache { 904119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 905119614Sache out = _rl_find_prev_mbchar (line, _rl_screenchars, MB_FIND_ANY); 906119614Sache else 907119614Sache out = _rl_screenchars - 1; 908119614Sache } 90921308Sache 91021308Sache /* The first line is at character position 0 in the buffer. The 91121308Sache second and subsequent lines start at inv_lbreaks[N], offset by 91221308Sache OFFSET (which has already been calculated above). */ 91321308Sache 914257586Ssbruno#define INVIS_FIRST() (prompt_physical_chars > _rl_screenwidth ? prompt_invis_chars_first_line : wrap_offset) 915257586Ssbruno#define WRAP_OFFSET(line, offset) ((line == 0) \ 916257586Ssbruno ? (offset ? INVIS_FIRST() : 0) \ 917257586Ssbruno : ((line == prompt_last_screen_line) ? wrap_offset-prompt_invis_chars_first_line : 0)) 91821308Sache#define W_OFFSET(line, offset) ((line) == 0 ? offset : 0) 91921308Sache#define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l])) 92021308Sache#define INV_LLEN(l) (inv_lbreaks[l+1] - inv_lbreaks[l]) 92121308Sache#define VIS_CHARS(line) (visible_line + vis_lbreaks[line]) 92221308Sache#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line) 92321308Sache#define INV_LINE(line) (invisible_line + inv_lbreaks[line]) 92421308Sache 92521308Sache /* For each line in the buffer, do the updating display. */ 92621308Sache for (linenum = 0; linenum <= inv_botlin; linenum++) 92721308Sache { 928165675Sache /* This can lead us astray if we execute a program that changes 929165675Sache the locale from a non-multibyte to a multibyte one. */ 930157188Sache o_cpos = _rl_last_c_pos; 931157188Sache cpos_adjusted = 0; 93221308Sache update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum, 93321308Sache VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin); 93421308Sache 935157188Sache /* update_line potentially changes _rl_last_c_pos, but doesn't 936157188Sache take invisible characters into account, since _rl_last_c_pos 937157188Sache is an absolute cursor position in a multibyte locale. See 938157188Sache if compensating here is the right thing, or if we have to 939157188Sache change update_line itself. There is one case in which 940157188Sache update_line adjusts _rl_last_c_pos itself (so it can pass 941157188Sache _rl_move_cursor_relative accurate values); it communicates 942165675Sache this back by setting cpos_adjusted. If we assume that 943165675Sache _rl_last_c_pos is correct (an absolute cursor position) each 944165675Sache time update_line is called, then we can assume in our 945165675Sache calculations that o_cpos does not need to be adjusted by 946165675Sache wrap_offset. */ 947157188Sache if (linenum == 0 && (MB_CUR_MAX > 1 && rl_byte_oriented == 0) && 948157188Sache cpos_adjusted == 0 && 949157188Sache _rl_last_c_pos != o_cpos && 950157188Sache _rl_last_c_pos > wrap_offset && 951157188Sache o_cpos < prompt_last_invisible) 952257586Ssbruno _rl_last_c_pos -= prompt_invis_chars_first_line; /* XXX - was wrap_offset */ 953257586Ssbruno else if (linenum == prompt_last_screen_line && prompt_physical_chars > _rl_screenwidth && 954257586Ssbruno (MB_CUR_MAX > 1 && rl_byte_oriented == 0) && 955257586Ssbruno cpos_adjusted == 0 && 956257586Ssbruno _rl_last_c_pos != o_cpos && 957257586Ssbruno _rl_last_c_pos > (prompt_last_invisible - _rl_screenwidth - prompt_invis_chars_first_line)) 958257586Ssbruno _rl_last_c_pos -= (wrap_offset-prompt_invis_chars_first_line); 959157188Sache 96021308Sache /* If this is the line with the prompt, we might need to 96121308Sache compensate for invisible characters in the new line. Do 96221308Sache this only if there is not more than one new line (which 96321308Sache implies that we completely overwrite the old visible line) 96421308Sache and the new line is shorter than the old. Make sure we are 96521308Sache at the end of the new line before clearing. */ 96621308Sache if (linenum == 0 && 96721308Sache inv_botlin == 0 && _rl_last_c_pos == out && 96821308Sache (wrap_offset > visible_wrap_offset) && 96921308Sache (_rl_last_c_pos < visible_first_line_len)) 97021308Sache { 971157188Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 972157188Sache nleft = _rl_screenwidth - _rl_last_c_pos; 973157188Sache else 974157188Sache nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos; 97521308Sache if (nleft) 97626497Sache _rl_clear_to_eol (nleft); 97721308Sache } 97821308Sache 97921308Sache /* Since the new first line is now visible, save its length. */ 98021308Sache if (linenum == 0) 98121308Sache visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset; 98221308Sache } 98321308Sache 98421308Sache /* We may have deleted some lines. If so, clear the left over 98521308Sache blank ones at the bottom out. */ 98621308Sache if (_rl_vis_botlin > inv_botlin) 98721308Sache { 98821308Sache char *tt; 98921308Sache for (; linenum <= _rl_vis_botlin; linenum++) 99021308Sache { 99121308Sache tt = VIS_CHARS (linenum); 99221308Sache _rl_move_vert (linenum); 99321308Sache _rl_move_cursor_relative (0, tt); 99426497Sache _rl_clear_to_eol 99575409Sache ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth); 99621308Sache } 99721308Sache } 99821308Sache _rl_vis_botlin = inv_botlin; 99921308Sache 100021308Sache /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a 100121308Sache different screen line during this redisplay. */ 100221308Sache changed_screen_line = _rl_last_v_pos != cursor_linenum; 100321308Sache if (changed_screen_line) 100421308Sache { 100521308Sache _rl_move_vert (cursor_linenum); 100675409Sache /* If we moved up to the line with the prompt using _rl_term_up, 100747563Sache the physical cursor position on the screen stays the same, 100847563Sache but the buffer position needs to be adjusted to account 100947563Sache for invisible characters. */ 1010157188Sache if ((MB_CUR_MAX == 1 || rl_byte_oriented) && cursor_linenum == 0 && wrap_offset) 101147563Sache _rl_last_c_pos += wrap_offset; 101221308Sache } 101321308Sache 101421308Sache /* We have to reprint the prompt if it contains invisible 101521308Sache characters, since it's not generally OK to just reprint 101621308Sache the characters from the current cursor position. But we 101721308Sache only need to reprint it if the cursor is before the last 101821308Sache invisible character in the prompt string. */ 101975409Sache nleft = prompt_visible_length + wrap_offset; 102021308Sache if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 && 1021165675Sache#if 0 1022165675Sache _rl_last_c_pos <= PROMPT_ENDING_INDEX && local_prompt) 1023165675Sache#else 1024165675Sache _rl_last_c_pos < PROMPT_ENDING_INDEX && local_prompt) 1025165675Sache#endif 102621308Sache { 102758314Sache#if defined (__MSDOS__) 102858314Sache putc ('\r', rl_outstream); 102958314Sache#else 103075409Sache if (_rl_term_cr) 103175409Sache tputs (_rl_term_cr, 1, _rl_output_character_function); 103258314Sache#endif 103321308Sache _rl_output_some_chars (local_prompt, nleft); 1034119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1035157188Sache _rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft) - wrap_offset; 1036119614Sache else 1037119614Sache _rl_last_c_pos = nleft; 103821308Sache } 103921308Sache 104021308Sache /* Where on that line? And where does that line start 104121308Sache in the buffer? */ 104221308Sache pos = inv_lbreaks[cursor_linenum]; 104321308Sache /* nleft == number of characters in the line buffer between the 1044165675Sache start of the line and the desired cursor position. */ 1045165675Sache nleft = cpos_buffer_position - pos; 104621308Sache 1047157188Sache /* NLEFT is now a number of characters in a buffer. When in a 1048157188Sache multibyte locale, however, _rl_last_c_pos is an absolute cursor 1049157188Sache position that doesn't take invisible characters in the prompt 1050157188Sache into account. We use a fudge factor to compensate. */ 1051157188Sache 105221308Sache /* Since _rl_backspace() doesn't know about invisible characters in the 105321308Sache prompt, and there's no good way to tell it, we compensate for 105421308Sache those characters here and call _rl_backspace() directly. */ 105521308Sache if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos) 105621308Sache { 1057165675Sache /* TX == new physical cursor position in multibyte locale. */ 1058119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1059157188Sache tx = _rl_col_width (&visible_line[pos], 0, nleft) - visible_wrap_offset; 1060119614Sache else 1061157188Sache tx = nleft; 1062257586Ssbruno if (tx >= 0 && _rl_last_c_pos > tx) 1063157188Sache { 1064157188Sache _rl_backspace (_rl_last_c_pos - tx); /* XXX */ 1065157188Sache _rl_last_c_pos = tx; 1066157188Sache } 106721308Sache } 106821308Sache 1069157188Sache /* We need to note that in a multibyte locale we are dealing with 1070157188Sache _rl_last_c_pos as an absolute cursor position, but moving to a 1071157188Sache point specified by a buffer position (NLEFT) that doesn't take 1072157188Sache invisible characters into account. */ 1073119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 107421308Sache _rl_move_cursor_relative (nleft, &invisible_line[pos]); 1075119614Sache else if (nleft != _rl_last_c_pos) 1076119614Sache _rl_move_cursor_relative (nleft, &invisible_line[pos]); 107721308Sache } 107821308Sache } 107921308Sache else /* Do horizontal scrolling. */ 108021308Sache { 108121308Sache#define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0) 108221308Sache int lmargin, ndisp, nleft, phys_c_pos, t; 108321308Sache 108421308Sache /* Always at top line. */ 108521308Sache _rl_last_v_pos = 0; 108621308Sache 108721308Sache /* Compute where in the buffer the displayed line should start. This 108821308Sache will be LMARGIN. */ 108921308Sache 109021308Sache /* The number of characters that will be displayed before the cursor. */ 1091165675Sache ndisp = cpos_buffer_position - wrap_offset; 109275409Sache nleft = prompt_visible_length + wrap_offset; 109321308Sache /* Where the new cursor position will be on the screen. This can be 109447563Sache longer than SCREENWIDTH; if it is, lmargin will be adjusted. */ 1095165675Sache phys_c_pos = cpos_buffer_position - (last_lmargin ? last_lmargin : wrap_offset); 109675409Sache t = _rl_screenwidth / 3; 109721308Sache 109821308Sache /* If the number of characters had already exceeded the screenwidth, 109947563Sache last_lmargin will be > 0. */ 110021308Sache 110121308Sache /* If the number of characters to be displayed is more than the screen 110247563Sache width, compute the starting offset so that the cursor is about 110347563Sache two-thirds of the way across the screen. */ 110475409Sache if (phys_c_pos > _rl_screenwidth - 2) 110521308Sache { 1106165675Sache lmargin = cpos_buffer_position - (2 * t); 110721308Sache if (lmargin < 0) 110821308Sache lmargin = 0; 110921308Sache /* If the left margin would be in the middle of a prompt with 111021308Sache invisible characters, don't display the prompt at all. */ 111121308Sache if (wrap_offset && lmargin > 0 && lmargin < nleft) 111221308Sache lmargin = nleft; 111321308Sache } 111475409Sache else if (ndisp < _rl_screenwidth - 2) /* XXX - was -1 */ 111547563Sache lmargin = 0; 111621308Sache else if (phys_c_pos < 1) 111721308Sache { 111821308Sache /* If we are moving back towards the beginning of the line and 111921308Sache the last margin is no longer correct, compute a new one. */ 1120165675Sache lmargin = ((cpos_buffer_position - 1) / t) * t; /* XXX */ 112121308Sache if (wrap_offset && lmargin > 0 && lmargin < nleft) 112221308Sache lmargin = nleft; 112321308Sache } 112421308Sache else 112547563Sache lmargin = last_lmargin; 112621308Sache 112721308Sache /* If the first character on the screen isn't the first character 112821308Sache in the display line, indicate this with a special character. */ 112921308Sache if (lmargin > 0) 113021308Sache line[lmargin] = '<'; 113121308Sache 113221308Sache /* If SCREENWIDTH characters starting at LMARGIN do not encompass 113347563Sache the whole line, indicate that with a special character at the 113447563Sache right edge of the screen. If LMARGIN is 0, we need to take the 113547563Sache wrap offset into account. */ 113675409Sache t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth; 113721308Sache if (t < out) 113847563Sache line[t - 1] = '>'; 113921308Sache 114021308Sache if (!rl_display_fixed || forced_display || lmargin != last_lmargin) 114121308Sache { 114221308Sache forced_display = 0; 114321308Sache update_line (&visible_line[last_lmargin], 114421308Sache &invisible_line[lmargin], 114521308Sache 0, 114675409Sache _rl_screenwidth + visible_wrap_offset, 114775409Sache _rl_screenwidth + (lmargin ? 0 : wrap_offset), 114821308Sache 0); 114921308Sache 115021308Sache /* If the visible new line is shorter than the old, but the number 115121308Sache of invisible characters is greater, and we are at the end of 115221308Sache the new line, we need to clear to eol. */ 115321308Sache t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset); 115421308Sache if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) && 115521308Sache (_rl_last_c_pos == out) && 115621308Sache t < visible_first_line_len) 115721308Sache { 115875409Sache nleft = _rl_screenwidth - t; 115926497Sache _rl_clear_to_eol (nleft); 116021308Sache } 116121308Sache visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset); 116275409Sache if (visible_first_line_len > _rl_screenwidth) 116375409Sache visible_first_line_len = _rl_screenwidth; 116421308Sache 1165165675Sache _rl_move_cursor_relative (cpos_buffer_position - lmargin, &invisible_line[lmargin]); 116621308Sache last_lmargin = lmargin; 116721308Sache } 116821308Sache } 116921308Sache fflush (rl_outstream); 117021308Sache 117121308Sache /* Swap visible and non-visible lines. */ 117221308Sache { 117375409Sache char *vtemp = visible_line; 117458314Sache int *itemp = vis_lbreaks, ntemp = vis_lbsize; 117558314Sache 117621308Sache visible_line = invisible_line; 117775409Sache invisible_line = vtemp; 117858314Sache 117921308Sache vis_lbreaks = inv_lbreaks; 118021308Sache inv_lbreaks = itemp; 118158314Sache 118258314Sache vis_lbsize = inv_lbsize; 118358314Sache inv_lbsize = ntemp; 118458314Sache 118521308Sache rl_display_fixed = 0; 118621308Sache /* If we are displaying on a single line, and last_lmargin is > 0, we 118721308Sache are not displaying any invisible characters, so set visible_wrap_offset 118821308Sache to 0. */ 118921308Sache if (_rl_horizontal_scroll_mode && last_lmargin) 119021308Sache visible_wrap_offset = 0; 119121308Sache else 119221308Sache visible_wrap_offset = wrap_offset; 119321308Sache } 119421308Sache} 119521308Sache 119621308Sache/* PWP: update_line() is based on finding the middle difference of each 119721308Sache line on the screen; vis: 119821308Sache 119921308Sache /old first difference 120021308Sache /beginning of line | /old last same /old EOL 120121308Sache v v v v 120221308Sacheold: eddie> Oh, my little gruntle-buggy is to me, as lurgid as 120321308Sachenew: eddie> Oh, my little buggy says to me, as lurgid as 120421308Sache ^ ^ ^ ^ 120521308Sache \beginning of line | \new last same \new end of line 120621308Sache \new first difference 120721308Sache 120821308Sache All are character pointers for the sake of speed. Special cases for 120947563Sache no differences, as well as for end of line additions must be handled. 121021308Sache 121121308Sache Could be made even smarter, but this works well enough */ 121221308Sachestatic void 121321308Sacheupdate_line (old, new, current_line, omax, nmax, inv_botlin) 121421308Sache register char *old, *new; 121521308Sache int current_line, omax, nmax, inv_botlin; 121621308Sache{ 121721308Sache register char *ofd, *ols, *oe, *nfd, *nls, *ne; 1218257586Ssbruno int temp, lendiff, wsatend, od, nd, twidth, o_cpos; 121921308Sache int current_invis_chars; 1220119614Sache int col_lendiff, col_temp; 1221119614Sache#if defined (HANDLE_MULTIBYTE) 1222119614Sache mbstate_t ps_new, ps_old; 1223165675Sache int new_offset, old_offset; 1224119614Sache#endif 122521308Sache 122621308Sache /* If we're at the right edge of a terminal that supports xn, we're 122721308Sache ready to wrap around, so do so. This fixes problems with knowing 122821308Sache the exact cursor position and cut-and-paste with certain terminal 122921308Sache emulators. In this calculation, TEMP is the physical screen 123021308Sache position of the cursor. */ 1231157188Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1232157188Sache temp = _rl_last_c_pos; 1233157188Sache else 1234257586Ssbruno temp = _rl_last_c_pos - WRAP_OFFSET (_rl_last_v_pos, visible_wrap_offset); 123575409Sache if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode 1236119614Sache && _rl_last_v_pos == current_line - 1) 123721308Sache { 1238119614Sache#if defined (HANDLE_MULTIBYTE) 1239119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1240119614Sache { 1241119614Sache wchar_t wc; 1242119614Sache mbstate_t ps; 1243119614Sache int tempwidth, bytes; 1244119614Sache size_t ret; 1245119614Sache 1246119614Sache /* This fixes only double-column characters, but if the wrapped 1247119614Sache character comsumes more than three columns, spaces will be 1248119614Sache inserted in the string buffer. */ 1249119614Sache if (_rl_wrapped_line[current_line] > 0) 1250119614Sache _rl_clear_to_eol (_rl_wrapped_line[current_line]); 1251119614Sache 1252119614Sache memset (&ps, 0, sizeof (mbstate_t)); 1253119614Sache ret = mbrtowc (&wc, new, MB_CUR_MAX, &ps); 1254136759Speter if (MB_INVALIDCH (ret)) 1255119614Sache { 1256119614Sache tempwidth = 1; 1257119614Sache ret = 1; 1258119614Sache } 1259136759Speter else if (MB_NULLWCH (ret)) 1260119614Sache tempwidth = 0; 1261119614Sache else 1262119614Sache tempwidth = wcwidth (wc); 1263119614Sache 1264119614Sache if (tempwidth > 0) 1265119614Sache { 1266119614Sache int count; 1267119614Sache bytes = ret; 1268119614Sache for (count = 0; count < bytes; count++) 1269119614Sache putc (new[count], rl_outstream); 1270119614Sache _rl_last_c_pos = tempwidth; 1271119614Sache _rl_last_v_pos++; 1272119614Sache memset (&ps, 0, sizeof (mbstate_t)); 1273119614Sache ret = mbrtowc (&wc, old, MB_CUR_MAX, &ps); 1274119614Sache if (ret != 0 && bytes != 0) 1275119614Sache { 1276136759Speter if (MB_INVALIDCH (ret)) 1277119614Sache memmove (old+bytes, old+1, strlen (old+1)); 1278119614Sache else 1279119614Sache memmove (old+bytes, old+ret, strlen (old+ret)); 1280119614Sache memcpy (old, new, bytes); 1281119614Sache } 1282119614Sache } 1283119614Sache else 1284119614Sache { 1285119614Sache putc (' ', rl_outstream); 1286119614Sache _rl_last_c_pos = 1; 1287119614Sache _rl_last_v_pos++; 1288119614Sache if (old[0] && new[0]) 1289119614Sache old[0] = new[0]; 1290119614Sache } 1291119614Sache } 129221308Sache else 1293119614Sache#endif 1294119614Sache { 1295119614Sache if (new[0]) 1296119614Sache putc (new[0], rl_outstream); 1297119614Sache else 1298119614Sache putc (' ', rl_outstream); 1299157188Sache _rl_last_c_pos = 1; 1300119614Sache _rl_last_v_pos++; 1301119614Sache if (old[0] && new[0]) 1302119614Sache old[0] = new[0]; 1303119614Sache } 130421308Sache } 1305119614Sache 130621308Sache 130721308Sache /* Find first difference. */ 1308119614Sache#if defined (HANDLE_MULTIBYTE) 1309119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1310119614Sache { 1311136759Speter /* See if the old line is a subset of the new line, so that the 1312136759Speter only change is adding characters. */ 1313136759Speter temp = (omax < nmax) ? omax : nmax; 1314136759Speter if (memcmp (old, new, temp) == 0) 1315119614Sache { 1316136759Speter ofd = old + temp; 1317136759Speter nfd = new + temp; 1318119614Sache } 1319136759Speter else 1320136759Speter { 1321136759Speter memset (&ps_new, 0, sizeof(mbstate_t)); 1322136759Speter memset (&ps_old, 0, sizeof(mbstate_t)); 1323136759Speter 1324136759Speter if (omax == nmax && STREQN (new, old, omax)) 1325136759Speter { 1326136759Speter ofd = old + omax; 1327136759Speter nfd = new + nmax; 1328136759Speter } 1329136759Speter else 1330136759Speter { 1331136759Speter new_offset = old_offset = 0; 1332136759Speter for (ofd = old, nfd = new; 1333136759Speter (ofd - old < omax) && *ofd && 1334136759Speter _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new); ) 1335136759Speter { 1336136759Speter old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY); 1337136759Speter new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY); 1338136759Speter ofd = old + old_offset; 1339136759Speter nfd = new + new_offset; 1340136759Speter } 1341136759Speter } 1342136759Speter } 1343119614Sache } 1344119614Sache else 1345119614Sache#endif 134621308Sache for (ofd = old, nfd = new; 134721308Sache (ofd - old < omax) && *ofd && (*ofd == *nfd); 134821308Sache ofd++, nfd++) 134921308Sache ; 135021308Sache 135121308Sache /* Move to the end of the screen line. ND and OD are used to keep track 135221308Sache of the distance between ne and new and oe and old, respectively, to 135321308Sache move a subtraction out of each loop. */ 135421308Sache for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++); 135521308Sache for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++); 135621308Sache 135721308Sache /* If no difference, continue to next line. */ 135821308Sache if (ofd == oe && nfd == ne) 135921308Sache return; 136021308Sache 136121308Sache wsatend = 1; /* flag for trailing whitespace */ 1362119614Sache 1363119614Sache#if defined (HANDLE_MULTIBYTE) 1364119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1365119614Sache { 1366119614Sache ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY); 1367119614Sache nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY); 1368119614Sache while ((ols > ofd) && (nls > nfd)) 1369119614Sache { 1370119614Sache memset (&ps_old, 0, sizeof (mbstate_t)); 1371119614Sache memset (&ps_new, 0, sizeof (mbstate_t)); 1372119614Sache 1373136759Speter#if 0 1374136759Speter /* On advice from jir@yamato.ibm.com */ 1375119614Sache _rl_adjust_point (old, ols - old, &ps_old); 1376119614Sache _rl_adjust_point (new, nls - new, &ps_new); 1377136759Speter#endif 1378119614Sache 1379119614Sache if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0) 1380119614Sache break; 1381119614Sache 1382119614Sache if (*ols == ' ') 1383119614Sache wsatend = 0; 1384119614Sache 1385119614Sache ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY); 1386119614Sache nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY); 1387119614Sache } 1388119614Sache } 1389119614Sache else 1390119614Sache { 1391119614Sache#endif /* HANDLE_MULTIBYTE */ 139221308Sache ols = oe - 1; /* find last same */ 139321308Sache nls = ne - 1; 139421308Sache while ((ols > ofd) && (nls > nfd) && (*ols == *nls)) 139521308Sache { 139621308Sache if (*ols != ' ') 139721308Sache wsatend = 0; 139821308Sache ols--; 139921308Sache nls--; 140021308Sache } 1401119614Sache#if defined (HANDLE_MULTIBYTE) 1402119614Sache } 1403119614Sache#endif 140421308Sache 140521308Sache if (wsatend) 140621308Sache { 140721308Sache ols = oe; 140821308Sache nls = ne; 140921308Sache } 1410119614Sache#if defined (HANDLE_MULTIBYTE) 1411119614Sache /* This may not work for stateful encoding, but who cares? To handle 1412119614Sache stateful encoding properly, we have to scan each string from the 1413119614Sache beginning and compare. */ 1414119614Sache else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0) 1415119614Sache#else 141621308Sache else if (*ols != *nls) 1417119614Sache#endif 141821308Sache { 141921308Sache if (*ols) /* don't step past the NUL */ 1420119614Sache { 1421119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1422119614Sache ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY); 1423119614Sache else 1424119614Sache ols++; 1425119614Sache } 142621308Sache if (*nls) 1427119614Sache { 1428119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1429119614Sache nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY); 1430119614Sache else 1431119614Sache nls++; 1432119614Sache } 143321308Sache } 143421308Sache 143521308Sache /* count of invisible characters in the current invisible line. */ 143621308Sache current_invis_chars = W_OFFSET (current_line, wrap_offset); 143721308Sache if (_rl_last_v_pos != current_line) 143821308Sache { 143921308Sache _rl_move_vert (current_line); 1440157188Sache if ((MB_CUR_MAX == 1 || rl_byte_oriented) && current_line == 0 && visible_wrap_offset) 144121308Sache _rl_last_c_pos += visible_wrap_offset; 144221308Sache } 144321308Sache 144421308Sache /* If this is the first line and there are invisible characters in the 144521308Sache prompt string, and the prompt string has not changed, and the current 144621308Sache cursor position is before the last invisible character in the prompt, 144721308Sache and the index of the character to move to is past the end of the prompt 144821308Sache string, then redraw the entire prompt string. We can only do this 144921308Sache reliably if the terminal supports a `cr' capability. 145021308Sache 145121308Sache This is not an efficiency hack -- there is a problem with redrawing 145221308Sache portions of the prompt string if they contain terminal escape 145321308Sache sequences (like drawing the `unbold' sequence without a corresponding 145421308Sache `bold') that manifests itself on certain terminals. */ 145521308Sache 1456165675Sache lendiff = local_prompt_len; 145721308Sache od = ofd - old; /* index of first difference in visible line */ 145821308Sache if (current_line == 0 && !_rl_horizontal_scroll_mode && 145975409Sache _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 && 1460165675Sache od >= lendiff && _rl_last_c_pos < PROMPT_ENDING_INDEX) 146121308Sache { 146258314Sache#if defined (__MSDOS__) 146358314Sache putc ('\r', rl_outstream); 146458314Sache#else 146575409Sache tputs (_rl_term_cr, 1, _rl_output_character_function); 146658314Sache#endif 146721308Sache _rl_output_some_chars (local_prompt, lendiff); 1468119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1469157188Sache { 1470157188Sache /* We take wrap_offset into account here so we can pass correct 1471157188Sache information to _rl_move_cursor_relative. */ 1472157188Sache _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff) - wrap_offset; 1473157188Sache cpos_adjusted = 1; 1474157188Sache } 1475119614Sache else 1476119614Sache _rl_last_c_pos = lendiff; 147721308Sache } 147821308Sache 1479257586Ssbruno o_cpos = _rl_last_c_pos; 1480257586Ssbruno 1481165675Sache /* When this function returns, _rl_last_c_pos is correct, and an absolute 1482165675Sache cursor postion in multibyte mode, but a buffer index when not in a 1483165675Sache multibyte locale. */ 148421308Sache _rl_move_cursor_relative (od, old); 1485165675Sache#if 1 1486165675Sache#if defined (HANDLE_MULTIBYTE) 1487165675Sache /* We need to indicate that the cursor position is correct in the presence of 1488165675Sache invisible characters in the prompt string. Let's see if setting this when 1489165675Sache we make sure we're at the end of the drawn prompt string works. */ 1490257586Ssbruno if (current_line == 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0 && 1491257586Ssbruno (_rl_last_c_pos > 0 || o_cpos > 0) && 1492257586Ssbruno _rl_last_c_pos == prompt_physical_chars) 1493165675Sache cpos_adjusted = 1; 1494165675Sache#endif 1495165675Sache#endif 149621308Sache 1497119614Sache /* if (len (new) > len (old)) 1498119614Sache lendiff == difference in buffer 1499119614Sache col_lendiff == difference on screen 1500119614Sache When not using multibyte characters, these are equal */ 150121308Sache lendiff = (nls - nfd) - (ols - ofd); 1502119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1503119614Sache col_lendiff = _rl_col_width (new, nfd - new, nls - new) - _rl_col_width (old, ofd - old, ols - old); 1504119614Sache else 1505119614Sache col_lendiff = lendiff; 150621308Sache 150721308Sache /* If we are changing the number of invisible characters in a line, and 150821308Sache the spot of first difference is before the end of the invisible chars, 150921308Sache lendiff needs to be adjusted. */ 151021308Sache if (current_line == 0 && !_rl_horizontal_scroll_mode && 151121308Sache current_invis_chars != visible_wrap_offset) 1512119614Sache { 1513119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1514119614Sache { 1515119614Sache lendiff += visible_wrap_offset - current_invis_chars; 1516119614Sache col_lendiff += visible_wrap_offset - current_invis_chars; 1517119614Sache } 1518119614Sache else 1519119614Sache { 1520119614Sache lendiff += visible_wrap_offset - current_invis_chars; 1521119614Sache col_lendiff = lendiff; 1522119614Sache } 1523119614Sache } 152421308Sache 152521308Sache /* Insert (diff (len (old), len (new)) ch. */ 152621308Sache temp = ne - nfd; 1527119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1528119614Sache col_temp = _rl_col_width (new, nfd - new, ne - new); 1529119614Sache else 1530119614Sache col_temp = temp; 1531119614Sache 1532119614Sache if (col_lendiff > 0) /* XXX - was lendiff */ 153321308Sache { 153421308Sache /* Non-zero if we're increasing the number of lines. */ 153521308Sache int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin; 1536173406Sache /* If col_lendiff is > 0, implying that the new string takes up more 1537173406Sache screen real estate than the old, but lendiff is < 0, meaning that it 1538173406Sache takes fewer bytes, we need to just output the characters starting 1539173406Sache from the first difference. These will overwrite what is on the 1540173406Sache display, so there's no reason to do a smart update. This can really 1541173406Sache only happen in a multibyte environment. */ 1542173406Sache if (lendiff < 0) 1543173406Sache { 1544173406Sache _rl_output_some_chars (nfd, temp); 1545173406Sache _rl_last_c_pos += _rl_col_width (nfd, 0, temp); 1546173406Sache /* If nfd begins before any invisible characters in the prompt, 1547173406Sache adjust _rl_last_c_pos to account for wrap_offset and set 1548173406Sache cpos_adjusted to let the caller know. */ 1549173406Sache if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible)) 1550173406Sache { 1551173406Sache _rl_last_c_pos -= wrap_offset; 1552173406Sache cpos_adjusted = 1; 1553173406Sache } 1554173406Sache return; 1555173406Sache } 155621308Sache /* Sometimes it is cheaper to print the characters rather than 155721308Sache use the terminal's capabilities. If we're growing the number 155821308Sache of lines, make sure we actually cause the new line to wrap 155921308Sache around on auto-wrapping terminals. */ 1560173406Sache else if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl)) 156121308Sache { 156275409Sache /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and 156321308Sache _rl_horizontal_scroll_mode == 1, inserting the characters with 156475409Sache _rl_term_IC or _rl_term_ic will screw up the screen because of the 156521308Sache invisible characters. We need to just draw them. */ 156621308Sache if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 || 156775409Sache lendiff <= prompt_visible_length || !current_invis_chars)) 156821308Sache { 1569119614Sache insert_some_chars (nfd, lendiff, col_lendiff); 1570119614Sache _rl_last_c_pos += col_lendiff; 157121308Sache } 1572157188Sache else if ((MB_CUR_MAX == 1 || rl_byte_oriented != 0) && *ols == 0 && lendiff > 0) 157321308Sache { 157421308Sache /* At the end of a line the characters do not have to 157521308Sache be "inserted". They can just be placed on the screen. */ 157621308Sache /* However, this screws up the rest of this block, which 157747563Sache assumes you've done the insert because you can. */ 157821308Sache _rl_output_some_chars (nfd, lendiff); 1579119614Sache _rl_last_c_pos += col_lendiff; 158021308Sache } 158121308Sache else 158221308Sache { 158321308Sache _rl_output_some_chars (nfd, temp); 1584119614Sache _rl_last_c_pos += col_temp; 1585257586Ssbruno /* If nfd begins before any invisible characters in the prompt, 1586257586Ssbruno adjust _rl_last_c_pos to account for wrap_offset and set 1587257586Ssbruno cpos_adjusted to let the caller know. */ 1588257586Ssbruno if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible)) 1589257586Ssbruno { 1590257586Ssbruno _rl_last_c_pos -= wrap_offset; 1591257586Ssbruno cpos_adjusted = 1; 1592257586Ssbruno } 159321308Sache return; 159421308Sache } 159521308Sache /* Copy (new) chars to screen from first diff to last match. */ 159621308Sache temp = nls - nfd; 159721308Sache if ((temp - lendiff) > 0) 159821308Sache { 159921308Sache _rl_output_some_chars (nfd + lendiff, temp - lendiff); 1600136759Speter /* XXX -- this bears closer inspection. Fixes a redisplay bug 1601136759Speter reported against bash-3.0-alpha by Andreas Schwab involving 1602136759Speter multibyte characters and prompt strings with invisible 1603136759Speter characters, but was previously disabled. */ 1604257586Ssbruno if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1605257586Ssbruno twidth = _rl_col_width (nfd+lendiff, 0, temp-col_lendiff); 1606257586Ssbruno else 1607257586Ssbruno twidth = temp - lendiff; 1608257586Ssbruno _rl_last_c_pos += twidth; 160921308Sache } 161021308Sache } 161121308Sache else 161221308Sache { 161321308Sache /* cannot insert chars, write to EOL */ 161421308Sache _rl_output_some_chars (nfd, temp); 1615119614Sache _rl_last_c_pos += col_temp; 1616157188Sache /* If we're in a multibyte locale and were before the last invisible 1617157188Sache char in the current line (which implies we just output some invisible 1618157188Sache characters) we need to adjust _rl_last_c_pos, since it represents 1619157188Sache a physical character position. */ 162021308Sache } 162121308Sache } 162221308Sache else /* Delete characters from line. */ 162321308Sache { 162421308Sache /* If possible and inexpensive to use terminal deletion, then do so. */ 1625119614Sache if (_rl_term_dc && (2 * col_temp) >= -col_lendiff) 162621308Sache { 162721308Sache /* If all we're doing is erasing the invisible characters in the 162821308Sache prompt string, don't bother. It screws up the assumptions 162921308Sache about what's on the screen. */ 163021308Sache if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 && 163121308Sache -lendiff == visible_wrap_offset) 1632119614Sache col_lendiff = 0; 163321308Sache 1634119614Sache if (col_lendiff) 1635119614Sache delete_chars (-col_lendiff); /* delete (diff) characters */ 163621308Sache 163721308Sache /* Copy (new) chars to screen from first diff to last match */ 163821308Sache temp = nls - nfd; 163921308Sache if (temp > 0) 164021308Sache { 1641173406Sache /* If nfd begins at the prompt, or before the invisible 1642173406Sache characters in the prompt, we need to adjust _rl_last_c_pos 1643173406Sache in a multibyte locale to account for the wrap offset and 1644173406Sache set cpos_adjusted accordingly. */ 164521308Sache _rl_output_some_chars (nfd, temp); 1646173406Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1647173406Sache { 1648173406Sache _rl_last_c_pos += _rl_col_width (nfd, 0, temp); 1649173406Sache if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible)) 1650173406Sache { 1651173406Sache _rl_last_c_pos -= wrap_offset; 1652173406Sache cpos_adjusted = 1; 1653173406Sache } 1654173406Sache } 1655173406Sache else 1656173406Sache _rl_last_c_pos += temp; 165721308Sache } 165821308Sache } 165921308Sache /* Otherwise, print over the existing material. */ 166021308Sache else 166121308Sache { 166221308Sache if (temp > 0) 166321308Sache { 1664173406Sache /* If nfd begins at the prompt, or before the invisible 1665173406Sache characters in the prompt, we need to adjust _rl_last_c_pos 1666173406Sache in a multibyte locale to account for the wrap offset and 1667173406Sache set cpos_adjusted accordingly. */ 166821308Sache _rl_output_some_chars (nfd, temp); 1669157188Sache _rl_last_c_pos += col_temp; /* XXX */ 1670173406Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1671173406Sache { 1672173406Sache if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible)) 1673173406Sache { 1674173406Sache _rl_last_c_pos -= wrap_offset; 1675173406Sache cpos_adjusted = 1; 1676173406Sache } 1677173406Sache } 167821308Sache } 167921308Sache lendiff = (oe - old) - (ne - new); 1680119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1681119614Sache col_lendiff = _rl_col_width (old, 0, oe - old) - _rl_col_width (new, 0, ne - new); 1682119614Sache else 1683119614Sache col_lendiff = lendiff; 1684119614Sache 1685119614Sache if (col_lendiff) 168647563Sache { 168747563Sache if (_rl_term_autowrap && current_line < inv_botlin) 1688119614Sache space_to_eol (col_lendiff); 168947563Sache else 1690119614Sache _rl_clear_to_eol (col_lendiff); 169147563Sache } 169221308Sache } 169321308Sache } 169421308Sache} 169521308Sache 169621308Sache/* Tell the update routines that we have moved onto a new (empty) line. */ 169721308Sacheint 169821308Sacherl_on_new_line () 169921308Sache{ 170021308Sache if (visible_line) 170121308Sache visible_line[0] = '\0'; 170221308Sache 170321308Sache _rl_last_c_pos = _rl_last_v_pos = 0; 170421308Sache _rl_vis_botlin = last_lmargin = 0; 170521308Sache if (vis_lbreaks) 170621308Sache vis_lbreaks[0] = vis_lbreaks[1] = 0; 170721308Sache visible_wrap_offset = 0; 170821308Sache return 0; 170921308Sache} 171021308Sache 171158314Sache/* Tell the update routines that we have moved onto a new line with the 171258314Sache prompt already displayed. Code originally from the version of readline 1713136759Speter distributed with CLISP. rl_expand_prompt must have already been called 1714136759Speter (explicitly or implicitly). This still doesn't work exactly right. */ 171558314Sacheint 171658314Sacherl_on_new_line_with_prompt () 171758314Sache{ 171858314Sache int prompt_size, i, l, real_screenwidth, newlines; 1719136759Speter char *prompt_last_line, *lprompt; 172058314Sache 172158314Sache /* Initialize visible_line and invisible_line to ensure that they can hold 172258314Sache the already-displayed prompt. */ 172358314Sache prompt_size = strlen (rl_prompt) + 1; 172458314Sache init_line_structures (prompt_size); 172558314Sache 172658314Sache /* Make sure the line structures hold the already-displayed prompt for 172758314Sache redisplay. */ 1728136759Speter lprompt = local_prompt ? local_prompt : rl_prompt; 1729136759Speter strcpy (visible_line, lprompt); 1730136759Speter strcpy (invisible_line, lprompt); 173158314Sache 173258314Sache /* If the prompt contains newlines, take the last tail. */ 173358314Sache prompt_last_line = strrchr (rl_prompt, '\n'); 173458314Sache if (!prompt_last_line) 173558314Sache prompt_last_line = rl_prompt; 173658314Sache 173758314Sache l = strlen (prompt_last_line); 1738119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1739157188Sache _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l); /* XXX */ 1740119614Sache else 1741119614Sache _rl_last_c_pos = l; 174258314Sache 174358314Sache /* Dissect prompt_last_line into screen lines. Note that here we have 174458314Sache to use the real screenwidth. Readline's notion of screenwidth might be 174558314Sache one less, see terminal.c. */ 174675409Sache real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1); 174758314Sache _rl_last_v_pos = l / real_screenwidth; 174858314Sache /* If the prompt length is a multiple of real_screenwidth, we don't know 174958314Sache whether the cursor is at the end of the last line, or already at the 175058314Sache beginning of the next line. Output a newline just to be safe. */ 175158314Sache if (l > 0 && (l % real_screenwidth) == 0) 175258314Sache _rl_output_some_chars ("\n", 1); 175358314Sache last_lmargin = 0; 175458314Sache 175558314Sache newlines = 0; i = 0; 175658314Sache while (i <= l) 175758314Sache { 175858314Sache _rl_vis_botlin = newlines; 175958314Sache vis_lbreaks[newlines++] = i; 176058314Sache i += real_screenwidth; 176158314Sache } 176258314Sache vis_lbreaks[newlines] = l; 176358314Sache visible_wrap_offset = 0; 176458314Sache 1765136759Speter rl_display_prompt = rl_prompt; /* XXX - make sure it's set */ 1766136759Speter 176758314Sache return 0; 176858314Sache} 176958314Sache 177021308Sache/* Actually update the display, period. */ 177121308Sacheint 177221308Sacherl_forced_update_display () 177321308Sache{ 1774165675Sache register char *temp; 1775165675Sache 177621308Sache if (visible_line) 177721308Sache { 1778165675Sache temp = visible_line; 177921308Sache while (*temp) 178047563Sache *temp++ = '\0'; 178121308Sache } 178221308Sache rl_on_new_line (); 178321308Sache forced_display++; 178421308Sache (*rl_redisplay_function) (); 178521308Sache return 0; 178621308Sache} 178721308Sache 178821308Sache/* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices. 1789157188Sache (Well, when we don't have multibyte characters, _rl_last_c_pos is a 1790157188Sache buffer index.) 179121308Sache DATA is the contents of the screen line of interest; i.e., where 179221308Sache the movement is being done. */ 179321308Sachevoid 179421308Sache_rl_move_cursor_relative (new, data) 179521308Sache int new; 179675409Sache const char *data; 179721308Sache{ 179821308Sache register int i; 1799157188Sache int woff; /* number of invisible chars on current line */ 1800157188Sache int cpos, dpos; /* current and desired cursor positions */ 180121308Sache 1802257586Ssbruno woff = WRAP_OFFSET (_rl_last_v_pos, wrap_offset); 1803157188Sache cpos = _rl_last_c_pos; 1804119614Sache#if defined (HANDLE_MULTIBYTE) 1805119614Sache /* If we have multibyte characters, NEW is indexed by the buffer point in 1806119614Sache a multibyte string, but _rl_last_c_pos is the display position. In 1807136759Speter this case, NEW's display position is not obvious and must be 1808157188Sache calculated. We need to account for invisible characters in this line, 1809157188Sache as long as we are past them and they are counted by _rl_col_width. */ 1810157188Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1811136759Speter { 1812157188Sache dpos = _rl_col_width (data, 0, new); 1813173406Sache /* Use NEW when comparing against the last invisible character in the 1814173406Sache prompt string, since they're both buffer indices and DPOS is a 1815173406Sache desired display position. */ 1816257586Ssbruno if ((new > prompt_last_invisible) || /* XXX - don't use woff here */ 1817257586Ssbruno (prompt_physical_chars > _rl_screenwidth && 1818257586Ssbruno _rl_last_v_pos == prompt_last_screen_line && 1819257586Ssbruno wrap_offset != woff && 1820257586Ssbruno new > (prompt_last_invisible-_rl_screenwidth-wrap_offset))) 1821165675Sache { 1822165675Sache dpos -= woff; 1823165675Sache /* Since this will be assigned to _rl_last_c_pos at the end (more 1824165675Sache precisely, _rl_last_c_pos == dpos when this function returns), 1825165675Sache let the caller know. */ 1826165675Sache cpos_adjusted = 1; 1827165675Sache } 1828136759Speter } 1829157188Sache else 1830119614Sache#endif 1831157188Sache dpos = new; 183221308Sache 1833157188Sache /* If we don't have to do anything, then return. */ 1834157188Sache if (cpos == dpos) 1835157188Sache return; 1836157188Sache 183721308Sache /* It may be faster to output a CR, and then move forwards instead 183821308Sache of moving backwards. */ 183921308Sache /* i == current physical cursor position. */ 1840157188Sache#if defined (HANDLE_MULTIBYTE) 1841157188Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1842157188Sache i = _rl_last_c_pos; 1843157188Sache else 1844157188Sache#endif 1845157188Sache i = _rl_last_c_pos - woff; 1846165675Sache if (dpos == 0 || CR_FASTER (dpos, _rl_last_c_pos) || 184775409Sache (_rl_term_autowrap && i == _rl_screenwidth)) 184821308Sache { 184921308Sache#if defined (__MSDOS__) 185021308Sache putc ('\r', rl_outstream); 185121308Sache#else 185275409Sache tputs (_rl_term_cr, 1, _rl_output_character_function); 185321308Sache#endif /* !__MSDOS__ */ 1854157188Sache cpos = _rl_last_c_pos = 0; 185521308Sache } 185621308Sache 1857157188Sache if (cpos < dpos) 185821308Sache { 185921308Sache /* Move the cursor forward. We do it by printing the command 186021308Sache to move the cursor forward if there is one, else print that 186121308Sache portion of the output buffer again. Which is cheaper? */ 186221308Sache 186321308Sache /* The above comment is left here for posterity. It is faster 186421308Sache to print one character (non-control) than to print a control 186521308Sache sequence telling the terminal to move forward one character. 186621308Sache That kind of control is for people who don't know what the 186721308Sache data is underneath the cursor. */ 1868165675Sache 1869165675Sache /* However, we need a handle on where the current display position is 1870165675Sache in the buffer for the immediately preceding comment to be true. 1871165675Sache In multibyte locales, we don't currently have that info available. 1872165675Sache Without it, we don't know where the data we have to display begins 1873165675Sache in the buffer and we have to go back to the beginning of the screen 1874165675Sache line. In this case, we can use the terminal sequence to move forward 1875165675Sache if it's available. */ 1876119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1877119614Sache { 1878165675Sache if (_rl_term_forward_char) 1879165675Sache { 1880165675Sache for (i = cpos; i < dpos; i++) 1881165675Sache tputs (_rl_term_forward_char, 1, _rl_output_character_function); 1882165675Sache } 1883165675Sache else 1884165675Sache { 1885165675Sache tputs (_rl_term_cr, 1, _rl_output_character_function); 1886165675Sache for (i = 0; i < new; i++) 1887165675Sache putc (data[i], rl_outstream); 1888165675Sache } 1889119614Sache } 189021308Sache else 1891157188Sache for (i = cpos; i < new; i++) 189221308Sache putc (data[i], rl_outstream); 1893157188Sache } 1894119614Sache 1895119614Sache#if defined (HANDLE_MULTIBYTE) 1896119614Sache /* NEW points to the buffer point, but _rl_last_c_pos is the display point. 1897119614Sache The byte length of the string is probably bigger than the column width 1898119614Sache of the string, which means that if NEW == _rl_last_c_pos, then NEW's 1899119614Sache display point is less than _rl_last_c_pos. */ 1900119614Sache#endif 1901157188Sache else if (cpos > dpos) 1902157188Sache _rl_backspace (cpos - dpos); 1903119614Sache 1904157188Sache _rl_last_c_pos = dpos; 190521308Sache} 190621308Sache 190721308Sache/* PWP: move the cursor up or down. */ 190821308Sachevoid 190921308Sache_rl_move_vert (to) 191021308Sache int to; 191121308Sache{ 191221308Sache register int delta, i; 191321308Sache 191475409Sache if (_rl_last_v_pos == to || to > _rl_screenheight) 191521308Sache return; 191621308Sache 191721308Sache if ((delta = to - _rl_last_v_pos) > 0) 191821308Sache { 191921308Sache for (i = 0; i < delta; i++) 192021308Sache putc ('\n', rl_outstream); 192158314Sache#if defined (__MSDOS__) 192258314Sache putc ('\r', rl_outstream); 192358314Sache#else 192475409Sache tputs (_rl_term_cr, 1, _rl_output_character_function); 192558314Sache#endif 192621308Sache _rl_last_c_pos = 0; 192721308Sache } 192821308Sache else 192921308Sache { /* delta < 0 */ 193075409Sache if (_rl_term_up && *_rl_term_up) 193121308Sache for (i = 0; i < -delta; i++) 193275409Sache tputs (_rl_term_up, 1, _rl_output_character_function); 193321308Sache } 193458314Sache 193521308Sache _rl_last_v_pos = to; /* Now TO is here */ 193621308Sache} 193721308Sache 193821308Sache/* Physically print C on rl_outstream. This is for functions which know 193921308Sache how to optimize the display. Return the number of characters output. */ 194021308Sacheint 194121308Sacherl_show_char (c) 194221308Sache int c; 194321308Sache{ 194421308Sache int n = 1; 194521308Sache if (META_CHAR (c) && (_rl_output_meta_chars == 0)) 194621308Sache { 194721308Sache fprintf (rl_outstream, "M-"); 194821308Sache n += 2; 194921308Sache c = UNMETA (c); 195021308Sache } 195121308Sache 195221308Sache#if defined (DISPLAY_TABS) 195321308Sache if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT) 195421308Sache#else 195521308Sache if (CTRL_CHAR (c) || c == RUBOUT) 195621308Sache#endif /* !DISPLAY_TABS */ 195721308Sache { 195821308Sache fprintf (rl_outstream, "C-"); 195921308Sache n += 2; 196021308Sache c = CTRL_CHAR (c) ? UNCTRL (c) : '?'; 196121308Sache } 196221308Sache 196321308Sache putc (c, rl_outstream); 196421308Sache fflush (rl_outstream); 196521308Sache return n; 196621308Sache} 196721308Sache 196821308Sacheint 196921308Sacherl_character_len (c, pos) 197021308Sache register int c, pos; 197121308Sache{ 197221308Sache unsigned char uc; 197321308Sache 197421308Sache uc = (unsigned char)c; 197521308Sache 197621308Sache if (META_CHAR (uc)) 197721308Sache return ((_rl_output_meta_chars == 0) ? 4 : 1); 197821308Sache 197921308Sache if (uc == '\t') 198021308Sache { 198121308Sache#if defined (DISPLAY_TABS) 198221308Sache return (((pos | 7) + 1) - pos); 198321308Sache#else 198421308Sache return (2); 198521308Sache#endif /* !DISPLAY_TABS */ 198621308Sache } 198721308Sache 198821308Sache if (CTRL_CHAR (c) || c == RUBOUT) 198921308Sache return (2); 199021308Sache 1991119614Sache return ((ISPRINT (uc)) ? 1 : 2); 199221308Sache} 199321308Sache/* How to print things in the "echo-area". The prompt is treated as a 199421308Sache mini-modeline. */ 1995157188Sachestatic int msg_saved_prompt = 0; 199621308Sache 199721308Sache#if defined (USE_VARARGS) 199821308Sacheint 199921308Sache#if defined (PREFER_STDARG) 200021308Sacherl_message (const char *format, ...) 200121308Sache#else 200221308Sacherl_message (va_alist) 200321308Sache va_dcl 200421308Sache#endif 200521308Sache{ 200621308Sache va_list args; 200721308Sache#if defined (PREFER_VARARGS) 200821308Sache char *format; 200921308Sache#endif 201021308Sache 201121308Sache#if defined (PREFER_STDARG) 201221308Sache va_start (args, format); 201321308Sache#else 201421308Sache va_start (args); 201521308Sache format = va_arg (args, char *); 201621308Sache#endif 201721308Sache 2018119614Sache#if defined (HAVE_VSNPRINTF) 2019119614Sache vsnprintf (msg_buf, sizeof (msg_buf) - 1, format, args); 2020119614Sache#else 202121308Sache vsprintf (msg_buf, format, args); 2022119614Sache msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */ 2023119614Sache#endif 202421308Sache va_end (args); 202521308Sache 2026157188Sache if (saved_local_prompt == 0) 2027157188Sache { 2028157188Sache rl_save_prompt (); 2029157188Sache msg_saved_prompt = 1; 2030157188Sache } 203121308Sache rl_display_prompt = msg_buf; 2032157188Sache local_prompt = expand_prompt (msg_buf, &prompt_visible_length, 2033157188Sache &prompt_last_invisible, 2034157188Sache &prompt_invis_chars_first_line, 2035157188Sache &prompt_physical_chars); 2036157188Sache local_prompt_prefix = (char *)NULL; 2037165675Sache local_prompt_len = local_prompt ? strlen (local_prompt) : 0; 203821308Sache (*rl_redisplay_function) (); 2039157188Sache 204021308Sache return 0; 204121308Sache} 204221308Sache#else /* !USE_VARARGS */ 204321308Sacheint 204421308Sacherl_message (format, arg1, arg2) 204521308Sache char *format; 204621308Sache{ 204721308Sache sprintf (msg_buf, format, arg1, arg2); 2048119614Sache msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */ 2049157188Sache 205021308Sache rl_display_prompt = msg_buf; 2051157188Sache if (saved_local_prompt == 0) 2052157188Sache { 2053157188Sache rl_save_prompt (); 2054157188Sache msg_saved_prompt = 1; 2055157188Sache } 2056157188Sache local_prompt = expand_prompt (msg_buf, &prompt_visible_length, 2057157188Sache &prompt_last_invisible, 2058157188Sache &prompt_invis_chars_first_line, 2059157188Sache &prompt_physical_chars); 2060157188Sache local_prompt_prefix = (char *)NULL; 2061165675Sache local_prompt_len = local_prompt ? strlen (local_prompt) : 0; 206221308Sache (*rl_redisplay_function) (); 2063157188Sache 206421308Sache return 0; 206521308Sache} 206621308Sache#endif /* !USE_VARARGS */ 206721308Sache 206821308Sache/* How to clear things from the "echo-area". */ 206921308Sacheint 207021308Sacherl_clear_message () 207121308Sache{ 207221308Sache rl_display_prompt = rl_prompt; 2073157188Sache if (msg_saved_prompt) 2074157188Sache { 2075157188Sache rl_restore_prompt (); 2076157188Sache msg_saved_prompt = 0; 2077157188Sache } 207821308Sache (*rl_redisplay_function) (); 207921308Sache return 0; 208021308Sache} 208121308Sache 208221308Sacheint 208321308Sacherl_reset_line_state () 208421308Sache{ 208521308Sache rl_on_new_line (); 208621308Sache 208721308Sache rl_display_prompt = rl_prompt ? rl_prompt : ""; 208821308Sache forced_display = 1; 208921308Sache return 0; 209021308Sache} 209121308Sache 209221308Sachevoid 209347563Sacherl_save_prompt () 209421308Sache{ 209521308Sache saved_local_prompt = local_prompt; 209621308Sache saved_local_prefix = local_prompt_prefix; 2097157188Sache saved_prefix_length = prompt_prefix_length; 2098165675Sache saved_local_length = local_prompt_len; 209975409Sache saved_last_invisible = prompt_last_invisible; 210075409Sache saved_visible_length = prompt_visible_length; 2101136759Speter saved_invis_chars_first_line = prompt_invis_chars_first_line; 2102136759Speter saved_physical_chars = prompt_physical_chars; 210321308Sache 210421308Sache local_prompt = local_prompt_prefix = (char *)0; 2105165675Sache local_prompt_len = 0; 2106157188Sache prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0; 2107136759Speter prompt_invis_chars_first_line = prompt_physical_chars = 0; 210821308Sache} 210921308Sache 211021308Sachevoid 211147563Sacherl_restore_prompt () 211221308Sache{ 211375409Sache FREE (local_prompt); 211475409Sache FREE (local_prompt_prefix); 211521308Sache 211621308Sache local_prompt = saved_local_prompt; 211721308Sache local_prompt_prefix = saved_local_prefix; 2118165675Sache local_prompt_len = saved_local_length; 2119157188Sache prompt_prefix_length = saved_prefix_length; 212075409Sache prompt_last_invisible = saved_last_invisible; 212175409Sache prompt_visible_length = saved_visible_length; 2122136759Speter prompt_invis_chars_first_line = saved_invis_chars_first_line; 2123136759Speter prompt_physical_chars = saved_physical_chars; 2124157188Sache 2125157188Sache /* can test saved_local_prompt to see if prompt info has been saved. */ 2126157188Sache saved_local_prompt = saved_local_prefix = (char *)0; 2127165675Sache saved_local_length = 0; 2128157188Sache saved_last_invisible = saved_visible_length = saved_prefix_length = 0; 2129157188Sache saved_invis_chars_first_line = saved_physical_chars = 0; 213021308Sache} 213121308Sache 213221308Sachechar * 213321308Sache_rl_make_prompt_for_search (pchar) 213421308Sache int pchar; 213521308Sache{ 213621308Sache int len; 2137157195Sache char *pmt, *p; 213821308Sache 213947563Sache rl_save_prompt (); 214021308Sache 2141157195Sache /* We've saved the prompt, and can do anything with the various prompt 2142157195Sache strings we need before they're restored. We want the unexpanded 2143157195Sache portion of the prompt string after any final newline. */ 2144157195Sache p = rl_prompt ? strrchr (rl_prompt, '\n') : 0; 2145157195Sache if (p == 0) 214621308Sache { 214721308Sache len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0; 2148119614Sache pmt = (char *)xmalloc (len + 2); 214921308Sache if (len) 215047563Sache strcpy (pmt, rl_prompt); 215121308Sache pmt[len] = pchar; 215221308Sache pmt[len+1] = '\0'; 215321308Sache } 215421308Sache else 215521308Sache { 2156157195Sache p++; 2157157195Sache len = strlen (p); 2158119614Sache pmt = (char *)xmalloc (len + 2); 215921308Sache if (len) 2160157195Sache strcpy (pmt, p); 216121308Sache pmt[len] = pchar; 216221308Sache pmt[len+1] = '\0'; 2163157195Sache } 2164136759Speter 2165157195Sache /* will be overwritten by expand_prompt, called from rl_message */ 2166157188Sache prompt_physical_chars = saved_physical_chars + 1; 216721308Sache return pmt; 216821308Sache} 216921308Sache 217021308Sache/* Quick redisplay hack when erasing characters at the end of the line. */ 217121308Sachevoid 217221308Sache_rl_erase_at_end_of_line (l) 217321308Sache int l; 217421308Sache{ 217521308Sache register int i; 217621308Sache 217721308Sache _rl_backspace (l); 217821308Sache for (i = 0; i < l; i++) 217921308Sache putc (' ', rl_outstream); 218021308Sache _rl_backspace (l); 218121308Sache for (i = 0; i < l; i++) 218221308Sache visible_line[--_rl_last_c_pos] = '\0'; 218321308Sache rl_display_fixed++; 218421308Sache} 218521308Sache 218621308Sache/* Clear to the end of the line. COUNT is the minimum 218721308Sache number of character spaces to clear, */ 218826497Sachevoid 218926497Sache_rl_clear_to_eol (count) 219021308Sache int count; 219121308Sache{ 219275409Sache if (_rl_term_clreol) 219375409Sache tputs (_rl_term_clreol, 1, _rl_output_character_function); 219426497Sache else if (count) 219521308Sache space_to_eol (count); 219621308Sache} 219721308Sache 219821308Sache/* Clear to the end of the line using spaces. COUNT is the minimum 219921308Sache number of character spaces to clear, */ 220021308Sachestatic void 220121308Sachespace_to_eol (count) 220221308Sache int count; 220321308Sache{ 220421308Sache register int i; 220521308Sache 220621308Sache for (i = 0; i < count; i++) 220721308Sache putc (' ', rl_outstream); 220821308Sache 220921308Sache _rl_last_c_pos += count; 221021308Sache} 221121308Sache 221226497Sachevoid 221326497Sache_rl_clear_screen () 221426497Sache{ 221575409Sache if (_rl_term_clrpag) 221675409Sache tputs (_rl_term_clrpag, 1, _rl_output_character_function); 221726497Sache else 221875409Sache rl_crlf (); 221926497Sache} 222026497Sache 2221119614Sache/* Insert COUNT characters from STRING to the output stream at column COL. */ 222221308Sachestatic void 2223119614Sacheinsert_some_chars (string, count, col) 222421308Sache char *string; 2225119614Sache int count, col; 222621308Sache{ 2227157188Sache#if defined (__MSDOS__) || defined (__MINGW32__) 2228157188Sache _rl_output_some_chars (string, count); 2229157188Sache#else 2230119614Sache /* DEBUGGING */ 2231119614Sache if (MB_CUR_MAX == 1 || rl_byte_oriented) 2232119614Sache if (count != col) 2233119614Sache fprintf(stderr, "readline: debug: insert_some_chars: count (%d) != col (%d)\n", count, col); 2234119614Sache 223521308Sache /* If IC is defined, then we do not have to "enter" insert mode. */ 223675409Sache if (_rl_term_IC) 223721308Sache { 223821308Sache char *buffer; 2239119614Sache 2240119614Sache buffer = tgoto (_rl_term_IC, 0, col); 224121308Sache tputs (buffer, 1, _rl_output_character_function); 224221308Sache _rl_output_some_chars (string, count); 224321308Sache } 224421308Sache else 224521308Sache { 224621308Sache register int i; 224721308Sache 224821308Sache /* If we have to turn on insert-mode, then do so. */ 224975409Sache if (_rl_term_im && *_rl_term_im) 225075409Sache tputs (_rl_term_im, 1, _rl_output_character_function); 225121308Sache 225221308Sache /* If there is a special command for inserting characters, then 225321308Sache use that first to open up the space. */ 225475409Sache if (_rl_term_ic && *_rl_term_ic) 225521308Sache { 2256119614Sache for (i = col; i--; ) 225775409Sache tputs (_rl_term_ic, 1, _rl_output_character_function); 225821308Sache } 225921308Sache 226021308Sache /* Print the text. */ 226121308Sache _rl_output_some_chars (string, count); 226221308Sache 226321308Sache /* If there is a string to turn off insert mode, we had best use 226421308Sache it now. */ 226575409Sache if (_rl_term_ei && *_rl_term_ei) 226675409Sache tputs (_rl_term_ei, 1, _rl_output_character_function); 226721308Sache } 2268157188Sache#endif /* __MSDOS__ || __MINGW32__ */ 226921308Sache} 227021308Sache 227121308Sache/* Delete COUNT characters from the display line. */ 227221308Sachestatic void 227321308Sachedelete_chars (count) 227421308Sache int count; 227521308Sache{ 227675409Sache if (count > _rl_screenwidth) /* XXX */ 227721308Sache return; 227821308Sache 2279157188Sache#if !defined (__MSDOS__) && !defined (__MINGW32__) 228075409Sache if (_rl_term_DC && *_rl_term_DC) 228121308Sache { 228221308Sache char *buffer; 228375409Sache buffer = tgoto (_rl_term_DC, count, count); 228421308Sache tputs (buffer, count, _rl_output_character_function); 228521308Sache } 228621308Sache else 228721308Sache { 228875409Sache if (_rl_term_dc && *_rl_term_dc) 228921308Sache while (count--) 229075409Sache tputs (_rl_term_dc, 1, _rl_output_character_function); 229121308Sache } 2292157188Sache#endif /* !__MSDOS__ && !__MINGW32__ */ 229321308Sache} 229421308Sache 229521308Sachevoid 229621308Sache_rl_update_final () 229721308Sache{ 229821308Sache int full_lines; 229921308Sache 230021308Sache full_lines = 0; 230121308Sache /* If the cursor is the only thing on an otherwise-blank last line, 230221308Sache compensate so we don't print an extra CRLF. */ 230321308Sache if (_rl_vis_botlin && _rl_last_c_pos == 0 && 230426497Sache visible_line[vis_lbreaks[_rl_vis_botlin]] == 0) 230521308Sache { 230621308Sache _rl_vis_botlin--; 230721308Sache full_lines = 1; 230821308Sache } 230921308Sache _rl_move_vert (_rl_vis_botlin); 231021308Sache /* If we've wrapped lines, remove the final xterm line-wrap flag. */ 231175409Sache if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth)) 231221308Sache { 231321308Sache char *last_line; 2314119614Sache 231558314Sache last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]]; 2316165675Sache cpos_buffer_position = -1; /* don't know where we are in buffer */ 2317165675Sache _rl_move_cursor_relative (_rl_screenwidth - 1, last_line); /* XXX */ 231826497Sache _rl_clear_to_eol (0); 231975409Sache putc (last_line[_rl_screenwidth - 1], rl_outstream); 232021308Sache } 232121308Sache _rl_vis_botlin = 0; 232275409Sache rl_crlf (); 232321308Sache fflush (rl_outstream); 232421308Sache rl_display_fixed++; 232521308Sache} 232621308Sache 232721308Sache/* Move to the start of the current line. */ 232821308Sachestatic void 232921308Sachecr () 233021308Sache{ 233175409Sache if (_rl_term_cr) 233221308Sache { 233358314Sache#if defined (__MSDOS__) 233458314Sache putc ('\r', rl_outstream); 233558314Sache#else 233675409Sache tputs (_rl_term_cr, 1, _rl_output_character_function); 233758314Sache#endif 233821308Sache _rl_last_c_pos = 0; 233921308Sache } 234021308Sache} 234121308Sache 234258314Sache/* Redraw the last line of a multi-line prompt that may possibly contain 234358314Sache terminal escape sequences. Called with the cursor at column 0 of the 234458314Sache line to draw the prompt on. */ 234558314Sachestatic void 234658314Sacheredraw_prompt (t) 234758314Sache char *t; 234858314Sache{ 2349157188Sache char *oldp; 235058314Sache 235158314Sache oldp = rl_display_prompt; 2352157188Sache rl_save_prompt (); 235358314Sache 235458314Sache rl_display_prompt = t; 235575409Sache local_prompt = expand_prompt (t, &prompt_visible_length, 235675409Sache &prompt_last_invisible, 2357136759Speter &prompt_invis_chars_first_line, 2358136759Speter &prompt_physical_chars); 235958314Sache local_prompt_prefix = (char *)NULL; 2360165675Sache local_prompt_len = local_prompt ? strlen (local_prompt) : 0; 2361157188Sache 236258314Sache rl_forced_update_display (); 236358314Sache 236458314Sache rl_display_prompt = oldp; 2365157188Sache rl_restore_prompt(); 236658314Sache} 236758314Sache 236821308Sache/* Redisplay the current line after a SIGWINCH is received. */ 236921308Sachevoid 237021308Sache_rl_redisplay_after_sigwinch () 237121308Sache{ 237258314Sache char *t; 237321308Sache 237421308Sache /* Clear the current line and put the cursor at column 0. Make sure 237521308Sache the right thing happens if we have wrapped to a new screen line. */ 237675409Sache if (_rl_term_cr) 237721308Sache { 237858314Sache#if defined (__MSDOS__) 237958314Sache putc ('\r', rl_outstream); 238058314Sache#else 238175409Sache tputs (_rl_term_cr, 1, _rl_output_character_function); 238258314Sache#endif 238321308Sache _rl_last_c_pos = 0; 238458314Sache#if defined (__MSDOS__) 238575409Sache space_to_eol (_rl_screenwidth); 238658314Sache putc ('\r', rl_outstream); 238758314Sache#else 238875409Sache if (_rl_term_clreol) 238975409Sache tputs (_rl_term_clreol, 1, _rl_output_character_function); 239021308Sache else 239121308Sache { 239275409Sache space_to_eol (_rl_screenwidth); 239375409Sache tputs (_rl_term_cr, 1, _rl_output_character_function); 239421308Sache } 239558314Sache#endif 239621308Sache if (_rl_last_v_pos > 0) 239721308Sache _rl_move_vert (0); 239821308Sache } 239921308Sache else 240075409Sache rl_crlf (); 240121308Sache 240221308Sache /* Redraw only the last line of a multi-line prompt. */ 240321308Sache t = strrchr (rl_display_prompt, '\n'); 240421308Sache if (t) 240558314Sache redraw_prompt (++t); 240621308Sache else 240721308Sache rl_forced_update_display (); 240821308Sache} 240921308Sache 241021308Sachevoid 241121308Sache_rl_clean_up_for_exit () 241221308Sache{ 241321308Sache if (readline_echoing_p) 241421308Sache { 241521308Sache _rl_move_vert (_rl_vis_botlin); 241621308Sache _rl_vis_botlin = 0; 241721308Sache fflush (rl_outstream); 241847563Sache rl_restart_output (1, 0); 241921308Sache } 242021308Sache} 242147563Sache 242247563Sachevoid 242347563Sache_rl_erase_entire_line () 242447563Sache{ 242547563Sache cr (); 242647563Sache _rl_clear_to_eol (0); 242747563Sache cr (); 242847563Sache fflush (rl_outstream); 242947563Sache} 243058314Sache 243158314Sache/* return the `current display line' of the cursor -- the number of lines to 243258314Sache move up to get to the first screen line of the current readline line. */ 243358314Sacheint 243458314Sache_rl_current_display_line () 243558314Sache{ 243658314Sache int ret, nleft; 243758314Sache 243858314Sache /* Find out whether or not there might be invisible characters in the 243958314Sache editing buffer. */ 244058314Sache if (rl_display_prompt == rl_prompt) 244175409Sache nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length; 244258314Sache else 244375409Sache nleft = _rl_last_c_pos - _rl_screenwidth; 244458314Sache 244558314Sache if (nleft > 0) 244675409Sache ret = 1 + nleft / _rl_screenwidth; 244758314Sache else 244858314Sache ret = 0; 244958314Sache 245058314Sache return ret; 245158314Sache} 2452119614Sache 2453119614Sache#if defined (HANDLE_MULTIBYTE) 2454119614Sache/* Calculate the number of screen columns occupied by STR from START to END. 2455119614Sache In the case of multibyte characters with stateful encoding, we have to 2456119614Sache scan from the beginning of the string to take the state into account. */ 2457119614Sachestatic int 2458119614Sache_rl_col_width (str, start, end) 2459136759Speter const char *str; 2460119614Sache int start, end; 2461119614Sache{ 2462119614Sache wchar_t wc; 2463165675Sache mbstate_t ps; 2464119614Sache int tmp, point, width, max; 2465119614Sache 2466119614Sache if (end <= start) 2467119614Sache return 0; 2468165680Sache if (MB_CUR_MAX == 1 || rl_byte_oriented) 2469165680Sache return (end - start); 2470119614Sache 2471165675Sache memset (&ps, 0, sizeof (mbstate_t)); 2472165675Sache 2473119614Sache point = 0; 2474119614Sache max = end; 2475119614Sache 2476119614Sache while (point < start) 2477119614Sache { 2478119614Sache tmp = mbrlen (str + point, max, &ps); 2479136759Speter if (MB_INVALIDCH ((size_t)tmp)) 2480119614Sache { 2481119614Sache /* In this case, the bytes are invalid or too short to compose a 2482119614Sache multibyte character, so we assume that the first byte represents 2483119614Sache a single character. */ 2484119614Sache point++; 2485119614Sache max--; 2486119614Sache 2487119614Sache /* Clear the state of the byte sequence, because in this case the 2488119614Sache effect of mbstate is undefined. */ 2489119614Sache memset (&ps, 0, sizeof (mbstate_t)); 2490119614Sache } 2491136759Speter else if (MB_NULLWCH (tmp)) 2492136759Speter break; /* Found '\0' */ 2493119614Sache else 2494119614Sache { 2495119614Sache point += tmp; 2496119614Sache max -= tmp; 2497119614Sache } 2498119614Sache } 2499119614Sache 2500119614Sache /* If START is not a byte that starts a character, then POINT will be 2501119614Sache greater than START. In this case, assume that (POINT - START) gives 2502119614Sache a byte count that is the number of columns of difference. */ 2503119614Sache width = point - start; 2504119614Sache 2505119614Sache while (point < end) 2506119614Sache { 2507119614Sache tmp = mbrtowc (&wc, str + point, max, &ps); 2508136759Speter if (MB_INVALIDCH ((size_t)tmp)) 2509119614Sache { 2510119614Sache /* In this case, the bytes are invalid or too short to compose a 2511119614Sache multibyte character, so we assume that the first byte represents 2512119614Sache a single character. */ 2513119614Sache point++; 2514119614Sache max--; 2515119614Sache 2516119614Sache /* and assume that the byte occupies a single column. */ 2517119614Sache width++; 2518119614Sache 2519119614Sache /* Clear the state of the byte sequence, because in this case the 2520119614Sache effect of mbstate is undefined. */ 2521119614Sache memset (&ps, 0, sizeof (mbstate_t)); 2522119614Sache } 2523136759Speter else if (MB_NULLWCH (tmp)) 2524136759Speter break; /* Found '\0' */ 2525119614Sache else 2526119614Sache { 2527119614Sache point += tmp; 2528119614Sache max -= tmp; 2529119614Sache tmp = wcwidth(wc); 2530119614Sache width += (tmp >= 0) ? tmp : 1; 2531119614Sache } 2532119614Sache } 2533119614Sache 2534119614Sache width += point - end; 2535119614Sache 2536119614Sache return width; 2537119614Sache} 2538119614Sache#endif /* HANDLE_MULTIBYTE */ 2539