display.c revision 136759
150276Speter/* $FreeBSD: head/contrib/libreadline/display.c 136759 2004-10-21 20:10:14Z peter $ */ 2184989Srafan 350276Speter/* display.c -- readline redisplay facility. */ 450276Speter 550276Speter/* Copyright (C) 1987-2004 Free Software Foundation, Inc. 650276Speter 750276Speter This file is part of the GNU Readline Library, a library for 850276Speter reading lines of text with interactive input and history editing. 950276Speter 1050276Speter The GNU Readline Library is free software; you can redistribute it 1150276Speter and/or modify it under the terms of the GNU General Public License 1250276Speter as published by the Free Software Foundation; either version 2, or 1350276Speter (at your option) any later version. 1450276Speter 1550276Speter The GNU Readline Library is distributed in the hope that it will be 1650276Speter useful, but WITHOUT ANY WARRANTY; without even the implied warranty 1750276Speter of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1850276Speter GNU General Public License for more details. 1950276Speter 2050276Speter The GNU General Public License is often shipped with GNU software, and 2150276Speter is generally kept in a file called COPYING or LICENSE. If you do not 2250276Speter have a copy of the license, write to the Free Software Foundation, 2350276Speter 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ 2450276Speter#define READLINE_LIBRARY 2550276Speter 2650276Speter#if defined (HAVE_CONFIG_H) 2750276Speter# include <config.h> 2850276Speter#endif 2950276Speter 3050276Speter#include <sys/types.h> 3150276Speter 32166124Srafan#if defined (HAVE_UNISTD_H) 3350276Speter# include <unistd.h> 3450276Speter#endif /* HAVE_UNISTD_H */ 3550276Speter 3650276Speter#include "posixstat.h" 3750276Speter 3850276Speter#if defined (HAVE_STDLIB_H) 3950276Speter# include <stdlib.h> 4050276Speter#else 4150276Speter# include "ansi_stdlib.h" 4250276Speter#endif /* HAVE_STDLIB_H */ 43166124Srafan 4450276Speter#include <stdio.h> 4550276Speter 4650276Speter/* System-specific feature definitions and include files. */ 4750276Speter#include "rldefs.h" 4850276Speter#include "rlmbutil.h" 4950276Speter 5050276Speter/* Termcap library stuff. */ 5150276Speter#include "tcap.h" 5250276Speter 5350276Speter/* Some standard library routines. */ 5450276Speter#include "readline.h" 5550276Speter#include "history.h" 5650276Speter 5750276Speter#include "rlprivate.h" 5850276Speter#include "xmalloc.h" 5950276Speter 6050276Speter#if !defined (strchr) && !defined (__STDC__) 6150276Speterextern char *strchr (), *strrchr (); 6250276Speter#endif /* !strchr && !__STDC__ */ 6350276Speter 6450276Speter#if defined (HACK_TERMCAP_MOTION) 6550276Speterextern char *_rl_term_forward_char; 6650276Speter#endif 6750276Speter 6850276Speterstatic void update_line PARAMS((char *, char *, int, int, int, int)); 6950276Speterstatic void space_to_eol PARAMS((int)); 7050276Speterstatic void delete_chars PARAMS((int)); 7150276Speterstatic void insert_some_chars PARAMS((char *, int, int)); 7250276Speterstatic void cr PARAMS((void)); 7350276Speter 7450276Speter#if defined (HANDLE_MULTIBYTE) 7550276Speterstatic int _rl_col_width PARAMS((const char *, int, int)); 7650276Speterstatic int *_rl_wrapped_line; 7750276Speter#else 7850276Speter# define _rl_col_width(l, s, e) (((e) <= (s)) ? 0 : (e) - (s)) 7950276Speter#endif 8050276Speter 8150276Speterstatic int *inv_lbreaks, *vis_lbreaks; 8250276Speterstatic int inv_lbsize, vis_lbsize; 8350276Speter 8450276Speter/* Heuristic used to decide whether it is faster to move from CUR to NEW 8550276Speter by backing up or outputting a carriage return and moving forward. */ 8650276Speter#define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new))) 8750276Speter 8850276Speter/* **************************************************************** */ 8950276Speter/* */ 9050276Speter/* Display stuff */ 9150276Speter/* */ 9250276Speter/* **************************************************************** */ 9350276Speter 9450276Speter/* This is the stuff that is hard for me. I never seem to write good 9550276Speter display routines in C. Let's see how I do this time. */ 96184989Srafan 9750276Speter/* (PWP) Well... Good for a simple line updater, but totally ignores 9850276Speter the problems of input lines longer than the screen width. 9950276Speter 10050276Speter update_line and the code that calls it makes a multiple line, 10150276Speter automatically wrapping line update. Careful attention needs 10250276Speter to be paid to the vertical position variables. */ 10350276Speter 10450276Speter/* Keep two buffers; one which reflects the current contents of the 10550276Speter screen, and the other to draw what we think the new contents should 10650276Speter be. Then compare the buffers, and make whatever changes to the 10750276Speter screen itself that we should. Finally, make the buffer that we 10850276Speter just drew into be the one which reflects the current contents of the 10962449Speter screen, and place the cursor where it belongs. 11050276Speter 11150276Speter Commands that want to can fix the display themselves, and then let 11262449Speter this function know that the display has been fixed by setting the 11362449Speter RL_DISPLAY_FIXED variable. This is good for efficiency. */ 11450276Speter 11550276Speter/* Application-specific redisplay function. */ 11662449Speterrl_voidfunc_t *rl_redisplay_function = rl_redisplay; 11762449Speter 11862449Speter/* Global variables declared here. */ 119166124Srafan/* What YOU turn on when you have handled all redisplay yourself. */ 12050276Speterint rl_display_fixed = 0; 12162449Speter 12262449Speterint _rl_suppress_redisplay = 0; 12350276Speter 12450276Speter/* The stuff that gets printed out before the actual text of the line. 12562449Speter This is usually pointing to rl_prompt. */ 12662449Speterchar *rl_display_prompt = (char *)NULL; 12750276Speter 12862449Speter/* Pseudo-global variables declared here. */ 12962449Speter/* The visible cursor position. If you print some text, adjust this. */ 13062449Speterint _rl_last_c_pos = 0; 13162449Speterint _rl_last_v_pos = 0; 13262449Speter 133166124Srafan/* Number of lines currently on screen minus 1. */ 13462449Speterint _rl_vis_botlin = 0; 13562449Speter 13662449Speter/* Variables used only in this file. */ 13762449Speter/* The last left edge of text that was displayed. This is used when 13850276Speter doing horizontal scrolling. It shifts in thirds of a screenwidth. */ 13950276Speterstatic int last_lmargin; 140166124Srafan 141166124Srafan/* The line display buffers. One is the line currently displayed on 14250276Speter the screen. The other is the line about to be displayed. */ 14362449Speterstatic char *visible_line = (char *)NULL; 144166124Srafanstatic char *invisible_line = (char *)NULL; 14562449Speter 14650276Speter/* A buffer for `modeline' messages. */ 14750276Speterstatic char msg_buf[128]; 14862449Speter 14962449Speter/* Non-zero forces the redisplay even if we thought it was unnecessary. */ 15050276Speterstatic int forced_display; 15150276Speter 152184989Srafan/* Default and initial buffer size. Can grow. */ 15350276Speterstatic int line_size = 1024; 15450276Speter 15550276Speter/* Variables to keep track of the expanded prompt string, which may 15650276Speter include invisible characters. */ 15750276Speter 15862449Speterstatic char *local_prompt, *local_prompt_prefix; 15962449Speterstatic int prompt_visible_length, prompt_prefix_length; 16050276Speter 16150276Speter/* The number of invisible characters in the line currently being 16250276Speter displayed on the screen. */ 16350276Speterstatic int visible_wrap_offset; 16450276Speter 16550276Speter/* The number of invisible characters in the prompt string. Static so it 16650276Speter can be shared between rl_redisplay and update_line */ 16762449Speterstatic int wrap_offset; 16850276Speter 16950276Speter/* The index of the last invisible character in the prompt string. */ 17050276Speterstatic int prompt_last_invisible; 17150276Speter 17262449Speter/* The length (buffer offset) of the first line of the last (possibly 17362449Speter multi-line) buffer displayed on the screen. */ 17450276Speterstatic int visible_first_line_len; 17550276Speter 17650276Speter/* Number of invisible characters on the first physical line of the prompt. 17750276Speter Only valid when the number of physical characters in the prompt exceeds 17850276Speter (or is equal to) _rl_screenwidth. */ 17962449Speterstatic int prompt_invis_chars_first_line; 18050276Speter 18162449Speterstatic int prompt_last_screen_line; 18250276Speter 18350276Speterstatic int prompt_physical_chars; 18450276Speter 18550276Speter/* Expand the prompt string S and return the number of visible 186184989Srafan characters in *LP, if LP is not null. This is currently more-or-less 18750276Speter a placeholder for expansion. LIP, if non-null is a place to store the 18850276Speter index of the last invisible character in the returned string. NIFLP, 18950276Speter if non-zero, is a place to store the number of invisible characters in 19050276Speter the first prompt line. The previous are used as byte counts -- indexes 19150276Speter into a character buffer. */ 19250276Speter 19350276Speter/* Current implementation: 19450276Speter \001 (^A) start non-visible characters 19550276Speter \002 (^B) end non-visible characters 19650276Speter all characters except \001 and \002 (following a \001) are copied to 19750276Speter the returned string; all characters except those between \001 and 19897049Speter \002 are assumed to be `visible'. */ 19950276Speter 20050276Speterstatic char * 20150276Speterexpand_prompt (pmt, lp, lip, niflp, vlp) 20250276Speter char *pmt; 20350276Speter int *lp, *lip, *niflp, *vlp; 204184989Srafan{ 20550276Speter char *r, *ret, *p; 20650276Speter int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars; 20750276Speter 20850276Speter /* Short-circuit if we can. */ 20950276Speter if ((MB_CUR_MAX <= 1 || rl_byte_oriented) && strchr (pmt, RL_PROMPT_START_IGNORE) == 0) 21050276Speter { 21150276Speter r = savestring (pmt); 21250276Speter if (lp) 21350276Speter *lp = strlen (r); 214184989Srafan if (lip) 21550276Speter *lip = 0; 21650276Speter if (niflp) 21750276Speter *niflp = 0; 21862449Speter if (vlp) 21962449Speter *vlp = lp ? *lp : strlen (r); 22062449Speter return r; 22150276Speter } 22262449Speter 22350276Speter l = strlen (pmt); 22462449Speter r = ret = (char *)xmalloc (l + 1); 22550276Speter 22662449Speter invfl = 0; /* invisible chars in first line of prompt */ 22762449Speter invflset = 0; /* we only want to set invfl once */ 22862449Speter 22950276Speter for (rl = ignoring = last = ninvis = physchars = 0, p = pmt; p && *p; p++) 23050276Speter { 23150276Speter /* This code strips the invisible character string markers 23250276Speter RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */ 23362449Speter if (*p == RL_PROMPT_START_IGNORE) 23462449Speter { 23550276Speter ignoring++; 23650276Speter continue; 23762449Speter } 23862449Speter else if (ignoring && *p == RL_PROMPT_END_IGNORE) 23962449Speter { 24062449Speter ignoring = 0; 24162449Speter last = r - ret - 1; 24262449Speter continue; 24362449Speter } 24462449Speter else 24562449Speter { 24662449Speter#if defined (HANDLE_MULTIBYTE) 24762449Speter if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 24862449Speter { 24962449Speter pind = p - pmt; 25050276Speter ind = _rl_find_next_mbchar (pmt, pind, 1, MB_FIND_NONZERO); 25162449Speter l = ind - pind; 25262449Speter while (l--) 25362449Speter *r++ = *p++; 25462449Speter if (!ignoring) 25550276Speter { 25662449Speter rl += ind - pind; 25750276Speter physchars += _rl_col_width (pmt, pind, ind); 25862449Speter } 25962449Speter else 26062449Speter ninvis += ind - pind; 26162449Speter p--; /* compensate for later increment */ 26250276Speter } 26362449Speter else 26462449Speter#endif 26562449Speter { 26650276Speter *r++ = *p; 26762449Speter if (!ignoring) 26862449Speter { 26962449Speter rl++; /* visible length byte counter */ 27050276Speter physchars++; 27150276Speter } 27276726Speter else 27376726Speter ninvis++; /* invisible chars byte counter */ 27476726Speter } 27576726Speter 276166124Srafan if (invflset == 0 && rl >= _rl_screenwidth) 27776726Speter { 27876726Speter invfl = ninvis; 27976726Speter invflset = 1; 280166124Srafan } 281166124Srafan } 28250276Speter } 28350276Speter 28450276Speter if (rl < _rl_screenwidth) 28550276Speter invfl = ninvis; 28650276Speter 28750276Speter *r = '\0'; 28850276Speter if (lp) 28950276Speter *lp = rl; 29050276Speter if (lip) 29150276Speter *lip = last; 29262449Speter if (niflp) 29350276Speter *niflp = invfl; 29450276Speter if (vlp) 29550276Speter *vlp = physchars; 29650276Speter return ret; 29750276Speter} 298166124Srafan 29962449Speter/* Just strip out RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE from 30097049Speter PMT and return the rest of PMT. */ 30150276Speterchar * 30250276Speter_rl_strip_prompt (pmt) 30362449Speter char *pmt; 30462449Speter{ 30550276Speter char *ret; 30650276Speter 307166124Srafan ret = expand_prompt (pmt, (int *)NULL, (int *)NULL, (int *)NULL, (int *)NULL); 30862449Speter return ret; 30950276Speter} 31050276Speter 31162449Speter/* 31262449Speter * Expand the prompt string into the various display components, if 31362449Speter * necessary. 31462449Speter * 31550276Speter * local_prompt = expanded last line of string in rl_display_prompt 31650276Speter * (portion after the final newline) 31750276Speter * local_prompt_prefix = portion before last newline of rl_display_prompt, 31850276Speter * expanded via expand_prompt 31950276Speter * prompt_visible_length = number of visible characters in local_prompt 32050276Speter * prompt_prefix_length = number of visible characters in local_prompt_prefix 32150276Speter * 32250276Speter * This function is called once per call to readline(). It may also be 32350276Speter * called arbitrarily to expand the primary prompt. 32450276Speter * 32550276Speter * The return value is the number of visible characters on the last line 32650276Speter * of the (possibly multi-line) prompt. 32750276Speter */ 32850276Speterint 32950276Speterrl_expand_prompt (prompt) 33062449Speter char *prompt; 33162449Speter{ 33262449Speter char *p, *t; 33350276Speter int c; 33450276Speter 33562449Speter /* Clear out any saved values. */ 33662449Speter FREE (local_prompt); 33762449Speter FREE (local_prompt_prefix); 33862449Speter 33950276Speter local_prompt = local_prompt_prefix = (char *)0; 34050276Speter prompt_last_invisible = prompt_visible_length = 0; 34150276Speter 34250276Speter if (prompt == 0 || *prompt == 0) 34362449Speter return (0); 34450276Speter 34550276Speter p = strrchr (prompt, '\n'); 34650276Speter if (!p) 34750276Speter { 34862449Speter /* The prompt is only one logical line, though it might wrap. */ 34950276Speter local_prompt = expand_prompt (prompt, &prompt_visible_length, 35062449Speter &prompt_last_invisible, 35150276Speter &prompt_invis_chars_first_line, 35262449Speter &prompt_physical_chars); 35350276Speter local_prompt_prefix = (char *)0; 35450276Speter return (prompt_visible_length); 35550276Speter } 35676726Speter else 35750276Speter { 35850276Speter /* The prompt spans multiple lines. */ 35950276Speter t = ++p; 36050276Speter local_prompt = expand_prompt (p, &prompt_visible_length, 36150276Speter &prompt_last_invisible, 36250276Speter (int *)NULL, 36350276Speter &prompt_physical_chars); 36450276Speter c = *t; *t = '\0'; 36550276Speter /* The portion of the prompt string up to and including the 36650276Speter final newline is now null-terminated. */ 36750276Speter local_prompt_prefix = expand_prompt (prompt, &prompt_prefix_length, 36850276Speter (int *)NULL, 36950276Speter &prompt_invis_chars_first_line, 37050276Speter (int *)NULL); 37150276Speter *t = c; 37262449Speter return (prompt_prefix_length); 37350276Speter } 37462449Speter} 37550276Speter 37650276Speter/* Initialize the VISIBLE_LINE and INVISIBLE_LINE arrays, and their associated 37762449Speter arrays of line break markers. MINSIZE is the minimum size of VISIBLE_LINE 37850276Speter and INVISIBLE_LINE; if it is greater than LINE_SIZE, LINE_SIZE is 37950276Speter increased. If the lines have already been allocated, this ensures that 38062449Speter they can hold at least MINSIZE characters. */ 38150276Speterstatic void 38250276Speterinit_line_structures (minsize) 38362449Speter int minsize; 38450276Speter{ 38550276Speter register int n; 38650276Speter 38750276Speter if (invisible_line == 0) /* initialize it */ 38850276Speter { 38950276Speter if (line_size < minsize) 39050276Speter line_size = minsize; 39150276Speter visible_line = (char *)xmalloc (line_size); 39250276Speter invisible_line = (char *)xmalloc (line_size); 39362449Speter } 39450276Speter else if (line_size < minsize) /* ensure it can hold MINSIZE chars */ 39550276Speter { 39650276Speter line_size *= 2; 39750276Speter if (line_size < minsize) 39850276Speter line_size = minsize; 39950276Speter visible_line = (char *)xrealloc (visible_line, line_size); 40050276Speter invisible_line = (char *)xrealloc (invisible_line, line_size); 40150276Speter } 40262449Speter 40350276Speter for (n = minsize; n < line_size; n++) 40450276Speter { 40550276Speter visible_line[n] = 0; 40650276Speter invisible_line[n] = 1; 40762449Speter } 40850276Speter 40950276Speter if (vis_lbreaks == 0) 41050276Speter { 41150276Speter /* should be enough. */ 41250276Speter inv_lbsize = vis_lbsize = 256; 41350276Speter inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int)); 41462449Speter vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int)); 41550276Speter#if defined (HANDLE_MULTIBYTE) 41650276Speter _rl_wrapped_line = (int *)xmalloc (vis_lbsize * sizeof (int)); 41762449Speter#endif 41850276Speter inv_lbreaks[0] = vis_lbreaks[0] = 0; 41950276Speter } 42050276Speter} 42150276Speter 42250276Speter/* Basic redisplay algorithm. */ 42350276Spetervoid 42462449Speterrl_redisplay () 42550276Speter{ 42650276Speter register int in, out, c, linenum, cursor_linenum; 42750276Speter register char *line; 42850276Speter int c_pos, inv_botlin, lb_botlin, lb_linenum; 42962449Speter int newlines, lpos, temp, modmark, n0, num; 43050276Speter char *prompt_this_line; 43150276Speter#if defined (HANDLE_MULTIBYTE) 43262449Speter wchar_t wc; 43350276Speter size_t wc_bytes; 43450276Speter int wc_width; 43550276Speter mbstate_t ps; 43650276Speter int _rl_wrapped_multicolumn = 0; 43750276Speter#endif 43850276Speter 43950276Speter if (!readline_echoing_p) 44062449Speter return; 44150276Speter 44250276Speter if (!rl_display_prompt) 44362449Speter rl_display_prompt = ""; 44462449Speter 44550276Speter if (invisible_line == 0) 44662449Speter { 44750276Speter init_line_structures (0); 44850276Speter rl_on_new_line (); 44950276Speter } 45050276Speter 45162449Speter /* Draw the line into the buffer. */ 45250276Speter c_pos = -1; 45350276Speter 45450276Speter line = invisible_line; 45550276Speter out = inv_botlin = 0; 45650276Speter 45750276Speter /* Mark the line as modified or not. We only do this for history 45850276Speter lines. */ 45950276Speter modmark = 0; 46050276Speter if (_rl_mark_modified_lines && current_history () && rl_undo_list) 46162449Speter { 46250276Speter line[out++] = '*'; 46362449Speter line[out] = '\0'; 46462449Speter modmark = 1; 46562449Speter } 46650276Speter 46762449Speter /* If someone thought that the redisplay was handled, but the currently 468166124Srafan visible line has a different modification state than the one about 46950276Speter to become visible, then correct the caller's misconception. */ 47050276Speter if (visible_line[0] != invisible_line[0]) 47150276Speter rl_display_fixed = 0; 47250276Speter 47350276Speter /* If the prompt to be displayed is the `primary' readline prompt (the 47462449Speter one passed to readline()), use the values we have already expanded. 47562449Speter If not, use what's already in rl_display_prompt. WRAP_OFFSET is the 47662449Speter number of non-visible characters in the prompt string. */ 47750276Speter if (rl_display_prompt == rl_prompt || local_prompt) 47862449Speter { 47962449Speter int local_len = local_prompt ? strlen (local_prompt) : 0; 48062449Speter if (local_prompt_prefix && forced_display) 48150276Speter _rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix)); 48262449Speter 48362449Speter if (local_len > 0) 48462449Speter { 48550276Speter temp = local_len + out + 2; 48662449Speter if (temp >= line_size) 48762449Speter { 48862449Speter line_size = (temp + 1024) - (temp % 1024); 48950276Speter visible_line = (char *)xrealloc (visible_line, line_size); 49062449Speter line = invisible_line = (char *)xrealloc (invisible_line, line_size); 49162449Speter } 49262449Speter strncpy (line + out, local_prompt, local_len); 49350276Speter out += local_len; 49462449Speter } 49562449Speter line[out] = '\0'; 49662449Speter wrap_offset = local_len - prompt_visible_length; 49750276Speter } 49862449Speter else 49962449Speter { 50062449Speter int pmtlen; 50150276Speter prompt_this_line = strrchr (rl_display_prompt, '\n'); 50262449Speter if (!prompt_this_line) 50362449Speter prompt_this_line = rl_display_prompt; 50462449Speter else 50550276Speter { 50662449Speter prompt_this_line++; 50762449Speter pmtlen = prompt_this_line - rl_display_prompt; /* temp var */ 50862449Speter if (forced_display) 50950276Speter { 51062449Speter _rl_output_some_chars (rl_display_prompt, pmtlen); 51162449Speter /* Make sure we are at column zero even after a newline, 51262449Speter regardless of the state of terminal output processing. */ 51350276Speter if (pmtlen < 2 || prompt_this_line[-2] != '\r') 51462449Speter cr (); 51562449Speter } 51662449Speter } 51750276Speter 51850276Speter prompt_physical_chars = pmtlen = strlen (prompt_this_line); 51962449Speter temp = pmtlen + out + 2; 52050276Speter if (temp >= line_size) 52150276Speter { 52262449Speter line_size = (temp + 1024) - (temp % 1024); 52362449Speter visible_line = (char *)xrealloc (visible_line, line_size); 52450276Speter line = invisible_line = (char *)xrealloc (invisible_line, line_size); 52550276Speter } 52662449Speter strncpy (line + out, prompt_this_line, pmtlen); 52762449Speter out += pmtlen; 52862449Speter line[out] = '\0'; 52962449Speter wrap_offset = prompt_invis_chars_first_line = 0; 53050276Speter } 53150276Speter 53262449Speter#define CHECK_INV_LBREAKS() \ 53350276Speter do { \ 53450276Speter if (newlines >= (inv_lbsize - 2)) \ 53550276Speter { \ 53662449Speter inv_lbsize *= 2; \ 53750276Speter inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \ 53850276Speter } \ 53950276Speter } while (0) 54050276Speter 54150276Speter#if defined (HANDLE_MULTIBYTE) 54250276Speter#define CHECK_LPOS() \ 54350276Speter do { \ 54450276Speter lpos++; \ 54550276Speter if (lpos >= _rl_screenwidth) \ 54662449Speter { \ 54762449Speter if (newlines >= (inv_lbsize - 2)) \ 54862449Speter { \ 54997049Speter inv_lbsize *= 2; \ 55062449Speter inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \ 55150276Speter _rl_wrapped_line = (int *)xrealloc (_rl_wrapped_line, inv_lbsize * sizeof (int)); \ 55250276Speter } \ 55362449Speter inv_lbreaks[++newlines] = out; \ 55450276Speter _rl_wrapped_line[newlines] = _rl_wrapped_multicolumn; \ 55550276Speter lpos = 0; \ 55662449Speter } \ 55762449Speter } while (0) 55850276Speter#else 55950276Speter#define CHECK_LPOS() \ 56050276Speter do { \ 56162449Speter lpos++; \ 56262449Speter if (lpos >= _rl_screenwidth) \ 56362449Speter { \ 56462449Speter if (newlines >= (inv_lbsize - 2)) \ 56562449Speter { \ 56662449Speter inv_lbsize *= 2; \ 56762449Speter inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \ 56862449Speter } \ 56962449Speter inv_lbreaks[++newlines] = out; \ 57062449Speter lpos = 0; \ 57162449Speter } \ 57262449Speter } while (0) 57397049Speter#endif 57497049Speter 57562449Speter /* inv_lbreaks[i] is where line i starts in the buffer. */ 57662449Speter inv_lbreaks[newlines = 0] = 0; 57762449Speter#if 0 57862449Speter lpos = out - wrap_offset; 57962449Speter#else 58062449Speter lpos = prompt_physical_chars + modmark; 58162449Speter#endif 58262449Speter 58362449Speter#if defined (HANDLE_MULTIBYTE) 58462449Speter memset (_rl_wrapped_line, 0, vis_lbsize); 58562449Speter num = 0; 58662449Speter#endif 58762449Speter 58862449Speter /* prompt_invis_chars_first_line is the number of invisible characters in 58962449Speter the first physical line of the prompt. 59062449Speter wrap_offset - prompt_invis_chars_first_line is the number of invis 59162449Speter chars on the second line. */ 59262449Speter 59362449Speter /* what if lpos is already >= _rl_screenwidth before we start drawing the 59462449Speter contents of the command line? */ 59562449Speter while (lpos >= _rl_screenwidth) 59662449Speter { 59762449Speter /* fix from Darin Johnson <darin@acuson.com> for prompt string with 59862449Speter invisible characters that is longer than the screen width. The 59962449Speter prompt_invis_chars_first_line variable could be made into an array 60062449Speter saying how many invisible characters there are per line, but that's 60176726Speter probably too much work for the benefit gained. How many people have 60262449Speter prompts that exceed two physical lines? 60362449Speter Additional logic fix from Edward Catmur <ed@catmur.co.uk> */ 60462449Speter#if defined (HANDLE_MULTIBYTE) 60562449Speter n0 = num; 60662449Speter temp = local_prompt ? strlen (local_prompt) : 0; 60762449Speter while (num < temp) 60862449Speter { 60962449Speter if (_rl_col_width (local_prompt, n0, num) > _rl_screenwidth) 61062449Speter { 61162449Speter num = _rl_find_prev_mbchar (local_prompt, num, MB_FIND_ANY); 61262449Speter break; 61362449Speter } 61462449Speter num++; 61562449Speter } 61662449Speter temp = num + 61762449Speter#else 61862449Speter temp = ((newlines + 1) * _rl_screenwidth) + 61950276Speter#endif /* !HANDLE_MULTIBYTE */ 62050276Speter ((local_prompt_prefix == 0) ? ((newlines == 0) ? prompt_invis_chars_first_line 62150276Speter : ((newlines == 1) ? wrap_offset : 0)) 62250276Speter : ((newlines == 0) ? wrap_offset :0)); 62350276Speter 62450276Speter inv_lbreaks[++newlines] = temp; 62550276Speter#if defined (HANDLE_MULTIBYTE) 62650276Speter lpos -= _rl_col_width (local_prompt, n0, num); 62750276Speter#else 62850276Speter lpos -= _rl_screenwidth; 62950276Speter#endif 63050276Speter } 63150276Speter 63250276Speter prompt_last_screen_line = newlines; 63350276Speter 63450276Speter /* Draw the rest of the line (after the prompt) into invisible_line, keeping 63550276Speter track of where the cursor is (c_pos), the number of the line containing 63676726Speter the cursor (lb_linenum), the last line number (lb_botlin and inv_botlin). 63776726Speter It maintains an array of line breaks for display (inv_lbreaks). 63876726Speter This handles expanding tabs for display and displaying meta characters. */ 63976726Speter lb_linenum = 0; 640166124Srafan#if defined (HANDLE_MULTIBYTE) 641166124Srafan in = 0; 64250276Speter if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 64362449Speter { 64450276Speter memset (&ps, 0, sizeof (mbstate_t)); 64550276Speter wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps); 64650276Speter } 64750276Speter else 64862449Speter wc_bytes = 1; 64962449Speter while (in < rl_end) 65050276Speter#else 65150276Speter for (in = 0; in < rl_end; in++) 65250276Speter#endif 653166124Srafan { 65450276Speter c = (unsigned char)rl_line_buffer[in]; 65597049Speter 65650276Speter#if defined (HANDLE_MULTIBYTE) 657166124Srafan if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 65850276Speter { 65950276Speter if (MB_INVALIDCH (wc_bytes)) 66050276Speter { 66197049Speter /* Byte sequence is invalid or shortened. Assume that the 66250276Speter first byte represents a character. */ 66350276Speter wc_bytes = 1; 66450276Speter /* Assume that a character occupies a single column. */ 66562449Speter wc_width = 1; 66662449Speter memset (&ps, 0, sizeof (mbstate_t)); 66762449Speter } 66850276Speter else if (MB_NULLWCH (wc_bytes)) 66962449Speter break; /* Found '\0' */ 67050276Speter else 67162449Speter { 67250276Speter temp = wcwidth (wc); 67397049Speter wc_width = (temp >= 0) ? temp : 1; 67476726Speter } 67576726Speter } 67676726Speter#endif 67776726Speter 67850276Speter if (out + 8 >= line_size) /* XXX - 8 for \t */ 67950276Speter { 68062449Speter line_size *= 2; 68162449Speter visible_line = (char *)xrealloc (visible_line, line_size); 682166124Srafan invisible_line = (char *)xrealloc (invisible_line, line_size); 683166124Srafan line = invisible_line; 68450276Speter } 68562449Speter 68650276Speter if (in == rl_point) 68762449Speter { 68862449Speter c_pos = out; 68950276Speter lb_linenum = newlines; 69062449Speter } 69162449Speter 69250276Speter#if defined (HANDLE_MULTIBYTE) 69362449Speter if (META_CHAR (c) && _rl_output_meta_chars == 0) /* XXX - clean up */ 69462449Speter#else 69550276Speter if (META_CHAR (c)) 69662449Speter#endif 69762449Speter { 69862449Speter if (_rl_output_meta_chars == 0) 69962449Speter { 70062449Speter sprintf (line + out, "\\%o", c); 70162449Speter 70276726Speter if (lpos + 4 >= _rl_screenwidth) 70350276Speter { 70462449Speter temp = _rl_screenwidth - lpos; 70550276Speter CHECK_INV_LBREAKS (); 70650276Speter inv_lbreaks[++newlines] = out + temp; 70750276Speter lpos = 4 - temp; 70862449Speter } 70950276Speter else 71062449Speter lpos += 4; 71162449Speter 71250276Speter out += 4; 71362449Speter } 71462449Speter else 71550276Speter { 71662449Speter line[out++] = c; 71762449Speter CHECK_LPOS(); 71850276Speter } 71962449Speter } 72050276Speter#if defined (DISPLAY_TABS) 72162449Speter else if (c == '\t') 72262449Speter { 72350276Speter register int newout; 72462449Speter 72550276Speter#if 0 72650276Speter newout = (out | (int)7) + 1; 72750276Speter#else 72850276Speter newout = out + 8 - lpos % 8; 72950276Speter#endif 73050276Speter temp = newout - out; 73150276Speter if (lpos + temp >= _rl_screenwidth) 73250276Speter { 73350276Speter register int temp2; 73450276Speter temp2 = _rl_screenwidth - lpos; 73550276Speter CHECK_INV_LBREAKS (); 73650276Speter inv_lbreaks[++newlines] = out + temp2; 73750276Speter lpos = temp - temp2; 73850276Speter while (out < newout) 73950276Speter line[out++] = ' '; 74050276Speter } 74150276Speter else 74297049Speter { 74350276Speter while (out < newout) 74462449Speter line[out++] = ' '; 74562449Speter lpos += temp; 74662449Speter } 74762449Speter } 74850276Speter#endif 74950276Speter else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up) 75050276Speter { 75162449Speter line[out++] = '\0'; /* XXX - sentinel */ 75250276Speter CHECK_INV_LBREAKS (); 75350276Speter inv_lbreaks[++newlines] = out; 75450276Speter lpos = 0; 75562449Speter } 75650276Speter else if (CTRL_CHAR (c) || c == RUBOUT) 75750276Speter { 75862449Speter line[out++] = '^'; 75962449Speter CHECK_LPOS(); 76062449Speter line[out++] = CTRL_CHAR (c) ? UNCTRL (c) : '?'; 76162449Speter CHECK_LPOS(); 76262449Speter } 76350276Speter else 76462449Speter { 76550276Speter#if defined (HANDLE_MULTIBYTE) 76650276Speter if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 76750276Speter { 76850276Speter register int i; 76950276Speter 77050276Speter _rl_wrapped_multicolumn = 0; 77162449Speter 77262449Speter if (_rl_screenwidth < lpos + wc_width) 77362449Speter for (i = lpos; i < _rl_screenwidth; i++) 77450276Speter { 77550276Speter /* The space will be removed in update_line() */ 77662449Speter line[out++] = ' '; 77762449Speter _rl_wrapped_multicolumn++; 77850276Speter CHECK_LPOS(); 77950276Speter } 78050276Speter if (in == rl_point) 78162449Speter { 78250276Speter c_pos = out; 78350276Speter lb_linenum = newlines; 78450276Speter } 78562449Speter for (i = in; i < in+wc_bytes; i++) 78662449Speter line[out++] = rl_line_buffer[i]; 78762449Speter for (i = 0; i < wc_width; i++) 78862449Speter CHECK_LPOS(); 78962449Speter } 79050276Speter else 791184989Srafan { 792184989Srafan line[out++] = c; 793184989Srafan CHECK_LPOS(); 794184989Srafan } 795184989Srafan#else 79650276Speter line[out++] = c; 79750276Speter CHECK_LPOS(); 79850276Speter#endif 79962449Speter } 80050276Speter 80162449Speter#if defined (HANDLE_MULTIBYTE) 80250276Speter if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 80350276Speter { 80450276Speter in += wc_bytes; 80550276Speter wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps); 80650276Speter } 80750276Speter else 80862449Speter in++; 80962449Speter#endif 81050276Speter 81150276Speter } 81250276Speter line[out] = '\0'; 81350276Speter if (c_pos < 0) 81462449Speter { 81550276Speter c_pos = out; 81650276Speter lb_linenum = newlines; 81750276Speter } 81850276Speter 81950276Speter inv_botlin = lb_botlin = newlines; 82050276Speter CHECK_INV_LBREAKS (); 82162449Speter inv_lbreaks[newlines+1] = out; 82262449Speter cursor_linenum = lb_linenum; 82350276Speter 82450276Speter /* C_POS == position in buffer where cursor should be placed. 82550276Speter CURSOR_LINENUM == line number where the cursor should be placed. */ 82650276Speter 82750276Speter /* PWP: now is when things get a bit hairy. The visible and invisible 82850276Speter line buffers are really multiple lines, which would wrap every 82950276Speter (screenwidth - 1) characters. Go through each in turn, finding 83062449Speter the changed region and updating it. The line order is top to bottom. */ 83162449Speter 83250276Speter /* If we can move the cursor up and down, then use multiple lines, 83350276Speter otherwise, let long lines display in a single terminal line, and 83450276Speter horizontally scroll it. */ 83562449Speter 83650276Speter if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up) 83750276Speter { 83850276Speter int nleft, pos, changed_screen_line; 83962449Speter 84050276Speter if (!rl_display_fixed || forced_display) 84150276Speter { 84250276Speter forced_display = 0; 843166124Srafan 844166124Srafan /* If we have more than a screenful of material to display, then 845166124Srafan only display a screenful. We should display the last screen, 846166124Srafan not the first. */ 847166124Srafan if (out >= _rl_screenchars) 848166124Srafan { 849166124Srafan if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 850166124Srafan out = _rl_find_prev_mbchar (line, _rl_screenchars, MB_FIND_ANY); 851166124Srafan else 852166124Srafan out = _rl_screenchars - 1; 853 } 854 855 /* The first line is at character position 0 in the buffer. The 856 second and subsequent lines start at inv_lbreaks[N], offset by 857 OFFSET (which has already been calculated above). */ 858 859#define W_OFFSET(line, offset) ((line) == 0 ? offset : 0) 860#define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l])) 861#define INV_LLEN(l) (inv_lbreaks[l+1] - inv_lbreaks[l]) 862#define VIS_CHARS(line) (visible_line + vis_lbreaks[line]) 863#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line) 864#define INV_LINE(line) (invisible_line + inv_lbreaks[line]) 865 866 /* For each line in the buffer, do the updating display. */ 867 for (linenum = 0; linenum <= inv_botlin; linenum++) 868 { 869 update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum, 870 VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin); 871 872 /* If this is the line with the prompt, we might need to 873 compensate for invisible characters in the new line. Do 874 this only if there is not more than one new line (which 875 implies that we completely overwrite the old visible line) 876 and the new line is shorter than the old. Make sure we are 877 at the end of the new line before clearing. */ 878 if (linenum == 0 && 879 inv_botlin == 0 && _rl_last_c_pos == out && 880 (wrap_offset > visible_wrap_offset) && 881 (_rl_last_c_pos < visible_first_line_len)) 882 { 883 nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos; 884 if (nleft) 885 _rl_clear_to_eol (nleft); 886 } 887 888 /* Since the new first line is now visible, save its length. */ 889 if (linenum == 0) 890 visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset; 891 } 892 893 /* We may have deleted some lines. If so, clear the left over 894 blank ones at the bottom out. */ 895 if (_rl_vis_botlin > inv_botlin) 896 { 897 char *tt; 898 for (; linenum <= _rl_vis_botlin; linenum++) 899 { 900 tt = VIS_CHARS (linenum); 901 _rl_move_vert (linenum); 902 _rl_move_cursor_relative (0, tt); 903 _rl_clear_to_eol 904 ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth); 905 } 906 } 907 _rl_vis_botlin = inv_botlin; 908 909 /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a 910 different screen line during this redisplay. */ 911 changed_screen_line = _rl_last_v_pos != cursor_linenum; 912 if (changed_screen_line) 913 { 914 _rl_move_vert (cursor_linenum); 915 /* If we moved up to the line with the prompt using _rl_term_up, 916 the physical cursor position on the screen stays the same, 917 but the buffer position needs to be adjusted to account 918 for invisible characters. */ 919 if (cursor_linenum == 0 && wrap_offset) 920 _rl_last_c_pos += wrap_offset; 921 } 922 923 /* We have to reprint the prompt if it contains invisible 924 characters, since it's not generally OK to just reprint 925 the characters from the current cursor position. But we 926 only need to reprint it if the cursor is before the last 927 invisible character in the prompt string. */ 928 nleft = prompt_visible_length + wrap_offset; 929 if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 && 930 _rl_last_c_pos <= prompt_last_invisible && local_prompt) 931 { 932#if defined (__MSDOS__) 933 putc ('\r', rl_outstream); 934#else 935 if (_rl_term_cr) 936 tputs (_rl_term_cr, 1, _rl_output_character_function); 937#endif 938 _rl_output_some_chars (local_prompt, nleft); 939 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 940 _rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft); 941 else 942 _rl_last_c_pos = nleft; 943 } 944 945 /* Where on that line? And where does that line start 946 in the buffer? */ 947 pos = inv_lbreaks[cursor_linenum]; 948 /* nleft == number of characters in the line buffer between the 949 start of the line and the cursor position. */ 950 nleft = c_pos - pos; 951 952 /* Since _rl_backspace() doesn't know about invisible characters in the 953 prompt, and there's no good way to tell it, we compensate for 954 those characters here and call _rl_backspace() directly. */ 955 if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos) 956 { 957 _rl_backspace (_rl_last_c_pos - nleft); 958 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 959 _rl_last_c_pos = _rl_col_width (&visible_line[pos], 0, nleft); 960 else 961 _rl_last_c_pos = nleft; 962 } 963 964 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 965 _rl_move_cursor_relative (nleft, &invisible_line[pos]); 966 else if (nleft != _rl_last_c_pos) 967 _rl_move_cursor_relative (nleft, &invisible_line[pos]); 968 } 969 } 970 else /* Do horizontal scrolling. */ 971 { 972#define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0) 973 int lmargin, ndisp, nleft, phys_c_pos, t; 974 975 /* Always at top line. */ 976 _rl_last_v_pos = 0; 977 978 /* Compute where in the buffer the displayed line should start. This 979 will be LMARGIN. */ 980 981 /* The number of characters that will be displayed before the cursor. */ 982 ndisp = c_pos - wrap_offset; 983 nleft = prompt_visible_length + wrap_offset; 984 /* Where the new cursor position will be on the screen. This can be 985 longer than SCREENWIDTH; if it is, lmargin will be adjusted. */ 986 phys_c_pos = c_pos - (last_lmargin ? last_lmargin : wrap_offset); 987 t = _rl_screenwidth / 3; 988 989 /* If the number of characters had already exceeded the screenwidth, 990 last_lmargin will be > 0. */ 991 992 /* If the number of characters to be displayed is more than the screen 993 width, compute the starting offset so that the cursor is about 994 two-thirds of the way across the screen. */ 995 if (phys_c_pos > _rl_screenwidth - 2) 996 { 997 lmargin = c_pos - (2 * t); 998 if (lmargin < 0) 999 lmargin = 0; 1000 /* If the left margin would be in the middle of a prompt with 1001 invisible characters, don't display the prompt at all. */ 1002 if (wrap_offset && lmargin > 0 && lmargin < nleft) 1003 lmargin = nleft; 1004 } 1005 else if (ndisp < _rl_screenwidth - 2) /* XXX - was -1 */ 1006 lmargin = 0; 1007 else if (phys_c_pos < 1) 1008 { 1009 /* If we are moving back towards the beginning of the line and 1010 the last margin is no longer correct, compute a new one. */ 1011 lmargin = ((c_pos - 1) / t) * t; /* XXX */ 1012 if (wrap_offset && lmargin > 0 && lmargin < nleft) 1013 lmargin = nleft; 1014 } 1015 else 1016 lmargin = last_lmargin; 1017 1018 /* If the first character on the screen isn't the first character 1019 in the display line, indicate this with a special character. */ 1020 if (lmargin > 0) 1021 line[lmargin] = '<'; 1022 1023 /* If SCREENWIDTH characters starting at LMARGIN do not encompass 1024 the whole line, indicate that with a special character at the 1025 right edge of the screen. If LMARGIN is 0, we need to take the 1026 wrap offset into account. */ 1027 t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth; 1028 if (t < out) 1029 line[t - 1] = '>'; 1030 1031 if (!rl_display_fixed || forced_display || lmargin != last_lmargin) 1032 { 1033 forced_display = 0; 1034 update_line (&visible_line[last_lmargin], 1035 &invisible_line[lmargin], 1036 0, 1037 _rl_screenwidth + visible_wrap_offset, 1038 _rl_screenwidth + (lmargin ? 0 : wrap_offset), 1039 0); 1040 1041 /* If the visible new line is shorter than the old, but the number 1042 of invisible characters is greater, and we are at the end of 1043 the new line, we need to clear to eol. */ 1044 t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset); 1045 if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) && 1046 (_rl_last_c_pos == out) && 1047 t < visible_first_line_len) 1048 { 1049 nleft = _rl_screenwidth - t; 1050 _rl_clear_to_eol (nleft); 1051 } 1052 visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset); 1053 if (visible_first_line_len > _rl_screenwidth) 1054 visible_first_line_len = _rl_screenwidth; 1055 1056 _rl_move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]); 1057 last_lmargin = lmargin; 1058 } 1059 } 1060 fflush (rl_outstream); 1061 1062 /* Swap visible and non-visible lines. */ 1063 { 1064 char *vtemp = visible_line; 1065 int *itemp = vis_lbreaks, ntemp = vis_lbsize; 1066 1067 visible_line = invisible_line; 1068 invisible_line = vtemp; 1069 1070 vis_lbreaks = inv_lbreaks; 1071 inv_lbreaks = itemp; 1072 1073 vis_lbsize = inv_lbsize; 1074 inv_lbsize = ntemp; 1075 1076 rl_display_fixed = 0; 1077 /* If we are displaying on a single line, and last_lmargin is > 0, we 1078 are not displaying any invisible characters, so set visible_wrap_offset 1079 to 0. */ 1080 if (_rl_horizontal_scroll_mode && last_lmargin) 1081 visible_wrap_offset = 0; 1082 else 1083 visible_wrap_offset = wrap_offset; 1084 } 1085} 1086 1087/* PWP: update_line() is based on finding the middle difference of each 1088 line on the screen; vis: 1089 1090 /old first difference 1091 /beginning of line | /old last same /old EOL 1092 v v v v 1093old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as 1094new: eddie> Oh, my little buggy says to me, as lurgid as 1095 ^ ^ ^ ^ 1096 \beginning of line | \new last same \new end of line 1097 \new first difference 1098 1099 All are character pointers for the sake of speed. Special cases for 1100 no differences, as well as for end of line additions must be handled. 1101 1102 Could be made even smarter, but this works well enough */ 1103static void 1104update_line (old, new, current_line, omax, nmax, inv_botlin) 1105 register char *old, *new; 1106 int current_line, omax, nmax, inv_botlin; 1107{ 1108 register char *ofd, *ols, *oe, *nfd, *nls, *ne; 1109 int temp, lendiff, wsatend, od, nd; 1110 int current_invis_chars; 1111 int col_lendiff, col_temp; 1112#if defined (HANDLE_MULTIBYTE) 1113 mbstate_t ps_new, ps_old; 1114 int new_offset, old_offset, tmp; 1115#endif 1116 1117 /* If we're at the right edge of a terminal that supports xn, we're 1118 ready to wrap around, so do so. This fixes problems with knowing 1119 the exact cursor position and cut-and-paste with certain terminal 1120 emulators. In this calculation, TEMP is the physical screen 1121 position of the cursor. */ 1122 temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset); 1123 if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode 1124 && _rl_last_v_pos == current_line - 1) 1125 { 1126#if defined (HANDLE_MULTIBYTE) 1127 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1128 { 1129 wchar_t wc; 1130 mbstate_t ps; 1131 int tempwidth, bytes; 1132 size_t ret; 1133 1134 /* This fixes only double-column characters, but if the wrapped 1135 character comsumes more than three columns, spaces will be 1136 inserted in the string buffer. */ 1137 if (_rl_wrapped_line[current_line] > 0) 1138 _rl_clear_to_eol (_rl_wrapped_line[current_line]); 1139 1140 memset (&ps, 0, sizeof (mbstate_t)); 1141 ret = mbrtowc (&wc, new, MB_CUR_MAX, &ps); 1142 if (MB_INVALIDCH (ret)) 1143 { 1144 tempwidth = 1; 1145 ret = 1; 1146 } 1147 else if (MB_NULLWCH (ret)) 1148 tempwidth = 0; 1149 else 1150 tempwidth = wcwidth (wc); 1151 1152 if (tempwidth > 0) 1153 { 1154 int count; 1155 bytes = ret; 1156 for (count = 0; count < bytes; count++) 1157 putc (new[count], rl_outstream); 1158 _rl_last_c_pos = tempwidth; 1159 _rl_last_v_pos++; 1160 memset (&ps, 0, sizeof (mbstate_t)); 1161 ret = mbrtowc (&wc, old, MB_CUR_MAX, &ps); 1162 if (ret != 0 && bytes != 0) 1163 { 1164 if (MB_INVALIDCH (ret)) 1165 memmove (old+bytes, old+1, strlen (old+1)); 1166 else 1167 memmove (old+bytes, old+ret, strlen (old+ret)); 1168 memcpy (old, new, bytes); 1169 } 1170 } 1171 else 1172 { 1173 putc (' ', rl_outstream); 1174 _rl_last_c_pos = 1; 1175 _rl_last_v_pos++; 1176 if (old[0] && new[0]) 1177 old[0] = new[0]; 1178 } 1179 } 1180 else 1181#endif 1182 { 1183 if (new[0]) 1184 putc (new[0], rl_outstream); 1185 else 1186 putc (' ', rl_outstream); 1187 _rl_last_c_pos = 1; /* XXX */ 1188 _rl_last_v_pos++; 1189 if (old[0] && new[0]) 1190 old[0] = new[0]; 1191 } 1192 } 1193 1194 1195 /* Find first difference. */ 1196#if defined (HANDLE_MULTIBYTE) 1197 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1198 { 1199 /* See if the old line is a subset of the new line, so that the 1200 only change is adding characters. */ 1201 temp = (omax < nmax) ? omax : nmax; 1202 if (memcmp (old, new, temp) == 0) 1203 { 1204 ofd = old + temp; 1205 nfd = new + temp; 1206 } 1207 else 1208 { 1209 memset (&ps_new, 0, sizeof(mbstate_t)); 1210 memset (&ps_old, 0, sizeof(mbstate_t)); 1211 1212 if (omax == nmax && STREQN (new, old, omax)) 1213 { 1214 ofd = old + omax; 1215 nfd = new + nmax; 1216 } 1217 else 1218 { 1219 new_offset = old_offset = 0; 1220 for (ofd = old, nfd = new; 1221 (ofd - old < omax) && *ofd && 1222 _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new); ) 1223 { 1224 old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY); 1225 new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY); 1226 ofd = old + old_offset; 1227 nfd = new + new_offset; 1228 } 1229 } 1230 } 1231 } 1232 else 1233#endif 1234 for (ofd = old, nfd = new; 1235 (ofd - old < omax) && *ofd && (*ofd == *nfd); 1236 ofd++, nfd++) 1237 ; 1238 1239 /* Move to the end of the screen line. ND and OD are used to keep track 1240 of the distance between ne and new and oe and old, respectively, to 1241 move a subtraction out of each loop. */ 1242 for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++); 1243 for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++); 1244 1245 /* If no difference, continue to next line. */ 1246 if (ofd == oe && nfd == ne) 1247 return; 1248 1249 wsatend = 1; /* flag for trailing whitespace */ 1250 1251#if defined (HANDLE_MULTIBYTE) 1252 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1253 { 1254 ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY); 1255 nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY); 1256 while ((ols > ofd) && (nls > nfd)) 1257 { 1258 memset (&ps_old, 0, sizeof (mbstate_t)); 1259 memset (&ps_new, 0, sizeof (mbstate_t)); 1260 1261#if 0 1262 /* On advice from jir@yamato.ibm.com */ 1263 _rl_adjust_point (old, ols - old, &ps_old); 1264 _rl_adjust_point (new, nls - new, &ps_new); 1265#endif 1266 1267 if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0) 1268 break; 1269 1270 if (*ols == ' ') 1271 wsatend = 0; 1272 1273 ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY); 1274 nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY); 1275 } 1276 } 1277 else 1278 { 1279#endif /* HANDLE_MULTIBYTE */ 1280 ols = oe - 1; /* find last same */ 1281 nls = ne - 1; 1282 while ((ols > ofd) && (nls > nfd) && (*ols == *nls)) 1283 { 1284 if (*ols != ' ') 1285 wsatend = 0; 1286 ols--; 1287 nls--; 1288 } 1289#if defined (HANDLE_MULTIBYTE) 1290 } 1291#endif 1292 1293 if (wsatend) 1294 { 1295 ols = oe; 1296 nls = ne; 1297 } 1298#if defined (HANDLE_MULTIBYTE) 1299 /* This may not work for stateful encoding, but who cares? To handle 1300 stateful encoding properly, we have to scan each string from the 1301 beginning and compare. */ 1302 else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0) 1303#else 1304 else if (*ols != *nls) 1305#endif 1306 { 1307 if (*ols) /* don't step past the NUL */ 1308 { 1309 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1310 ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY); 1311 else 1312 ols++; 1313 } 1314 if (*nls) 1315 { 1316 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1317 nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY); 1318 else 1319 nls++; 1320 } 1321 } 1322 1323 /* count of invisible characters in the current invisible line. */ 1324 current_invis_chars = W_OFFSET (current_line, wrap_offset); 1325 if (_rl_last_v_pos != current_line) 1326 { 1327 _rl_move_vert (current_line); 1328 if (current_line == 0 && visible_wrap_offset) 1329 _rl_last_c_pos += visible_wrap_offset; 1330 } 1331 1332 /* If this is the first line and there are invisible characters in the 1333 prompt string, and the prompt string has not changed, and the current 1334 cursor position is before the last invisible character in the prompt, 1335 and the index of the character to move to is past the end of the prompt 1336 string, then redraw the entire prompt string. We can only do this 1337 reliably if the terminal supports a `cr' capability. 1338 1339 This is not an efficiency hack -- there is a problem with redrawing 1340 portions of the prompt string if they contain terminal escape 1341 sequences (like drawing the `unbold' sequence without a corresponding 1342 `bold') that manifests itself on certain terminals. */ 1343 1344 lendiff = local_prompt ? strlen (local_prompt) : 0; 1345 od = ofd - old; /* index of first difference in visible line */ 1346 if (current_line == 0 && !_rl_horizontal_scroll_mode && 1347 _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 && 1348 od >= lendiff && _rl_last_c_pos <= prompt_last_invisible) 1349 { 1350#if defined (__MSDOS__) 1351 putc ('\r', rl_outstream); 1352#else 1353 tputs (_rl_term_cr, 1, _rl_output_character_function); 1354#endif 1355 _rl_output_some_chars (local_prompt, lendiff); 1356 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1357 _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff); 1358 else 1359 _rl_last_c_pos = lendiff; 1360 } 1361 1362 _rl_move_cursor_relative (od, old); 1363 1364 /* if (len (new) > len (old)) 1365 lendiff == difference in buffer 1366 col_lendiff == difference on screen 1367 When not using multibyte characters, these are equal */ 1368 lendiff = (nls - nfd) - (ols - ofd); 1369 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1370 col_lendiff = _rl_col_width (new, nfd - new, nls - new) - _rl_col_width (old, ofd - old, ols - old); 1371 else 1372 col_lendiff = lendiff; 1373 1374 /* If we are changing the number of invisible characters in a line, and 1375 the spot of first difference is before the end of the invisible chars, 1376 lendiff needs to be adjusted. */ 1377 if (current_line == 0 && !_rl_horizontal_scroll_mode && 1378 current_invis_chars != visible_wrap_offset) 1379 { 1380 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1381 { 1382 lendiff += visible_wrap_offset - current_invis_chars; 1383 col_lendiff += visible_wrap_offset - current_invis_chars; 1384 } 1385 else 1386 { 1387 lendiff += visible_wrap_offset - current_invis_chars; 1388 col_lendiff = lendiff; 1389 } 1390 } 1391 1392 /* Insert (diff (len (old), len (new)) ch. */ 1393 temp = ne - nfd; 1394 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1395 col_temp = _rl_col_width (new, nfd - new, ne - new); 1396 else 1397 col_temp = temp; 1398 1399 if (col_lendiff > 0) /* XXX - was lendiff */ 1400 { 1401 /* Non-zero if we're increasing the number of lines. */ 1402 int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin; 1403 /* Sometimes it is cheaper to print the characters rather than 1404 use the terminal's capabilities. If we're growing the number 1405 of lines, make sure we actually cause the new line to wrap 1406 around on auto-wrapping terminals. */ 1407 if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl)) 1408 { 1409 /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and 1410 _rl_horizontal_scroll_mode == 1, inserting the characters with 1411 _rl_term_IC or _rl_term_ic will screw up the screen because of the 1412 invisible characters. We need to just draw them. */ 1413 if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 || 1414 lendiff <= prompt_visible_length || !current_invis_chars)) 1415 { 1416 insert_some_chars (nfd, lendiff, col_lendiff); 1417 _rl_last_c_pos += col_lendiff; 1418 } 1419 else if (*ols == 0 && lendiff > 0) 1420 { 1421 /* At the end of a line the characters do not have to 1422 be "inserted". They can just be placed on the screen. */ 1423 /* However, this screws up the rest of this block, which 1424 assumes you've done the insert because you can. */ 1425 _rl_output_some_chars (nfd, lendiff); 1426 _rl_last_c_pos += col_lendiff; 1427 } 1428 else 1429 { 1430 /* We have horizontal scrolling and we are not inserting at 1431 the end. We have invisible characters in this line. This 1432 is a dumb update. */ 1433 _rl_output_some_chars (nfd, temp); 1434 _rl_last_c_pos += col_temp; 1435 return; 1436 } 1437 /* Copy (new) chars to screen from first diff to last match. */ 1438 temp = nls - nfd; 1439 if ((temp - lendiff) > 0) 1440 { 1441 _rl_output_some_chars (nfd + lendiff, temp - lendiff); 1442#if 1 1443 /* XXX -- this bears closer inspection. Fixes a redisplay bug 1444 reported against bash-3.0-alpha by Andreas Schwab involving 1445 multibyte characters and prompt strings with invisible 1446 characters, but was previously disabled. */ 1447 _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-col_lendiff); 1448#else 1449 _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-lendiff); 1450#endif 1451 } 1452 } 1453 else 1454 { 1455 /* cannot insert chars, write to EOL */ 1456 _rl_output_some_chars (nfd, temp); 1457 _rl_last_c_pos += col_temp; 1458 } 1459 } 1460 else /* Delete characters from line. */ 1461 { 1462 /* If possible and inexpensive to use terminal deletion, then do so. */ 1463 if (_rl_term_dc && (2 * col_temp) >= -col_lendiff) 1464 { 1465 /* If all we're doing is erasing the invisible characters in the 1466 prompt string, don't bother. It screws up the assumptions 1467 about what's on the screen. */ 1468 if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 && 1469 -lendiff == visible_wrap_offset) 1470 col_lendiff = 0; 1471 1472 if (col_lendiff) 1473 delete_chars (-col_lendiff); /* delete (diff) characters */ 1474 1475 /* Copy (new) chars to screen from first diff to last match */ 1476 temp = nls - nfd; 1477 if (temp > 0) 1478 { 1479 _rl_output_some_chars (nfd, temp); 1480 _rl_last_c_pos += _rl_col_width (nfd, 0, temp);; 1481 } 1482 } 1483 /* Otherwise, print over the existing material. */ 1484 else 1485 { 1486 if (temp > 0) 1487 { 1488 _rl_output_some_chars (nfd, temp); 1489 _rl_last_c_pos += col_temp; 1490 } 1491 lendiff = (oe - old) - (ne - new); 1492 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1493 col_lendiff = _rl_col_width (old, 0, oe - old) - _rl_col_width (new, 0, ne - new); 1494 else 1495 col_lendiff = lendiff; 1496 1497 if (col_lendiff) 1498 { 1499 if (_rl_term_autowrap && current_line < inv_botlin) 1500 space_to_eol (col_lendiff); 1501 else 1502 _rl_clear_to_eol (col_lendiff); 1503 } 1504 } 1505 } 1506} 1507 1508/* Tell the update routines that we have moved onto a new (empty) line. */ 1509int 1510rl_on_new_line () 1511{ 1512 if (visible_line) 1513 visible_line[0] = '\0'; 1514 1515 _rl_last_c_pos = _rl_last_v_pos = 0; 1516 _rl_vis_botlin = last_lmargin = 0; 1517 if (vis_lbreaks) 1518 vis_lbreaks[0] = vis_lbreaks[1] = 0; 1519 visible_wrap_offset = 0; 1520 return 0; 1521} 1522 1523/* Tell the update routines that we have moved onto a new line with the 1524 prompt already displayed. Code originally from the version of readline 1525 distributed with CLISP. rl_expand_prompt must have already been called 1526 (explicitly or implicitly). This still doesn't work exactly right. */ 1527int 1528rl_on_new_line_with_prompt () 1529{ 1530 int prompt_size, i, l, real_screenwidth, newlines; 1531 char *prompt_last_line, *lprompt; 1532 1533 /* Initialize visible_line and invisible_line to ensure that they can hold 1534 the already-displayed prompt. */ 1535 prompt_size = strlen (rl_prompt) + 1; 1536 init_line_structures (prompt_size); 1537 1538 /* Make sure the line structures hold the already-displayed prompt for 1539 redisplay. */ 1540 lprompt = local_prompt ? local_prompt : rl_prompt; 1541 strcpy (visible_line, lprompt); 1542 strcpy (invisible_line, lprompt); 1543 1544 /* If the prompt contains newlines, take the last tail. */ 1545 prompt_last_line = strrchr (rl_prompt, '\n'); 1546 if (!prompt_last_line) 1547 prompt_last_line = rl_prompt; 1548 1549 l = strlen (prompt_last_line); 1550 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1551 _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l); 1552 else 1553 _rl_last_c_pos = l; 1554 1555 /* Dissect prompt_last_line into screen lines. Note that here we have 1556 to use the real screenwidth. Readline's notion of screenwidth might be 1557 one less, see terminal.c. */ 1558 real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1); 1559 _rl_last_v_pos = l / real_screenwidth; 1560 /* If the prompt length is a multiple of real_screenwidth, we don't know 1561 whether the cursor is at the end of the last line, or already at the 1562 beginning of the next line. Output a newline just to be safe. */ 1563 if (l > 0 && (l % real_screenwidth) == 0) 1564 _rl_output_some_chars ("\n", 1); 1565 last_lmargin = 0; 1566 1567 newlines = 0; i = 0; 1568 while (i <= l) 1569 { 1570 _rl_vis_botlin = newlines; 1571 vis_lbreaks[newlines++] = i; 1572 i += real_screenwidth; 1573 } 1574 vis_lbreaks[newlines] = l; 1575 visible_wrap_offset = 0; 1576 1577 rl_display_prompt = rl_prompt; /* XXX - make sure it's set */ 1578 1579 return 0; 1580} 1581 1582/* Actually update the display, period. */ 1583int 1584rl_forced_update_display () 1585{ 1586 if (visible_line) 1587 { 1588 register char *temp = visible_line; 1589 1590 while (*temp) 1591 *temp++ = '\0'; 1592 } 1593 rl_on_new_line (); 1594 forced_display++; 1595 (*rl_redisplay_function) (); 1596 return 0; 1597} 1598 1599/* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices. 1600 DATA is the contents of the screen line of interest; i.e., where 1601 the movement is being done. */ 1602void 1603_rl_move_cursor_relative (new, data) 1604 int new; 1605 const char *data; 1606{ 1607 register int i; 1608 1609 /* If we don't have to do anything, then return. */ 1610#if defined (HANDLE_MULTIBYTE) 1611 /* If we have multibyte characters, NEW is indexed by the buffer point in 1612 a multibyte string, but _rl_last_c_pos is the display position. In 1613 this case, NEW's display position is not obvious and must be 1614 calculated. */ 1615 if (MB_CUR_MAX == 1 || rl_byte_oriented) 1616 { 1617 if (_rl_last_c_pos == new) 1618 return; 1619 } 1620 else if (_rl_last_c_pos == _rl_col_width (data, 0, new)) 1621 return; 1622#else 1623 if (_rl_last_c_pos == new) return; 1624#endif 1625 1626 /* It may be faster to output a CR, and then move forwards instead 1627 of moving backwards. */ 1628 /* i == current physical cursor position. */ 1629 i = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset); 1630 if (new == 0 || CR_FASTER (new, _rl_last_c_pos) || 1631 (_rl_term_autowrap && i == _rl_screenwidth)) 1632 { 1633#if defined (__MSDOS__) 1634 putc ('\r', rl_outstream); 1635#else 1636 tputs (_rl_term_cr, 1, _rl_output_character_function); 1637#endif /* !__MSDOS__ */ 1638 _rl_last_c_pos = 0; 1639 } 1640 1641 if (_rl_last_c_pos < new) 1642 { 1643 /* Move the cursor forward. We do it by printing the command 1644 to move the cursor forward if there is one, else print that 1645 portion of the output buffer again. Which is cheaper? */ 1646 1647 /* The above comment is left here for posterity. It is faster 1648 to print one character (non-control) than to print a control 1649 sequence telling the terminal to move forward one character. 1650 That kind of control is for people who don't know what the 1651 data is underneath the cursor. */ 1652#if defined (HACK_TERMCAP_MOTION) 1653 if (_rl_term_forward_char) 1654 { 1655 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1656 { 1657 int width; 1658 width = _rl_col_width (data, _rl_last_c_pos, new); 1659 for (i = 0; i < width; i++) 1660 tputs (_rl_term_forward_char, 1, _rl_output_character_function); 1661 } 1662 else 1663 { 1664 for (i = _rl_last_c_pos; i < new; i++) 1665 tputs (_rl_term_forward_char, 1, _rl_output_character_function); 1666 } 1667 } 1668 else if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1669 { 1670 tputs (_rl_term_cr, 1, _rl_output_character_function); 1671 for (i = 0; i < new; i++) 1672 putc (data[i], rl_outstream); 1673 } 1674 else 1675 for (i = _rl_last_c_pos; i < new; i++) 1676 putc (data[i], rl_outstream); 1677 1678#else /* !HACK_TERMCAP_MOTION */ 1679 1680 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1681 { 1682 tputs (_rl_term_cr, 1, _rl_output_character_function); 1683 for (i = 0; i < new; i++) 1684 putc (data[i], rl_outstream); 1685 } 1686 else 1687 for (i = _rl_last_c_pos; i < new; i++) 1688 putc (data[i], rl_outstream); 1689 1690#endif /* !HACK_TERMCAP_MOTION */ 1691 1692 } 1693#if defined (HANDLE_MULTIBYTE) 1694 /* NEW points to the buffer point, but _rl_last_c_pos is the display point. 1695 The byte length of the string is probably bigger than the column width 1696 of the string, which means that if NEW == _rl_last_c_pos, then NEW's 1697 display point is less than _rl_last_c_pos. */ 1698 else if (_rl_last_c_pos >= new) 1699#else 1700 else if (_rl_last_c_pos > new) 1701#endif 1702 { 1703 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1704 _rl_backspace (_rl_last_c_pos - _rl_col_width (data, 0, new)); 1705 else 1706 _rl_backspace (_rl_last_c_pos - new); 1707 } 1708 1709 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1710 _rl_last_c_pos = _rl_col_width (data, 0, new); 1711 else 1712 _rl_last_c_pos = new; 1713} 1714 1715/* PWP: move the cursor up or down. */ 1716void 1717_rl_move_vert (to) 1718 int to; 1719{ 1720 register int delta, i; 1721 1722 if (_rl_last_v_pos == to || to > _rl_screenheight) 1723 return; 1724 1725 if ((delta = to - _rl_last_v_pos) > 0) 1726 { 1727 for (i = 0; i < delta; i++) 1728 putc ('\n', rl_outstream); 1729#if defined (__MSDOS__) 1730 putc ('\r', rl_outstream); 1731#else 1732 tputs (_rl_term_cr, 1, _rl_output_character_function); 1733#endif 1734 _rl_last_c_pos = 0; 1735 } 1736 else 1737 { /* delta < 0 */ 1738 if (_rl_term_up && *_rl_term_up) 1739 for (i = 0; i < -delta; i++) 1740 tputs (_rl_term_up, 1, _rl_output_character_function); 1741 } 1742 1743 _rl_last_v_pos = to; /* Now TO is here */ 1744} 1745 1746/* Physically print C on rl_outstream. This is for functions which know 1747 how to optimize the display. Return the number of characters output. */ 1748int 1749rl_show_char (c) 1750 int c; 1751{ 1752 int n = 1; 1753 if (META_CHAR (c) && (_rl_output_meta_chars == 0)) 1754 { 1755 fprintf (rl_outstream, "M-"); 1756 n += 2; 1757 c = UNMETA (c); 1758 } 1759 1760#if defined (DISPLAY_TABS) 1761 if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT) 1762#else 1763 if (CTRL_CHAR (c) || c == RUBOUT) 1764#endif /* !DISPLAY_TABS */ 1765 { 1766 fprintf (rl_outstream, "C-"); 1767 n += 2; 1768 c = CTRL_CHAR (c) ? UNCTRL (c) : '?'; 1769 } 1770 1771 putc (c, rl_outstream); 1772 fflush (rl_outstream); 1773 return n; 1774} 1775 1776int 1777rl_character_len (c, pos) 1778 register int c, pos; 1779{ 1780 unsigned char uc; 1781 1782 uc = (unsigned char)c; 1783 1784 if (META_CHAR (uc)) 1785 return ((_rl_output_meta_chars == 0) ? 4 : 1); 1786 1787 if (uc == '\t') 1788 { 1789#if defined (DISPLAY_TABS) 1790 return (((pos | 7) + 1) - pos); 1791#else 1792 return (2); 1793#endif /* !DISPLAY_TABS */ 1794 } 1795 1796 if (CTRL_CHAR (c) || c == RUBOUT) 1797 return (2); 1798 1799 return ((ISPRINT (uc)) ? 1 : 2); 1800} 1801 1802/* How to print things in the "echo-area". The prompt is treated as a 1803 mini-modeline. */ 1804 1805#if defined (USE_VARARGS) 1806int 1807#if defined (PREFER_STDARG) 1808rl_message (const char *format, ...) 1809#else 1810rl_message (va_alist) 1811 va_dcl 1812#endif 1813{ 1814 va_list args; 1815#if defined (PREFER_VARARGS) 1816 char *format; 1817#endif 1818 1819#if defined (PREFER_STDARG) 1820 va_start (args, format); 1821#else 1822 va_start (args); 1823 format = va_arg (args, char *); 1824#endif 1825 1826#if defined (HAVE_VSNPRINTF) 1827 vsnprintf (msg_buf, sizeof (msg_buf) - 1, format, args); 1828#else 1829 vsprintf (msg_buf, format, args); 1830 msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */ 1831#endif 1832 va_end (args); 1833 1834 rl_display_prompt = msg_buf; 1835 (*rl_redisplay_function) (); 1836 return 0; 1837} 1838#else /* !USE_VARARGS */ 1839int 1840rl_message (format, arg1, arg2) 1841 char *format; 1842{ 1843 sprintf (msg_buf, format, arg1, arg2); 1844 msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */ 1845 rl_display_prompt = msg_buf; 1846 (*rl_redisplay_function) (); 1847 return 0; 1848} 1849#endif /* !USE_VARARGS */ 1850 1851/* How to clear things from the "echo-area". */ 1852int 1853rl_clear_message () 1854{ 1855 rl_display_prompt = rl_prompt; 1856 (*rl_redisplay_function) (); 1857 return 0; 1858} 1859 1860int 1861rl_reset_line_state () 1862{ 1863 rl_on_new_line (); 1864 1865 rl_display_prompt = rl_prompt ? rl_prompt : ""; 1866 forced_display = 1; 1867 return 0; 1868} 1869 1870/* These are getting numerous enough that it's time to create a struct. */ 1871 1872static char *saved_local_prompt; 1873static char *saved_local_prefix; 1874static int saved_last_invisible; 1875static int saved_visible_length; 1876static int saved_invis_chars_first_line; 1877static int saved_physical_chars; 1878 1879void 1880rl_save_prompt () 1881{ 1882 saved_local_prompt = local_prompt; 1883 saved_local_prefix = local_prompt_prefix; 1884 saved_last_invisible = prompt_last_invisible; 1885 saved_visible_length = prompt_visible_length; 1886 saved_invis_chars_first_line = prompt_invis_chars_first_line; 1887 saved_physical_chars = prompt_physical_chars; 1888 1889 local_prompt = local_prompt_prefix = (char *)0; 1890 prompt_last_invisible = prompt_visible_length = 0; 1891 prompt_invis_chars_first_line = prompt_physical_chars = 0; 1892} 1893 1894void 1895rl_restore_prompt () 1896{ 1897 FREE (local_prompt); 1898 FREE (local_prompt_prefix); 1899 1900 local_prompt = saved_local_prompt; 1901 local_prompt_prefix = saved_local_prefix; 1902 prompt_last_invisible = saved_last_invisible; 1903 prompt_visible_length = saved_visible_length; 1904 prompt_invis_chars_first_line = saved_invis_chars_first_line; 1905 prompt_physical_chars = saved_physical_chars; 1906} 1907 1908char * 1909_rl_make_prompt_for_search (pchar) 1910 int pchar; 1911{ 1912 int len; 1913 char *pmt; 1914 1915 rl_save_prompt (); 1916 1917 if (saved_local_prompt == 0) 1918 { 1919 len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0; 1920 pmt = (char *)xmalloc (len + 2); 1921 if (len) 1922 strcpy (pmt, rl_prompt); 1923 pmt[len] = pchar; 1924 pmt[len+1] = '\0'; 1925 } 1926 else 1927 { 1928 len = *saved_local_prompt ? strlen (saved_local_prompt) : 0; 1929 pmt = (char *)xmalloc (len + 2); 1930 if (len) 1931 strcpy (pmt, saved_local_prompt); 1932 pmt[len] = pchar; 1933 pmt[len+1] = '\0'; 1934 local_prompt = savestring (pmt); 1935 prompt_last_invisible = saved_last_invisible; 1936 prompt_visible_length = saved_visible_length + 1; 1937 } 1938 1939 return pmt; 1940} 1941 1942/* Quick redisplay hack when erasing characters at the end of the line. */ 1943void 1944_rl_erase_at_end_of_line (l) 1945 int l; 1946{ 1947 register int i; 1948 1949 _rl_backspace (l); 1950 for (i = 0; i < l; i++) 1951 putc (' ', rl_outstream); 1952 _rl_backspace (l); 1953 for (i = 0; i < l; i++) 1954 visible_line[--_rl_last_c_pos] = '\0'; 1955 rl_display_fixed++; 1956} 1957 1958/* Clear to the end of the line. COUNT is the minimum 1959 number of character spaces to clear, */ 1960void 1961_rl_clear_to_eol (count) 1962 int count; 1963{ 1964 if (_rl_term_clreol) 1965 tputs (_rl_term_clreol, 1, _rl_output_character_function); 1966 else if (count) 1967 space_to_eol (count); 1968} 1969 1970/* Clear to the end of the line using spaces. COUNT is the minimum 1971 number of character spaces to clear, */ 1972static void 1973space_to_eol (count) 1974 int count; 1975{ 1976 register int i; 1977 1978 for (i = 0; i < count; i++) 1979 putc (' ', rl_outstream); 1980 1981 _rl_last_c_pos += count; 1982} 1983 1984void 1985_rl_clear_screen () 1986{ 1987 if (_rl_term_clrpag) 1988 tputs (_rl_term_clrpag, 1, _rl_output_character_function); 1989 else 1990 rl_crlf (); 1991} 1992 1993/* Insert COUNT characters from STRING to the output stream at column COL. */ 1994static void 1995insert_some_chars (string, count, col) 1996 char *string; 1997 int count, col; 1998{ 1999 /* DEBUGGING */ 2000 if (MB_CUR_MAX == 1 || rl_byte_oriented) 2001 if (count != col) 2002 fprintf(stderr, "readline: debug: insert_some_chars: count (%d) != col (%d)\n", count, col); 2003 2004 /* If IC is defined, then we do not have to "enter" insert mode. */ 2005 if (_rl_term_IC) 2006 { 2007 char *buffer; 2008 2009 buffer = tgoto (_rl_term_IC, 0, col); 2010 tputs (buffer, 1, _rl_output_character_function); 2011 _rl_output_some_chars (string, count); 2012 } 2013 else 2014 { 2015 register int i; 2016 2017 /* If we have to turn on insert-mode, then do so. */ 2018 if (_rl_term_im && *_rl_term_im) 2019 tputs (_rl_term_im, 1, _rl_output_character_function); 2020 2021 /* If there is a special command for inserting characters, then 2022 use that first to open up the space. */ 2023 if (_rl_term_ic && *_rl_term_ic) 2024 { 2025 for (i = col; i--; ) 2026 tputs (_rl_term_ic, 1, _rl_output_character_function); 2027 } 2028 2029 /* Print the text. */ 2030 _rl_output_some_chars (string, count); 2031 2032 /* If there is a string to turn off insert mode, we had best use 2033 it now. */ 2034 if (_rl_term_ei && *_rl_term_ei) 2035 tputs (_rl_term_ei, 1, _rl_output_character_function); 2036 } 2037} 2038 2039/* Delete COUNT characters from the display line. */ 2040static void 2041delete_chars (count) 2042 int count; 2043{ 2044 if (count > _rl_screenwidth) /* XXX */ 2045 return; 2046 2047 if (_rl_term_DC && *_rl_term_DC) 2048 { 2049 char *buffer; 2050 buffer = tgoto (_rl_term_DC, count, count); 2051 tputs (buffer, count, _rl_output_character_function); 2052 } 2053 else 2054 { 2055 if (_rl_term_dc && *_rl_term_dc) 2056 while (count--) 2057 tputs (_rl_term_dc, 1, _rl_output_character_function); 2058 } 2059} 2060 2061void 2062_rl_update_final () 2063{ 2064 int full_lines; 2065 2066 full_lines = 0; 2067 /* If the cursor is the only thing on an otherwise-blank last line, 2068 compensate so we don't print an extra CRLF. */ 2069 if (_rl_vis_botlin && _rl_last_c_pos == 0 && 2070 visible_line[vis_lbreaks[_rl_vis_botlin]] == 0) 2071 { 2072 _rl_vis_botlin--; 2073 full_lines = 1; 2074 } 2075 _rl_move_vert (_rl_vis_botlin); 2076 /* If we've wrapped lines, remove the final xterm line-wrap flag. */ 2077 if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth)) 2078 { 2079 char *last_line; 2080 2081 last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]]; 2082 _rl_move_cursor_relative (_rl_screenwidth - 1, last_line); 2083 _rl_clear_to_eol (0); 2084 putc (last_line[_rl_screenwidth - 1], rl_outstream); 2085 } 2086 _rl_vis_botlin = 0; 2087 rl_crlf (); 2088 fflush (rl_outstream); 2089 rl_display_fixed++; 2090} 2091 2092/* Move to the start of the current line. */ 2093static void 2094cr () 2095{ 2096 if (_rl_term_cr) 2097 { 2098#if defined (__MSDOS__) 2099 putc ('\r', rl_outstream); 2100#else 2101 tputs (_rl_term_cr, 1, _rl_output_character_function); 2102#endif 2103 _rl_last_c_pos = 0; 2104 } 2105} 2106 2107/* Redraw the last line of a multi-line prompt that may possibly contain 2108 terminal escape sequences. Called with the cursor at column 0 of the 2109 line to draw the prompt on. */ 2110static void 2111redraw_prompt (t) 2112 char *t; 2113{ 2114 char *oldp, *oldl, *oldlprefix; 2115 int oldlen, oldlast, oldplen, oldninvis, oldphyschars; 2116 2117 /* Geez, I should make this a struct. */ 2118 oldp = rl_display_prompt; 2119 oldl = local_prompt; 2120 oldlprefix = local_prompt_prefix; 2121 oldlen = prompt_visible_length; 2122 oldplen = prompt_prefix_length; 2123 oldlast = prompt_last_invisible; 2124 oldninvis = prompt_invis_chars_first_line; 2125 oldphyschars = prompt_physical_chars; 2126 2127 rl_display_prompt = t; 2128 local_prompt = expand_prompt (t, &prompt_visible_length, 2129 &prompt_last_invisible, 2130 &prompt_invis_chars_first_line, 2131 &prompt_physical_chars); 2132 local_prompt_prefix = (char *)NULL; 2133 rl_forced_update_display (); 2134 2135 rl_display_prompt = oldp; 2136 local_prompt = oldl; 2137 local_prompt_prefix = oldlprefix; 2138 prompt_visible_length = oldlen; 2139 prompt_prefix_length = oldplen; 2140 prompt_last_invisible = oldlast; 2141 prompt_invis_chars_first_line = oldninvis; 2142 prompt_physical_chars = oldphyschars; 2143} 2144 2145/* Redisplay the current line after a SIGWINCH is received. */ 2146void 2147_rl_redisplay_after_sigwinch () 2148{ 2149 char *t; 2150 2151 /* Clear the current line and put the cursor at column 0. Make sure 2152 the right thing happens if we have wrapped to a new screen line. */ 2153 if (_rl_term_cr) 2154 { 2155#if defined (__MSDOS__) 2156 putc ('\r', rl_outstream); 2157#else 2158 tputs (_rl_term_cr, 1, _rl_output_character_function); 2159#endif 2160 _rl_last_c_pos = 0; 2161#if defined (__MSDOS__) 2162 space_to_eol (_rl_screenwidth); 2163 putc ('\r', rl_outstream); 2164#else 2165 if (_rl_term_clreol) 2166 tputs (_rl_term_clreol, 1, _rl_output_character_function); 2167 else 2168 { 2169 space_to_eol (_rl_screenwidth); 2170 tputs (_rl_term_cr, 1, _rl_output_character_function); 2171 } 2172#endif 2173 if (_rl_last_v_pos > 0) 2174 _rl_move_vert (0); 2175 } 2176 else 2177 rl_crlf (); 2178 2179 /* Redraw only the last line of a multi-line prompt. */ 2180 t = strrchr (rl_display_prompt, '\n'); 2181 if (t) 2182 redraw_prompt (++t); 2183 else 2184 rl_forced_update_display (); 2185} 2186 2187void 2188_rl_clean_up_for_exit () 2189{ 2190 if (readline_echoing_p) 2191 { 2192 _rl_move_vert (_rl_vis_botlin); 2193 _rl_vis_botlin = 0; 2194 fflush (rl_outstream); 2195 rl_restart_output (1, 0); 2196 } 2197} 2198 2199void 2200_rl_erase_entire_line () 2201{ 2202 cr (); 2203 _rl_clear_to_eol (0); 2204 cr (); 2205 fflush (rl_outstream); 2206} 2207 2208/* return the `current display line' of the cursor -- the number of lines to 2209 move up to get to the first screen line of the current readline line. */ 2210int 2211_rl_current_display_line () 2212{ 2213 int ret, nleft; 2214 2215 /* Find out whether or not there might be invisible characters in the 2216 editing buffer. */ 2217 if (rl_display_prompt == rl_prompt) 2218 nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length; 2219 else 2220 nleft = _rl_last_c_pos - _rl_screenwidth; 2221 2222 if (nleft > 0) 2223 ret = 1 + nleft / _rl_screenwidth; 2224 else 2225 ret = 0; 2226 2227 return ret; 2228} 2229 2230#if defined (HANDLE_MULTIBYTE) 2231/* Calculate the number of screen columns occupied by STR from START to END. 2232 In the case of multibyte characters with stateful encoding, we have to 2233 scan from the beginning of the string to take the state into account. */ 2234static int 2235_rl_col_width (str, start, end) 2236 const char *str; 2237 int start, end; 2238{ 2239 wchar_t wc; 2240 mbstate_t ps = {0}; 2241 int tmp, point, width, max; 2242 2243 if (end <= start) 2244 return 0; 2245 2246 point = 0; 2247 max = end; 2248 2249 while (point < start) 2250 { 2251 tmp = mbrlen (str + point, max, &ps); 2252 if (MB_INVALIDCH ((size_t)tmp)) 2253 { 2254 /* In this case, the bytes are invalid or too short to compose a 2255 multibyte character, so we assume that the first byte represents 2256 a single character. */ 2257 point++; 2258 max--; 2259 2260 /* Clear the state of the byte sequence, because in this case the 2261 effect of mbstate is undefined. */ 2262 memset (&ps, 0, sizeof (mbstate_t)); 2263 } 2264 else if (MB_NULLWCH (tmp)) 2265 break; /* Found '\0' */ 2266 else 2267 { 2268 point += tmp; 2269 max -= tmp; 2270 } 2271 } 2272 2273 /* If START is not a byte that starts a character, then POINT will be 2274 greater than START. In this case, assume that (POINT - START) gives 2275 a byte count that is the number of columns of difference. */ 2276 width = point - start; 2277 2278 while (point < end) 2279 { 2280 tmp = mbrtowc (&wc, str + point, max, &ps); 2281 if (MB_INVALIDCH ((size_t)tmp)) 2282 { 2283 /* In this case, the bytes are invalid or too short to compose a 2284 multibyte character, so we assume that the first byte represents 2285 a single character. */ 2286 point++; 2287 max--; 2288 2289 /* and assume that the byte occupies a single column. */ 2290 width++; 2291 2292 /* Clear the state of the byte sequence, because in this case the 2293 effect of mbstate is undefined. */ 2294 memset (&ps, 0, sizeof (mbstate_t)); 2295 } 2296 else if (MB_NULLWCH (tmp)) 2297 break; /* Found '\0' */ 2298 else 2299 { 2300 point += tmp; 2301 max -= tmp; 2302 tmp = wcwidth(wc); 2303 width += (tmp >= 0) ? tmp : 1; 2304 } 2305 } 2306 2307 width += point - end; 2308 2309 return width; 2310} 2311#endif /* HANDLE_MULTIBYTE */ 2312