158314Sache/* $FreeBSD$ */ 221308Sache/* display.c -- readline redisplay facility. */ 321308Sache 4165675Sache/* Copyright (C) 1987-2006 Free Software Foundation, Inc. 521308Sache 621308Sache This file is part of the GNU Readline Library, a library for 721308Sache reading lines of text with interactive input and history editing. 821308Sache 921308Sache The GNU Readline Library is free software; you can redistribute it 1021308Sache and/or modify it under the terms of the GNU General Public License 1158314Sache as published by the Free Software Foundation; either version 2, or 1221308Sache (at your option) any later version. 1321308Sache 1421308Sache The GNU Readline Library is distributed in the hope that it will be 1521308Sache useful, but WITHOUT ANY WARRANTY; without even the implied warranty 1621308Sache of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1721308Sache GNU General Public License for more details. 1821308Sache 1921308Sache The GNU General Public License is often shipped with GNU software, and 2021308Sache is generally kept in a file called COPYING or LICENSE. If you do not 2121308Sache have a copy of the license, write to the Free Software Foundation, 2258314Sache 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ 2321308Sache#define READLINE_LIBRARY 2421308Sache 2521308Sache#if defined (HAVE_CONFIG_H) 2621308Sache# include <config.h> 2721308Sache#endif 2821308Sache 2921308Sache#include <sys/types.h> 3021308Sache 3121308Sache#if defined (HAVE_UNISTD_H) 3221308Sache# include <unistd.h> 3321308Sache#endif /* HAVE_UNISTD_H */ 3421308Sache 3526497Sache#include "posixstat.h" 3626497Sache 3721308Sache#if defined (HAVE_STDLIB_H) 3821308Sache# include <stdlib.h> 3921308Sache#else 4021308Sache# include "ansi_stdlib.h" 4121308Sache#endif /* HAVE_STDLIB_H */ 4221308Sache 4326497Sache#include <stdio.h> 4421308Sache 4521308Sache/* System-specific feature definitions and include files. */ 4621308Sache#include "rldefs.h" 47119614Sache#include "rlmbutil.h" 4821308Sache 4921308Sache/* Termcap library stuff. */ 5021308Sache#include "tcap.h" 5121308Sache 5221308Sache/* Some standard library routines. */ 5321308Sache#include "readline.h" 5421308Sache#include "history.h" 5521308Sache 5658314Sache#include "rlprivate.h" 5758314Sache#include "xmalloc.h" 5858314Sache 5921308Sache#if !defined (strchr) && !defined (__STDC__) 6021308Sacheextern char *strchr (), *strrchr (); 6121308Sache#endif /* !strchr && !__STDC__ */ 6221308Sache 63119614Sachestatic void update_line PARAMS((char *, char *, int, int, int, int)); 64119614Sachestatic void space_to_eol PARAMS((int)); 65119614Sachestatic void delete_chars PARAMS((int)); 66119614Sachestatic void insert_some_chars PARAMS((char *, int, int)); 67119614Sachestatic void cr PARAMS((void)); 6821308Sache 69119614Sache#if defined (HANDLE_MULTIBYTE) 70136759Speterstatic int _rl_col_width PARAMS((const char *, int, int)); 71119614Sachestatic int *_rl_wrapped_line; 72119614Sache#else 73119614Sache# define _rl_col_width(l, s, e) (((e) <= (s)) ? 0 : (e) - (s)) 74119614Sache#endif 75119614Sache 7621308Sachestatic int *inv_lbreaks, *vis_lbreaks; 7758314Sachestatic int inv_lbsize, vis_lbsize; 7821308Sache 7921308Sache/* Heuristic used to decide whether it is faster to move from CUR to NEW 80165675Sache by backing up or outputting a carriage return and moving forward. CUR 81165675Sache and NEW are either both buffer positions or absolute screen positions. */ 8221308Sache#define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new))) 8321308Sache 84165675Sache/* _rl_last_c_pos is an absolute cursor position in multibyte locales and a 85165675Sache buffer index in others. This macro is used when deciding whether the 86165675Sache current cursor position is in the middle of a prompt string containing 87165675Sache invisible characters. */ 88165675Sache#define PROMPT_ENDING_INDEX \ 89165675Sache ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) ? prompt_physical_chars : prompt_last_invisible+1) 90165675Sache 91165675Sache 9221308Sache/* **************************************************************** */ 9321308Sache/* */ 9421308Sache/* Display stuff */ 9521308Sache/* */ 9621308Sache/* **************************************************************** */ 9721308Sache 9821308Sache/* This is the stuff that is hard for me. I never seem to write good 9921308Sache display routines in C. Let's see how I do this time. */ 10021308Sache 10121308Sache/* (PWP) Well... Good for a simple line updater, but totally ignores 10221308Sache the problems of input lines longer than the screen width. 10321308Sache 10421308Sache update_line and the code that calls it makes a multiple line, 10521308Sache automatically wrapping line update. Careful attention needs 10621308Sache to be paid to the vertical position variables. */ 10721308Sache 10821308Sache/* Keep two buffers; one which reflects the current contents of the 10921308Sache screen, and the other to draw what we think the new contents should 11021308Sache be. Then compare the buffers, and make whatever changes to the 11121308Sache screen itself that we should. Finally, make the buffer that we 11221308Sache just drew into be the one which reflects the current contents of the 11321308Sache screen, and place the cursor where it belongs. 11421308Sache 11521308Sache Commands that want to can fix the display themselves, and then let 11621308Sache this function know that the display has been fixed by setting the 11721308Sache RL_DISPLAY_FIXED variable. This is good for efficiency. */ 11821308Sache 11921308Sache/* Application-specific redisplay function. */ 12075409Sacherl_voidfunc_t *rl_redisplay_function = rl_redisplay; 12121308Sache 12221308Sache/* Global variables declared here. */ 12321308Sache/* What YOU turn on when you have handled all redisplay yourself. */ 12421308Sacheint rl_display_fixed = 0; 12521308Sache 12621308Sacheint _rl_suppress_redisplay = 0; 127157188Sacheint _rl_want_redisplay = 0; 12821308Sache 12921308Sache/* The stuff that gets printed out before the actual text of the line. 13021308Sache This is usually pointing to rl_prompt. */ 13121308Sachechar *rl_display_prompt = (char *)NULL; 13221308Sache 13321308Sache/* Pseudo-global variables declared here. */ 134157188Sache 13521308Sache/* The visible cursor position. If you print some text, adjust this. */ 136157188Sache/* NOTE: _rl_last_c_pos is used as a buffer index when not in a locale 137157188Sache supporting multibyte characters, and an absolute cursor position when 138157188Sache in such a locale. This is an artifact of the donated multibyte support. 139157188Sache Care must be taken when modifying its value. */ 14021308Sacheint _rl_last_c_pos = 0; 14121308Sacheint _rl_last_v_pos = 0; 14221308Sache 143157188Sachestatic int cpos_adjusted; 144165675Sachestatic int cpos_buffer_position; 145157188Sache 14621308Sache/* Number of lines currently on screen minus 1. */ 14721308Sacheint _rl_vis_botlin = 0; 14821308Sache 14921308Sache/* Variables used only in this file. */ 15021308Sache/* The last left edge of text that was displayed. This is used when 15121308Sache doing horizontal scrolling. It shifts in thirds of a screenwidth. */ 15221308Sachestatic int last_lmargin; 15321308Sache 15421308Sache/* The line display buffers. One is the line currently displayed on 15521308Sache the screen. The other is the line about to be displayed. */ 15621308Sachestatic char *visible_line = (char *)NULL; 15721308Sachestatic char *invisible_line = (char *)NULL; 15821308Sache 15921308Sache/* A buffer for `modeline' messages. */ 16021308Sachestatic char msg_buf[128]; 16121308Sache 16221308Sache/* Non-zero forces the redisplay even if we thought it was unnecessary. */ 16321308Sachestatic int forced_display; 16421308Sache 16521308Sache/* Default and initial buffer size. Can grow. */ 16621308Sachestatic int line_size = 1024; 16721308Sache 16875409Sache/* Variables to keep track of the expanded prompt string, which may 16975409Sache include invisible characters. */ 17075409Sache 17121308Sachestatic char *local_prompt, *local_prompt_prefix; 172165675Sachestatic int local_prompt_len; 17375409Sachestatic int prompt_visible_length, prompt_prefix_length; 17421308Sache 17521308Sache/* The number of invisible characters in the line currently being 17621308Sache displayed on the screen. */ 17721308Sachestatic int visible_wrap_offset; 17821308Sache 17975409Sache/* The number of invisible characters in the prompt string. Static so it 18075409Sache can be shared between rl_redisplay and update_line */ 18121308Sachestatic int wrap_offset; 18221308Sache 18375409Sache/* The index of the last invisible character in the prompt string. */ 18475409Sachestatic int prompt_last_invisible; 18521308Sache 18621308Sache/* The length (buffer offset) of the first line of the last (possibly 18721308Sache multi-line) buffer displayed on the screen. */ 18821308Sachestatic int visible_first_line_len; 18921308Sache 19075409Sache/* Number of invisible characters on the first physical line of the prompt. 19175409Sache Only valid when the number of physical characters in the prompt exceeds 19275409Sache (or is equal to) _rl_screenwidth. */ 19375409Sachestatic int prompt_invis_chars_first_line; 19475409Sache 19575409Sachestatic int prompt_last_screen_line; 19675409Sache 197136759Speterstatic int prompt_physical_chars; 198136759Speter 199157188Sache/* Variables to save and restore prompt and display information. */ 200157188Sache 201157188Sache/* These are getting numerous enough that it's time to create a struct. */ 202157188Sache 203157188Sachestatic char *saved_local_prompt; 204157188Sachestatic char *saved_local_prefix; 205157188Sachestatic int saved_last_invisible; 206157188Sachestatic int saved_visible_length; 207157188Sachestatic int saved_prefix_length; 208165675Sachestatic int saved_local_length; 209157188Sachestatic int saved_invis_chars_first_line; 210157188Sachestatic int saved_physical_chars; 211157188Sache 21221308Sache/* Expand the prompt string S and return the number of visible 21321308Sache characters in *LP, if LP is not null. This is currently more-or-less 21421308Sache a placeholder for expansion. LIP, if non-null is a place to store the 21575409Sache index of the last invisible character in the returned string. NIFLP, 21675409Sache if non-zero, is a place to store the number of invisible characters in 217136759Speter the first prompt line. The previous are used as byte counts -- indexes 218136759Speter into a character buffer. */ 21921308Sache 22021308Sache/* Current implementation: 22121308Sache \001 (^A) start non-visible characters 22221308Sache \002 (^B) end non-visible characters 22321308Sache all characters except \001 and \002 (following a \001) are copied to 22421308Sache the returned string; all characters except those between \001 and 22521308Sache \002 are assumed to be `visible'. */ 22621308Sache 22721308Sachestatic char * 228136759Speterexpand_prompt (pmt, lp, lip, niflp, vlp) 22921308Sache char *pmt; 230136759Speter int *lp, *lip, *niflp, *vlp; 23121308Sache{ 232165675Sache char *r, *ret, *p, *igstart; 233136759Speter int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars; 23421308Sache 23521308Sache /* Short-circuit if we can. */ 236136759Speter if ((MB_CUR_MAX <= 1 || rl_byte_oriented) && strchr (pmt, RL_PROMPT_START_IGNORE) == 0) 23721308Sache { 23821308Sache r = savestring (pmt); 23921308Sache if (lp) 24021308Sache *lp = strlen (r); 241136759Speter if (lip) 242136759Speter *lip = 0; 243136759Speter if (niflp) 244136759Speter *niflp = 0; 245136759Speter if (vlp) 246136759Speter *vlp = lp ? *lp : strlen (r); 24721308Sache return r; 24821308Sache } 24921308Sache 25021308Sache l = strlen (pmt); 251119614Sache r = ret = (char *)xmalloc (l + 1); 25275409Sache 25375409Sache invfl = 0; /* invisible chars in first line of prompt */ 254136759Speter invflset = 0; /* we only want to set invfl once */ 25575409Sache 256165675Sache igstart = 0; 257136759Speter for (rl = ignoring = last = ninvis = physchars = 0, p = pmt; p && *p; p++) 25821308Sache { 25921308Sache /* This code strips the invisible character string markers 26021308Sache RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */ 261165675Sache if (ignoring == 0 && *p == RL_PROMPT_START_IGNORE) /* XXX - check ignoring? */ 26221308Sache { 263165675Sache ignoring = 1; 264165675Sache igstart = p; 26521308Sache continue; 26621308Sache } 26721308Sache else if (ignoring && *p == RL_PROMPT_END_IGNORE) 26821308Sache { 26921308Sache ignoring = 0; 270165675Sache if (p != (igstart + 1)) 271157188Sache last = r - ret - 1; 27221308Sache continue; 27321308Sache } 27421308Sache else 27521308Sache { 276136759Speter#if defined (HANDLE_MULTIBYTE) 277136759Speter if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 278136759Speter { 279136759Speter pind = p - pmt; 280136759Speter ind = _rl_find_next_mbchar (pmt, pind, 1, MB_FIND_NONZERO); 281136759Speter l = ind - pind; 282136759Speter while (l--) 283136759Speter *r++ = *p++; 284136759Speter if (!ignoring) 285136759Speter { 286136759Speter rl += ind - pind; 287136759Speter physchars += _rl_col_width (pmt, pind, ind); 288136759Speter } 289136759Speter else 290136759Speter ninvis += ind - pind; 291136759Speter p--; /* compensate for later increment */ 292136759Speter } 29375409Sache else 294136759Speter#endif 295136759Speter { 296136759Speter *r++ = *p; 297136759Speter if (!ignoring) 298136759Speter { 299136759Speter rl++; /* visible length byte counter */ 300136759Speter physchars++; 301136759Speter } 302136759Speter else 303136759Speter ninvis++; /* invisible chars byte counter */ 304136759Speter } 305136759Speter 306136759Speter if (invflset == 0 && rl >= _rl_screenwidth) 307136759Speter { 308136759Speter invfl = ninvis; 309136759Speter invflset = 1; 310136759Speter } 31121308Sache } 31221308Sache } 31321308Sache 31475409Sache if (rl < _rl_screenwidth) 31575409Sache invfl = ninvis; 31675409Sache 31721308Sache *r = '\0'; 31821308Sache if (lp) 31921308Sache *lp = rl; 32021308Sache if (lip) 32121308Sache *lip = last; 32275409Sache if (niflp) 32375409Sache *niflp = invfl; 324136759Speter if (vlp) 325136759Speter *vlp = physchars; 32621308Sache return ret; 32721308Sache} 32821308Sache 32958314Sache/* Just strip out RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE from 33058314Sache PMT and return the rest of PMT. */ 33158314Sachechar * 33258314Sache_rl_strip_prompt (pmt) 33358314Sache char *pmt; 33458314Sache{ 33558314Sache char *ret; 33658314Sache 337136759Speter ret = expand_prompt (pmt, (int *)NULL, (int *)NULL, (int *)NULL, (int *)NULL); 33858314Sache return ret; 33958314Sache} 34058314Sache 34121308Sache/* 34221308Sache * Expand the prompt string into the various display components, if 34321308Sache * necessary. 34421308Sache * 34521308Sache * local_prompt = expanded last line of string in rl_display_prompt 34621308Sache * (portion after the final newline) 34721308Sache * local_prompt_prefix = portion before last newline of rl_display_prompt, 34821308Sache * expanded via expand_prompt 34975409Sache * prompt_visible_length = number of visible characters in local_prompt 35075409Sache * prompt_prefix_length = number of visible characters in local_prompt_prefix 35121308Sache * 35221308Sache * This function is called once per call to readline(). It may also be 35321308Sache * called arbitrarily to expand the primary prompt. 35421308Sache * 35521308Sache * The return value is the number of visible characters on the last line 35621308Sache * of the (possibly multi-line) prompt. 35721308Sache */ 35821308Sacheint 35921308Sacherl_expand_prompt (prompt) 36021308Sache char *prompt; 36121308Sache{ 36221308Sache char *p, *t; 36321308Sache int c; 36421308Sache 36521308Sache /* Clear out any saved values. */ 36675409Sache FREE (local_prompt); 36775409Sache FREE (local_prompt_prefix); 36875409Sache 36921308Sache local_prompt = local_prompt_prefix = (char *)0; 370165675Sache local_prompt_len = 0; 371157188Sache prompt_last_invisible = prompt_invis_chars_first_line = 0; 372157188Sache prompt_visible_length = prompt_physical_chars = 0; 37321308Sache 37421308Sache if (prompt == 0 || *prompt == 0) 37521308Sache return (0); 37621308Sache 37721308Sache p = strrchr (prompt, '\n'); 37821308Sache if (!p) 37921308Sache { 38075409Sache /* The prompt is only one logical line, though it might wrap. */ 38175409Sache local_prompt = expand_prompt (prompt, &prompt_visible_length, 38275409Sache &prompt_last_invisible, 383136759Speter &prompt_invis_chars_first_line, 384136759Speter &prompt_physical_chars); 38521308Sache local_prompt_prefix = (char *)0; 386165675Sache local_prompt_len = local_prompt ? strlen (local_prompt) : 0; 38775409Sache return (prompt_visible_length); 38821308Sache } 38921308Sache else 39021308Sache { 39121308Sache /* The prompt spans multiple lines. */ 39221308Sache t = ++p; 39375409Sache local_prompt = expand_prompt (p, &prompt_visible_length, 39475409Sache &prompt_last_invisible, 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; 1522173406Sache /* If col_lendiff is > 0, implying that the new string takes up more 1523173406Sache screen real estate than the old, but lendiff is < 0, meaning that it 1524173406Sache takes fewer bytes, we need to just output the characters starting 1525173406Sache from the first difference. These will overwrite what is on the 1526173406Sache display, so there's no reason to do a smart update. This can really 1527173406Sache only happen in a multibyte environment. */ 1528173406Sache if (lendiff < 0) 1529173406Sache { 1530173406Sache _rl_output_some_chars (nfd, temp); 1531173406Sache _rl_last_c_pos += _rl_col_width (nfd, 0, temp); 1532173406Sache /* If nfd begins before any invisible characters in the prompt, 1533173406Sache adjust _rl_last_c_pos to account for wrap_offset and set 1534173406Sache cpos_adjusted to let the caller know. */ 1535173406Sache if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible)) 1536173406Sache { 1537173406Sache _rl_last_c_pos -= wrap_offset; 1538173406Sache cpos_adjusted = 1; 1539173406Sache } 1540173406Sache return; 1541173406Sache } 154221308Sache /* Sometimes it is cheaper to print the characters rather than 154321308Sache use the terminal's capabilities. If we're growing the number 154421308Sache of lines, make sure we actually cause the new line to wrap 154521308Sache around on auto-wrapping terminals. */ 1546173406Sache else if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl)) 154721308Sache { 154875409Sache /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and 154921308Sache _rl_horizontal_scroll_mode == 1, inserting the characters with 155075409Sache _rl_term_IC or _rl_term_ic will screw up the screen because of the 155121308Sache invisible characters. We need to just draw them. */ 155221308Sache if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 || 155375409Sache lendiff <= prompt_visible_length || !current_invis_chars)) 155421308Sache { 1555119614Sache insert_some_chars (nfd, lendiff, col_lendiff); 1556119614Sache _rl_last_c_pos += col_lendiff; 155721308Sache } 1558157188Sache else if ((MB_CUR_MAX == 1 || rl_byte_oriented != 0) && *ols == 0 && lendiff > 0) 155921308Sache { 156021308Sache /* At the end of a line the characters do not have to 156121308Sache be "inserted". They can just be placed on the screen. */ 156221308Sache /* However, this screws up the rest of this block, which 156347563Sache assumes you've done the insert because you can. */ 156421308Sache _rl_output_some_chars (nfd, lendiff); 1565119614Sache _rl_last_c_pos += col_lendiff; 156621308Sache } 156721308Sache else 156821308Sache { 156921308Sache /* We have horizontal scrolling and we are not inserting at 157021308Sache the end. We have invisible characters in this line. This 157121308Sache is a dumb update. */ 157221308Sache _rl_output_some_chars (nfd, temp); 1573119614Sache _rl_last_c_pos += col_temp; 157421308Sache return; 157521308Sache } 157621308Sache /* Copy (new) chars to screen from first diff to last match. */ 157721308Sache temp = nls - nfd; 157821308Sache if ((temp - lendiff) > 0) 157921308Sache { 158021308Sache _rl_output_some_chars (nfd + lendiff, temp - lendiff); 1581136759Speter#if 1 1582136759Speter /* XXX -- this bears closer inspection. Fixes a redisplay bug 1583136759Speter reported against bash-3.0-alpha by Andreas Schwab involving 1584136759Speter multibyte characters and prompt strings with invisible 1585136759Speter characters, but was previously disabled. */ 1586136759Speter _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-col_lendiff); 1587119614Sache#else 1588136759Speter _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-lendiff); 1589119614Sache#endif 159021308Sache } 159121308Sache } 159221308Sache else 159321308Sache { 159421308Sache /* cannot insert chars, write to EOL */ 159521308Sache _rl_output_some_chars (nfd, temp); 1596119614Sache _rl_last_c_pos += col_temp; 1597157188Sache /* If we're in a multibyte locale and were before the last invisible 1598157188Sache char in the current line (which implies we just output some invisible 1599157188Sache characters) we need to adjust _rl_last_c_pos, since it represents 1600157188Sache a physical character position. */ 160121308Sache } 160221308Sache } 160321308Sache else /* Delete characters from line. */ 160421308Sache { 160521308Sache /* If possible and inexpensive to use terminal deletion, then do so. */ 1606119614Sache if (_rl_term_dc && (2 * col_temp) >= -col_lendiff) 160721308Sache { 160821308Sache /* If all we're doing is erasing the invisible characters in the 160921308Sache prompt string, don't bother. It screws up the assumptions 161021308Sache about what's on the screen. */ 161121308Sache if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 && 161221308Sache -lendiff == visible_wrap_offset) 1613119614Sache col_lendiff = 0; 161421308Sache 1615119614Sache if (col_lendiff) 1616119614Sache delete_chars (-col_lendiff); /* delete (diff) characters */ 161721308Sache 161821308Sache /* Copy (new) chars to screen from first diff to last match */ 161921308Sache temp = nls - nfd; 162021308Sache if (temp > 0) 162121308Sache { 1622173406Sache /* If nfd begins at the prompt, or before the invisible 1623173406Sache characters in the prompt, we need to adjust _rl_last_c_pos 1624173406Sache in a multibyte locale to account for the wrap offset and 1625173406Sache set cpos_adjusted accordingly. */ 162621308Sache _rl_output_some_chars (nfd, temp); 1627173406Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1628173406Sache { 1629173406Sache _rl_last_c_pos += _rl_col_width (nfd, 0, temp); 1630173406Sache if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible)) 1631173406Sache { 1632173406Sache _rl_last_c_pos -= wrap_offset; 1633173406Sache cpos_adjusted = 1; 1634173406Sache } 1635173406Sache } 1636173406Sache else 1637173406Sache _rl_last_c_pos += temp; 163821308Sache } 163921308Sache } 164021308Sache /* Otherwise, print over the existing material. */ 164121308Sache else 164221308Sache { 164321308Sache if (temp > 0) 164421308Sache { 1645173406Sache /* If nfd begins at the prompt, or before the invisible 1646173406Sache characters in the prompt, we need to adjust _rl_last_c_pos 1647173406Sache in a multibyte locale to account for the wrap offset and 1648173406Sache set cpos_adjusted accordingly. */ 164921308Sache _rl_output_some_chars (nfd, temp); 1650157188Sache _rl_last_c_pos += col_temp; /* XXX */ 1651173406Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1652173406Sache { 1653173406Sache if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible)) 1654173406Sache { 1655173406Sache _rl_last_c_pos -= wrap_offset; 1656173406Sache cpos_adjusted = 1; 1657173406Sache } 1658173406Sache } 165921308Sache } 166021308Sache lendiff = (oe - old) - (ne - new); 1661119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1662119614Sache col_lendiff = _rl_col_width (old, 0, oe - old) - _rl_col_width (new, 0, ne - new); 1663119614Sache else 1664119614Sache col_lendiff = lendiff; 1665119614Sache 1666119614Sache if (col_lendiff) 166747563Sache { 166847563Sache if (_rl_term_autowrap && current_line < inv_botlin) 1669119614Sache space_to_eol (col_lendiff); 167047563Sache else 1671119614Sache _rl_clear_to_eol (col_lendiff); 167247563Sache } 167321308Sache } 167421308Sache } 167521308Sache} 167621308Sache 167721308Sache/* Tell the update routines that we have moved onto a new (empty) line. */ 167821308Sacheint 167921308Sacherl_on_new_line () 168021308Sache{ 168121308Sache if (visible_line) 168221308Sache visible_line[0] = '\0'; 168321308Sache 168421308Sache _rl_last_c_pos = _rl_last_v_pos = 0; 168521308Sache _rl_vis_botlin = last_lmargin = 0; 168621308Sache if (vis_lbreaks) 168721308Sache vis_lbreaks[0] = vis_lbreaks[1] = 0; 168821308Sache visible_wrap_offset = 0; 168921308Sache return 0; 169021308Sache} 169121308Sache 169258314Sache/* Tell the update routines that we have moved onto a new line with the 169358314Sache prompt already displayed. Code originally from the version of readline 1694136759Speter distributed with CLISP. rl_expand_prompt must have already been called 1695136759Speter (explicitly or implicitly). This still doesn't work exactly right. */ 169658314Sacheint 169758314Sacherl_on_new_line_with_prompt () 169858314Sache{ 169958314Sache int prompt_size, i, l, real_screenwidth, newlines; 1700136759Speter char *prompt_last_line, *lprompt; 170158314Sache 170258314Sache /* Initialize visible_line and invisible_line to ensure that they can hold 170358314Sache the already-displayed prompt. */ 170458314Sache prompt_size = strlen (rl_prompt) + 1; 170558314Sache init_line_structures (prompt_size); 170658314Sache 170758314Sache /* Make sure the line structures hold the already-displayed prompt for 170858314Sache redisplay. */ 1709136759Speter lprompt = local_prompt ? local_prompt : rl_prompt; 1710136759Speter strcpy (visible_line, lprompt); 1711136759Speter strcpy (invisible_line, lprompt); 171258314Sache 171358314Sache /* If the prompt contains newlines, take the last tail. */ 171458314Sache prompt_last_line = strrchr (rl_prompt, '\n'); 171558314Sache if (!prompt_last_line) 171658314Sache prompt_last_line = rl_prompt; 171758314Sache 171858314Sache l = strlen (prompt_last_line); 1719119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1720157188Sache _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l); /* XXX */ 1721119614Sache else 1722119614Sache _rl_last_c_pos = l; 172358314Sache 172458314Sache /* Dissect prompt_last_line into screen lines. Note that here we have 172558314Sache to use the real screenwidth. Readline's notion of screenwidth might be 172658314Sache one less, see terminal.c. */ 172775409Sache real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1); 172858314Sache _rl_last_v_pos = l / real_screenwidth; 172958314Sache /* If the prompt length is a multiple of real_screenwidth, we don't know 173058314Sache whether the cursor is at the end of the last line, or already at the 173158314Sache beginning of the next line. Output a newline just to be safe. */ 173258314Sache if (l > 0 && (l % real_screenwidth) == 0) 173358314Sache _rl_output_some_chars ("\n", 1); 173458314Sache last_lmargin = 0; 173558314Sache 173658314Sache newlines = 0; i = 0; 173758314Sache while (i <= l) 173858314Sache { 173958314Sache _rl_vis_botlin = newlines; 174058314Sache vis_lbreaks[newlines++] = i; 174158314Sache i += real_screenwidth; 174258314Sache } 174358314Sache vis_lbreaks[newlines] = l; 174458314Sache visible_wrap_offset = 0; 174558314Sache 1746136759Speter rl_display_prompt = rl_prompt; /* XXX - make sure it's set */ 1747136759Speter 174858314Sache return 0; 174958314Sache} 175058314Sache 175121308Sache/* Actually update the display, period. */ 175221308Sacheint 175321308Sacherl_forced_update_display () 175421308Sache{ 1755165675Sache register char *temp; 1756165675Sache 175721308Sache if (visible_line) 175821308Sache { 1759165675Sache temp = visible_line; 176021308Sache while (*temp) 176147563Sache *temp++ = '\0'; 176221308Sache } 176321308Sache rl_on_new_line (); 176421308Sache forced_display++; 176521308Sache (*rl_redisplay_function) (); 176621308Sache return 0; 176721308Sache} 176821308Sache 176921308Sache/* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices. 1770157188Sache (Well, when we don't have multibyte characters, _rl_last_c_pos is a 1771157188Sache buffer index.) 177221308Sache DATA is the contents of the screen line of interest; i.e., where 177321308Sache the movement is being done. */ 177421308Sachevoid 177521308Sache_rl_move_cursor_relative (new, data) 177621308Sache int new; 177775409Sache const char *data; 177821308Sache{ 177921308Sache register int i; 1780157188Sache int woff; /* number of invisible chars on current line */ 1781157188Sache int cpos, dpos; /* current and desired cursor positions */ 178221308Sache 1783157188Sache woff = W_OFFSET (_rl_last_v_pos, wrap_offset); 1784157188Sache cpos = _rl_last_c_pos; 1785119614Sache#if defined (HANDLE_MULTIBYTE) 1786119614Sache /* If we have multibyte characters, NEW is indexed by the buffer point in 1787119614Sache a multibyte string, but _rl_last_c_pos is the display position. In 1788136759Speter this case, NEW's display position is not obvious and must be 1789157188Sache calculated. We need to account for invisible characters in this line, 1790157188Sache as long as we are past them and they are counted by _rl_col_width. */ 1791157188Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1792136759Speter { 1793157188Sache dpos = _rl_col_width (data, 0, new); 1794173406Sache /* Use NEW when comparing against the last invisible character in the 1795173406Sache prompt string, since they're both buffer indices and DPOS is a 1796173406Sache desired display position. */ 1797173406Sache if (new > prompt_last_invisible) /* XXX - don't use woff here */ 1798165675Sache { 1799165675Sache dpos -= woff; 1800165675Sache /* Since this will be assigned to _rl_last_c_pos at the end (more 1801165675Sache precisely, _rl_last_c_pos == dpos when this function returns), 1802165675Sache let the caller know. */ 1803165675Sache cpos_adjusted = 1; 1804165675Sache } 1805136759Speter } 1806157188Sache else 1807119614Sache#endif 1808157188Sache dpos = new; 180921308Sache 1810157188Sache /* If we don't have to do anything, then return. */ 1811157188Sache if (cpos == dpos) 1812157188Sache return; 1813157188Sache 181421308Sache /* It may be faster to output a CR, and then move forwards instead 181521308Sache of moving backwards. */ 181621308Sache /* i == current physical cursor position. */ 1817157188Sache#if defined (HANDLE_MULTIBYTE) 1818157188Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1819157188Sache i = _rl_last_c_pos; 1820157188Sache else 1821157188Sache#endif 1822157188Sache i = _rl_last_c_pos - woff; 1823165675Sache if (dpos == 0 || CR_FASTER (dpos, _rl_last_c_pos) || 182475409Sache (_rl_term_autowrap && i == _rl_screenwidth)) 182521308Sache { 182621308Sache#if defined (__MSDOS__) 182721308Sache putc ('\r', rl_outstream); 182821308Sache#else 182975409Sache tputs (_rl_term_cr, 1, _rl_output_character_function); 183021308Sache#endif /* !__MSDOS__ */ 1831157188Sache cpos = _rl_last_c_pos = 0; 183221308Sache } 183321308Sache 1834157188Sache if (cpos < dpos) 183521308Sache { 183621308Sache /* Move the cursor forward. We do it by printing the command 183721308Sache to move the cursor forward if there is one, else print that 183821308Sache portion of the output buffer again. Which is cheaper? */ 183921308Sache 184021308Sache /* The above comment is left here for posterity. It is faster 184121308Sache to print one character (non-control) than to print a control 184221308Sache sequence telling the terminal to move forward one character. 184321308Sache That kind of control is for people who don't know what the 184421308Sache data is underneath the cursor. */ 1845165675Sache 1846165675Sache /* However, we need a handle on where the current display position is 1847165675Sache in the buffer for the immediately preceding comment to be true. 1848165675Sache In multibyte locales, we don't currently have that info available. 1849165675Sache Without it, we don't know where the data we have to display begins 1850165675Sache in the buffer and we have to go back to the beginning of the screen 1851165675Sache line. In this case, we can use the terminal sequence to move forward 1852165675Sache if it's available. */ 1853119614Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1854119614Sache { 1855165675Sache if (_rl_term_forward_char) 1856165675Sache { 1857165675Sache for (i = cpos; i < dpos; i++) 1858165675Sache tputs (_rl_term_forward_char, 1, _rl_output_character_function); 1859165675Sache } 1860165675Sache else 1861165675Sache { 1862165675Sache tputs (_rl_term_cr, 1, _rl_output_character_function); 1863165675Sache for (i = 0; i < new; i++) 1864165675Sache putc (data[i], rl_outstream); 1865165675Sache } 1866119614Sache } 186721308Sache else 1868157188Sache for (i = cpos; i < new; i++) 186921308Sache putc (data[i], rl_outstream); 1870157188Sache } 1871119614Sache 1872119614Sache#if defined (HANDLE_MULTIBYTE) 1873119614Sache /* NEW points to the buffer point, but _rl_last_c_pos is the display point. 1874119614Sache The byte length of the string is probably bigger than the column width 1875119614Sache of the string, which means that if NEW == _rl_last_c_pos, then NEW's 1876119614Sache display point is less than _rl_last_c_pos. */ 1877119614Sache#endif 1878157188Sache else if (cpos > dpos) 1879157188Sache _rl_backspace (cpos - dpos); 1880119614Sache 1881157188Sache _rl_last_c_pos = dpos; 188221308Sache} 188321308Sache 188421308Sache/* PWP: move the cursor up or down. */ 188521308Sachevoid 188621308Sache_rl_move_vert (to) 188721308Sache int to; 188821308Sache{ 188921308Sache register int delta, i; 189021308Sache 189175409Sache if (_rl_last_v_pos == to || to > _rl_screenheight) 189221308Sache return; 189321308Sache 189421308Sache if ((delta = to - _rl_last_v_pos) > 0) 189521308Sache { 189621308Sache for (i = 0; i < delta; i++) 189721308Sache putc ('\n', rl_outstream); 189858314Sache#if defined (__MSDOS__) 189958314Sache putc ('\r', rl_outstream); 190058314Sache#else 190175409Sache tputs (_rl_term_cr, 1, _rl_output_character_function); 190258314Sache#endif 190321308Sache _rl_last_c_pos = 0; 190421308Sache } 190521308Sache else 190621308Sache { /* delta < 0 */ 190775409Sache if (_rl_term_up && *_rl_term_up) 190821308Sache for (i = 0; i < -delta; i++) 190975409Sache tputs (_rl_term_up, 1, _rl_output_character_function); 191021308Sache } 191158314Sache 191221308Sache _rl_last_v_pos = to; /* Now TO is here */ 191321308Sache} 191421308Sache 191521308Sache/* Physically print C on rl_outstream. This is for functions which know 191621308Sache how to optimize the display. Return the number of characters output. */ 191721308Sacheint 191821308Sacherl_show_char (c) 191921308Sache int c; 192021308Sache{ 192121308Sache int n = 1; 192221308Sache if (META_CHAR (c) && (_rl_output_meta_chars == 0)) 192321308Sache { 192421308Sache fprintf (rl_outstream, "M-"); 192521308Sache n += 2; 192621308Sache c = UNMETA (c); 192721308Sache } 192821308Sache 192921308Sache#if defined (DISPLAY_TABS) 193021308Sache if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT) 193121308Sache#else 193221308Sache if (CTRL_CHAR (c) || c == RUBOUT) 193321308Sache#endif /* !DISPLAY_TABS */ 193421308Sache { 193521308Sache fprintf (rl_outstream, "C-"); 193621308Sache n += 2; 193721308Sache c = CTRL_CHAR (c) ? UNCTRL (c) : '?'; 193821308Sache } 193921308Sache 194021308Sache putc (c, rl_outstream); 194121308Sache fflush (rl_outstream); 194221308Sache return n; 194321308Sache} 194421308Sache 194521308Sacheint 194621308Sacherl_character_len (c, pos) 194721308Sache register int c, pos; 194821308Sache{ 194921308Sache unsigned char uc; 195021308Sache 195121308Sache uc = (unsigned char)c; 195221308Sache 195321308Sache if (META_CHAR (uc)) 195421308Sache return ((_rl_output_meta_chars == 0) ? 4 : 1); 195521308Sache 195621308Sache if (uc == '\t') 195721308Sache { 195821308Sache#if defined (DISPLAY_TABS) 195921308Sache return (((pos | 7) + 1) - pos); 196021308Sache#else 196121308Sache return (2); 196221308Sache#endif /* !DISPLAY_TABS */ 196321308Sache } 196421308Sache 196521308Sache if (CTRL_CHAR (c) || c == RUBOUT) 196621308Sache return (2); 196721308Sache 1968119614Sache return ((ISPRINT (uc)) ? 1 : 2); 196921308Sache} 197021308Sache/* How to print things in the "echo-area". The prompt is treated as a 197121308Sache mini-modeline. */ 1972157188Sachestatic int msg_saved_prompt = 0; 197321308Sache 197421308Sache#if defined (USE_VARARGS) 197521308Sacheint 197621308Sache#if defined (PREFER_STDARG) 197721308Sacherl_message (const char *format, ...) 197821308Sache#else 197921308Sacherl_message (va_alist) 198021308Sache va_dcl 198121308Sache#endif 198221308Sache{ 198321308Sache va_list args; 198421308Sache#if defined (PREFER_VARARGS) 198521308Sache char *format; 198621308Sache#endif 198721308Sache 198821308Sache#if defined (PREFER_STDARG) 198921308Sache va_start (args, format); 199021308Sache#else 199121308Sache va_start (args); 199221308Sache format = va_arg (args, char *); 199321308Sache#endif 199421308Sache 1995119614Sache#if defined (HAVE_VSNPRINTF) 1996119614Sache vsnprintf (msg_buf, sizeof (msg_buf) - 1, format, args); 1997119614Sache#else 199821308Sache vsprintf (msg_buf, format, args); 1999119614Sache msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */ 2000119614Sache#endif 200121308Sache va_end (args); 200221308Sache 2003157188Sache if (saved_local_prompt == 0) 2004157188Sache { 2005157188Sache rl_save_prompt (); 2006157188Sache msg_saved_prompt = 1; 2007157188Sache } 200821308Sache rl_display_prompt = msg_buf; 2009157188Sache local_prompt = expand_prompt (msg_buf, &prompt_visible_length, 2010157188Sache &prompt_last_invisible, 2011157188Sache &prompt_invis_chars_first_line, 2012157188Sache &prompt_physical_chars); 2013157188Sache local_prompt_prefix = (char *)NULL; 2014165675Sache local_prompt_len = local_prompt ? strlen (local_prompt) : 0; 201521308Sache (*rl_redisplay_function) (); 2016157188Sache 201721308Sache return 0; 201821308Sache} 201921308Sache#else /* !USE_VARARGS */ 202021308Sacheint 202121308Sacherl_message (format, arg1, arg2) 202221308Sache char *format; 202321308Sache{ 202421308Sache sprintf (msg_buf, format, arg1, arg2); 2025119614Sache msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */ 2026157188Sache 202721308Sache rl_display_prompt = msg_buf; 2028157188Sache if (saved_local_prompt == 0) 2029157188Sache { 2030157188Sache rl_save_prompt (); 2031157188Sache msg_saved_prompt = 1; 2032157188Sache } 2033157188Sache local_prompt = expand_prompt (msg_buf, &prompt_visible_length, 2034157188Sache &prompt_last_invisible, 2035157188Sache &prompt_invis_chars_first_line, 2036157188Sache &prompt_physical_chars); 2037157188Sache local_prompt_prefix = (char *)NULL; 2038165675Sache local_prompt_len = local_prompt ? strlen (local_prompt) : 0; 203921308Sache (*rl_redisplay_function) (); 2040157188Sache 204121308Sache return 0; 204221308Sache} 204321308Sache#endif /* !USE_VARARGS */ 204421308Sache 204521308Sache/* How to clear things from the "echo-area". */ 204621308Sacheint 204721308Sacherl_clear_message () 204821308Sache{ 204921308Sache rl_display_prompt = rl_prompt; 2050157188Sache if (msg_saved_prompt) 2051157188Sache { 2052157188Sache rl_restore_prompt (); 2053157188Sache msg_saved_prompt = 0; 2054157188Sache } 205521308Sache (*rl_redisplay_function) (); 205621308Sache return 0; 205721308Sache} 205821308Sache 205921308Sacheint 206021308Sacherl_reset_line_state () 206121308Sache{ 206221308Sache rl_on_new_line (); 206321308Sache 206421308Sache rl_display_prompt = rl_prompt ? rl_prompt : ""; 206521308Sache forced_display = 1; 206621308Sache return 0; 206721308Sache} 206821308Sache 206921308Sachevoid 207047563Sacherl_save_prompt () 207121308Sache{ 207221308Sache saved_local_prompt = local_prompt; 207321308Sache saved_local_prefix = local_prompt_prefix; 2074157188Sache saved_prefix_length = prompt_prefix_length; 2075165675Sache saved_local_length = local_prompt_len; 207675409Sache saved_last_invisible = prompt_last_invisible; 207775409Sache saved_visible_length = prompt_visible_length; 2078136759Speter saved_invis_chars_first_line = prompt_invis_chars_first_line; 2079136759Speter saved_physical_chars = prompt_physical_chars; 208021308Sache 208121308Sache local_prompt = local_prompt_prefix = (char *)0; 2082165675Sache local_prompt_len = 0; 2083157188Sache prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0; 2084136759Speter prompt_invis_chars_first_line = prompt_physical_chars = 0; 208521308Sache} 208621308Sache 208721308Sachevoid 208847563Sacherl_restore_prompt () 208921308Sache{ 209075409Sache FREE (local_prompt); 209175409Sache FREE (local_prompt_prefix); 209221308Sache 209321308Sache local_prompt = saved_local_prompt; 209421308Sache local_prompt_prefix = saved_local_prefix; 2095165675Sache local_prompt_len = saved_local_length; 2096157188Sache prompt_prefix_length = saved_prefix_length; 209775409Sache prompt_last_invisible = saved_last_invisible; 209875409Sache prompt_visible_length = saved_visible_length; 2099136759Speter prompt_invis_chars_first_line = saved_invis_chars_first_line; 2100136759Speter prompt_physical_chars = saved_physical_chars; 2101157188Sache 2102157188Sache /* can test saved_local_prompt to see if prompt info has been saved. */ 2103157188Sache saved_local_prompt = saved_local_prefix = (char *)0; 2104165675Sache saved_local_length = 0; 2105157188Sache saved_last_invisible = saved_visible_length = saved_prefix_length = 0; 2106157188Sache saved_invis_chars_first_line = saved_physical_chars = 0; 210721308Sache} 210821308Sache 210921308Sachechar * 211021308Sache_rl_make_prompt_for_search (pchar) 211121308Sache int pchar; 211221308Sache{ 211321308Sache int len; 2114157195Sache char *pmt, *p; 211521308Sache 211647563Sache rl_save_prompt (); 211721308Sache 2118157195Sache /* We've saved the prompt, and can do anything with the various prompt 2119157195Sache strings we need before they're restored. We want the unexpanded 2120157195Sache portion of the prompt string after any final newline. */ 2121157195Sache p = rl_prompt ? strrchr (rl_prompt, '\n') : 0; 2122157195Sache if (p == 0) 212321308Sache { 212421308Sache len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0; 2125119614Sache pmt = (char *)xmalloc (len + 2); 212621308Sache if (len) 212747563Sache strcpy (pmt, rl_prompt); 212821308Sache pmt[len] = pchar; 212921308Sache pmt[len+1] = '\0'; 213021308Sache } 213121308Sache else 213221308Sache { 2133157195Sache p++; 2134157195Sache len = strlen (p); 2135119614Sache pmt = (char *)xmalloc (len + 2); 213621308Sache if (len) 2137157195Sache strcpy (pmt, p); 213821308Sache pmt[len] = pchar; 213921308Sache pmt[len+1] = '\0'; 2140157195Sache } 2141136759Speter 2142157195Sache /* will be overwritten by expand_prompt, called from rl_message */ 2143157188Sache prompt_physical_chars = saved_physical_chars + 1; 214421308Sache return pmt; 214521308Sache} 214621308Sache 214721308Sache/* Quick redisplay hack when erasing characters at the end of the line. */ 214821308Sachevoid 214921308Sache_rl_erase_at_end_of_line (l) 215021308Sache int l; 215121308Sache{ 215221308Sache register int i; 215321308Sache 215421308Sache _rl_backspace (l); 215521308Sache for (i = 0; i < l; i++) 215621308Sache putc (' ', rl_outstream); 215721308Sache _rl_backspace (l); 215821308Sache for (i = 0; i < l; i++) 215921308Sache visible_line[--_rl_last_c_pos] = '\0'; 216021308Sache rl_display_fixed++; 216121308Sache} 216221308Sache 216321308Sache/* Clear to the end of the line. COUNT is the minimum 216421308Sache number of character spaces to clear, */ 216526497Sachevoid 216626497Sache_rl_clear_to_eol (count) 216721308Sache int count; 216821308Sache{ 216975409Sache if (_rl_term_clreol) 217075409Sache tputs (_rl_term_clreol, 1, _rl_output_character_function); 217126497Sache else if (count) 217221308Sache space_to_eol (count); 217321308Sache} 217421308Sache 217521308Sache/* Clear to the end of the line using spaces. COUNT is the minimum 217621308Sache number of character spaces to clear, */ 217721308Sachestatic void 217821308Sachespace_to_eol (count) 217921308Sache int count; 218021308Sache{ 218121308Sache register int i; 218221308Sache 218321308Sache for (i = 0; i < count; i++) 218421308Sache putc (' ', rl_outstream); 218521308Sache 218621308Sache _rl_last_c_pos += count; 218721308Sache} 218821308Sache 218926497Sachevoid 219026497Sache_rl_clear_screen () 219126497Sache{ 219275409Sache if (_rl_term_clrpag) 219375409Sache tputs (_rl_term_clrpag, 1, _rl_output_character_function); 219426497Sache else 219575409Sache rl_crlf (); 219626497Sache} 219726497Sache 2198119614Sache/* Insert COUNT characters from STRING to the output stream at column COL. */ 219921308Sachestatic void 2200119614Sacheinsert_some_chars (string, count, col) 220121308Sache char *string; 2202119614Sache int count, col; 220321308Sache{ 2204157188Sache#if defined (__MSDOS__) || defined (__MINGW32__) 2205157188Sache _rl_output_some_chars (string, count); 2206157188Sache#else 2207119614Sache /* DEBUGGING */ 2208119614Sache if (MB_CUR_MAX == 1 || rl_byte_oriented) 2209119614Sache if (count != col) 2210119614Sache fprintf(stderr, "readline: debug: insert_some_chars: count (%d) != col (%d)\n", count, col); 2211119614Sache 221221308Sache /* If IC is defined, then we do not have to "enter" insert mode. */ 221375409Sache if (_rl_term_IC) 221421308Sache { 221521308Sache char *buffer; 2216119614Sache 2217119614Sache buffer = tgoto (_rl_term_IC, 0, col); 221821308Sache tputs (buffer, 1, _rl_output_character_function); 221921308Sache _rl_output_some_chars (string, count); 222021308Sache } 222121308Sache else 222221308Sache { 222321308Sache register int i; 222421308Sache 222521308Sache /* If we have to turn on insert-mode, then do so. */ 222675409Sache if (_rl_term_im && *_rl_term_im) 222775409Sache tputs (_rl_term_im, 1, _rl_output_character_function); 222821308Sache 222921308Sache /* If there is a special command for inserting characters, then 223021308Sache use that first to open up the space. */ 223175409Sache if (_rl_term_ic && *_rl_term_ic) 223221308Sache { 2233119614Sache for (i = col; i--; ) 223475409Sache tputs (_rl_term_ic, 1, _rl_output_character_function); 223521308Sache } 223621308Sache 223721308Sache /* Print the text. */ 223821308Sache _rl_output_some_chars (string, count); 223921308Sache 224021308Sache /* If there is a string to turn off insert mode, we had best use 224121308Sache it now. */ 224275409Sache if (_rl_term_ei && *_rl_term_ei) 224375409Sache tputs (_rl_term_ei, 1, _rl_output_character_function); 224421308Sache } 2245157188Sache#endif /* __MSDOS__ || __MINGW32__ */ 224621308Sache} 224721308Sache 224821308Sache/* Delete COUNT characters from the display line. */ 224921308Sachestatic void 225021308Sachedelete_chars (count) 225121308Sache int count; 225221308Sache{ 225375409Sache if (count > _rl_screenwidth) /* XXX */ 225421308Sache return; 225521308Sache 2256157188Sache#if !defined (__MSDOS__) && !defined (__MINGW32__) 225775409Sache if (_rl_term_DC && *_rl_term_DC) 225821308Sache { 225921308Sache char *buffer; 226075409Sache buffer = tgoto (_rl_term_DC, count, count); 226121308Sache tputs (buffer, count, _rl_output_character_function); 226221308Sache } 226321308Sache else 226421308Sache { 226575409Sache if (_rl_term_dc && *_rl_term_dc) 226621308Sache while (count--) 226775409Sache tputs (_rl_term_dc, 1, _rl_output_character_function); 226821308Sache } 2269157188Sache#endif /* !__MSDOS__ && !__MINGW32__ */ 227021308Sache} 227121308Sache 227221308Sachevoid 227321308Sache_rl_update_final () 227421308Sache{ 227521308Sache int full_lines; 227621308Sache 227721308Sache full_lines = 0; 227821308Sache /* If the cursor is the only thing on an otherwise-blank last line, 227921308Sache compensate so we don't print an extra CRLF. */ 228021308Sache if (_rl_vis_botlin && _rl_last_c_pos == 0 && 228126497Sache visible_line[vis_lbreaks[_rl_vis_botlin]] == 0) 228221308Sache { 228321308Sache _rl_vis_botlin--; 228421308Sache full_lines = 1; 228521308Sache } 228621308Sache _rl_move_vert (_rl_vis_botlin); 228721308Sache /* If we've wrapped lines, remove the final xterm line-wrap flag. */ 228875409Sache if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth)) 228921308Sache { 229021308Sache char *last_line; 2291119614Sache 229258314Sache last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]]; 2293165675Sache cpos_buffer_position = -1; /* don't know where we are in buffer */ 2294165675Sache _rl_move_cursor_relative (_rl_screenwidth - 1, last_line); /* XXX */ 229526497Sache _rl_clear_to_eol (0); 229675409Sache putc (last_line[_rl_screenwidth - 1], rl_outstream); 229721308Sache } 229821308Sache _rl_vis_botlin = 0; 229975409Sache rl_crlf (); 230021308Sache fflush (rl_outstream); 230121308Sache rl_display_fixed++; 230221308Sache} 230321308Sache 230421308Sache/* Move to the start of the current line. */ 230521308Sachestatic void 230621308Sachecr () 230721308Sache{ 230875409Sache if (_rl_term_cr) 230921308Sache { 231058314Sache#if defined (__MSDOS__) 231158314Sache putc ('\r', rl_outstream); 231258314Sache#else 231375409Sache tputs (_rl_term_cr, 1, _rl_output_character_function); 231458314Sache#endif 231521308Sache _rl_last_c_pos = 0; 231621308Sache } 231721308Sache} 231821308Sache 231958314Sache/* Redraw the last line of a multi-line prompt that may possibly contain 232058314Sache terminal escape sequences. Called with the cursor at column 0 of the 232158314Sache line to draw the prompt on. */ 232258314Sachestatic void 232358314Sacheredraw_prompt (t) 232458314Sache char *t; 232558314Sache{ 2326157188Sache char *oldp; 232758314Sache 232858314Sache oldp = rl_display_prompt; 2329157188Sache rl_save_prompt (); 233058314Sache 233158314Sache rl_display_prompt = t; 233275409Sache local_prompt = expand_prompt (t, &prompt_visible_length, 233375409Sache &prompt_last_invisible, 2334136759Speter &prompt_invis_chars_first_line, 2335136759Speter &prompt_physical_chars); 233658314Sache local_prompt_prefix = (char *)NULL; 2337165675Sache local_prompt_len = local_prompt ? strlen (local_prompt) : 0; 2338157188Sache 233958314Sache rl_forced_update_display (); 234058314Sache 234158314Sache rl_display_prompt = oldp; 2342157188Sache rl_restore_prompt(); 234358314Sache} 234458314Sache 234521308Sache/* Redisplay the current line after a SIGWINCH is received. */ 234621308Sachevoid 234721308Sache_rl_redisplay_after_sigwinch () 234821308Sache{ 234958314Sache char *t; 235021308Sache 235121308Sache /* Clear the current line and put the cursor at column 0. Make sure 235221308Sache the right thing happens if we have wrapped to a new screen line. */ 235375409Sache if (_rl_term_cr) 235421308Sache { 235558314Sache#if defined (__MSDOS__) 235658314Sache putc ('\r', rl_outstream); 235758314Sache#else 235875409Sache tputs (_rl_term_cr, 1, _rl_output_character_function); 235958314Sache#endif 236021308Sache _rl_last_c_pos = 0; 236158314Sache#if defined (__MSDOS__) 236275409Sache space_to_eol (_rl_screenwidth); 236358314Sache putc ('\r', rl_outstream); 236458314Sache#else 236575409Sache if (_rl_term_clreol) 236675409Sache tputs (_rl_term_clreol, 1, _rl_output_character_function); 236721308Sache else 236821308Sache { 236975409Sache space_to_eol (_rl_screenwidth); 237075409Sache tputs (_rl_term_cr, 1, _rl_output_character_function); 237121308Sache } 237258314Sache#endif 237321308Sache if (_rl_last_v_pos > 0) 237421308Sache _rl_move_vert (0); 237521308Sache } 237621308Sache else 237775409Sache rl_crlf (); 237821308Sache 237921308Sache /* Redraw only the last line of a multi-line prompt. */ 238021308Sache t = strrchr (rl_display_prompt, '\n'); 238121308Sache if (t) 238258314Sache redraw_prompt (++t); 238321308Sache else 238421308Sache rl_forced_update_display (); 238521308Sache} 238621308Sache 238721308Sachevoid 238821308Sache_rl_clean_up_for_exit () 238921308Sache{ 239021308Sache if (readline_echoing_p) 239121308Sache { 239221308Sache _rl_move_vert (_rl_vis_botlin); 239321308Sache _rl_vis_botlin = 0; 239421308Sache fflush (rl_outstream); 239547563Sache rl_restart_output (1, 0); 239621308Sache } 239721308Sache} 239847563Sache 239947563Sachevoid 240047563Sache_rl_erase_entire_line () 240147563Sache{ 240247563Sache cr (); 240347563Sache _rl_clear_to_eol (0); 240447563Sache cr (); 240547563Sache fflush (rl_outstream); 240647563Sache} 240758314Sache 240858314Sache/* return the `current display line' of the cursor -- the number of lines to 240958314Sache move up to get to the first screen line of the current readline line. */ 241058314Sacheint 241158314Sache_rl_current_display_line () 241258314Sache{ 241358314Sache int ret, nleft; 241458314Sache 241558314Sache /* Find out whether or not there might be invisible characters in the 241658314Sache editing buffer. */ 241758314Sache if (rl_display_prompt == rl_prompt) 241875409Sache nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length; 241958314Sache else 242075409Sache nleft = _rl_last_c_pos - _rl_screenwidth; 242158314Sache 242258314Sache if (nleft > 0) 242375409Sache ret = 1 + nleft / _rl_screenwidth; 242458314Sache else 242558314Sache ret = 0; 242658314Sache 242758314Sache return ret; 242858314Sache} 2429119614Sache 2430119614Sache#if defined (HANDLE_MULTIBYTE) 2431119614Sache/* Calculate the number of screen columns occupied by STR from START to END. 2432119614Sache In the case of multibyte characters with stateful encoding, we have to 2433119614Sache scan from the beginning of the string to take the state into account. */ 2434119614Sachestatic int 2435119614Sache_rl_col_width (str, start, end) 2436136759Speter const char *str; 2437119614Sache int start, end; 2438119614Sache{ 2439119614Sache wchar_t wc; 2440165675Sache mbstate_t ps; 2441119614Sache int tmp, point, width, max; 2442119614Sache 2443119614Sache if (end <= start) 2444119614Sache return 0; 2445165680Sache if (MB_CUR_MAX == 1 || rl_byte_oriented) 2446165680Sache return (end - start); 2447119614Sache 2448165675Sache memset (&ps, 0, sizeof (mbstate_t)); 2449165675Sache 2450119614Sache point = 0; 2451119614Sache max = end; 2452119614Sache 2453119614Sache while (point < start) 2454119614Sache { 2455119614Sache tmp = mbrlen (str + point, max, &ps); 2456136759Speter if (MB_INVALIDCH ((size_t)tmp)) 2457119614Sache { 2458119614Sache /* In this case, the bytes are invalid or too short to compose a 2459119614Sache multibyte character, so we assume that the first byte represents 2460119614Sache a single character. */ 2461119614Sache point++; 2462119614Sache max--; 2463119614Sache 2464119614Sache /* Clear the state of the byte sequence, because in this case the 2465119614Sache effect of mbstate is undefined. */ 2466119614Sache memset (&ps, 0, sizeof (mbstate_t)); 2467119614Sache } 2468136759Speter else if (MB_NULLWCH (tmp)) 2469136759Speter break; /* Found '\0' */ 2470119614Sache else 2471119614Sache { 2472119614Sache point += tmp; 2473119614Sache max -= tmp; 2474119614Sache } 2475119614Sache } 2476119614Sache 2477119614Sache /* If START is not a byte that starts a character, then POINT will be 2478119614Sache greater than START. In this case, assume that (POINT - START) gives 2479119614Sache a byte count that is the number of columns of difference. */ 2480119614Sache width = point - start; 2481119614Sache 2482119614Sache while (point < end) 2483119614Sache { 2484119614Sache tmp = mbrtowc (&wc, str + point, max, &ps); 2485136759Speter if (MB_INVALIDCH ((size_t)tmp)) 2486119614Sache { 2487119614Sache /* In this case, the bytes are invalid or too short to compose a 2488119614Sache multibyte character, so we assume that the first byte represents 2489119614Sache a single character. */ 2490119614Sache point++; 2491119614Sache max--; 2492119614Sache 2493119614Sache /* and assume that the byte occupies a single column. */ 2494119614Sache width++; 2495119614Sache 2496119614Sache /* Clear the state of the byte sequence, because in this case the 2497119614Sache effect of mbstate is undefined. */ 2498119614Sache memset (&ps, 0, sizeof (mbstate_t)); 2499119614Sache } 2500136759Speter else if (MB_NULLWCH (tmp)) 2501136759Speter break; /* Found '\0' */ 2502119614Sache else 2503119614Sache { 2504119614Sache point += tmp; 2505119614Sache max -= tmp; 2506119614Sache tmp = wcwidth(wc); 2507119614Sache width += (tmp >= 0) ? tmp : 1; 2508119614Sache } 2509119614Sache } 2510119614Sache 2511119614Sache width += point - end; 2512119614Sache 2513119614Sache return width; 2514119614Sache} 2515119614Sache#endif /* HANDLE_MULTIBYTE */ 2516