00001 /* display.c -- readline redisplay facility. */ 00002 00003 /* Copyright (C) 1987-2004 Free Software Foundation, Inc. 00004 00005 This file is part of the GNU Readline Library, a library for 00006 reading lines of text with interactive input and history editing. 00007 00008 The GNU Readline Library is free software; you can redistribute it 00009 and/or modify it under the terms of the GNU General Public License 00010 as published by the Free Software Foundation; either version 2, or 00011 (at your option) any later version. 00012 00013 The GNU Readline Library is distributed in the hope that it will be 00014 useful, but WITHOUT ANY WARRANTY; without even the implied warranty 00015 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 The GNU General Public License is often shipped with GNU software, and 00019 is generally kept in a file called COPYING or LICENSE. If you do not 00020 have a copy of the license, write to the Free Software Foundation, 00021 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ 00022 #define READLINE_LIBRARY 00023 00024 #ifndef _XOPEN_SOURCE 00025 #define _XOPEN_SOURCE 500 00026 #endif 00027 00028 #include "config_readline.h" 00029 00030 #include <sys/types.h> 00031 00032 /* To get SuSE 9.3 to define wcwidth() (in wchar.h) */ 00033 00034 #if defined (HAVE_UNISTD_H) 00035 # include <unistd.h> 00036 #endif /* HAVE_UNISTD_H */ 00037 00038 #include "posixstat.h" 00039 00040 #if defined (HAVE_STDLIB_H) 00041 # include <stdlib.h> 00042 #else 00043 # include "ansi_stdlib.h" 00044 #endif /* HAVE_STDLIB_H */ 00045 00046 #include <stdio.h> 00047 00048 /* System-specific feature definitions and include files. */ 00049 #include "rldefs.h" 00050 #include "rlmbutil.h" 00051 00052 /* Termcap library stuff. */ 00053 #include "tcap.h" 00054 00055 /* Some standard library routines. */ 00056 #include "readline.h" 00057 #include "history.h" 00058 00059 #include "rlprivate.h" 00060 #include "xmalloc.h" 00061 00062 #if !defined (strchr) && !defined (__STDC__) 00063 extern char *strchr (), *strrchr (); 00064 #endif /* !strchr && !__STDC__ */ 00065 00066 #if defined (HACK_TERMCAP_MOTION) 00067 extern char *_rl_term_forward_char; 00068 #endif 00069 00070 static void update_line PARAMS((char *, char *, int, int, int, int)); 00071 static void space_to_eol PARAMS((int)); 00072 static void delete_chars PARAMS((int)); 00073 static void insert_some_chars PARAMS((char *, int, int)); 00074 static void cr PARAMS((void)); 00075 00076 #if defined (HANDLE_MULTIBYTE) 00077 static int _rl_col_width PARAMS((const char *, int, int)); 00078 static int *_rl_wrapped_line; 00079 #else 00080 # define _rl_col_width(l, s, e) (((e) <= (s)) ? 0 : (e) - (s)) 00081 #endif 00082 00083 static int *inv_lbreaks, *vis_lbreaks; 00084 static int inv_lbsize, vis_lbsize; 00085 00086 /* Heuristic used to decide whether it is faster to move from CUR to NEW 00087 by backing up or outputting a carriage return and moving forward. */ 00088 #define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new))) 00089 00090 /* **************************************************************** */ 00091 /* */ 00092 /* Display stuff */ 00093 /* */ 00094 /* **************************************************************** */ 00095 00096 /* This is the stuff that is hard for me. I never seem to write good 00097 display routines in C. Let's see how I do this time. */ 00098 00099 /* (PWP) Well... Good for a simple line updater, but totally ignores 00100 the problems of input lines longer than the screen width. 00101 00102 update_line and the code that calls it makes a multiple line, 00103 automatically wrapping line update. Careful attention needs 00104 to be paid to the vertical position variables. */ 00105 00106 /* Keep two buffers; one which reflects the current contents of the 00107 screen, and the other to draw what we think the new contents should 00108 be. Then compare the buffers, and make whatever changes to the 00109 screen itself that we should. Finally, make the buffer that we 00110 just drew into be the one which reflects the current contents of the 00111 screen, and place the cursor where it belongs. 00112 00113 Commands that want to can fix the display themselves, and then let 00114 this function know that the display has been fixed by setting the 00115 RL_DISPLAY_FIXED variable. This is good for efficiency. */ 00116 00117 /* Application-specific redisplay function. */ 00118 rl_voidfunc_t *rl_redisplay_function = rl_redisplay; 00119 00120 /* Global variables declared here. */ 00121 /* What YOU turn on when you have handled all redisplay yourself. */ 00122 int rl_display_fixed = 0; 00123 00124 int _rl_suppress_redisplay = 0; 00125 00126 /* The stuff that gets printed out before the actual text of the line. 00127 This is usually pointing to rl_prompt. */ 00128 char *rl_display_prompt = (char *)NULL; 00129 00130 /* Pseudo-global variables declared here. */ 00131 /* The visible cursor position. If you print some text, adjust this. */ 00132 int _rl_last_c_pos = 0; 00133 int _rl_last_v_pos = 0; 00134 00135 /* Number of lines currently on screen minus 1. */ 00136 int _rl_vis_botlin = 0; 00137 00138 /* Variables used only in this file. */ 00139 /* The last left edge of text that was displayed. This is used when 00140 doing horizontal scrolling. It shifts in thirds of a screenwidth. */ 00141 static int last_lmargin; 00142 00143 /* The line display buffers. One is the line currently displayed on 00144 the screen. The other is the line about to be displayed. */ 00145 static char *visible_line = (char *)NULL; 00146 static char *invisible_line = (char *)NULL; 00147 00148 /* A buffer for `modeline' messages. */ 00149 static char msg_buf[128]; 00150 00151 /* Non-zero forces the redisplay even if we thought it was unnecessary. */ 00152 static int forced_display; 00153 00154 /* Default and initial buffer size. Can grow. */ 00155 static int line_size = 1024; 00156 00157 /* Variables to keep track of the expanded prompt string, which may 00158 include invisible characters. */ 00159 00160 static char *local_prompt, *local_prompt_prefix; 00161 static int prompt_visible_length, prompt_prefix_length; 00162 00163 /* The number of invisible characters in the line currently being 00164 displayed on the screen. */ 00165 static int visible_wrap_offset; 00166 00167 /* The number of invisible characters in the prompt string. Static so it 00168 can be shared between rl_redisplay and update_line */ 00169 static int wrap_offset; 00170 00171 /* The index of the last invisible character in the prompt string. */ 00172 static int prompt_last_invisible; 00173 00174 /* The length (buffer offset) of the first line of the last (possibly 00175 multi-line) buffer displayed on the screen. */ 00176 static int visible_first_line_len; 00177 00178 /* Number of invisible characters on the first physical line of the prompt. 00179 Only valid when the number of physical characters in the prompt exceeds 00180 (or is equal to) _rl_screenwidth. */ 00181 static int prompt_invis_chars_first_line; 00182 00183 static int prompt_last_screen_line; 00184 00185 static int prompt_physical_chars; 00186 00187 /* Expand the prompt string S and return the number of visible 00188 characters in *LP, if LP is not null. This is currently more-or-less 00189 a placeholder for expansion. LIP, if non-null is a place to store the 00190 index of the last invisible character in the returned string. NIFLP, 00191 if non-zero, is a place to store the number of invisible characters in 00192 the first prompt line. The previous are used as byte counts -- indexes 00193 into a character buffer. */ 00194 00195 /* Current implementation: 00196 \001 (^A) start non-visible characters 00197 \002 (^B) end non-visible characters 00198 all characters except \001 and \002 (following a \001) are copied to 00199 the returned string; all characters except those between \001 and 00200 \002 are assumed to be `visible'. */ 00201 00202 static char * 00203 expand_prompt (pmt, lp, lip, niflp, vlp) 00204 char *pmt; 00205 int *lp, *lip, *niflp, *vlp; 00206 { 00207 char *r, *ret, *p; 00208 int l, rl, last, ignoring, ninvis, invfl, ind, pind, physchars; 00209 00210 /* Short-circuit if we can. */ 00211 if ((MB_CUR_MAX <= 1 || rl_byte_oriented) && strchr (pmt, RL_PROMPT_START_IGNORE) == 0) 00212 { 00213 r = savestring (pmt); 00214 if (lp) 00215 *lp = strlen (r); 00216 if (lip) 00217 *lip = 0; 00218 if (niflp) 00219 *niflp = 0; 00220 if (vlp) 00221 *vlp = lp ? *lp : strlen (r); 00222 return r; 00223 } 00224 00225 l = strlen (pmt); 00226 r = ret = (char *)xmalloc (l + 1); 00227 00228 invfl = 0; /* invisible chars in first line of prompt */ 00229 00230 for (rl = ignoring = last = ninvis = physchars = 0, p = pmt; p && *p; p++) 00231 { 00232 /* This code strips the invisible character string markers 00233 RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */ 00234 if (*p == RL_PROMPT_START_IGNORE) 00235 { 00236 ignoring++; 00237 continue; 00238 } 00239 else if (ignoring && *p == RL_PROMPT_END_IGNORE) 00240 { 00241 ignoring = 0; 00242 last = r - ret - 1; 00243 continue; 00244 } 00245 else 00246 { 00247 #if defined (HANDLE_MULTIBYTE) 00248 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 00249 { 00250 pind = p - pmt; 00251 ind = _rl_find_next_mbchar (pmt, pind, 1, MB_FIND_NONZERO); 00252 l = ind - pind; 00253 while (l--) 00254 *r++ = *p++; 00255 if (!ignoring) 00256 rl += ind - pind; 00257 else 00258 ninvis += ind - pind; 00259 p--; /* compensate for later increment */ 00260 } 00261 else 00262 #endif 00263 { 00264 *r++ = *p; 00265 if (!ignoring) 00266 rl++; /* visible length byte counter */ 00267 else 00268 ninvis++; /* invisible chars byte counter */ 00269 } 00270 00271 if (rl >= _rl_screenwidth) 00272 invfl = ninvis; 00273 00274 if (ignoring == 0) 00275 physchars++; 00276 } 00277 } 00278 00279 if (rl < _rl_screenwidth) 00280 invfl = ninvis; 00281 00282 *r = '\0'; 00283 if (lp) 00284 *lp = rl; 00285 if (lip) 00286 *lip = last; 00287 if (niflp) 00288 *niflp = invfl; 00289 if (vlp) 00290 *vlp = physchars; 00291 return ret; 00292 } 00293 00294 /* Just strip out RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE from 00295 PMT and return the rest of PMT. */ 00296 char * 00297 _rl_strip_prompt (pmt) 00298 char *pmt; 00299 { 00300 char *ret; 00301 00302 ret = expand_prompt (pmt, (int *)NULL, (int *)NULL, (int *)NULL, (int *)NULL); 00303 return ret; 00304 } 00305 00306 /* 00307 * Expand the prompt string into the various display components, if 00308 * necessary. 00309 * 00310 * local_prompt = expanded last line of string in rl_display_prompt 00311 * (portion after the final newline) 00312 * local_prompt_prefix = portion before last newline of rl_display_prompt, 00313 * expanded via expand_prompt 00314 * prompt_visible_length = number of visible characters in local_prompt 00315 * prompt_prefix_length = number of visible characters in local_prompt_prefix 00316 * 00317 * This function is called once per call to readline(). It may also be 00318 * called arbitrarily to expand the primary prompt. 00319 * 00320 * The return value is the number of visible characters on the last line 00321 * of the (possibly multi-line) prompt. 00322 */ 00323 int 00324 rl_expand_prompt (prompt) 00325 char *prompt; 00326 { 00327 char *p, *t; 00328 int c; 00329 00330 /* Clear out any saved values. */ 00331 FREE (local_prompt); 00332 FREE (local_prompt_prefix); 00333 00334 local_prompt = local_prompt_prefix = (char *)0; 00335 prompt_last_invisible = prompt_visible_length = 0; 00336 00337 if (prompt == 0 || *prompt == 0) 00338 return (0); 00339 00340 p = strrchr (prompt, '\n'); 00341 if (!p) 00342 { 00343 /* The prompt is only one logical line, though it might wrap. */ 00344 local_prompt = expand_prompt (prompt, &prompt_visible_length, 00345 &prompt_last_invisible, 00346 &prompt_invis_chars_first_line, 00347 &prompt_physical_chars); 00348 local_prompt_prefix = (char *)0; 00349 return (prompt_visible_length); 00350 } 00351 else 00352 { 00353 /* The prompt spans multiple lines. */ 00354 t = ++p; 00355 local_prompt = expand_prompt (p, &prompt_visible_length, 00356 &prompt_last_invisible, 00357 (int *)NULL, 00358 (int *)NULL); 00359 c = *t; *t = '\0'; 00360 /* The portion of the prompt string up to and including the 00361 final newline is now null-terminated. */ 00362 local_prompt_prefix = expand_prompt (prompt, &prompt_prefix_length, 00363 (int *)NULL, 00364 &prompt_invis_chars_first_line, 00365 &prompt_physical_chars); 00366 *t = c; 00367 return (prompt_prefix_length); 00368 } 00369 } 00370 00371 /* Initialize the VISIBLE_LINE and INVISIBLE_LINE arrays, and their associated 00372 arrays of line break markers. MINSIZE is the minimum size of VISIBLE_LINE 00373 and INVISIBLE_LINE; if it is greater than LINE_SIZE, LINE_SIZE is 00374 increased. If the lines have already been allocated, this ensures that 00375 they can hold at least MINSIZE characters. */ 00376 static void 00377 init_line_structures (minsize) 00378 int minsize; 00379 { 00380 register int n; 00381 00382 if (invisible_line == 0) /* initialize it */ 00383 { 00384 if (line_size < minsize) 00385 line_size = minsize; 00386 visible_line = (char *)xmalloc (line_size); 00387 invisible_line = (char *)xmalloc (line_size); 00388 } 00389 else if (line_size < minsize) /* ensure it can hold MINSIZE chars */ 00390 { 00391 line_size *= 2; 00392 if (line_size < minsize) 00393 line_size = minsize; 00394 visible_line = (char *)xrealloc (visible_line, line_size); 00395 invisible_line = (char *)xrealloc (invisible_line, line_size); 00396 } 00397 00398 for (n = minsize; n < line_size; n++) 00399 { 00400 visible_line[n] = 0; 00401 invisible_line[n] = 1; 00402 } 00403 00404 if (vis_lbreaks == 0) 00405 { 00406 /* should be enough. */ 00407 inv_lbsize = vis_lbsize = 256; 00408 inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int)); 00409 vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int)); 00410 #if defined (HANDLE_MULTIBYTE) 00411 _rl_wrapped_line = (int *)xmalloc (vis_lbsize * sizeof (int)); 00412 #endif 00413 inv_lbreaks[0] = vis_lbreaks[0] = 0; 00414 } 00415 } 00416 00417 /* Basic redisplay algorithm. */ 00418 void 00419 rl_redisplay () 00420 { 00421 register int in, out, c, linenum, cursor_linenum; 00422 register char *line; 00423 int c_pos, inv_botlin, lb_botlin, lb_linenum; 00424 int newlines, lpos, temp, modmark; 00425 char *prompt_this_line; 00426 #if defined (HANDLE_MULTIBYTE) 00427 wchar_t wc; 00428 size_t wc_bytes; 00429 int wc_width; 00430 mbstate_t ps; 00431 int _rl_wrapped_multicolumn = 0; 00432 #endif 00433 00434 if (!readline_echoing_p) 00435 return; 00436 00437 if (!rl_display_prompt) 00438 rl_display_prompt = ""; 00439 00440 if (invisible_line == 0) 00441 { 00442 init_line_structures (0); 00443 rl_on_new_line (); 00444 } 00445 00446 /* Draw the line into the buffer. */ 00447 c_pos = -1; 00448 00449 line = invisible_line; 00450 out = inv_botlin = 0; 00451 00452 /* Mark the line as modified or not. We only do this for history 00453 lines. */ 00454 modmark = 0; 00455 if (_rl_mark_modified_lines && current_history () && rl_undo_list) 00456 { 00457 line[out++] = '*'; 00458 line[out] = '\0'; 00459 modmark = 1; 00460 } 00461 00462 /* If someone thought that the redisplay was handled, but the currently 00463 visible line has a different modification state than the one about 00464 to become visible, then correct the caller's misconception. */ 00465 if (visible_line[0] != invisible_line[0]) 00466 rl_display_fixed = 0; 00467 00468 /* If the prompt to be displayed is the `primary' readline prompt (the 00469 one passed to readline()), use the values we have already expanded. 00470 If not, use what's already in rl_display_prompt. WRAP_OFFSET is the 00471 number of non-visible characters in the prompt string. */ 00472 if (rl_display_prompt == rl_prompt || local_prompt) 00473 { 00474 int local_len = local_prompt ? strlen (local_prompt) : 0; 00475 if (local_prompt_prefix && forced_display) 00476 _rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix)); 00477 00478 if (local_len > 0) 00479 { 00480 temp = local_len + out + 2; 00481 if (temp >= line_size) 00482 { 00483 line_size = (temp + 1024) - (temp % 1024); 00484 visible_line = (char *)xrealloc (visible_line, line_size); 00485 line = invisible_line = (char *)xrealloc (invisible_line, line_size); 00486 } 00487 strncpy (line + out, local_prompt, local_len); 00488 out += local_len; 00489 } 00490 line[out] = '\0'; 00491 wrap_offset = local_len - prompt_visible_length; 00492 } 00493 else 00494 { 00495 int pmtlen; 00496 prompt_this_line = strrchr (rl_display_prompt, '\n'); 00497 if (!prompt_this_line) 00498 prompt_this_line = rl_display_prompt; 00499 else 00500 { 00501 prompt_this_line++; 00502 pmtlen = prompt_this_line - rl_display_prompt; /* temp var */ 00503 if (forced_display) 00504 { 00505 _rl_output_some_chars (rl_display_prompt, pmtlen); 00506 /* Make sure we are at column zero even after a newline, 00507 regardless of the state of terminal output processing. */ 00508 if (pmtlen < 2 || prompt_this_line[-2] != '\r') 00509 cr (); 00510 } 00511 } 00512 00513 prompt_physical_chars = pmtlen = strlen (prompt_this_line); 00514 temp = pmtlen + out + 2; 00515 if (temp >= line_size) 00516 { 00517 line_size = (temp + 1024) - (temp % 1024); 00518 visible_line = (char *)xrealloc (visible_line, line_size); 00519 line = invisible_line = (char *)xrealloc (invisible_line, line_size); 00520 } 00521 strncpy (line + out, prompt_this_line, pmtlen); 00522 out += pmtlen; 00523 line[out] = '\0'; 00524 wrap_offset = prompt_invis_chars_first_line = 0; 00525 } 00526 00527 #define CHECK_INV_LBREAKS() \ 00528 do { \ 00529 if (newlines >= (inv_lbsize - 2)) \ 00530 { \ 00531 inv_lbsize *= 2; \ 00532 inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \ 00533 } \ 00534 } while (0) 00535 00536 #if defined (HANDLE_MULTIBYTE) 00537 #define CHECK_LPOS() \ 00538 do { \ 00539 lpos++; \ 00540 if (lpos >= _rl_screenwidth) \ 00541 { \ 00542 if (newlines >= (inv_lbsize - 2)) \ 00543 { \ 00544 inv_lbsize *= 2; \ 00545 inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \ 00546 _rl_wrapped_line = (int *)xrealloc (_rl_wrapped_line, inv_lbsize * sizeof (int)); \ 00547 } \ 00548 inv_lbreaks[++newlines] = out; \ 00549 _rl_wrapped_line[newlines] = _rl_wrapped_multicolumn; \ 00550 lpos = 0; \ 00551 } \ 00552 } while (0) 00553 #else 00554 #define CHECK_LPOS() \ 00555 do { \ 00556 lpos++; \ 00557 if (lpos >= _rl_screenwidth) \ 00558 { \ 00559 if (newlines >= (inv_lbsize - 2)) \ 00560 { \ 00561 inv_lbsize *= 2; \ 00562 inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \ 00563 } \ 00564 inv_lbreaks[++newlines] = out; \ 00565 lpos = 0; \ 00566 } \ 00567 } while (0) 00568 #endif 00569 00570 /* inv_lbreaks[i] is where line i starts in the buffer. */ 00571 inv_lbreaks[newlines = 0] = 0; 00572 #if 0 00573 lpos = out - wrap_offset; 00574 #else 00575 lpos = prompt_physical_chars + modmark; 00576 #endif 00577 00578 #if defined (HANDLE_MULTIBYTE) 00579 memset (_rl_wrapped_line, 0, vis_lbsize); 00580 #endif 00581 00582 /* prompt_invis_chars_first_line is the number of invisible characters in 00583 the first physical line of the prompt. 00584 wrap_offset - prompt_invis_chars_first_line is the number of invis 00585 chars on the second line. */ 00586 00587 /* what if lpos is already >= _rl_screenwidth before we start drawing the 00588 contents of the command line? */ 00589 while (lpos >= _rl_screenwidth) 00590 { 00591 /* fix from Darin Johnson <darin@acuson.com> for prompt string with 00592 invisible characters that is longer than the screen width. The 00593 prompt_invis_chars_first_line variable could be made into an array 00594 saying how many invisible characters there are per line, but that's 00595 probably too much work for the benefit gained. How many people have 00596 prompts that exceed two physical lines? 00597 Additional logic fix from Edward Catmur <ed@catmur.co.uk> */ 00598 temp = ((newlines + 1) * _rl_screenwidth) + 00599 ((local_prompt_prefix == 0) ? ((newlines == 0) ? prompt_invis_chars_first_line 00600 : ((newlines == 1) ? wrap_offset : 0)) 00601 : ((newlines == 0) ? wrap_offset :0)); 00602 00603 inv_lbreaks[++newlines] = temp; 00604 lpos -= _rl_screenwidth; 00605 } 00606 00607 prompt_last_screen_line = newlines; 00608 00609 /* Draw the rest of the line (after the prompt) into invisible_line, keeping 00610 track of where the cursor is (c_pos), the number of the line containing 00611 the cursor (lb_linenum), the last line number (lb_botlin and inv_botlin). 00612 It maintains an array of line breaks for display (inv_lbreaks). 00613 This handles expanding tabs for display and displaying meta characters. */ 00614 lb_linenum = 0; 00615 #if defined (HANDLE_MULTIBYTE) 00616 in = 0; 00617 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 00618 { 00619 memset (&ps, 0, sizeof (mbstate_t)); 00620 wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps); 00621 } 00622 else 00623 wc_bytes = 1; 00624 while (in < rl_end) 00625 #else 00626 for (in = 0; in < rl_end; in++) 00627 #endif 00628 { 00629 c = (unsigned char)rl_line_buffer[in]; 00630 00631 #if defined (HANDLE_MULTIBYTE) 00632 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 00633 { 00634 if (MB_INVALIDCH (wc_bytes)) 00635 { 00636 /* Byte sequence is invalid or shortened. Assume that the 00637 first byte represents a character. */ 00638 wc_bytes = 1; 00639 /* Assume that a character occupies a single column. */ 00640 wc_width = 1; 00641 memset (&ps, 0, sizeof (mbstate_t)); 00642 } 00643 else if (MB_NULLWCH (wc_bytes)) 00644 break; /* Found '\0' */ 00645 else 00646 { 00647 temp = wcwidth (wc); 00648 wc_width = (temp >= 0) ? temp : 1; 00649 } 00650 } 00651 #endif 00652 00653 if (out + 8 >= line_size) /* XXX - 8 for \t */ 00654 { 00655 line_size *= 2; 00656 visible_line = (char *)xrealloc (visible_line, line_size); 00657 invisible_line = (char *)xrealloc (invisible_line, line_size); 00658 line = invisible_line; 00659 } 00660 00661 if (in == rl_point) 00662 { 00663 c_pos = out; 00664 lb_linenum = newlines; 00665 } 00666 00667 #if defined (HANDLE_MULTIBYTE) 00668 if (META_CHAR (c) && _rl_output_meta_chars == 0) /* XXX - clean up */ 00669 #else 00670 if (META_CHAR (c)) 00671 #endif 00672 { 00673 if (_rl_output_meta_chars == 0) 00674 { 00675 sprintf (line + out, "\\%o", c); 00676 00677 if (lpos + 4 >= _rl_screenwidth) 00678 { 00679 temp = _rl_screenwidth - lpos; 00680 CHECK_INV_LBREAKS (); 00681 inv_lbreaks[++newlines] = out + temp; 00682 lpos = 4 - temp; 00683 } 00684 else 00685 lpos += 4; 00686 00687 out += 4; 00688 } 00689 else 00690 { 00691 line[out++] = c; 00692 CHECK_LPOS(); 00693 } 00694 } 00695 #if defined (DISPLAY_TABS) 00696 else if (c == '\t') 00697 { 00698 register int newout; 00699 00700 #if 0 00701 newout = (out | (int)7) + 1; 00702 #else 00703 newout = out + 8 - lpos % 8; 00704 #endif 00705 temp = newout - out; 00706 if (lpos + temp >= _rl_screenwidth) 00707 { 00708 register int temp2; 00709 temp2 = _rl_screenwidth - lpos; 00710 CHECK_INV_LBREAKS (); 00711 inv_lbreaks[++newlines] = out + temp2; 00712 lpos = temp - temp2; 00713 while (out < newout) 00714 line[out++] = ' '; 00715 } 00716 else 00717 { 00718 while (out < newout) 00719 line[out++] = ' '; 00720 lpos += temp; 00721 } 00722 } 00723 #endif 00724 else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up) 00725 { 00726 line[out++] = '\0'; /* XXX - sentinel */ 00727 CHECK_INV_LBREAKS (); 00728 inv_lbreaks[++newlines] = out; 00729 lpos = 0; 00730 } 00731 else if (CTRL_CHAR (c) || c == RUBOUT) 00732 { 00733 line[out++] = '^'; 00734 CHECK_LPOS(); 00735 line[out++] = CTRL_CHAR (c) ? UNCTRL (c) : '?'; 00736 CHECK_LPOS(); 00737 } 00738 else 00739 { 00740 #if defined (HANDLE_MULTIBYTE) 00741 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 00742 { 00743 register int i; 00744 00745 _rl_wrapped_multicolumn = 0; 00746 00747 if (_rl_screenwidth < lpos + wc_width) 00748 for (i = lpos; i < _rl_screenwidth; i++) 00749 { 00750 /* The space will be removed in update_line() */ 00751 line[out++] = ' '; 00752 _rl_wrapped_multicolumn++; 00753 CHECK_LPOS(); 00754 } 00755 if (in == rl_point) 00756 { 00757 c_pos = out; 00758 lb_linenum = newlines; 00759 } 00760 for (i = in; i < in+wc_bytes; i++) 00761 line[out++] = rl_line_buffer[i]; 00762 for (i = 0; i < wc_width; i++) 00763 CHECK_LPOS(); 00764 } 00765 else 00766 { 00767 line[out++] = c; 00768 CHECK_LPOS(); 00769 } 00770 #else 00771 line[out++] = c; 00772 CHECK_LPOS(); 00773 #endif 00774 } 00775 00776 #if defined (HANDLE_MULTIBYTE) 00777 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 00778 { 00779 in += wc_bytes; 00780 wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps); 00781 } 00782 else 00783 in++; 00784 #endif 00785 00786 } 00787 line[out] = '\0'; 00788 if (c_pos < 0) 00789 { 00790 c_pos = out; 00791 lb_linenum = newlines; 00792 } 00793 00794 inv_botlin = lb_botlin = newlines; 00795 CHECK_INV_LBREAKS (); 00796 inv_lbreaks[newlines+1] = out; 00797 cursor_linenum = lb_linenum; 00798 00799 /* C_POS == position in buffer where cursor should be placed. 00800 CURSOR_LINENUM == line number where the cursor should be placed. */ 00801 00802 /* PWP: now is when things get a bit hairy. The visible and invisible 00803 line buffers are really multiple lines, which would wrap every 00804 (screenwidth - 1) characters. Go through each in turn, finding 00805 the changed region and updating it. The line order is top to bottom. */ 00806 00807 /* If we can move the cursor up and down, then use multiple lines, 00808 otherwise, let long lines display in a single terminal line, and 00809 horizontally scroll it. */ 00810 00811 if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up) 00812 { 00813 int nleft, pos, changed_screen_line; 00814 00815 if (!rl_display_fixed || forced_display) 00816 { 00817 forced_display = 0; 00818 00819 /* If we have more than a screenful of material to display, then 00820 only display a screenful. We should display the last screen, 00821 not the first. */ 00822 if (out >= _rl_screenchars) 00823 { 00824 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 00825 out = _rl_find_prev_mbchar (line, _rl_screenchars, MB_FIND_ANY); 00826 else 00827 out = _rl_screenchars - 1; 00828 } 00829 00830 /* The first line is at character position 0 in the buffer. The 00831 second and subsequent lines start at inv_lbreaks[N], offset by 00832 OFFSET (which has already been calculated above). */ 00833 00834 #define W_OFFSET(line, offset) ((line) == 0 ? offset : 0) 00835 #define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l])) 00836 #define INV_LLEN(l) (inv_lbreaks[l+1] - inv_lbreaks[l]) 00837 #define VIS_CHARS(line) (visible_line + vis_lbreaks[line]) 00838 #define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line) 00839 #define INV_LINE(line) (invisible_line + inv_lbreaks[line]) 00840 00841 /* For each line in the buffer, do the updating display. */ 00842 for (linenum = 0; linenum <= inv_botlin; linenum++) 00843 { 00844 update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum, 00845 VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin); 00846 00847 /* If this is the line with the prompt, we might need to 00848 compensate for invisible characters in the new line. Do 00849 this only if there is not more than one new line (which 00850 implies that we completely overwrite the old visible line) 00851 and the new line is shorter than the old. Make sure we are 00852 at the end of the new line before clearing. */ 00853 if (linenum == 0 && 00854 inv_botlin == 0 && _rl_last_c_pos == out && 00855 (wrap_offset > visible_wrap_offset) && 00856 (_rl_last_c_pos < visible_first_line_len)) 00857 { 00858 nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos; 00859 if (nleft) 00860 _rl_clear_to_eol (nleft); 00861 } 00862 00863 /* Since the new first line is now visible, save its length. */ 00864 if (linenum == 0) 00865 visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset; 00866 } 00867 00868 /* We may have deleted some lines. If so, clear the left over 00869 blank ones at the bottom out. */ 00870 if (_rl_vis_botlin > inv_botlin) 00871 { 00872 char *tt; 00873 for (; linenum <= _rl_vis_botlin; linenum++) 00874 { 00875 tt = VIS_CHARS (linenum); 00876 _rl_move_vert (linenum); 00877 _rl_move_cursor_relative (0, tt); 00878 _rl_clear_to_eol 00879 ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth); 00880 } 00881 } 00882 _rl_vis_botlin = inv_botlin; 00883 00884 /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a 00885 different screen line during this redisplay. */ 00886 changed_screen_line = _rl_last_v_pos != cursor_linenum; 00887 if (changed_screen_line) 00888 { 00889 _rl_move_vert (cursor_linenum); 00890 /* If we moved up to the line with the prompt using _rl_term_up, 00891 the physical cursor position on the screen stays the same, 00892 but the buffer position needs to be adjusted to account 00893 for invisible characters. */ 00894 if (cursor_linenum == 0 && wrap_offset) 00895 _rl_last_c_pos += wrap_offset; 00896 } 00897 00898 /* We have to reprint the prompt if it contains invisible 00899 characters, since it's not generally OK to just reprint 00900 the characters from the current cursor position. But we 00901 only need to reprint it if the cursor is before the last 00902 invisible character in the prompt string. */ 00903 nleft = prompt_visible_length + wrap_offset; 00904 if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 && 00905 _rl_last_c_pos <= prompt_last_invisible && local_prompt) 00906 { 00907 #if defined (__MSDOS__) 00908 putc ('\r', rl_outstream); 00909 #else 00910 if (_rl_term_cr) 00911 tputs (_rl_term_cr, 1, _rl_output_character_function); 00912 #endif 00913 _rl_output_some_chars (local_prompt, nleft); 00914 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 00915 _rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft); 00916 else 00917 _rl_last_c_pos = nleft; 00918 } 00919 00920 /* Where on that line? And where does that line start 00921 in the buffer? */ 00922 pos = inv_lbreaks[cursor_linenum]; 00923 /* nleft == number of characters in the line buffer between the 00924 start of the line and the cursor position. */ 00925 nleft = c_pos - pos; 00926 00927 /* Since _rl_backspace() doesn't know about invisible characters in the 00928 prompt, and there's no good way to tell it, we compensate for 00929 those characters here and call _rl_backspace() directly. */ 00930 if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos) 00931 { 00932 _rl_backspace (_rl_last_c_pos - nleft); 00933 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 00934 _rl_last_c_pos = _rl_col_width (&visible_line[pos], 0, nleft); 00935 else 00936 _rl_last_c_pos = nleft; 00937 } 00938 00939 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 00940 _rl_move_cursor_relative (nleft, &invisible_line[pos]); 00941 else if (nleft != _rl_last_c_pos) 00942 _rl_move_cursor_relative (nleft, &invisible_line[pos]); 00943 } 00944 } 00945 else /* Do horizontal scrolling. */ 00946 { 00947 #define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0) 00948 int lmargin, ndisp, nleft, phys_c_pos, t; 00949 00950 /* Always at top line. */ 00951 _rl_last_v_pos = 0; 00952 00953 /* Compute where in the buffer the displayed line should start. This 00954 will be LMARGIN. */ 00955 00956 /* The number of characters that will be displayed before the cursor. */ 00957 ndisp = c_pos - wrap_offset; 00958 nleft = prompt_visible_length + wrap_offset; 00959 /* Where the new cursor position will be on the screen. This can be 00960 longer than SCREENWIDTH; if it is, lmargin will be adjusted. */ 00961 phys_c_pos = c_pos - (last_lmargin ? last_lmargin : wrap_offset); 00962 t = _rl_screenwidth / 3; 00963 00964 /* If the number of characters had already exceeded the screenwidth, 00965 last_lmargin will be > 0. */ 00966 00967 /* If the number of characters to be displayed is more than the screen 00968 width, compute the starting offset so that the cursor is about 00969 two-thirds of the way across the screen. */ 00970 if (phys_c_pos > _rl_screenwidth - 2) 00971 { 00972 lmargin = c_pos - (2 * t); 00973 if (lmargin < 0) 00974 lmargin = 0; 00975 /* If the left margin would be in the middle of a prompt with 00976 invisible characters, don't display the prompt at all. */ 00977 if (wrap_offset && lmargin > 0 && lmargin < nleft) 00978 lmargin = nleft; 00979 } 00980 else if (ndisp < _rl_screenwidth - 2) /* XXX - was -1 */ 00981 lmargin = 0; 00982 else if (phys_c_pos < 1) 00983 { 00984 /* If we are moving back towards the beginning of the line and 00985 the last margin is no longer correct, compute a new one. */ 00986 lmargin = ((c_pos - 1) / t) * t; /* XXX */ 00987 if (wrap_offset && lmargin > 0 && lmargin < nleft) 00988 lmargin = nleft; 00989 } 00990 else 00991 lmargin = last_lmargin; 00992 00993 /* If the first character on the screen isn't the first character 00994 in the display line, indicate this with a special character. */ 00995 if (lmargin > 0) 00996 line[lmargin] = '<'; 00997 00998 /* If SCREENWIDTH characters starting at LMARGIN do not encompass 00999 the whole line, indicate that with a special character at the 01000 right edge of the screen. If LMARGIN is 0, we need to take the 01001 wrap offset into account. */ 01002 t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth; 01003 if (t < out) 01004 line[t - 1] = '>'; 01005 01006 if (!rl_display_fixed || forced_display || lmargin != last_lmargin) 01007 { 01008 forced_display = 0; 01009 update_line (&visible_line[last_lmargin], 01010 &invisible_line[lmargin], 01011 0, 01012 _rl_screenwidth + visible_wrap_offset, 01013 _rl_screenwidth + (lmargin ? 0 : wrap_offset), 01014 0); 01015 01016 /* If the visible new line is shorter than the old, but the number 01017 of invisible characters is greater, and we are at the end of 01018 the new line, we need to clear to eol. */ 01019 t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset); 01020 if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) && 01021 (_rl_last_c_pos == out) && 01022 t < visible_first_line_len) 01023 { 01024 nleft = _rl_screenwidth - t; 01025 _rl_clear_to_eol (nleft); 01026 } 01027 visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset); 01028 if (visible_first_line_len > _rl_screenwidth) 01029 visible_first_line_len = _rl_screenwidth; 01030 01031 _rl_move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]); 01032 last_lmargin = lmargin; 01033 } 01034 } 01035 fflush (rl_outstream); 01036 01037 /* Swap visible and non-visible lines. */ 01038 { 01039 char *vtemp = visible_line; 01040 int *itemp = vis_lbreaks, ntemp = vis_lbsize; 01041 01042 visible_line = invisible_line; 01043 invisible_line = vtemp; 01044 01045 vis_lbreaks = inv_lbreaks; 01046 inv_lbreaks = itemp; 01047 01048 vis_lbsize = inv_lbsize; 01049 inv_lbsize = ntemp; 01050 01051 rl_display_fixed = 0; 01052 /* If we are displaying on a single line, and last_lmargin is > 0, we 01053 are not displaying any invisible characters, so set visible_wrap_offset 01054 to 0. */ 01055 if (_rl_horizontal_scroll_mode && last_lmargin) 01056 visible_wrap_offset = 0; 01057 else 01058 visible_wrap_offset = wrap_offset; 01059 } 01060 } 01061 01062 /* PWP: update_line() is based on finding the middle difference of each 01063 line on the screen; vis: 01064 01065 /old first difference 01066 /beginning of line | /old last same /old EOL 01067 v v v v 01068 old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as 01069 new: eddie> Oh, my little buggy says to me, as lurgid as 01070 ^ ^ ^ ^ 01071 \beginning of line | \new last same \new end of line 01072 \new first difference 01073 01074 All are character pointers for the sake of speed. Special cases for 01075 no differences, as well as for end of line additions must be handled. 01076 01077 Could be made even smarter, but this works well enough */ 01078 static void 01079 update_line (old, new, current_line, omax, nmax, inv_botlin) 01080 register char *old, *new; 01081 int current_line, omax, nmax, inv_botlin; 01082 { 01083 register char *ofd, *ols, *oe, *nfd, *nls, *ne; 01084 int temp, lendiff, wsatend, od, nd; 01085 int current_invis_chars; 01086 int col_lendiff, col_temp; 01087 #if defined (HANDLE_MULTIBYTE) 01088 mbstate_t ps_new, ps_old; 01089 int new_offset, old_offset, tmp; 01090 #endif 01091 01092 /* If we're at the right edge of a terminal that supports xn, we're 01093 ready to wrap around, so do so. This fixes problems with knowing 01094 the exact cursor position and cut-and-paste with certain terminal 01095 emulators. In this calculation, TEMP is the physical screen 01096 position of the cursor. */ 01097 temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset); 01098 if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode 01099 && _rl_last_v_pos == current_line - 1) 01100 { 01101 #if defined (HANDLE_MULTIBYTE) 01102 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 01103 { 01104 wchar_t wc; 01105 mbstate_t ps; 01106 int tempwidth, bytes; 01107 size_t ret; 01108 01109 /* This fixes only double-column characters, but if the wrapped 01110 character comsumes more than three columns, spaces will be 01111 inserted in the string buffer. */ 01112 if (_rl_wrapped_line[current_line] > 0) 01113 _rl_clear_to_eol (_rl_wrapped_line[current_line]); 01114 01115 memset (&ps, 0, sizeof (mbstate_t)); 01116 ret = mbrtowc (&wc, new, MB_CUR_MAX, &ps); 01117 if (MB_INVALIDCH (ret)) 01118 { 01119 tempwidth = 1; 01120 ret = 1; 01121 } 01122 else if (MB_NULLWCH (ret)) 01123 tempwidth = 0; 01124 else 01125 tempwidth = wcwidth (wc); 01126 01127 if (tempwidth > 0) 01128 { 01129 int count; 01130 bytes = ret; 01131 for (count = 0; count < bytes; count++) 01132 putc (new[count], rl_outstream); 01133 _rl_last_c_pos = tempwidth; 01134 _rl_last_v_pos++; 01135 memset (&ps, 0, sizeof (mbstate_t)); 01136 ret = mbrtowc (&wc, old, MB_CUR_MAX, &ps); 01137 if (ret != 0 && bytes != 0) 01138 { 01139 if (MB_INVALIDCH (ret)) 01140 memmove (old+bytes, old+1, strlen (old+1)); 01141 else 01142 memmove (old+bytes, old+ret, strlen (old+ret)); 01143 memcpy (old, new, bytes); 01144 } 01145 } 01146 else 01147 { 01148 putc (' ', rl_outstream); 01149 _rl_last_c_pos = 1; 01150 _rl_last_v_pos++; 01151 if (old[0] && new[0]) 01152 old[0] = new[0]; 01153 } 01154 } 01155 else 01156 #endif 01157 { 01158 if (new[0]) 01159 putc (new[0], rl_outstream); 01160 else 01161 putc (' ', rl_outstream); 01162 _rl_last_c_pos = 1; /* XXX */ 01163 _rl_last_v_pos++; 01164 if (old[0] && new[0]) 01165 old[0] = new[0]; 01166 } 01167 } 01168 01169 01170 /* Find first difference. */ 01171 #if defined (HANDLE_MULTIBYTE) 01172 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 01173 { 01174 /* See if the old line is a subset of the new line, so that the 01175 only change is adding characters. */ 01176 temp = (omax < nmax) ? omax : nmax; 01177 if (memcmp (old, new, temp) == 0) 01178 { 01179 ofd = old + temp; 01180 nfd = new + temp; 01181 } 01182 else 01183 { 01184 memset (&ps_new, 0, sizeof(mbstate_t)); 01185 memset (&ps_old, 0, sizeof(mbstate_t)); 01186 01187 if (omax == nmax && STREQN (new, old, omax)) 01188 { 01189 ofd = old + omax; 01190 nfd = new + nmax; 01191 } 01192 else 01193 { 01194 new_offset = old_offset = 0; 01195 for (ofd = old, nfd = new; 01196 (ofd - old < omax) && *ofd && 01197 _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new); ) 01198 { 01199 old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY); 01200 new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY); 01201 ofd = old + old_offset; 01202 nfd = new + new_offset; 01203 } 01204 } 01205 } 01206 } 01207 else 01208 #endif 01209 for (ofd = old, nfd = new; 01210 (ofd - old < omax) && *ofd && (*ofd == *nfd); 01211 ofd++, nfd++) 01212 ; 01213 01214 /* Move to the end of the screen line. ND and OD are used to keep track 01215 of the distance between ne and new and oe and old, respectively, to 01216 move a subtraction out of each loop. */ 01217 for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++); 01218 for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++); 01219 01220 /* If no difference, continue to next line. */ 01221 if (ofd == oe && nfd == ne) 01222 return; 01223 01224 wsatend = 1; /* flag for trailing whitespace */ 01225 01226 #if defined (HANDLE_MULTIBYTE) 01227 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 01228 { 01229 ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY); 01230 nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY); 01231 while ((ols > ofd) && (nls > nfd)) 01232 { 01233 memset (&ps_old, 0, sizeof (mbstate_t)); 01234 memset (&ps_new, 0, sizeof (mbstate_t)); 01235 01236 #if 0 01237 /* On advice from jir@yamato.ibm.com */ 01238 _rl_adjust_point (old, ols - old, &ps_old); 01239 _rl_adjust_point (new, nls - new, &ps_new); 01240 #endif 01241 01242 if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0) 01243 break; 01244 01245 if (*ols == ' ') 01246 wsatend = 0; 01247 01248 ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY); 01249 nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY); 01250 } 01251 } 01252 else 01253 { 01254 #endif /* HANDLE_MULTIBYTE */ 01255 ols = oe - 1; /* find last same */ 01256 nls = ne - 1; 01257 while ((ols > ofd) && (nls > nfd) && (*ols == *nls)) 01258 { 01259 if (*ols != ' ') 01260 wsatend = 0; 01261 ols--; 01262 nls--; 01263 } 01264 #if defined (HANDLE_MULTIBYTE) 01265 } 01266 #endif 01267 01268 if (wsatend) 01269 { 01270 ols = oe; 01271 nls = ne; 01272 } 01273 #if defined (HANDLE_MULTIBYTE) 01274 /* This may not work for stateful encoding, but who cares? To handle 01275 stateful encoding properly, we have to scan each string from the 01276 beginning and compare. */ 01277 else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0) 01278 #else 01279 else if (*ols != *nls) 01280 #endif 01281 { 01282 if (*ols) /* don't step past the NUL */ 01283 { 01284 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 01285 ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY); 01286 else 01287 ols++; 01288 } 01289 if (*nls) 01290 { 01291 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 01292 nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY); 01293 else 01294 nls++; 01295 } 01296 } 01297 01298 /* count of invisible characters in the current invisible line. */ 01299 current_invis_chars = W_OFFSET (current_line, wrap_offset); 01300 if (_rl_last_v_pos != current_line) 01301 { 01302 _rl_move_vert (current_line); 01303 if (current_line == 0 && visible_wrap_offset) 01304 _rl_last_c_pos += visible_wrap_offset; 01305 } 01306 01307 /* If this is the first line and there are invisible characters in the 01308 prompt string, and the prompt string has not changed, and the current 01309 cursor position is before the last invisible character in the prompt, 01310 and the index of the character to move to is past the end of the prompt 01311 string, then redraw the entire prompt string. We can only do this 01312 reliably if the terminal supports a `cr' capability. 01313 01314 This is not an efficiency hack -- there is a problem with redrawing 01315 portions of the prompt string if they contain terminal escape 01316 sequences (like drawing the `unbold' sequence without a corresponding 01317 `bold') that manifests itself on certain terminals. */ 01318 01319 lendiff = local_prompt ? strlen (local_prompt) : 0; 01320 od = ofd - old; /* index of first difference in visible line */ 01321 if (current_line == 0 && !_rl_horizontal_scroll_mode && 01322 _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 && 01323 od >= lendiff && _rl_last_c_pos <= prompt_last_invisible) 01324 { 01325 #if defined (__MSDOS__) 01326 putc ('\r', rl_outstream); 01327 #else 01328 tputs (_rl_term_cr, 1, _rl_output_character_function); 01329 #endif 01330 _rl_output_some_chars (local_prompt, lendiff); 01331 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 01332 _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff); 01333 else 01334 _rl_last_c_pos = lendiff; 01335 } 01336 01337 _rl_move_cursor_relative (od, old); 01338 01339 /* if (len (new) > len (old)) 01340 lendiff == difference in buffer 01341 col_lendiff == difference on screen 01342 When not using multibyte characters, these are equal */ 01343 lendiff = (nls - nfd) - (ols - ofd); 01344 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 01345 col_lendiff = _rl_col_width (new, nfd - new, nls - new) - _rl_col_width (old, ofd - old, ols - old); 01346 else 01347 col_lendiff = lendiff; 01348 01349 /* If we are changing the number of invisible characters in a line, and 01350 the spot of first difference is before the end of the invisible chars, 01351 lendiff needs to be adjusted. */ 01352 if (current_line == 0 && !_rl_horizontal_scroll_mode && 01353 current_invis_chars != visible_wrap_offset) 01354 { 01355 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 01356 { 01357 lendiff += visible_wrap_offset - current_invis_chars; 01358 col_lendiff += visible_wrap_offset - current_invis_chars; 01359 } 01360 else 01361 { 01362 lendiff += visible_wrap_offset - current_invis_chars; 01363 col_lendiff = lendiff; 01364 } 01365 } 01366 01367 /* Insert (diff (len (old), len (new)) ch. */ 01368 temp = ne - nfd; 01369 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 01370 col_temp = _rl_col_width (new, nfd - new, ne - new); 01371 else 01372 col_temp = temp; 01373 01374 if (col_lendiff > 0) /* XXX - was lendiff */ 01375 { 01376 /* Non-zero if we're increasing the number of lines. */ 01377 int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin; 01378 /* Sometimes it is cheaper to print the characters rather than 01379 use the terminal's capabilities. If we're growing the number 01380 of lines, make sure we actually cause the new line to wrap 01381 around on auto-wrapping terminals. */ 01382 if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl)) 01383 { 01384 /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and 01385 _rl_horizontal_scroll_mode == 1, inserting the characters with 01386 _rl_term_IC or _rl_term_ic will screw up the screen because of the 01387 invisible characters. We need to just draw them. */ 01388 if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 || 01389 lendiff <= prompt_visible_length || !current_invis_chars)) 01390 { 01391 insert_some_chars (nfd, lendiff, col_lendiff); 01392 _rl_last_c_pos += col_lendiff; 01393 } 01394 else if (*ols == 0 && lendiff > 0) 01395 { 01396 /* At the end of a line the characters do not have to 01397 be "inserted". They can just be placed on the screen. */ 01398 /* However, this screws up the rest of this block, which 01399 assumes you've done the insert because you can. */ 01400 _rl_output_some_chars (nfd, lendiff); 01401 _rl_last_c_pos += col_lendiff; 01402 } 01403 else 01404 { 01405 /* We have horizontal scrolling and we are not inserting at 01406 the end. We have invisible characters in this line. This 01407 is a dumb update. */ 01408 _rl_output_some_chars (nfd, temp); 01409 _rl_last_c_pos += col_temp; 01410 return; 01411 } 01412 /* Copy (new) chars to screen from first diff to last match. */ 01413 temp = nls - nfd; 01414 if ((temp - lendiff) > 0) 01415 { 01416 _rl_output_some_chars (nfd + lendiff, temp - lendiff); 01417 #if 1 01418 /* XXX -- this bears closer inspection. Fixes a redisplay bug 01419 reported against bash-3.0-alpha by Andreas Schwab involving 01420 multibyte characters and prompt strings with invisible 01421 characters, but was previously disabled. */ 01422 _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-col_lendiff); 01423 #else 01424 _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-lendiff); 01425 #endif 01426 } 01427 } 01428 else 01429 { 01430 /* cannot insert chars, write to EOL */ 01431 _rl_output_some_chars (nfd, temp); 01432 _rl_last_c_pos += col_temp; 01433 } 01434 } 01435 else /* Delete characters from line. */ 01436 { 01437 /* If possible and inexpensive to use terminal deletion, then do so. */ 01438 if (_rl_term_dc && (2 * col_temp) >= -col_lendiff) 01439 { 01440 /* If all we're doing is erasing the invisible characters in the 01441 prompt string, don't bother. It screws up the assumptions 01442 about what's on the screen. */ 01443 if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 && 01444 -lendiff == visible_wrap_offset) 01445 col_lendiff = 0; 01446 01447 if (col_lendiff) 01448 delete_chars (-col_lendiff); /* delete (diff) characters */ 01449 01450 /* Copy (new) chars to screen from first diff to last match */ 01451 temp = nls - nfd; 01452 if (temp > 0) 01453 { 01454 _rl_output_some_chars (nfd, temp); 01455 _rl_last_c_pos += _rl_col_width (nfd, 0, temp);; 01456 } 01457 } 01458 /* Otherwise, print over the existing material. */ 01459 else 01460 { 01461 if (temp > 0) 01462 { 01463 _rl_output_some_chars (nfd, temp); 01464 _rl_last_c_pos += col_temp; 01465 } 01466 lendiff = (oe - old) - (ne - new); 01467 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 01468 col_lendiff = _rl_col_width (old, 0, oe - old) - _rl_col_width (new, 0, ne - new); 01469 else 01470 col_lendiff = lendiff; 01471 01472 if (col_lendiff) 01473 { 01474 if (_rl_term_autowrap && current_line < inv_botlin) 01475 space_to_eol (col_lendiff); 01476 else 01477 _rl_clear_to_eol (col_lendiff); 01478 } 01479 } 01480 } 01481 } 01482 01483 /* Tell the update routines that we have moved onto a new (empty) line. */ 01484 int 01485 rl_on_new_line () 01486 { 01487 if (visible_line) 01488 visible_line[0] = '\0'; 01489 01490 _rl_last_c_pos = _rl_last_v_pos = 0; 01491 _rl_vis_botlin = last_lmargin = 0; 01492 if (vis_lbreaks) 01493 vis_lbreaks[0] = vis_lbreaks[1] = 0; 01494 visible_wrap_offset = 0; 01495 return 0; 01496 } 01497 01498 /* Tell the update routines that we have moved onto a new line with the 01499 prompt already displayed. Code originally from the version of readline 01500 distributed with CLISP. rl_expand_prompt must have already been called 01501 (explicitly or implicitly). This still doesn't work exactly right. */ 01502 int 01503 rl_on_new_line_with_prompt () 01504 { 01505 int prompt_size, i, l, real_screenwidth, newlines; 01506 char *prompt_last_line, *lprompt; 01507 01508 /* Initialize visible_line and invisible_line to ensure that they can hold 01509 the already-displayed prompt. */ 01510 prompt_size = strlen (rl_prompt) + 1; 01511 init_line_structures (prompt_size); 01512 01513 /* Make sure the line structures hold the already-displayed prompt for 01514 redisplay. */ 01515 lprompt = local_prompt ? local_prompt : rl_prompt; 01516 strcpy (visible_line, lprompt); 01517 strcpy (invisible_line, lprompt); 01518 01519 /* If the prompt contains newlines, take the last tail. */ 01520 prompt_last_line = strrchr (rl_prompt, '\n'); 01521 if (!prompt_last_line) 01522 prompt_last_line = rl_prompt; 01523 01524 l = strlen (prompt_last_line); 01525 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 01526 _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l); 01527 else 01528 _rl_last_c_pos = l; 01529 01530 /* Dissect prompt_last_line into screen lines. Note that here we have 01531 to use the real screenwidth. Readline's notion of screenwidth might be 01532 one less, see terminal.c. */ 01533 real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1); 01534 _rl_last_v_pos = l / real_screenwidth; 01535 /* If the prompt length is a multiple of real_screenwidth, we don't know 01536 whether the cursor is at the end of the last line, or already at the 01537 beginning of the next line. Output a newline just to be safe. */ 01538 if (l > 0 && (l % real_screenwidth) == 0) 01539 _rl_output_some_chars ("\n", 1); 01540 last_lmargin = 0; 01541 01542 newlines = 0; i = 0; 01543 while (i <= l) 01544 { 01545 _rl_vis_botlin = newlines; 01546 vis_lbreaks[newlines++] = i; 01547 i += real_screenwidth; 01548 } 01549 vis_lbreaks[newlines] = l; 01550 visible_wrap_offset = 0; 01551 01552 rl_display_prompt = rl_prompt; /* XXX - make sure it's set */ 01553 01554 return 0; 01555 } 01556 01557 /* Actually update the display, period. */ 01558 int 01559 rl_forced_update_display () 01560 { 01561 if (visible_line) 01562 { 01563 register char *temp = visible_line; 01564 01565 while (*temp) 01566 *temp++ = '\0'; 01567 } 01568 rl_on_new_line (); 01569 forced_display++; 01570 (*rl_redisplay_function) (); 01571 return 0; 01572 } 01573 01574 /* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices. 01575 DATA is the contents of the screen line of interest; i.e., where 01576 the movement is being done. */ 01577 void 01578 _rl_move_cursor_relative (new, data) 01579 int new; 01580 const char *data; 01581 { 01582 register int i; 01583 01584 /* If we don't have to do anything, then return. */ 01585 #if defined (HANDLE_MULTIBYTE) 01586 /* If we have multibyte characters, NEW is indexed by the buffer point in 01587 a multibyte string, but _rl_last_c_pos is the display position. In 01588 this case, NEW's display position is not obvious and must be 01589 calculated. */ 01590 if (MB_CUR_MAX == 1 || rl_byte_oriented) 01591 { 01592 if (_rl_last_c_pos == new) 01593 return; 01594 } 01595 else if (_rl_last_c_pos == _rl_col_width (data, 0, new)) 01596 return; 01597 #else 01598 if (_rl_last_c_pos == new) return; 01599 #endif 01600 01601 /* It may be faster to output a CR, and then move forwards instead 01602 of moving backwards. */ 01603 /* i == current physical cursor position. */ 01604 i = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset); 01605 if (new == 0 || CR_FASTER (new, _rl_last_c_pos) || 01606 (_rl_term_autowrap && i == _rl_screenwidth)) 01607 { 01608 #if defined (__MSDOS__) 01609 putc ('\r', rl_outstream); 01610 #else 01611 tputs (_rl_term_cr, 1, _rl_output_character_function); 01612 #endif /* !__MSDOS__ */ 01613 _rl_last_c_pos = 0; 01614 } 01615 01616 if (_rl_last_c_pos < new) 01617 { 01618 /* Move the cursor forward. We do it by printing the command 01619 to move the cursor forward if there is one, else print that 01620 portion of the output buffer again. Which is cheaper? */ 01621 01622 /* The above comment is left here for posterity. It is faster 01623 to print one character (non-control) than to print a control 01624 sequence telling the terminal to move forward one character. 01625 That kind of control is for people who don't know what the 01626 data is underneath the cursor. */ 01627 #if defined (HACK_TERMCAP_MOTION) 01628 if (_rl_term_forward_char) 01629 { 01630 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 01631 { 01632 int width; 01633 width = _rl_col_width (data, _rl_last_c_pos, new); 01634 for (i = 0; i < width; i++) 01635 tputs (_rl_term_forward_char, 1, _rl_output_character_function); 01636 } 01637 else 01638 { 01639 for (i = _rl_last_c_pos; i < new; i++) 01640 tputs (_rl_term_forward_char, 1, _rl_output_character_function); 01641 } 01642 } 01643 else if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 01644 { 01645 tputs (_rl_term_cr, 1, _rl_output_character_function); 01646 for (i = 0; i < new; i++) 01647 putc (data[i], rl_outstream); 01648 } 01649 else 01650 for (i = _rl_last_c_pos; i < new; i++) 01651 putc (data[i], rl_outstream); 01652 01653 #else /* !HACK_TERMCAP_MOTION */ 01654 01655 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 01656 { 01657 tputs (_rl_term_cr, 1, _rl_output_character_function); 01658 for (i = 0; i < new; i++) 01659 putc (data[i], rl_outstream); 01660 } 01661 else 01662 for (i = _rl_last_c_pos; i < new; i++) 01663 putc (data[i], rl_outstream); 01664 01665 #endif /* !HACK_TERMCAP_MOTION */ 01666 01667 } 01668 #if defined (HANDLE_MULTIBYTE) 01669 /* NEW points to the buffer point, but _rl_last_c_pos is the display point. 01670 The byte length of the string is probably bigger than the column width 01671 of the string, which means that if NEW == _rl_last_c_pos, then NEW's 01672 display point is less than _rl_last_c_pos. */ 01673 else if (_rl_last_c_pos >= new) 01674 #else 01675 else if (_rl_last_c_pos > new) 01676 #endif 01677 { 01678 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 01679 _rl_backspace (_rl_last_c_pos - _rl_col_width (data, 0, new)); 01680 else 01681 _rl_backspace (_rl_last_c_pos - new); 01682 } 01683 01684 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 01685 _rl_last_c_pos = _rl_col_width (data, 0, new); 01686 else 01687 _rl_last_c_pos = new; 01688 } 01689 01690 /* PWP: move the cursor up or down. */ 01691 void 01692 _rl_move_vert (to) 01693 int to; 01694 { 01695 register int delta, i; 01696 01697 if (_rl_last_v_pos == to || to > _rl_screenheight) 01698 return; 01699 01700 if ((delta = to - _rl_last_v_pos) > 0) 01701 { 01702 for (i = 0; i < delta; i++) 01703 putc ('\n', rl_outstream); 01704 #if defined (__MSDOS__) 01705 putc ('\r', rl_outstream); 01706 #else 01707 tputs (_rl_term_cr, 1, _rl_output_character_function); 01708 #endif 01709 _rl_last_c_pos = 0; 01710 } 01711 else 01712 { /* delta < 0 */ 01713 if (_rl_term_up && *_rl_term_up) 01714 for (i = 0; i < -delta; i++) 01715 tputs (_rl_term_up, 1, _rl_output_character_function); 01716 } 01717 01718 _rl_last_v_pos = to; /* Now TO is here */ 01719 } 01720 01721 /* Physically print C on rl_outstream. This is for functions which know 01722 how to optimize the display. Return the number of characters output. */ 01723 int 01724 rl_show_char (c) 01725 int c; 01726 { 01727 int n = 1; 01728 if (META_CHAR (c) && (_rl_output_meta_chars == 0)) 01729 { 01730 fprintf (rl_outstream, "M-"); 01731 n += 2; 01732 c = UNMETA (c); 01733 } 01734 01735 #if defined (DISPLAY_TABS) 01736 if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT) 01737 #else 01738 if (CTRL_CHAR (c) || c == RUBOUT) 01739 #endif /* !DISPLAY_TABS */ 01740 { 01741 fprintf (rl_outstream, "C-"); 01742 n += 2; 01743 c = CTRL_CHAR (c) ? UNCTRL (c) : '?'; 01744 } 01745 01746 putc (c, rl_outstream); 01747 fflush (rl_outstream); 01748 return n; 01749 } 01750 01751 int 01752 rl_character_len (c, pos) 01753 register int c, pos; 01754 { 01755 unsigned char uc; 01756 01757 uc = (unsigned char)c; 01758 01759 if (META_CHAR (uc)) 01760 return ((_rl_output_meta_chars == 0) ? 4 : 1); 01761 01762 if (uc == '\t') 01763 { 01764 #if defined (DISPLAY_TABS) 01765 return (((pos | 7) + 1) - pos); 01766 #else 01767 return (2); 01768 #endif /* !DISPLAY_TABS */ 01769 } 01770 01771 if (CTRL_CHAR (c) || c == RUBOUT) 01772 return (2); 01773 01774 return ((ISPRINT (uc)) ? 1 : 2); 01775 } 01776 01777 /* How to print things in the "echo-area". The prompt is treated as a 01778 mini-modeline. */ 01779 01780 #if defined (USE_VARARGS) 01781 int 01782 #if defined (PREFER_STDARG) 01783 rl_message (const char *format, ...) 01784 #else 01785 rl_message (va_alist) 01786 va_dcl 01787 #endif 01788 { 01789 va_list args; 01790 #if defined (PREFER_VARARGS) 01791 char *format; 01792 #endif 01793 01794 #if defined (PREFER_STDARG) 01795 va_start (args, format); 01796 #else 01797 va_start (args); 01798 format = va_arg (args, char *); 01799 #endif 01800 01801 #if defined (HAVE_VSNPRINTF) 01802 vsnprintf (msg_buf, sizeof (msg_buf) - 1, format, args); 01803 #else 01804 vsprintf (msg_buf, format, args); 01805 msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */ 01806 #endif 01807 va_end (args); 01808 01809 rl_display_prompt = msg_buf; 01810 (*rl_redisplay_function) (); 01811 return 0; 01812 } 01813 #else /* !USE_VARARGS */ 01814 int 01815 rl_message (format, arg1, arg2) 01816 char *format; 01817 { 01818 sprintf (msg_buf, format, arg1, arg2); 01819 msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */ 01820 rl_display_prompt = msg_buf; 01821 (*rl_redisplay_function) (); 01822 return 0; 01823 } 01824 #endif /* !USE_VARARGS */ 01825 01826 /* How to clear things from the "echo-area". */ 01827 int 01828 rl_clear_message () 01829 { 01830 rl_display_prompt = rl_prompt; 01831 (*rl_redisplay_function) (); 01832 return 0; 01833 } 01834 01835 int 01836 rl_reset_line_state () 01837 { 01838 rl_on_new_line (); 01839 01840 rl_display_prompt = rl_prompt ? rl_prompt : ""; 01841 forced_display = 1; 01842 return 0; 01843 } 01844 01845 /* These are getting numerous enough that it's time to create a struct. */ 01846 01847 static char *saved_local_prompt; 01848 static char *saved_local_prefix; 01849 static int saved_last_invisible; 01850 static int saved_visible_length; 01851 static int saved_invis_chars_first_line; 01852 static int saved_physical_chars; 01853 01854 void 01855 rl_save_prompt () 01856 { 01857 saved_local_prompt = local_prompt; 01858 saved_local_prefix = local_prompt_prefix; 01859 saved_last_invisible = prompt_last_invisible; 01860 saved_visible_length = prompt_visible_length; 01861 saved_invis_chars_first_line = prompt_invis_chars_first_line; 01862 saved_physical_chars = prompt_physical_chars; 01863 01864 local_prompt = local_prompt_prefix = (char *)0; 01865 prompt_last_invisible = prompt_visible_length = 0; 01866 prompt_invis_chars_first_line = prompt_physical_chars = 0; 01867 } 01868 01869 void 01870 rl_restore_prompt () 01871 { 01872 FREE (local_prompt); 01873 FREE (local_prompt_prefix); 01874 01875 local_prompt = saved_local_prompt; 01876 local_prompt_prefix = saved_local_prefix; 01877 prompt_last_invisible = saved_last_invisible; 01878 prompt_visible_length = saved_visible_length; 01879 prompt_invis_chars_first_line = saved_invis_chars_first_line; 01880 prompt_physical_chars = saved_physical_chars; 01881 } 01882 01883 char * 01884 _rl_make_prompt_for_search (pchar) 01885 int pchar; 01886 { 01887 int len; 01888 char *pmt; 01889 01890 rl_save_prompt (); 01891 01892 if (saved_local_prompt == 0) 01893 { 01894 len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0; 01895 pmt = (char *)xmalloc (len + 2); 01896 if (len) 01897 strcpy (pmt, rl_prompt); 01898 pmt[len] = pchar; 01899 pmt[len+1] = '\0'; 01900 } 01901 else 01902 { 01903 len = *saved_local_prompt ? strlen (saved_local_prompt) : 0; 01904 pmt = (char *)xmalloc (len + 2); 01905 if (len) 01906 strcpy (pmt, saved_local_prompt); 01907 pmt[len] = pchar; 01908 pmt[len+1] = '\0'; 01909 local_prompt = savestring (pmt); 01910 prompt_last_invisible = saved_last_invisible; 01911 prompt_visible_length = saved_visible_length + 1; 01912 } 01913 01914 return pmt; 01915 } 01916 01917 /* Quick redisplay hack when erasing characters at the end of the line. */ 01918 void 01919 _rl_erase_at_end_of_line (l) 01920 int l; 01921 { 01922 register int i; 01923 01924 _rl_backspace (l); 01925 for (i = 0; i < l; i++) 01926 putc (' ', rl_outstream); 01927 _rl_backspace (l); 01928 for (i = 0; i < l; i++) 01929 visible_line[--_rl_last_c_pos] = '\0'; 01930 rl_display_fixed++; 01931 } 01932 01933 /* Clear to the end of the line. COUNT is the minimum 01934 number of character spaces to clear, */ 01935 void 01936 _rl_clear_to_eol (count) 01937 int count; 01938 { 01939 if (_rl_term_clreol) 01940 tputs (_rl_term_clreol, 1, _rl_output_character_function); 01941 else if (count) 01942 space_to_eol (count); 01943 } 01944 01945 /* Clear to the end of the line using spaces. COUNT is the minimum 01946 number of character spaces to clear, */ 01947 static void 01948 space_to_eol (count) 01949 int count; 01950 { 01951 register int i; 01952 01953 for (i = 0; i < count; i++) 01954 putc (' ', rl_outstream); 01955 01956 _rl_last_c_pos += count; 01957 } 01958 01959 void 01960 _rl_clear_screen () 01961 { 01962 if (_rl_term_clrpag) 01963 tputs (_rl_term_clrpag, 1, _rl_output_character_function); 01964 else 01965 rl_crlf (); 01966 } 01967 01968 /* Insert COUNT characters from STRING to the output stream at column COL. */ 01969 static void 01970 insert_some_chars (string, count, col) 01971 char *string; 01972 int count, col; 01973 { 01974 /* DEBUGGING */ 01975 if (MB_CUR_MAX == 1 || rl_byte_oriented) 01976 if (count != col) 01977 fprintf(stderr, "readline: debug: insert_some_chars: count (%d) != col (%d)\n", count, col); 01978 01979 /* If IC is defined, then we do not have to "enter" insert mode. */ 01980 if (_rl_term_IC) 01981 { 01982 char *buffer; 01983 01984 buffer = tgoto (_rl_term_IC, 0, col); 01985 tputs (buffer, 1, _rl_output_character_function); 01986 _rl_output_some_chars (string, count); 01987 } 01988 else 01989 { 01990 register int i; 01991 01992 /* If we have to turn on insert-mode, then do so. */ 01993 if (_rl_term_im && *_rl_term_im) 01994 tputs (_rl_term_im, 1, _rl_output_character_function); 01995 01996 /* If there is a special command for inserting characters, then 01997 use that first to open up the space. */ 01998 if (_rl_term_ic && *_rl_term_ic) 01999 { 02000 for (i = col; i--; ) 02001 tputs (_rl_term_ic, 1, _rl_output_character_function); 02002 } 02003 02004 /* Print the text. */ 02005 _rl_output_some_chars (string, count); 02006 02007 /* If there is a string to turn off insert mode, we had best use 02008 it now. */ 02009 if (_rl_term_ei && *_rl_term_ei) 02010 tputs (_rl_term_ei, 1, _rl_output_character_function); 02011 } 02012 } 02013 02014 /* Delete COUNT characters from the display line. */ 02015 static void 02016 delete_chars (count) 02017 int count; 02018 { 02019 if (count > _rl_screenwidth) /* XXX */ 02020 return; 02021 02022 if (_rl_term_DC && *_rl_term_DC) 02023 { 02024 char *buffer; 02025 buffer = tgoto (_rl_term_DC, count, count); 02026 tputs (buffer, count, _rl_output_character_function); 02027 } 02028 else 02029 { 02030 if (_rl_term_dc && *_rl_term_dc) 02031 while (count--) 02032 tputs (_rl_term_dc, 1, _rl_output_character_function); 02033 } 02034 } 02035 02036 void 02037 _rl_update_final () 02038 { 02039 int full_lines; 02040 02041 full_lines = 0; 02042 /* If the cursor is the only thing on an otherwise-blank last line, 02043 compensate so we don't print an extra CRLF. */ 02044 if (_rl_vis_botlin && _rl_last_c_pos == 0 && 02045 visible_line[vis_lbreaks[_rl_vis_botlin]] == 0) 02046 { 02047 _rl_vis_botlin--; 02048 full_lines = 1; 02049 } 02050 _rl_move_vert (_rl_vis_botlin); 02051 /* If we've wrapped lines, remove the final xterm line-wrap flag. */ 02052 if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth)) 02053 { 02054 char *last_line; 02055 02056 last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]]; 02057 _rl_move_cursor_relative (_rl_screenwidth - 1, last_line); 02058 _rl_clear_to_eol (0); 02059 putc (last_line[_rl_screenwidth - 1], rl_outstream); 02060 } 02061 _rl_vis_botlin = 0; 02062 rl_crlf (); 02063 fflush (rl_outstream); 02064 rl_display_fixed++; 02065 } 02066 02067 /* Move to the start of the current line. */ 02068 static void 02069 cr () 02070 { 02071 if (_rl_term_cr) 02072 { 02073 #if defined (__MSDOS__) 02074 putc ('\r', rl_outstream); 02075 #else 02076 tputs (_rl_term_cr, 1, _rl_output_character_function); 02077 #endif 02078 _rl_last_c_pos = 0; 02079 } 02080 } 02081 02082 /* Redraw the last line of a multi-line prompt that may possibly contain 02083 terminal escape sequences. Called with the cursor at column 0 of the 02084 line to draw the prompt on. */ 02085 static void 02086 redraw_prompt (t) 02087 char *t; 02088 { 02089 char *oldp, *oldl, *oldlprefix; 02090 int oldlen, oldlast, oldplen, oldninvis, oldphyschars; 02091 02092 /* Geez, I should make this a struct. */ 02093 oldp = rl_display_prompt; 02094 oldl = local_prompt; 02095 oldlprefix = local_prompt_prefix; 02096 oldlen = prompt_visible_length; 02097 oldplen = prompt_prefix_length; 02098 oldlast = prompt_last_invisible; 02099 oldninvis = prompt_invis_chars_first_line; 02100 oldphyschars = prompt_physical_chars; 02101 02102 rl_display_prompt = t; 02103 local_prompt = expand_prompt (t, &prompt_visible_length, 02104 &prompt_last_invisible, 02105 &prompt_invis_chars_first_line, 02106 &prompt_physical_chars); 02107 local_prompt_prefix = (char *)NULL; 02108 rl_forced_update_display (); 02109 02110 rl_display_prompt = oldp; 02111 local_prompt = oldl; 02112 local_prompt_prefix = oldlprefix; 02113 prompt_visible_length = oldlen; 02114 prompt_prefix_length = oldplen; 02115 prompt_last_invisible = oldlast; 02116 prompt_invis_chars_first_line = oldninvis; 02117 prompt_physical_chars = oldphyschars; 02118 } 02119 02120 /* Redisplay the current line after a SIGWINCH is received. */ 02121 void 02122 _rl_redisplay_after_sigwinch () 02123 { 02124 char *t; 02125 02126 /* Clear the current line and put the cursor at column 0. Make sure 02127 the right thing happens if we have wrapped to a new screen line. */ 02128 if (_rl_term_cr) 02129 { 02130 #if defined (__MSDOS__) 02131 putc ('\r', rl_outstream); 02132 #else 02133 tputs (_rl_term_cr, 1, _rl_output_character_function); 02134 #endif 02135 _rl_last_c_pos = 0; 02136 #if defined (__MSDOS__) 02137 space_to_eol (_rl_screenwidth); 02138 putc ('\r', rl_outstream); 02139 #else 02140 if (_rl_term_clreol) 02141 tputs (_rl_term_clreol, 1, _rl_output_character_function); 02142 else 02143 { 02144 space_to_eol (_rl_screenwidth); 02145 tputs (_rl_term_cr, 1, _rl_output_character_function); 02146 } 02147 #endif 02148 if (_rl_last_v_pos > 0) 02149 _rl_move_vert (0); 02150 } 02151 else 02152 rl_crlf (); 02153 02154 /* Redraw only the last line of a multi-line prompt. */ 02155 t = strrchr (rl_display_prompt, '\n'); 02156 if (t) 02157 redraw_prompt (++t); 02158 else 02159 rl_forced_update_display (); 02160 } 02161 02162 void 02163 _rl_clean_up_for_exit () 02164 { 02165 if (readline_echoing_p) 02166 { 02167 _rl_move_vert (_rl_vis_botlin); 02168 _rl_vis_botlin = 0; 02169 fflush (rl_outstream); 02170 rl_restart_output (1, 0); 02171 } 02172 } 02173 02174 void 02175 _rl_erase_entire_line () 02176 { 02177 cr (); 02178 _rl_clear_to_eol (0); 02179 cr (); 02180 fflush (rl_outstream); 02181 } 02182 02183 /* return the `current display line' of the cursor -- the number of lines to 02184 move up to get to the first screen line of the current readline line. */ 02185 int 02186 _rl_current_display_line () 02187 { 02188 int ret, nleft; 02189 02190 /* Find out whether or not there might be invisible characters in the 02191 editing buffer. */ 02192 if (rl_display_prompt == rl_prompt) 02193 nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length; 02194 else 02195 nleft = _rl_last_c_pos - _rl_screenwidth; 02196 02197 if (nleft > 0) 02198 ret = 1 + nleft / _rl_screenwidth; 02199 else 02200 ret = 0; 02201 02202 return ret; 02203 } 02204 02205 #if defined (HANDLE_MULTIBYTE) 02206 /* Calculate the number of screen columns occupied by STR from START to END. 02207 In the case of multibyte characters with stateful encoding, we have to 02208 scan from the beginning of the string to take the state into account. */ 02209 static int 02210 _rl_col_width (str, start, end) 02211 const char *str; 02212 int start, end; 02213 { 02214 wchar_t wc; 02215 mbstate_t ps = {0}; 02216 int tmp, point, width, max; 02217 02218 if (end <= start) 02219 return 0; 02220 02221 point = 0; 02222 max = end; 02223 02224 while (point < start) 02225 { 02226 tmp = mbrlen (str + point, max, &ps); 02227 if (MB_INVALIDCH ((size_t)tmp)) 02228 { 02229 /* In this case, the bytes are invalid or too short to compose a 02230 multibyte character, so we assume that the first byte represents 02231 a single character. */ 02232 point++; 02233 max--; 02234 02235 /* Clear the state of the byte sequence, because in this case the 02236 effect of mbstate is undefined. */ 02237 memset (&ps, 0, sizeof (mbstate_t)); 02238 } 02239 else if (MB_NULLWCH (tmp)) 02240 break; /* Found '\0' */ 02241 else 02242 { 02243 point += tmp; 02244 max -= tmp; 02245 } 02246 } 02247 02248 /* If START is not a byte that starts a character, then POINT will be 02249 greater than START. In this case, assume that (POINT - START) gives 02250 a byte count that is the number of columns of difference. */ 02251 width = point - start; 02252 02253 while (point < end) 02254 { 02255 tmp = mbrtowc (&wc, str + point, max, &ps); 02256 if (MB_INVALIDCH ((size_t)tmp)) 02257 { 02258 /* In this case, the bytes are invalid or too short to compose a 02259 multibyte character, so we assume that the first byte represents 02260 a single character. */ 02261 point++; 02262 max--; 02263 02264 /* and assume that the byte occupies a single column. */ 02265 width++; 02266 02267 /* Clear the state of the byte sequence, because in this case the 02268 effect of mbstate is undefined. */ 02269 memset (&ps, 0, sizeof (mbstate_t)); 02270 } 02271 else if (MB_NULLWCH (tmp)) 02272 break; /* Found '\0' */ 02273 else 02274 { 02275 point += tmp; 02276 max -= tmp; 02277 tmp = wcwidth(wc); 02278 width += (tmp >= 0) ? tmp : 1; 02279 } 02280 } 02281 02282 width += point - end; 02283 02284 return width; 02285 } 02286 #endif /* HANDLE_MULTIBYTE */
1.4.7

