display.c revision 168666
158314Sache/* $FreeBSD: head/contrib/libreadline/display.c 168666 2007-04-12 14:45:25Z ache $ */ 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, 395136759Speter (int *)NULL, 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, 402136759Speter &prompt_invis_chars_first_line, 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 91421308Sache#define W_OFFSET(line, offset) ((line) == 0 ? offset : 0) 91521308Sache#define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l])) 91621308Sache#define INV_LLEN(l) (inv_lbreaks[l+1] - inv_lbreaks[l]) 91721308Sache#define VIS_CHARS(line) (visible_line + vis_lbreaks[line]) 91821308Sache#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line) 91921308Sache#define INV_LINE(line) (invisible_line + inv_lbreaks[line]) 92021308Sache 92121308Sache /* For each line in the buffer, do the updating display. */ 92221308Sache for (linenum = 0; linenum <= inv_botlin; linenum++) 92321308Sache { 924165675Sache /* This can lead us astray if we execute a program that changes 925165675Sache the locale from a non-multibyte to a multibyte one. */ 926157188Sache o_cpos = _rl_last_c_pos; 927157188Sache cpos_adjusted = 0; 92821308Sache update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum, 92921308Sache VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin); 93021308Sache 931157188Sache /* update_line potentially changes _rl_last_c_pos, but doesn't 932157188Sache take invisible characters into account, since _rl_last_c_pos 933157188Sache is an absolute cursor position in a multibyte locale. See 934157188Sache if compensating here is the right thing, or if we have to 935157188Sache change update_line itself. There is one case in which 936157188Sache update_line adjusts _rl_last_c_pos itself (so it can pass 937157188Sache _rl_move_cursor_relative accurate values); it communicates 938165675Sache this back by setting cpos_adjusted. If we assume that 939165675Sache _rl_last_c_pos is correct (an absolute cursor position) each 940165675Sache time update_line is called, then we can assume in our 941165675Sache calculations that o_cpos does not need to be adjusted by 942165675Sache wrap_offset. */ 943157188Sache if (linenum == 0 && (MB_CUR_MAX > 1 && rl_byte_oriented == 0) && 944157188Sache cpos_adjusted == 0 && 945157188Sache _rl_last_c_pos != o_cpos && 946157188Sache _rl_last_c_pos > wrap_offset && 947157188Sache o_cpos < prompt_last_invisible) 948157188Sache _rl_last_c_pos -= wrap_offset; 949157188Sache 95021308Sache /* If this is the line with the prompt, we might need to 95121308Sache compensate for invisible characters in the new line. Do 95221308Sache this only if there is not more than one new line (which 95321308Sache implies that we completely overwrite the old visible line) 95421308Sache and the new line is shorter than the old. Make sure we are 95521308Sache at the end of the new line before clearing. */ 95621308Sache if (linenum == 0 && 95721308Sache inv_botlin == 0 && _rl_last_c_pos == out && 95821308Sache (wrap_offset > visible_wrap_offset) && 95921308Sache (_rl_last_c_pos < visible_first_line_len)) 96021308Sache { 961157188Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 962157188Sache nleft = _rl_screenwidth - _rl_last_c_pos; 963157188Sache else 964157188Sache nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos; 96521308Sache if (nleft) 96626497Sache _rl_clear_to_eol (nleft); 96721308Sache } 96821308Sache 96921308Sache /* Since the new first line is now visible, save its length. */ 97021308Sache if (linenum == 0) 97121308Sache visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset; 97221308Sache } 97321308Sache 97421308Sache /* We may have deleted some lines. If so, clear the left over 97521308Sache blank ones at the bottom out. */ 97621308Sache if (_rl_vis_botlin > inv_botlin) 97721308Sache { 97821308Sache char *tt; 97921308Sache for (; linenum <= _rl_vis_botlin; linenum++) 98021308Sache { 98121308Sache tt = VIS_CHARS (linenum); 98221308Sache _rl_move_vert (linenum); 98321308Sache _rl_move_cursor_relative (0, tt); 98426497Sache _rl_clear_to_eol 98575409Sache ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth); 98621308Sache } 98721308Sache } 98821308Sache _rl_vis_botlin = inv_botlin; 98921308Sache 99021308Sache /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a 99121308Sache different screen line during this redisplay. */ 99221308Sache changed_screen_line = _rl_last_v_pos != cursor_linenum; 99321308Sache if (changed_screen_line) 99421308Sache { 99521308Sache _rl_move_vert (cursor_linenum); 99675409Sache /* If we moved up to the line with the prompt using _rl_term_up, 99747563Sache the physical cursor position on the screen stays the same, 99847563Sache but the buffer position needs to be adjusted to account 99947563Sache for invisible characters. */ 1000157188Sache if ((MB_CUR_MAX == 1 || rl_byte_oriented) && cursor_linenum == 0 && wrap_offset) 100147563Sache _rl_last_c_pos += wrap_offset; 100221308Sache } 100321308Sache 100421308Sache /* We have to reprint the prompt if it contains invisible 100521308Sache characters, since it's not generally OK to just reprint 100621308Sache the characters from the current cursor position. But we 100721308Sache only need to reprint it if the cursor is before the last 100821308Sache invisible character in the prompt string. */ 100975409Sache nleft = prompt_visible_length + wrap_offset; 101021308Sache if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 && 1011165675Sache#if 0 1012165675Sache _rl_last_c_pos <= PROMPT_ENDING_INDEX && local_prompt) 1013165675Sache#else 1014165675Sache _rl_last_c_pos < PROMPT_ENDING_INDEX && local_prompt) 1015165675Sache#endif 101621308Sache { 101758314Sache#if defined (__MSDOS__) 101858314Sache putc ('\r', rl_outstream); 101958314Sache#else 102075409Sache if (_rl_term_cr) 102175409Sache tputs (_rl_term_cr, 1, _rl_output_character_function); 102258314Sache#endif 102321308Sache _rl_output_some_chars (local_prompt, nleft); 1024119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1025157188Sache _rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft) - wrap_offset; 1026119614Sache else 1027119614Sache _rl_last_c_pos = nleft; 102821308Sache } 102921308Sache 103021308Sache /* Where on that line? And where does that line start 103121308Sache in the buffer? */ 103221308Sache pos = inv_lbreaks[cursor_linenum]; 103321308Sache /* nleft == number of characters in the line buffer between the 1034165675Sache start of the line and the desired cursor position. */ 1035165675Sache nleft = cpos_buffer_position - pos; 103621308Sache 1037157188Sache /* NLEFT is now a number of characters in a buffer. When in a 1038157188Sache multibyte locale, however, _rl_last_c_pos is an absolute cursor 1039157188Sache position that doesn't take invisible characters in the prompt 1040157188Sache into account. We use a fudge factor to compensate. */ 1041157188Sache 104221308Sache /* Since _rl_backspace() doesn't know about invisible characters in the 104321308Sache prompt, and there's no good way to tell it, we compensate for 104421308Sache those characters here and call _rl_backspace() directly. */ 104521308Sache if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos) 104621308Sache { 1047165675Sache /* TX == new physical cursor position in multibyte locale. */ 1048119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1049157188Sache tx = _rl_col_width (&visible_line[pos], 0, nleft) - visible_wrap_offset; 1050119614Sache else 1051157188Sache tx = nleft; 1052157188Sache if (_rl_last_c_pos > tx) 1053157188Sache { 1054157188Sache _rl_backspace (_rl_last_c_pos - tx); /* XXX */ 1055157188Sache _rl_last_c_pos = tx; 1056157188Sache } 105721308Sache } 105821308Sache 1059157188Sache /* We need to note that in a multibyte locale we are dealing with 1060157188Sache _rl_last_c_pos as an absolute cursor position, but moving to a 1061157188Sache point specified by a buffer position (NLEFT) that doesn't take 1062157188Sache invisible characters into account. */ 1063119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 106421308Sache _rl_move_cursor_relative (nleft, &invisible_line[pos]); 1065119614Sache else if (nleft != _rl_last_c_pos) 1066119614Sache _rl_move_cursor_relative (nleft, &invisible_line[pos]); 106721308Sache } 106821308Sache } 106921308Sache else /* Do horizontal scrolling. */ 107021308Sache { 107121308Sache#define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0) 107221308Sache int lmargin, ndisp, nleft, phys_c_pos, t; 107321308Sache 107421308Sache /* Always at top line. */ 107521308Sache _rl_last_v_pos = 0; 107621308Sache 107721308Sache /* Compute where in the buffer the displayed line should start. This 107821308Sache will be LMARGIN. */ 107921308Sache 108021308Sache /* The number of characters that will be displayed before the cursor. */ 1081165675Sache ndisp = cpos_buffer_position - wrap_offset; 108275409Sache nleft = prompt_visible_length + wrap_offset; 108321308Sache /* Where the new cursor position will be on the screen. This can be 108447563Sache longer than SCREENWIDTH; if it is, lmargin will be adjusted. */ 1085165675Sache phys_c_pos = cpos_buffer_position - (last_lmargin ? last_lmargin : wrap_offset); 108675409Sache t = _rl_screenwidth / 3; 108721308Sache 108821308Sache /* If the number of characters had already exceeded the screenwidth, 108947563Sache last_lmargin will be > 0. */ 109021308Sache 109121308Sache /* If the number of characters to be displayed is more than the screen 109247563Sache width, compute the starting offset so that the cursor is about 109347563Sache two-thirds of the way across the screen. */ 109475409Sache if (phys_c_pos > _rl_screenwidth - 2) 109521308Sache { 1096165675Sache lmargin = cpos_buffer_position - (2 * t); 109721308Sache if (lmargin < 0) 109821308Sache lmargin = 0; 109921308Sache /* If the left margin would be in the middle of a prompt with 110021308Sache invisible characters, don't display the prompt at all. */ 110121308Sache if (wrap_offset && lmargin > 0 && lmargin < nleft) 110221308Sache lmargin = nleft; 110321308Sache } 110475409Sache else if (ndisp < _rl_screenwidth - 2) /* XXX - was -1 */ 110547563Sache lmargin = 0; 110621308Sache else if (phys_c_pos < 1) 110721308Sache { 110821308Sache /* If we are moving back towards the beginning of the line and 110921308Sache the last margin is no longer correct, compute a new one. */ 1110165675Sache lmargin = ((cpos_buffer_position - 1) / t) * t; /* XXX */ 111121308Sache if (wrap_offset && lmargin > 0 && lmargin < nleft) 111221308Sache lmargin = nleft; 111321308Sache } 111421308Sache else 111547563Sache lmargin = last_lmargin; 111621308Sache 111721308Sache /* If the first character on the screen isn't the first character 111821308Sache in the display line, indicate this with a special character. */ 111921308Sache if (lmargin > 0) 112021308Sache line[lmargin] = '<'; 112121308Sache 112221308Sache /* If SCREENWIDTH characters starting at LMARGIN do not encompass 112347563Sache the whole line, indicate that with a special character at the 112447563Sache right edge of the screen. If LMARGIN is 0, we need to take the 112547563Sache wrap offset into account. */ 112675409Sache t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth; 112721308Sache if (t < out) 112847563Sache line[t - 1] = '>'; 112921308Sache 113021308Sache if (!rl_display_fixed || forced_display || lmargin != last_lmargin) 113121308Sache { 113221308Sache forced_display = 0; 113321308Sache update_line (&visible_line[last_lmargin], 113421308Sache &invisible_line[lmargin], 113521308Sache 0, 113675409Sache _rl_screenwidth + visible_wrap_offset, 113775409Sache _rl_screenwidth + (lmargin ? 0 : wrap_offset), 113821308Sache 0); 113921308Sache 114021308Sache /* If the visible new line is shorter than the old, but the number 114121308Sache of invisible characters is greater, and we are at the end of 114221308Sache the new line, we need to clear to eol. */ 114321308Sache t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset); 114421308Sache if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) && 114521308Sache (_rl_last_c_pos == out) && 114621308Sache t < visible_first_line_len) 114721308Sache { 114875409Sache nleft = _rl_screenwidth - t; 114926497Sache _rl_clear_to_eol (nleft); 115021308Sache } 115121308Sache visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset); 115275409Sache if (visible_first_line_len > _rl_screenwidth) 115375409Sache visible_first_line_len = _rl_screenwidth; 115421308Sache 1155165675Sache _rl_move_cursor_relative (cpos_buffer_position - lmargin, &invisible_line[lmargin]); 115621308Sache last_lmargin = lmargin; 115721308Sache } 115821308Sache } 115921308Sache fflush (rl_outstream); 116021308Sache 116121308Sache /* Swap visible and non-visible lines. */ 116221308Sache { 116375409Sache char *vtemp = visible_line; 116458314Sache int *itemp = vis_lbreaks, ntemp = vis_lbsize; 116558314Sache 116621308Sache visible_line = invisible_line; 116775409Sache invisible_line = vtemp; 116858314Sache 116921308Sache vis_lbreaks = inv_lbreaks; 117021308Sache inv_lbreaks = itemp; 117158314Sache 117258314Sache vis_lbsize = inv_lbsize; 117358314Sache inv_lbsize = ntemp; 117458314Sache 117521308Sache rl_display_fixed = 0; 117621308Sache /* If we are displaying on a single line, and last_lmargin is > 0, we 117721308Sache are not displaying any invisible characters, so set visible_wrap_offset 117821308Sache to 0. */ 117921308Sache if (_rl_horizontal_scroll_mode && last_lmargin) 118021308Sache visible_wrap_offset = 0; 118121308Sache else 118221308Sache visible_wrap_offset = wrap_offset; 118321308Sache } 118421308Sache} 118521308Sache 118621308Sache/* PWP: update_line() is based on finding the middle difference of each 118721308Sache line on the screen; vis: 118821308Sache 118921308Sache /old first difference 119021308Sache /beginning of line | /old last same /old EOL 119121308Sache v v v v 119221308Sacheold: eddie> Oh, my little gruntle-buggy is to me, as lurgid as 119321308Sachenew: eddie> Oh, my little buggy says to me, as lurgid as 119421308Sache ^ ^ ^ ^ 119521308Sache \beginning of line | \new last same \new end of line 119621308Sache \new first difference 119721308Sache 119821308Sache All are character pointers for the sake of speed. Special cases for 119947563Sache no differences, as well as for end of line additions must be handled. 120021308Sache 120121308Sache Could be made even smarter, but this works well enough */ 120221308Sachestatic void 120321308Sacheupdate_line (old, new, current_line, omax, nmax, inv_botlin) 120421308Sache register char *old, *new; 120521308Sache int current_line, omax, nmax, inv_botlin; 120621308Sache{ 120721308Sache register char *ofd, *ols, *oe, *nfd, *nls, *ne; 120821308Sache int temp, lendiff, wsatend, od, nd; 120921308Sache int current_invis_chars; 1210119614Sache int col_lendiff, col_temp; 1211119614Sache#if defined (HANDLE_MULTIBYTE) 1212119614Sache mbstate_t ps_new, ps_old; 1213165675Sache int new_offset, old_offset; 1214119614Sache#endif 121521308Sache 121621308Sache /* If we're at the right edge of a terminal that supports xn, we're 121721308Sache ready to wrap around, so do so. This fixes problems with knowing 121821308Sache the exact cursor position and cut-and-paste with certain terminal 121921308Sache emulators. In this calculation, TEMP is the physical screen 122021308Sache position of the cursor. */ 1221157188Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1222157188Sache temp = _rl_last_c_pos; 1223157188Sache else 1224157188Sache temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset); 122575409Sache if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode 1226119614Sache && _rl_last_v_pos == current_line - 1) 122721308Sache { 1228119614Sache#if defined (HANDLE_MULTIBYTE) 1229119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1230119614Sache { 1231119614Sache wchar_t wc; 1232119614Sache mbstate_t ps; 1233119614Sache int tempwidth, bytes; 1234119614Sache size_t ret; 1235119614Sache 1236119614Sache /* This fixes only double-column characters, but if the wrapped 1237119614Sache character comsumes more than three columns, spaces will be 1238119614Sache inserted in the string buffer. */ 1239119614Sache if (_rl_wrapped_line[current_line] > 0) 1240119614Sache _rl_clear_to_eol (_rl_wrapped_line[current_line]); 1241119614Sache 1242119614Sache memset (&ps, 0, sizeof (mbstate_t)); 1243119614Sache ret = mbrtowc (&wc, new, MB_CUR_MAX, &ps); 1244136759Speter if (MB_INVALIDCH (ret)) 1245119614Sache { 1246119614Sache tempwidth = 1; 1247119614Sache ret = 1; 1248119614Sache } 1249136759Speter else if (MB_NULLWCH (ret)) 1250119614Sache tempwidth = 0; 1251119614Sache else 1252119614Sache tempwidth = wcwidth (wc); 1253119614Sache 1254119614Sache if (tempwidth > 0) 1255119614Sache { 1256119614Sache int count; 1257119614Sache bytes = ret; 1258119614Sache for (count = 0; count < bytes; count++) 1259119614Sache putc (new[count], rl_outstream); 1260119614Sache _rl_last_c_pos = tempwidth; 1261119614Sache _rl_last_v_pos++; 1262119614Sache memset (&ps, 0, sizeof (mbstate_t)); 1263119614Sache ret = mbrtowc (&wc, old, MB_CUR_MAX, &ps); 1264119614Sache if (ret != 0 && bytes != 0) 1265119614Sache { 1266136759Speter if (MB_INVALIDCH (ret)) 1267119614Sache memmove (old+bytes, old+1, strlen (old+1)); 1268119614Sache else 1269119614Sache memmove (old+bytes, old+ret, strlen (old+ret)); 1270119614Sache memcpy (old, new, bytes); 1271119614Sache } 1272119614Sache } 1273119614Sache else 1274119614Sache { 1275119614Sache putc (' ', rl_outstream); 1276119614Sache _rl_last_c_pos = 1; 1277119614Sache _rl_last_v_pos++; 1278119614Sache if (old[0] && new[0]) 1279119614Sache old[0] = new[0]; 1280119614Sache } 1281119614Sache } 128221308Sache else 1283119614Sache#endif 1284119614Sache { 1285119614Sache if (new[0]) 1286119614Sache putc (new[0], rl_outstream); 1287119614Sache else 1288119614Sache putc (' ', rl_outstream); 1289157188Sache _rl_last_c_pos = 1; 1290119614Sache _rl_last_v_pos++; 1291119614Sache if (old[0] && new[0]) 1292119614Sache old[0] = new[0]; 1293119614Sache } 129421308Sache } 1295119614Sache 129621308Sache 129721308Sache /* Find first difference. */ 1298119614Sache#if defined (HANDLE_MULTIBYTE) 1299119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1300119614Sache { 1301136759Speter /* See if the old line is a subset of the new line, so that the 1302136759Speter only change is adding characters. */ 1303136759Speter temp = (omax < nmax) ? omax : nmax; 1304136759Speter if (memcmp (old, new, temp) == 0) 1305119614Sache { 1306136759Speter ofd = old + temp; 1307136759Speter nfd = new + temp; 1308119614Sache } 1309136759Speter else 1310136759Speter { 1311136759Speter memset (&ps_new, 0, sizeof(mbstate_t)); 1312136759Speter memset (&ps_old, 0, sizeof(mbstate_t)); 1313136759Speter 1314136759Speter if (omax == nmax && STREQN (new, old, omax)) 1315136759Speter { 1316136759Speter ofd = old + omax; 1317136759Speter nfd = new + nmax; 1318136759Speter } 1319136759Speter else 1320136759Speter { 1321136759Speter new_offset = old_offset = 0; 1322136759Speter for (ofd = old, nfd = new; 1323136759Speter (ofd - old < omax) && *ofd && 1324136759Speter _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new); ) 1325136759Speter { 1326136759Speter old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY); 1327136759Speter new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY); 1328136759Speter ofd = old + old_offset; 1329136759Speter nfd = new + new_offset; 1330136759Speter } 1331136759Speter } 1332136759Speter } 1333119614Sache } 1334119614Sache else 1335119614Sache#endif 133621308Sache for (ofd = old, nfd = new; 133721308Sache (ofd - old < omax) && *ofd && (*ofd == *nfd); 133821308Sache ofd++, nfd++) 133921308Sache ; 134021308Sache 134121308Sache /* Move to the end of the screen line. ND and OD are used to keep track 134221308Sache of the distance between ne and new and oe and old, respectively, to 134321308Sache move a subtraction out of each loop. */ 134421308Sache for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++); 134521308Sache for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++); 134621308Sache 134721308Sache /* If no difference, continue to next line. */ 134821308Sache if (ofd == oe && nfd == ne) 134921308Sache return; 135021308Sache 135121308Sache wsatend = 1; /* flag for trailing whitespace */ 1352119614Sache 1353119614Sache#if defined (HANDLE_MULTIBYTE) 1354119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1355119614Sache { 1356119614Sache ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY); 1357119614Sache nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY); 1358119614Sache while ((ols > ofd) && (nls > nfd)) 1359119614Sache { 1360119614Sache memset (&ps_old, 0, sizeof (mbstate_t)); 1361119614Sache memset (&ps_new, 0, sizeof (mbstate_t)); 1362119614Sache 1363136759Speter#if 0 1364136759Speter /* On advice from jir@yamato.ibm.com */ 1365119614Sache _rl_adjust_point (old, ols - old, &ps_old); 1366119614Sache _rl_adjust_point (new, nls - new, &ps_new); 1367136759Speter#endif 1368119614Sache 1369119614Sache if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0) 1370119614Sache break; 1371119614Sache 1372119614Sache if (*ols == ' ') 1373119614Sache wsatend = 0; 1374119614Sache 1375119614Sache ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY); 1376119614Sache nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY); 1377119614Sache } 1378119614Sache } 1379119614Sache else 1380119614Sache { 1381119614Sache#endif /* HANDLE_MULTIBYTE */ 138221308Sache ols = oe - 1; /* find last same */ 138321308Sache nls = ne - 1; 138421308Sache while ((ols > ofd) && (nls > nfd) && (*ols == *nls)) 138521308Sache { 138621308Sache if (*ols != ' ') 138721308Sache wsatend = 0; 138821308Sache ols--; 138921308Sache nls--; 139021308Sache } 1391119614Sache#if defined (HANDLE_MULTIBYTE) 1392119614Sache } 1393119614Sache#endif 139421308Sache 139521308Sache if (wsatend) 139621308Sache { 139721308Sache ols = oe; 139821308Sache nls = ne; 139921308Sache } 1400119614Sache#if defined (HANDLE_MULTIBYTE) 1401119614Sache /* This may not work for stateful encoding, but who cares? To handle 1402119614Sache stateful encoding properly, we have to scan each string from the 1403119614Sache beginning and compare. */ 1404119614Sache else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0) 1405119614Sache#else 140621308Sache else if (*ols != *nls) 1407119614Sache#endif 140821308Sache { 140921308Sache if (*ols) /* don't step past the NUL */ 1410119614Sache { 1411119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1412119614Sache ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY); 1413119614Sache else 1414119614Sache ols++; 1415119614Sache } 141621308Sache if (*nls) 1417119614Sache { 1418119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1419119614Sache nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY); 1420119614Sache else 1421119614Sache nls++; 1422119614Sache } 142321308Sache } 142421308Sache 142521308Sache /* count of invisible characters in the current invisible line. */ 142621308Sache current_invis_chars = W_OFFSET (current_line, wrap_offset); 142721308Sache if (_rl_last_v_pos != current_line) 142821308Sache { 142921308Sache _rl_move_vert (current_line); 1430157188Sache if ((MB_CUR_MAX == 1 || rl_byte_oriented) && current_line == 0 && visible_wrap_offset) 143121308Sache _rl_last_c_pos += visible_wrap_offset; 143221308Sache } 143321308Sache 143421308Sache /* If this is the first line and there are invisible characters in the 143521308Sache prompt string, and the prompt string has not changed, and the current 143621308Sache cursor position is before the last invisible character in the prompt, 143721308Sache and the index of the character to move to is past the end of the prompt 143821308Sache string, then redraw the entire prompt string. We can only do this 143921308Sache reliably if the terminal supports a `cr' capability. 144021308Sache 144121308Sache This is not an efficiency hack -- there is a problem with redrawing 144221308Sache portions of the prompt string if they contain terminal escape 144321308Sache sequences (like drawing the `unbold' sequence without a corresponding 144421308Sache `bold') that manifests itself on certain terminals. */ 144521308Sache 1446165675Sache lendiff = local_prompt_len; 144721308Sache od = ofd - old; /* index of first difference in visible line */ 144821308Sache if (current_line == 0 && !_rl_horizontal_scroll_mode && 144975409Sache _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 && 1450165675Sache od >= lendiff && _rl_last_c_pos < PROMPT_ENDING_INDEX) 145121308Sache { 145258314Sache#if defined (__MSDOS__) 145358314Sache putc ('\r', rl_outstream); 145458314Sache#else 145575409Sache tputs (_rl_term_cr, 1, _rl_output_character_function); 145658314Sache#endif 145721308Sache _rl_output_some_chars (local_prompt, lendiff); 1458119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1459157188Sache { 1460157188Sache /* We take wrap_offset into account here so we can pass correct 1461157188Sache information to _rl_move_cursor_relative. */ 1462157188Sache _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff) - wrap_offset; 1463157188Sache cpos_adjusted = 1; 1464157188Sache } 1465119614Sache else 1466119614Sache _rl_last_c_pos = lendiff; 146721308Sache } 146821308Sache 1469165675Sache /* When this function returns, _rl_last_c_pos is correct, and an absolute 1470165675Sache cursor postion in multibyte mode, but a buffer index when not in a 1471165675Sache multibyte locale. */ 147221308Sache _rl_move_cursor_relative (od, old); 1473165675Sache#if 1 1474165675Sache#if defined (HANDLE_MULTIBYTE) 1475165675Sache /* We need to indicate that the cursor position is correct in the presence of 1476165675Sache invisible characters in the prompt string. Let's see if setting this when 1477165675Sache we make sure we're at the end of the drawn prompt string works. */ 1478165675Sache if (current_line == 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0 && _rl_last_c_pos == prompt_physical_chars) 1479165675Sache cpos_adjusted = 1; 1480165675Sache#endif 1481165675Sache#endif 148221308Sache 1483119614Sache /* if (len (new) > len (old)) 1484119614Sache lendiff == difference in buffer 1485119614Sache col_lendiff == difference on screen 1486119614Sache When not using multibyte characters, these are equal */ 148721308Sache lendiff = (nls - nfd) - (ols - ofd); 1488119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1489119614Sache col_lendiff = _rl_col_width (new, nfd - new, nls - new) - _rl_col_width (old, ofd - old, ols - old); 1490119614Sache else 1491119614Sache col_lendiff = lendiff; 149221308Sache 149321308Sache /* If we are changing the number of invisible characters in a line, and 149421308Sache the spot of first difference is before the end of the invisible chars, 149521308Sache lendiff needs to be adjusted. */ 149621308Sache if (current_line == 0 && !_rl_horizontal_scroll_mode && 149721308Sache current_invis_chars != visible_wrap_offset) 1498119614Sache { 1499119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1500119614Sache { 1501119614Sache lendiff += visible_wrap_offset - current_invis_chars; 1502119614Sache col_lendiff += visible_wrap_offset - current_invis_chars; 1503119614Sache } 1504119614Sache else 1505119614Sache { 1506119614Sache lendiff += visible_wrap_offset - current_invis_chars; 1507119614Sache col_lendiff = lendiff; 1508119614Sache } 1509119614Sache } 151021308Sache 151121308Sache /* Insert (diff (len (old), len (new)) ch. */ 151221308Sache temp = ne - nfd; 1513119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1514119614Sache col_temp = _rl_col_width (new, nfd - new, ne - new); 1515119614Sache else 1516119614Sache col_temp = temp; 1517119614Sache 1518119614Sache if (col_lendiff > 0) /* XXX - was lendiff */ 151921308Sache { 152021308Sache /* Non-zero if we're increasing the number of lines. */ 152121308Sache int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin; 152221308Sache /* Sometimes it is cheaper to print the characters rather than 152321308Sache use the terminal's capabilities. If we're growing the number 152421308Sache of lines, make sure we actually cause the new line to wrap 152521308Sache around on auto-wrapping terminals. */ 1526119614Sache if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl)) 152721308Sache { 152875409Sache /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and 152921308Sache _rl_horizontal_scroll_mode == 1, inserting the characters with 153075409Sache _rl_term_IC or _rl_term_ic will screw up the screen because of the 153121308Sache invisible characters. We need to just draw them. */ 153221308Sache if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 || 153375409Sache lendiff <= prompt_visible_length || !current_invis_chars)) 153421308Sache { 1535119614Sache insert_some_chars (nfd, lendiff, col_lendiff); 1536119614Sache _rl_last_c_pos += col_lendiff; 153721308Sache } 1538157188Sache else if ((MB_CUR_MAX == 1 || rl_byte_oriented != 0) && *ols == 0 && lendiff > 0) 153921308Sache { 154021308Sache /* At the end of a line the characters do not have to 154121308Sache be "inserted". They can just be placed on the screen. */ 154221308Sache /* However, this screws up the rest of this block, which 154347563Sache assumes you've done the insert because you can. */ 154421308Sache _rl_output_some_chars (nfd, lendiff); 1545119614Sache _rl_last_c_pos += col_lendiff; 154621308Sache } 154721308Sache else 154821308Sache { 154921308Sache /* We have horizontal scrolling and we are not inserting at 155021308Sache the end. We have invisible characters in this line. This 155121308Sache is a dumb update. */ 155221308Sache _rl_output_some_chars (nfd, temp); 1553119614Sache _rl_last_c_pos += col_temp; 155421308Sache return; 155521308Sache } 155621308Sache /* Copy (new) chars to screen from first diff to last match. */ 155721308Sache temp = nls - nfd; 155821308Sache if ((temp - lendiff) > 0) 155921308Sache { 156021308Sache _rl_output_some_chars (nfd + lendiff, temp - lendiff); 1561136759Speter#if 1 1562136759Speter /* XXX -- this bears closer inspection. Fixes a redisplay bug 1563136759Speter reported against bash-3.0-alpha by Andreas Schwab involving 1564136759Speter multibyte characters and prompt strings with invisible 1565136759Speter characters, but was previously disabled. */ 1566136759Speter _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-col_lendiff); 1567119614Sache#else 1568136759Speter _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-lendiff); 1569119614Sache#endif 157021308Sache } 157121308Sache } 157221308Sache else 157321308Sache { 157421308Sache /* cannot insert chars, write to EOL */ 157521308Sache _rl_output_some_chars (nfd, temp); 1576119614Sache _rl_last_c_pos += col_temp; 1577157188Sache /* If we're in a multibyte locale and were before the last invisible 1578157188Sache char in the current line (which implies we just output some invisible 1579157188Sache characters) we need to adjust _rl_last_c_pos, since it represents 1580157188Sache a physical character position. */ 158121308Sache } 158221308Sache } 158321308Sache else /* Delete characters from line. */ 158421308Sache { 158521308Sache /* If possible and inexpensive to use terminal deletion, then do so. */ 1586119614Sache if (_rl_term_dc && (2 * col_temp) >= -col_lendiff) 158721308Sache { 158821308Sache /* If all we're doing is erasing the invisible characters in the 158921308Sache prompt string, don't bother. It screws up the assumptions 159021308Sache about what's on the screen. */ 159121308Sache if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 && 159221308Sache -lendiff == visible_wrap_offset) 1593119614Sache col_lendiff = 0; 159421308Sache 1595119614Sache if (col_lendiff) 1596119614Sache delete_chars (-col_lendiff); /* delete (diff) characters */ 159721308Sache 159821308Sache /* Copy (new) chars to screen from first diff to last match */ 159921308Sache temp = nls - nfd; 160021308Sache if (temp > 0) 160121308Sache { 160221308Sache _rl_output_some_chars (nfd, temp); 1603119614Sache _rl_last_c_pos += _rl_col_width (nfd, 0, temp);; 160421308Sache } 160521308Sache } 160621308Sache /* Otherwise, print over the existing material. */ 160721308Sache else 160821308Sache { 160921308Sache if (temp > 0) 161021308Sache { 161121308Sache _rl_output_some_chars (nfd, temp); 1612157188Sache _rl_last_c_pos += col_temp; /* XXX */ 161321308Sache } 161421308Sache lendiff = (oe - old) - (ne - new); 1615119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1616119614Sache col_lendiff = _rl_col_width (old, 0, oe - old) - _rl_col_width (new, 0, ne - new); 1617119614Sache else 1618119614Sache col_lendiff = lendiff; 1619119614Sache 1620119614Sache if (col_lendiff) 162147563Sache { 162247563Sache if (_rl_term_autowrap && current_line < inv_botlin) 1623119614Sache space_to_eol (col_lendiff); 162447563Sache else 1625119614Sache _rl_clear_to_eol (col_lendiff); 162647563Sache } 162721308Sache } 162821308Sache } 162921308Sache} 163021308Sache 163121308Sache/* Tell the update routines that we have moved onto a new (empty) line. */ 163221308Sacheint 163321308Sacherl_on_new_line () 163421308Sache{ 163521308Sache if (visible_line) 163621308Sache visible_line[0] = '\0'; 163721308Sache 163821308Sache _rl_last_c_pos = _rl_last_v_pos = 0; 163921308Sache _rl_vis_botlin = last_lmargin = 0; 164021308Sache if (vis_lbreaks) 164121308Sache vis_lbreaks[0] = vis_lbreaks[1] = 0; 164221308Sache visible_wrap_offset = 0; 164321308Sache return 0; 164421308Sache} 164521308Sache 164658314Sache/* Tell the update routines that we have moved onto a new line with the 164758314Sache prompt already displayed. Code originally from the version of readline 1648136759Speter distributed with CLISP. rl_expand_prompt must have already been called 1649136759Speter (explicitly or implicitly). This still doesn't work exactly right. */ 165058314Sacheint 165158314Sacherl_on_new_line_with_prompt () 165258314Sache{ 165358314Sache int prompt_size, i, l, real_screenwidth, newlines; 1654136759Speter char *prompt_last_line, *lprompt; 165558314Sache 165658314Sache /* Initialize visible_line and invisible_line to ensure that they can hold 165758314Sache the already-displayed prompt. */ 165858314Sache prompt_size = strlen (rl_prompt) + 1; 165958314Sache init_line_structures (prompt_size); 166058314Sache 166158314Sache /* Make sure the line structures hold the already-displayed prompt for 166258314Sache redisplay. */ 1663136759Speter lprompt = local_prompt ? local_prompt : rl_prompt; 1664136759Speter strcpy (visible_line, lprompt); 1665136759Speter strcpy (invisible_line, lprompt); 166658314Sache 166758314Sache /* If the prompt contains newlines, take the last tail. */ 166858314Sache prompt_last_line = strrchr (rl_prompt, '\n'); 166958314Sache if (!prompt_last_line) 167058314Sache prompt_last_line = rl_prompt; 167158314Sache 167258314Sache l = strlen (prompt_last_line); 1673119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1674157188Sache _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l); /* XXX */ 1675119614Sache else 1676119614Sache _rl_last_c_pos = l; 167758314Sache 167858314Sache /* Dissect prompt_last_line into screen lines. Note that here we have 167958314Sache to use the real screenwidth. Readline's notion of screenwidth might be 168058314Sache one less, see terminal.c. */ 168175409Sache real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1); 168258314Sache _rl_last_v_pos = l / real_screenwidth; 168358314Sache /* If the prompt length is a multiple of real_screenwidth, we don't know 168458314Sache whether the cursor is at the end of the last line, or already at the 168558314Sache beginning of the next line. Output a newline just to be safe. */ 168658314Sache if (l > 0 && (l % real_screenwidth) == 0) 168758314Sache _rl_output_some_chars ("\n", 1); 168858314Sache last_lmargin = 0; 168958314Sache 169058314Sache newlines = 0; i = 0; 169158314Sache while (i <= l) 169258314Sache { 169358314Sache _rl_vis_botlin = newlines; 169458314Sache vis_lbreaks[newlines++] = i; 169558314Sache i += real_screenwidth; 169658314Sache } 169758314Sache vis_lbreaks[newlines] = l; 169858314Sache visible_wrap_offset = 0; 169958314Sache 1700136759Speter rl_display_prompt = rl_prompt; /* XXX - make sure it's set */ 1701136759Speter 170258314Sache return 0; 170358314Sache} 170458314Sache 170521308Sache/* Actually update the display, period. */ 170621308Sacheint 170721308Sacherl_forced_update_display () 170821308Sache{ 1709165675Sache register char *temp; 1710165675Sache 171121308Sache if (visible_line) 171221308Sache { 1713165675Sache temp = visible_line; 171421308Sache while (*temp) 171547563Sache *temp++ = '\0'; 171621308Sache } 171721308Sache rl_on_new_line (); 171821308Sache forced_display++; 171921308Sache (*rl_redisplay_function) (); 172021308Sache return 0; 172121308Sache} 172221308Sache 172321308Sache/* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices. 1724157188Sache (Well, when we don't have multibyte characters, _rl_last_c_pos is a 1725157188Sache buffer index.) 172621308Sache DATA is the contents of the screen line of interest; i.e., where 172721308Sache the movement is being done. */ 172821308Sachevoid 172921308Sache_rl_move_cursor_relative (new, data) 173021308Sache int new; 173175409Sache const char *data; 173221308Sache{ 173321308Sache register int i; 1734157188Sache int woff; /* number of invisible chars on current line */ 1735157188Sache int cpos, dpos; /* current and desired cursor positions */ 173621308Sache 1737157188Sache woff = W_OFFSET (_rl_last_v_pos, wrap_offset); 1738157188Sache cpos = _rl_last_c_pos; 1739119614Sache#if defined (HANDLE_MULTIBYTE) 1740119614Sache /* If we have multibyte characters, NEW is indexed by the buffer point in 1741119614Sache a multibyte string, but _rl_last_c_pos is the display position. In 1742136759Speter this case, NEW's display position is not obvious and must be 1743157188Sache calculated. We need to account for invisible characters in this line, 1744157188Sache as long as we are past them and they are counted by _rl_col_width. */ 1745157188Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1746136759Speter { 1747157188Sache dpos = _rl_col_width (data, 0, new); 1748165675Sache if (dpos > prompt_last_invisible) /* XXX - don't use woff here */ 1749165675Sache { 1750165675Sache dpos -= woff; 1751165675Sache /* Since this will be assigned to _rl_last_c_pos at the end (more 1752165675Sache precisely, _rl_last_c_pos == dpos when this function returns), 1753165675Sache let the caller know. */ 1754165675Sache cpos_adjusted = 1; 1755165675Sache } 1756136759Speter } 1757157188Sache else 1758119614Sache#endif 1759157188Sache dpos = new; 176021308Sache 1761157188Sache /* If we don't have to do anything, then return. */ 1762157188Sache if (cpos == dpos) 1763157188Sache return; 1764157188Sache 176521308Sache /* It may be faster to output a CR, and then move forwards instead 176621308Sache of moving backwards. */ 176721308Sache /* i == current physical cursor position. */ 1768157188Sache#if defined (HANDLE_MULTIBYTE) 1769157188Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1770157188Sache i = _rl_last_c_pos; 1771157188Sache else 1772157188Sache#endif 1773157188Sache i = _rl_last_c_pos - woff; 1774165675Sache if (dpos == 0 || CR_FASTER (dpos, _rl_last_c_pos) || 177575409Sache (_rl_term_autowrap && i == _rl_screenwidth)) 177621308Sache { 177721308Sache#if defined (__MSDOS__) 177821308Sache putc ('\r', rl_outstream); 177921308Sache#else 178075409Sache tputs (_rl_term_cr, 1, _rl_output_character_function); 178121308Sache#endif /* !__MSDOS__ */ 1782157188Sache cpos = _rl_last_c_pos = 0; 178321308Sache } 178421308Sache 1785157188Sache if (cpos < dpos) 178621308Sache { 178721308Sache /* Move the cursor forward. We do it by printing the command 178821308Sache to move the cursor forward if there is one, else print that 178921308Sache portion of the output buffer again. Which is cheaper? */ 179021308Sache 179121308Sache /* The above comment is left here for posterity. It is faster 179221308Sache to print one character (non-control) than to print a control 179321308Sache sequence telling the terminal to move forward one character. 179421308Sache That kind of control is for people who don't know what the 179521308Sache data is underneath the cursor. */ 1796165675Sache 1797165675Sache /* However, we need a handle on where the current display position is 1798165675Sache in the buffer for the immediately preceding comment to be true. 1799165675Sache In multibyte locales, we don't currently have that info available. 1800165675Sache Without it, we don't know where the data we have to display begins 1801165675Sache in the buffer and we have to go back to the beginning of the screen 1802165675Sache line. In this case, we can use the terminal sequence to move forward 1803165675Sache if it's available. */ 1804119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1805119614Sache { 1806165675Sache if (_rl_term_forward_char) 1807165675Sache { 1808165675Sache for (i = cpos; i < dpos; i++) 1809165675Sache tputs (_rl_term_forward_char, 1, _rl_output_character_function); 1810165675Sache } 1811165675Sache else 1812165675Sache { 1813165675Sache tputs (_rl_term_cr, 1, _rl_output_character_function); 1814165675Sache for (i = 0; i < new; i++) 1815165675Sache putc (data[i], rl_outstream); 1816165675Sache } 1817119614Sache } 181821308Sache else 1819157188Sache for (i = cpos; i < new; i++) 182021308Sache putc (data[i], rl_outstream); 1821157188Sache } 1822119614Sache 1823119614Sache#if defined (HANDLE_MULTIBYTE) 1824119614Sache /* NEW points to the buffer point, but _rl_last_c_pos is the display point. 1825119614Sache The byte length of the string is probably bigger than the column width 1826119614Sache of the string, which means that if NEW == _rl_last_c_pos, then NEW's 1827119614Sache display point is less than _rl_last_c_pos. */ 1828119614Sache#endif 1829157188Sache else if (cpos > dpos) 1830157188Sache _rl_backspace (cpos - dpos); 1831119614Sache 1832157188Sache _rl_last_c_pos = dpos; 183321308Sache} 183421308Sache 183521308Sache/* PWP: move the cursor up or down. */ 183621308Sachevoid 183721308Sache_rl_move_vert (to) 183821308Sache int to; 183921308Sache{ 184021308Sache register int delta, i; 184121308Sache 184275409Sache if (_rl_last_v_pos == to || to > _rl_screenheight) 184321308Sache return; 184421308Sache 184521308Sache if ((delta = to - _rl_last_v_pos) > 0) 184621308Sache { 184721308Sache for (i = 0; i < delta; i++) 184821308Sache putc ('\n', rl_outstream); 184958314Sache#if defined (__MSDOS__) 185058314Sache putc ('\r', rl_outstream); 185158314Sache#else 185275409Sache tputs (_rl_term_cr, 1, _rl_output_character_function); 185358314Sache#endif 185421308Sache _rl_last_c_pos = 0; 185521308Sache } 185621308Sache else 185721308Sache { /* delta < 0 */ 185875409Sache if (_rl_term_up && *_rl_term_up) 185921308Sache for (i = 0; i < -delta; i++) 186075409Sache tputs (_rl_term_up, 1, _rl_output_character_function); 186121308Sache } 186258314Sache 186321308Sache _rl_last_v_pos = to; /* Now TO is here */ 186421308Sache} 186521308Sache 186621308Sache/* Physically print C on rl_outstream. This is for functions which know 186721308Sache how to optimize the display. Return the number of characters output. */ 186821308Sacheint 186921308Sacherl_show_char (c) 187021308Sache int c; 187121308Sache{ 187221308Sache int n = 1; 187321308Sache if (META_CHAR (c) && (_rl_output_meta_chars == 0)) 187421308Sache { 187521308Sache fprintf (rl_outstream, "M-"); 187621308Sache n += 2; 187721308Sache c = UNMETA (c); 187821308Sache } 187921308Sache 188021308Sache#if defined (DISPLAY_TABS) 188121308Sache if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT) 188221308Sache#else 188321308Sache if (CTRL_CHAR (c) || c == RUBOUT) 188421308Sache#endif /* !DISPLAY_TABS */ 188521308Sache { 188621308Sache fprintf (rl_outstream, "C-"); 188721308Sache n += 2; 188821308Sache c = CTRL_CHAR (c) ? UNCTRL (c) : '?'; 188921308Sache } 189021308Sache 189121308Sache putc (c, rl_outstream); 189221308Sache fflush (rl_outstream); 189321308Sache return n; 189421308Sache} 189521308Sache 189621308Sacheint 189721308Sacherl_character_len (c, pos) 189821308Sache register int c, pos; 189921308Sache{ 190021308Sache unsigned char uc; 190121308Sache 190221308Sache uc = (unsigned char)c; 190321308Sache 190421308Sache if (META_CHAR (uc)) 190521308Sache return ((_rl_output_meta_chars == 0) ? 4 : 1); 190621308Sache 190721308Sache if (uc == '\t') 190821308Sache { 190921308Sache#if defined (DISPLAY_TABS) 191021308Sache return (((pos | 7) + 1) - pos); 191121308Sache#else 191221308Sache return (2); 191321308Sache#endif /* !DISPLAY_TABS */ 191421308Sache } 191521308Sache 191621308Sache if (CTRL_CHAR (c) || c == RUBOUT) 191721308Sache return (2); 191821308Sache 1919119614Sache return ((ISPRINT (uc)) ? 1 : 2); 192021308Sache} 192121308Sache/* How to print things in the "echo-area". The prompt is treated as a 192221308Sache mini-modeline. */ 1923157188Sachestatic int msg_saved_prompt = 0; 192421308Sache 192521308Sache#if defined (USE_VARARGS) 192621308Sacheint 192721308Sache#if defined (PREFER_STDARG) 192821308Sacherl_message (const char *format, ...) 192921308Sache#else 193021308Sacherl_message (va_alist) 193121308Sache va_dcl 193221308Sache#endif 193321308Sache{ 193421308Sache va_list args; 193521308Sache#if defined (PREFER_VARARGS) 193621308Sache char *format; 193721308Sache#endif 193821308Sache 193921308Sache#if defined (PREFER_STDARG) 194021308Sache va_start (args, format); 194121308Sache#else 194221308Sache va_start (args); 194321308Sache format = va_arg (args, char *); 194421308Sache#endif 194521308Sache 1946119614Sache#if defined (HAVE_VSNPRINTF) 1947119614Sache vsnprintf (msg_buf, sizeof (msg_buf) - 1, format, args); 1948119614Sache#else 194921308Sache vsprintf (msg_buf, format, args); 1950119614Sache msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */ 1951119614Sache#endif 195221308Sache va_end (args); 195321308Sache 1954157188Sache if (saved_local_prompt == 0) 1955157188Sache { 1956157188Sache rl_save_prompt (); 1957157188Sache msg_saved_prompt = 1; 1958157188Sache } 195921308Sache rl_display_prompt = msg_buf; 1960157188Sache local_prompt = expand_prompt (msg_buf, &prompt_visible_length, 1961157188Sache &prompt_last_invisible, 1962157188Sache &prompt_invis_chars_first_line, 1963157188Sache &prompt_physical_chars); 1964157188Sache local_prompt_prefix = (char *)NULL; 1965165675Sache local_prompt_len = local_prompt ? strlen (local_prompt) : 0; 196621308Sache (*rl_redisplay_function) (); 1967157188Sache 196821308Sache return 0; 196921308Sache} 197021308Sache#else /* !USE_VARARGS */ 197121308Sacheint 197221308Sacherl_message (format, arg1, arg2) 197321308Sache char *format; 197421308Sache{ 197521308Sache sprintf (msg_buf, format, arg1, arg2); 1976119614Sache msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */ 1977157188Sache 197821308Sache rl_display_prompt = msg_buf; 1979157188Sache if (saved_local_prompt == 0) 1980157188Sache { 1981157188Sache rl_save_prompt (); 1982157188Sache msg_saved_prompt = 1; 1983157188Sache } 1984157188Sache local_prompt = expand_prompt (msg_buf, &prompt_visible_length, 1985157188Sache &prompt_last_invisible, 1986157188Sache &prompt_invis_chars_first_line, 1987157188Sache &prompt_physical_chars); 1988157188Sache local_prompt_prefix = (char *)NULL; 1989165675Sache local_prompt_len = local_prompt ? strlen (local_prompt) : 0; 199021308Sache (*rl_redisplay_function) (); 1991157188Sache 199221308Sache return 0; 199321308Sache} 199421308Sache#endif /* !USE_VARARGS */ 199521308Sache 199621308Sache/* How to clear things from the "echo-area". */ 199721308Sacheint 199821308Sacherl_clear_message () 199921308Sache{ 200021308Sache rl_display_prompt = rl_prompt; 2001157188Sache if (msg_saved_prompt) 2002157188Sache { 2003157188Sache rl_restore_prompt (); 2004157188Sache msg_saved_prompt = 0; 2005157188Sache } 200621308Sache (*rl_redisplay_function) (); 200721308Sache return 0; 200821308Sache} 200921308Sache 201021308Sacheint 201121308Sacherl_reset_line_state () 201221308Sache{ 201321308Sache rl_on_new_line (); 201421308Sache 201521308Sache rl_display_prompt = rl_prompt ? rl_prompt : ""; 201621308Sache forced_display = 1; 201721308Sache return 0; 201821308Sache} 201921308Sache 202021308Sachevoid 202147563Sacherl_save_prompt () 202221308Sache{ 202321308Sache saved_local_prompt = local_prompt; 202421308Sache saved_local_prefix = local_prompt_prefix; 2025157188Sache saved_prefix_length = prompt_prefix_length; 2026165675Sache saved_local_length = local_prompt_len; 202775409Sache saved_last_invisible = prompt_last_invisible; 202875409Sache saved_visible_length = prompt_visible_length; 2029136759Speter saved_invis_chars_first_line = prompt_invis_chars_first_line; 2030136759Speter saved_physical_chars = prompt_physical_chars; 203121308Sache 203221308Sache local_prompt = local_prompt_prefix = (char *)0; 2033165675Sache local_prompt_len = 0; 2034157188Sache prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0; 2035136759Speter prompt_invis_chars_first_line = prompt_physical_chars = 0; 203621308Sache} 203721308Sache 203821308Sachevoid 203947563Sacherl_restore_prompt () 204021308Sache{ 204175409Sache FREE (local_prompt); 204275409Sache FREE (local_prompt_prefix); 204321308Sache 204421308Sache local_prompt = saved_local_prompt; 204521308Sache local_prompt_prefix = saved_local_prefix; 2046165675Sache local_prompt_len = saved_local_length; 2047157188Sache prompt_prefix_length = saved_prefix_length; 204875409Sache prompt_last_invisible = saved_last_invisible; 204975409Sache prompt_visible_length = saved_visible_length; 2050136759Speter prompt_invis_chars_first_line = saved_invis_chars_first_line; 2051136759Speter prompt_physical_chars = saved_physical_chars; 2052157188Sache 2053157188Sache /* can test saved_local_prompt to see if prompt info has been saved. */ 2054157188Sache saved_local_prompt = saved_local_prefix = (char *)0; 2055165675Sache saved_local_length = 0; 2056157188Sache saved_last_invisible = saved_visible_length = saved_prefix_length = 0; 2057157188Sache saved_invis_chars_first_line = saved_physical_chars = 0; 205821308Sache} 205921308Sache 206021308Sachechar * 206121308Sache_rl_make_prompt_for_search (pchar) 206221308Sache int pchar; 206321308Sache{ 206421308Sache int len; 2065157195Sache char *pmt, *p; 206621308Sache 206747563Sache rl_save_prompt (); 206821308Sache 2069157195Sache /* We've saved the prompt, and can do anything with the various prompt 2070157195Sache strings we need before they're restored. We want the unexpanded 2071157195Sache portion of the prompt string after any final newline. */ 2072157195Sache p = rl_prompt ? strrchr (rl_prompt, '\n') : 0; 2073157195Sache if (p == 0) 207421308Sache { 207521308Sache len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0; 2076119614Sache pmt = (char *)xmalloc (len + 2); 207721308Sache if (len) 207847563Sache strcpy (pmt, rl_prompt); 207921308Sache pmt[len] = pchar; 208021308Sache pmt[len+1] = '\0'; 208121308Sache } 208221308Sache else 208321308Sache { 2084157195Sache p++; 2085157195Sache len = strlen (p); 2086119614Sache pmt = (char *)xmalloc (len + 2); 208721308Sache if (len) 2088157195Sache strcpy (pmt, p); 208921308Sache pmt[len] = pchar; 209021308Sache pmt[len+1] = '\0'; 2091157195Sache } 2092136759Speter 2093157195Sache /* will be overwritten by expand_prompt, called from rl_message */ 2094157188Sache prompt_physical_chars = saved_physical_chars + 1; 209521308Sache return pmt; 209621308Sache} 209721308Sache 209821308Sache/* Quick redisplay hack when erasing characters at the end of the line. */ 209921308Sachevoid 210021308Sache_rl_erase_at_end_of_line (l) 210121308Sache int l; 210221308Sache{ 210321308Sache register int i; 210421308Sache 210521308Sache _rl_backspace (l); 210621308Sache for (i = 0; i < l; i++) 210721308Sache putc (' ', rl_outstream); 210821308Sache _rl_backspace (l); 210921308Sache for (i = 0; i < l; i++) 211021308Sache visible_line[--_rl_last_c_pos] = '\0'; 211121308Sache rl_display_fixed++; 211221308Sache} 211321308Sache 211421308Sache/* Clear to the end of the line. COUNT is the minimum 211521308Sache number of character spaces to clear, */ 211626497Sachevoid 211726497Sache_rl_clear_to_eol (count) 211821308Sache int count; 211921308Sache{ 212075409Sache if (_rl_term_clreol) 212175409Sache tputs (_rl_term_clreol, 1, _rl_output_character_function); 212226497Sache else if (count) 212321308Sache space_to_eol (count); 212421308Sache} 212521308Sache 212621308Sache/* Clear to the end of the line using spaces. COUNT is the minimum 212721308Sache number of character spaces to clear, */ 212821308Sachestatic void 212921308Sachespace_to_eol (count) 213021308Sache int count; 213121308Sache{ 213221308Sache register int i; 213321308Sache 213421308Sache for (i = 0; i < count; i++) 213521308Sache putc (' ', rl_outstream); 213621308Sache 213721308Sache _rl_last_c_pos += count; 213821308Sache} 213921308Sache 214026497Sachevoid 214126497Sache_rl_clear_screen () 214226497Sache{ 214375409Sache if (_rl_term_clrpag) 214475409Sache tputs (_rl_term_clrpag, 1, _rl_output_character_function); 214526497Sache else 214675409Sache rl_crlf (); 214726497Sache} 214826497Sache 2149119614Sache/* Insert COUNT characters from STRING to the output stream at column COL. */ 215021308Sachestatic void 2151119614Sacheinsert_some_chars (string, count, col) 215221308Sache char *string; 2153119614Sache int count, col; 215421308Sache{ 2155157188Sache#if defined (__MSDOS__) || defined (__MINGW32__) 2156157188Sache _rl_output_some_chars (string, count); 2157157188Sache#else 2158119614Sache /* DEBUGGING */ 2159119614Sache if (MB_CUR_MAX == 1 || rl_byte_oriented) 2160119614Sache if (count != col) 2161119614Sache fprintf(stderr, "readline: debug: insert_some_chars: count (%d) != col (%d)\n", count, col); 2162119614Sache 216321308Sache /* If IC is defined, then we do not have to "enter" insert mode. */ 216475409Sache if (_rl_term_IC) 216521308Sache { 216621308Sache char *buffer; 2167119614Sache 2168119614Sache buffer = tgoto (_rl_term_IC, 0, col); 216921308Sache tputs (buffer, 1, _rl_output_character_function); 217021308Sache _rl_output_some_chars (string, count); 217121308Sache } 217221308Sache else 217321308Sache { 217421308Sache register int i; 217521308Sache 217621308Sache /* If we have to turn on insert-mode, then do so. */ 217775409Sache if (_rl_term_im && *_rl_term_im) 217875409Sache tputs (_rl_term_im, 1, _rl_output_character_function); 217921308Sache 218021308Sache /* If there is a special command for inserting characters, then 218121308Sache use that first to open up the space. */ 218275409Sache if (_rl_term_ic && *_rl_term_ic) 218321308Sache { 2184119614Sache for (i = col; i--; ) 218575409Sache tputs (_rl_term_ic, 1, _rl_output_character_function); 218621308Sache } 218721308Sache 218821308Sache /* Print the text. */ 218921308Sache _rl_output_some_chars (string, count); 219021308Sache 219121308Sache /* If there is a string to turn off insert mode, we had best use 219221308Sache it now. */ 219375409Sache if (_rl_term_ei && *_rl_term_ei) 219475409Sache tputs (_rl_term_ei, 1, _rl_output_character_function); 219521308Sache } 2196157188Sache#endif /* __MSDOS__ || __MINGW32__ */ 219721308Sache} 219821308Sache 219921308Sache/* Delete COUNT characters from the display line. */ 220021308Sachestatic void 220121308Sachedelete_chars (count) 220221308Sache int count; 220321308Sache{ 220475409Sache if (count > _rl_screenwidth) /* XXX */ 220521308Sache return; 220621308Sache 2207157188Sache#if !defined (__MSDOS__) && !defined (__MINGW32__) 220875409Sache if (_rl_term_DC && *_rl_term_DC) 220921308Sache { 221021308Sache char *buffer; 221175409Sache buffer = tgoto (_rl_term_DC, count, count); 221221308Sache tputs (buffer, count, _rl_output_character_function); 221321308Sache } 221421308Sache else 221521308Sache { 221675409Sache if (_rl_term_dc && *_rl_term_dc) 221721308Sache while (count--) 221875409Sache tputs (_rl_term_dc, 1, _rl_output_character_function); 221921308Sache } 2220157188Sache#endif /* !__MSDOS__ && !__MINGW32__ */ 222121308Sache} 222221308Sache 222321308Sachevoid 222421308Sache_rl_update_final () 222521308Sache{ 222621308Sache int full_lines; 222721308Sache 222821308Sache full_lines = 0; 222921308Sache /* If the cursor is the only thing on an otherwise-blank last line, 223021308Sache compensate so we don't print an extra CRLF. */ 223121308Sache if (_rl_vis_botlin && _rl_last_c_pos == 0 && 223226497Sache visible_line[vis_lbreaks[_rl_vis_botlin]] == 0) 223321308Sache { 223421308Sache _rl_vis_botlin--; 223521308Sache full_lines = 1; 223621308Sache } 223721308Sache _rl_move_vert (_rl_vis_botlin); 223821308Sache /* If we've wrapped lines, remove the final xterm line-wrap flag. */ 223975409Sache if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth)) 224021308Sache { 224121308Sache char *last_line; 2242119614Sache 224358314Sache last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]]; 2244165675Sache cpos_buffer_position = -1; /* don't know where we are in buffer */ 2245165675Sache _rl_move_cursor_relative (_rl_screenwidth - 1, last_line); /* XXX */ 224626497Sache _rl_clear_to_eol (0); 224775409Sache putc (last_line[_rl_screenwidth - 1], rl_outstream); 224821308Sache } 224921308Sache _rl_vis_botlin = 0; 225075409Sache rl_crlf (); 225121308Sache fflush (rl_outstream); 225221308Sache rl_display_fixed++; 225321308Sache} 225421308Sache 225521308Sache/* Move to the start of the current line. */ 225621308Sachestatic void 225721308Sachecr () 225821308Sache{ 225975409Sache if (_rl_term_cr) 226021308Sache { 226158314Sache#if defined (__MSDOS__) 226258314Sache putc ('\r', rl_outstream); 226358314Sache#else 226475409Sache tputs (_rl_term_cr, 1, _rl_output_character_function); 226558314Sache#endif 226621308Sache _rl_last_c_pos = 0; 226721308Sache } 226821308Sache} 226921308Sache 227058314Sache/* Redraw the last line of a multi-line prompt that may possibly contain 227158314Sache terminal escape sequences. Called with the cursor at column 0 of the 227258314Sache line to draw the prompt on. */ 227358314Sachestatic void 227458314Sacheredraw_prompt (t) 227558314Sache char *t; 227658314Sache{ 2277157188Sache char *oldp; 227858314Sache 227958314Sache oldp = rl_display_prompt; 2280157188Sache rl_save_prompt (); 228158314Sache 228258314Sache rl_display_prompt = t; 228375409Sache local_prompt = expand_prompt (t, &prompt_visible_length, 228475409Sache &prompt_last_invisible, 2285136759Speter &prompt_invis_chars_first_line, 2286136759Speter &prompt_physical_chars); 228758314Sache local_prompt_prefix = (char *)NULL; 2288165675Sache local_prompt_len = local_prompt ? strlen (local_prompt) : 0; 2289157188Sache 229058314Sache rl_forced_update_display (); 229158314Sache 229258314Sache rl_display_prompt = oldp; 2293157188Sache rl_restore_prompt(); 229458314Sache} 229558314Sache 229621308Sache/* Redisplay the current line after a SIGWINCH is received. */ 229721308Sachevoid 229821308Sache_rl_redisplay_after_sigwinch () 229921308Sache{ 230058314Sache char *t; 230121308Sache 230221308Sache /* Clear the current line and put the cursor at column 0. Make sure 230321308Sache the right thing happens if we have wrapped to a new screen line. */ 230475409Sache if (_rl_term_cr) 230521308Sache { 230658314Sache#if defined (__MSDOS__) 230758314Sache putc ('\r', rl_outstream); 230858314Sache#else 230975409Sache tputs (_rl_term_cr, 1, _rl_output_character_function); 231058314Sache#endif 231121308Sache _rl_last_c_pos = 0; 231258314Sache#if defined (__MSDOS__) 231375409Sache space_to_eol (_rl_screenwidth); 231458314Sache putc ('\r', rl_outstream); 231558314Sache#else 231675409Sache if (_rl_term_clreol) 231775409Sache tputs (_rl_term_clreol, 1, _rl_output_character_function); 231821308Sache else 231921308Sache { 232075409Sache space_to_eol (_rl_screenwidth); 232175409Sache tputs (_rl_term_cr, 1, _rl_output_character_function); 232221308Sache } 232358314Sache#endif 232421308Sache if (_rl_last_v_pos > 0) 232521308Sache _rl_move_vert (0); 232621308Sache } 232721308Sache else 232875409Sache rl_crlf (); 232921308Sache 233021308Sache /* Redraw only the last line of a multi-line prompt. */ 233121308Sache t = strrchr (rl_display_prompt, '\n'); 233221308Sache if (t) 233358314Sache redraw_prompt (++t); 233421308Sache else 233521308Sache rl_forced_update_display (); 233621308Sache} 233721308Sache 233821308Sachevoid 233921308Sache_rl_clean_up_for_exit () 234021308Sache{ 234121308Sache if (readline_echoing_p) 234221308Sache { 234321308Sache _rl_move_vert (_rl_vis_botlin); 234421308Sache _rl_vis_botlin = 0; 234521308Sache fflush (rl_outstream); 234647563Sache rl_restart_output (1, 0); 234721308Sache } 234821308Sache} 234947563Sache 235047563Sachevoid 235147563Sache_rl_erase_entire_line () 235247563Sache{ 235347563Sache cr (); 235447563Sache _rl_clear_to_eol (0); 235547563Sache cr (); 235647563Sache fflush (rl_outstream); 235747563Sache} 235858314Sache 235958314Sache/* return the `current display line' of the cursor -- the number of lines to 236058314Sache move up to get to the first screen line of the current readline line. */ 236158314Sacheint 236258314Sache_rl_current_display_line () 236358314Sache{ 236458314Sache int ret, nleft; 236558314Sache 236658314Sache /* Find out whether or not there might be invisible characters in the 236758314Sache editing buffer. */ 236858314Sache if (rl_display_prompt == rl_prompt) 236975409Sache nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length; 237058314Sache else 237175409Sache nleft = _rl_last_c_pos - _rl_screenwidth; 237258314Sache 237358314Sache if (nleft > 0) 237475409Sache ret = 1 + nleft / _rl_screenwidth; 237558314Sache else 237658314Sache ret = 0; 237758314Sache 237858314Sache return ret; 237958314Sache} 2380119614Sache 2381119614Sache#if defined (HANDLE_MULTIBYTE) 2382119614Sache/* Calculate the number of screen columns occupied by STR from START to END. 2383119614Sache In the case of multibyte characters with stateful encoding, we have to 2384119614Sache scan from the beginning of the string to take the state into account. */ 2385119614Sachestatic int 2386119614Sache_rl_col_width (str, start, end) 2387136759Speter const char *str; 2388119614Sache int start, end; 2389119614Sache{ 2390119614Sache wchar_t wc; 2391165675Sache mbstate_t ps; 2392119614Sache int tmp, point, width, max; 2393119614Sache 2394119614Sache if (end <= start) 2395119614Sache return 0; 2396165680Sache if (MB_CUR_MAX == 1 || rl_byte_oriented) 2397165680Sache return (end - start); 2398119614Sache 2399165675Sache memset (&ps, 0, sizeof (mbstate_t)); 2400165675Sache 2401119614Sache point = 0; 2402119614Sache max = end; 2403119614Sache 2404119614Sache while (point < start) 2405119614Sache { 2406119614Sache tmp = mbrlen (str + point, max, &ps); 2407136759Speter if (MB_INVALIDCH ((size_t)tmp)) 2408119614Sache { 2409119614Sache /* In this case, the bytes are invalid or too short to compose a 2410119614Sache multibyte character, so we assume that the first byte represents 2411119614Sache a single character. */ 2412119614Sache point++; 2413119614Sache max--; 2414119614Sache 2415119614Sache /* Clear the state of the byte sequence, because in this case the 2416119614Sache effect of mbstate is undefined. */ 2417119614Sache memset (&ps, 0, sizeof (mbstate_t)); 2418119614Sache } 2419136759Speter else if (MB_NULLWCH (tmp)) 2420136759Speter break; /* Found '\0' */ 2421119614Sache else 2422119614Sache { 2423119614Sache point += tmp; 2424119614Sache max -= tmp; 2425119614Sache } 2426119614Sache } 2427119614Sache 2428119614Sache /* If START is not a byte that starts a character, then POINT will be 2429119614Sache greater than START. In this case, assume that (POINT - START) gives 2430119614Sache a byte count that is the number of columns of difference. */ 2431119614Sache width = point - start; 2432119614Sache 2433119614Sache while (point < end) 2434119614Sache { 2435119614Sache tmp = mbrtowc (&wc, str + point, max, &ps); 2436136759Speter if (MB_INVALIDCH ((size_t)tmp)) 2437119614Sache { 2438119614Sache /* In this case, the bytes are invalid or too short to compose a 2439119614Sache multibyte character, so we assume that the first byte represents 2440119614Sache a single character. */ 2441119614Sache point++; 2442119614Sache max--; 2443119614Sache 2444119614Sache /* and assume that the byte occupies a single column. */ 2445119614Sache width++; 2446119614Sache 2447119614Sache /* Clear the state of the byte sequence, because in this case the 2448119614Sache effect of mbstate is undefined. */ 2449119614Sache memset (&ps, 0, sizeof (mbstate_t)); 2450119614Sache } 2451136759Speter else if (MB_NULLWCH (tmp)) 2452136759Speter break; /* Found '\0' */ 2453119614Sache else 2454119614Sache { 2455119614Sache point += tmp; 2456119614Sache max -= tmp; 2457119614Sache tmp = wcwidth(wc); 2458119614Sache width += (tmp >= 0) ? tmp : 1; 2459119614Sache } 2460119614Sache } 2461119614Sache 2462119614Sache width += point - end; 2463119614Sache 2464119614Sache return width; 2465119614Sache} 2466119614Sache#endif /* HANDLE_MULTIBYTE */ 2467