1/* display.c -- readline redisplay facility. */ 2 3/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. 4 5 This file is part of the GNU Readline Library, a library for 6 reading lines of text with interactive input and history editing. 7 8 The GNU Readline Library is free software; you can redistribute it 9 and/or modify it under the terms of the GNU General Public License 10 as published by the Free Software Foundation; either version 2, or 11 (at your option) any later version. 12 13 The GNU Readline Library is distributed in the hope that it will be 14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty 15 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 The GNU General Public License is often shipped with GNU software, and 19 is generally kept in a file called COPYING or LICENSE. If you do not 20 have a copy of the license, write to the Free Software Foundation, 21 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ 22#define READLINE_LIBRARY 23 24#if defined (HAVE_CONFIG_H) 25# include <config.h> 26#endif 27 28#include <sys/types.h> 29 30#if defined (HAVE_UNISTD_H) 31# include <unistd.h> 32#endif /* HAVE_UNISTD_H */ 33 34#include "posixstat.h" 35 36#if defined (HAVE_STDLIB_H) 37# include <stdlib.h> 38#else 39# include "ansi_stdlib.h" 40#endif /* HAVE_STDLIB_H */ 41 42#include <stdio.h> 43 44#ifdef __MSDOS__ 45# include <pc.h> 46#endif 47 48/* System-specific feature definitions and include files. */ 49#include "rldefs.h" 50#include "rlmbutil.h" 51 52/* Termcap library stuff. */ 53#include "tcap.h" 54 55/* Some standard library routines. */ 56#include "readline.h" 57#include "history.h" 58 59#include "rlprivate.h" 60#include "xmalloc.h" 61 62#if !defined (strchr) && !defined (__STDC__) 63extern char *strchr (), *strrchr (); 64#endif /* !strchr && !__STDC__ */ 65 66#if defined (HACK_TERMCAP_MOTION) 67extern char *_rl_term_forward_char; 68#endif 69 70static void update_line PARAMS((char *, char *, int, int, int, int)); 71static void space_to_eol PARAMS((int)); 72static void delete_chars PARAMS((int)); 73static void insert_some_chars PARAMS((char *, int, int)); 74static void cr PARAMS((void)); 75 76#if defined (HANDLE_MULTIBYTE) 77static int _rl_col_width PARAMS((const char *, int, int)); 78static int *_rl_wrapped_line; 79#else 80# define _rl_col_width(l, s, e) (((e) <= (s)) ? 0 : (e) - (s)) 81#endif 82 83static int *inv_lbreaks, *vis_lbreaks; 84static int inv_lbsize, vis_lbsize; 85 86/* Heuristic used to decide whether it is faster to move from CUR to NEW 87 by backing up or outputting a carriage return and moving forward. */ 88#define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new))) 89 90/* **************************************************************** */ 91/* */ 92/* Display stuff */ 93/* */ 94/* **************************************************************** */ 95 96/* This is the stuff that is hard for me. I never seem to write good 97 display routines in C. Let's see how I do this time. */ 98 99/* (PWP) Well... Good for a simple line updater, but totally ignores 100 the problems of input lines longer than the screen width. 101 102 update_line and the code that calls it makes a multiple line, 103 automatically wrapping line update. Careful attention needs 104 to be paid to the vertical position variables. */ 105 106/* Keep two buffers; one which reflects the current contents of the 107 screen, and the other to draw what we think the new contents should 108 be. Then compare the buffers, and make whatever changes to the 109 screen itself that we should. Finally, make the buffer that we 110 just drew into be the one which reflects the current contents of the 111 screen, and place the cursor where it belongs. 112 113 Commands that want to can fix the display themselves, and then let 114 this function know that the display has been fixed by setting the 115 RL_DISPLAY_FIXED variable. This is good for efficiency. */ 116 117/* Application-specific redisplay function. */ 118rl_voidfunc_t *rl_redisplay_function = rl_redisplay; 119 120/* Global variables declared here. */ 121/* What YOU turn on when you have handled all redisplay yourself. */ 122int rl_display_fixed = 0; 123 124int _rl_suppress_redisplay = 0; 125 126/* The stuff that gets printed out before the actual text of the line. 127 This is usually pointing to rl_prompt. */ 128char *rl_display_prompt = (char *)NULL; 129 130/* Pseudo-global variables declared here. */ 131/* The visible cursor position. If you print some text, adjust this. */ 132int _rl_last_c_pos = 0; 133int _rl_last_v_pos = 0; 134 135/* Number of lines currently on screen minus 1. */ 136int _rl_vis_botlin = 0; 137 138/* Variables used only in this file. */ 139/* The last left edge of text that was displayed. This is used when 140 doing horizontal scrolling. It shifts in thirds of a screenwidth. */ 141static int last_lmargin; 142 143/* The line display buffers. One is the line currently displayed on 144 the screen. The other is the line about to be displayed. */ 145static char *visible_line = (char *)NULL; 146static char *invisible_line = (char *)NULL; 147 148/* A buffer for `modeline' messages. */ 149static char msg_buf[128]; 150 151/* Non-zero forces the redisplay even if we thought it was unnecessary. */ 152static int forced_display; 153 154/* Default and initial buffer size. Can grow. */ 155static int line_size = 1024; 156 157/* Variables to keep track of the expanded prompt string, which may 158 include invisible characters. */ 159 160static char *local_prompt, *local_prompt_prefix; 161static int prompt_visible_length, prompt_prefix_length; 162 163/* The number of invisible characters in the line currently being 164 displayed on the screen. */ 165static int visible_wrap_offset; 166 167/* The number of invisible characters in the prompt string. Static so it 168 can be shared between rl_redisplay and update_line */ 169static int wrap_offset; 170 171/* The index of the last invisible character in the prompt string. */ 172static int prompt_last_invisible; 173 174/* The length (buffer offset) of the first line of the last (possibly 175 multi-line) buffer displayed on the screen. */ 176static int visible_first_line_len; 177 178/* Number of invisible characters on the first physical line of the prompt. 179 Only valid when the number of physical characters in the prompt exceeds 180 (or is equal to) _rl_screenwidth. */ 181static int prompt_invis_chars_first_line; 182 183static int prompt_last_screen_line; 184 185/* Expand the prompt string S and return the number of visible 186 characters in *LP, if LP is not null. This is currently more-or-less 187 a placeholder for expansion. LIP, if non-null is a place to store the 188 index of the last invisible character in the returned string. NIFLP, 189 if non-zero, is a place to store the number of invisible characters in 190 the first prompt line. */ 191 192/* Current implementation: 193 \001 (^A) start non-visible characters 194 \002 (^B) end non-visible characters 195 all characters except \001 and \002 (following a \001) are copied to 196 the returned string; all characters except those between \001 and 197 \002 are assumed to be `visible'. */ 198 199static char * 200expand_prompt (pmt, lp, lip, niflp) 201 char *pmt; 202 int *lp, *lip, *niflp; 203{ 204 char *r, *ret, *p; 205 int l, rl, last, ignoring, ninvis, invfl; 206 207 /* Short-circuit if we can. */ 208 if (strchr (pmt, RL_PROMPT_START_IGNORE) == 0) 209 { 210 r = savestring (pmt); 211 if (lp) 212 *lp = strlen (r); 213 return r; 214 } 215 216 l = strlen (pmt); 217 r = ret = (char *)xmalloc (l + 1); 218 219 invfl = 0; /* invisible chars in first line of prompt */ 220 221 for (rl = ignoring = last = ninvis = 0, p = pmt; p && *p; p++) 222 { 223 /* This code strips the invisible character string markers 224 RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */ 225 if (*p == RL_PROMPT_START_IGNORE) 226 { 227 ignoring++; 228 continue; 229 } 230 else if (ignoring && *p == RL_PROMPT_END_IGNORE) 231 { 232 ignoring = 0; 233 last = r - ret - 1; 234 continue; 235 } 236 else 237 { 238 *r++ = *p; 239 if (!ignoring) 240 rl++; 241 else 242 ninvis++; 243 if (rl == _rl_screenwidth) 244 invfl = ninvis; 245 } 246 } 247 248 if (rl < _rl_screenwidth) 249 invfl = ninvis; 250 251 *r = '\0'; 252 if (lp) 253 *lp = rl; 254 if (lip) 255 *lip = last; 256 if (niflp) 257 *niflp = invfl; 258 return ret; 259} 260 261/* Just strip out RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE from 262 PMT and return the rest of PMT. */ 263char * 264_rl_strip_prompt (pmt) 265 char *pmt; 266{ 267 char *ret; 268 269 ret = expand_prompt (pmt, (int *)NULL, (int *)NULL, (int *)NULL); 270 return ret; 271} 272 273/* 274 * Expand the prompt string into the various display components, if 275 * necessary. 276 * 277 * local_prompt = expanded last line of string in rl_display_prompt 278 * (portion after the final newline) 279 * local_prompt_prefix = portion before last newline of rl_display_prompt, 280 * expanded via expand_prompt 281 * prompt_visible_length = number of visible characters in local_prompt 282 * prompt_prefix_length = number of visible characters in local_prompt_prefix 283 * 284 * This function is called once per call to readline(). It may also be 285 * called arbitrarily to expand the primary prompt. 286 * 287 * The return value is the number of visible characters on the last line 288 * of the (possibly multi-line) prompt. 289 */ 290int 291rl_expand_prompt (prompt) 292 char *prompt; 293{ 294 char *p, *t; 295 int c; 296 297 /* Clear out any saved values. */ 298 FREE (local_prompt); 299 FREE (local_prompt_prefix); 300 301 local_prompt = local_prompt_prefix = (char *)0; 302 prompt_last_invisible = prompt_visible_length = 0; 303 304 if (prompt == 0 || *prompt == 0) 305 return (0); 306 307 p = strrchr (prompt, '\n'); 308 if (!p) 309 { 310 /* The prompt is only one logical line, though it might wrap. */ 311 local_prompt = expand_prompt (prompt, &prompt_visible_length, 312 &prompt_last_invisible, 313 &prompt_invis_chars_first_line); 314 local_prompt_prefix = (char *)0; 315 return (prompt_visible_length); 316 } 317 else 318 { 319 /* The prompt spans multiple lines. */ 320 t = ++p; 321 local_prompt = expand_prompt (p, &prompt_visible_length, 322 &prompt_last_invisible, 323 &prompt_invis_chars_first_line); 324 c = *t; *t = '\0'; 325 /* The portion of the prompt string up to and including the 326 final newline is now null-terminated. */ 327 local_prompt_prefix = expand_prompt (prompt, &prompt_prefix_length, 328 (int *)NULL, 329 &prompt_invis_chars_first_line); 330 *t = c; 331 return (prompt_prefix_length); 332 } 333} 334 335/* Initialize the VISIBLE_LINE and INVISIBLE_LINE arrays, and their associated 336 arrays of line break markers. MINSIZE is the minimum size of VISIBLE_LINE 337 and INVISIBLE_LINE; if it is greater than LINE_SIZE, LINE_SIZE is 338 increased. If the lines have already been allocated, this ensures that 339 they can hold at least MINSIZE characters. */ 340static void 341init_line_structures (minsize) 342 int minsize; 343{ 344 register int n; 345 346 if (invisible_line == 0) /* initialize it */ 347 { 348 if (line_size < minsize) 349 line_size = minsize; 350 visible_line = (char *)xmalloc (line_size); 351 invisible_line = (char *)xmalloc (line_size); 352 } 353 else if (line_size < minsize) /* ensure it can hold MINSIZE chars */ 354 { 355 line_size *= 2; 356 if (line_size < minsize) 357 line_size = minsize; 358 visible_line = (char *)xrealloc (visible_line, line_size); 359 invisible_line = (char *)xrealloc (invisible_line, line_size); 360 } 361 362 for (n = minsize; n < line_size; n++) 363 { 364 visible_line[n] = 0; 365 invisible_line[n] = 1; 366 } 367 368 if (vis_lbreaks == 0) 369 { 370 /* should be enough. */ 371 inv_lbsize = vis_lbsize = 256; 372 inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int)); 373 vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int)); 374#if defined (HANDLE_MULTIBYTE) 375 _rl_wrapped_line = (int *)xmalloc (vis_lbsize * sizeof (int)); 376#endif 377 inv_lbreaks[0] = vis_lbreaks[0] = 0; 378 } 379} 380 381/* Basic redisplay algorithm. */ 382void 383rl_redisplay () 384{ 385 register int in, out, c, linenum, cursor_linenum; 386 register char *line; 387 int c_pos, inv_botlin, lb_botlin, lb_linenum; 388 int newlines, lpos, temp; 389 char *prompt_this_line; 390#if defined (HANDLE_MULTIBYTE) 391 wchar_t wc; 392 size_t wc_bytes; 393 int wc_width; 394 mbstate_t ps; 395 int _rl_wrapped_multicolumn = 0; 396#endif 397 398 if (!readline_echoing_p) 399 return; 400 401 if (!rl_display_prompt) 402 rl_display_prompt = ""; 403 404 if (invisible_line == 0) 405 { 406 init_line_structures (0); 407 rl_on_new_line (); 408 } 409 410 /* Draw the line into the buffer. */ 411 c_pos = -1; 412 413 line = invisible_line; 414 out = inv_botlin = 0; 415 416 /* Mark the line as modified or not. We only do this for history 417 lines. */ 418 if (_rl_mark_modified_lines && current_history () && rl_undo_list) 419 { 420 line[out++] = '*'; 421 line[out] = '\0'; 422 } 423 424 /* If someone thought that the redisplay was handled, but the currently 425 visible line has a different modification state than the one about 426 to become visible, then correct the caller's misconception. */ 427 if (visible_line[0] != invisible_line[0]) 428 rl_display_fixed = 0; 429 430 /* If the prompt to be displayed is the `primary' readline prompt (the 431 one passed to readline()), use the values we have already expanded. 432 If not, use what's already in rl_display_prompt. WRAP_OFFSET is the 433 number of non-visible characters in the prompt string. */ 434 if (rl_display_prompt == rl_prompt || local_prompt) 435 { 436 int local_len = local_prompt ? strlen (local_prompt) : 0; 437 if (local_prompt_prefix && forced_display) 438 _rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix)); 439 440 if (local_len > 0) 441 { 442 temp = local_len + out + 2; 443 if (temp >= line_size) 444 { 445 line_size = (temp + 1024) - (temp % 1024); 446 visible_line = (char *)xrealloc (visible_line, line_size); 447 line = invisible_line = (char *)xrealloc (invisible_line, line_size); 448 } 449 strncpy (line + out, local_prompt, local_len); 450 out += local_len; 451 } 452 line[out] = '\0'; 453 wrap_offset = local_len - prompt_visible_length; 454 } 455 else 456 { 457 int pmtlen; 458 prompt_this_line = strrchr (rl_display_prompt, '\n'); 459 if (!prompt_this_line) 460 prompt_this_line = rl_display_prompt; 461 else 462 { 463 prompt_this_line++; 464 pmtlen = prompt_this_line - rl_display_prompt; /* temp var */ 465 if (forced_display) 466 { 467 _rl_output_some_chars (rl_display_prompt, pmtlen); 468 /* Make sure we are at column zero even after a newline, 469 regardless of the state of terminal output processing. */ 470 if (pmtlen < 2 || prompt_this_line[-2] != '\r') 471 cr (); 472 } 473 } 474 475 pmtlen = strlen (prompt_this_line); 476 temp = pmtlen + out + 2; 477 if (temp >= line_size) 478 { 479 line_size = (temp + 1024) - (temp % 1024); 480 visible_line = (char *)xrealloc (visible_line, line_size); 481 line = invisible_line = (char *)xrealloc (invisible_line, line_size); 482 } 483 strncpy (line + out, prompt_this_line, pmtlen); 484 out += pmtlen; 485 line[out] = '\0'; 486 wrap_offset = prompt_invis_chars_first_line = 0; 487 } 488 489#define CHECK_INV_LBREAKS() \ 490 do { \ 491 if (newlines >= (inv_lbsize - 2)) \ 492 { \ 493 inv_lbsize *= 2; \ 494 inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \ 495 } \ 496 } while (0) 497 498#if defined (HANDLE_MULTIBYTE) 499#define CHECK_LPOS() \ 500 do { \ 501 lpos++; \ 502 if (lpos >= _rl_screenwidth) \ 503 { \ 504 if (newlines >= (inv_lbsize - 2)) \ 505 { \ 506 inv_lbsize *= 2; \ 507 inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \ 508 _rl_wrapped_line = (int *)xrealloc (_rl_wrapped_line, inv_lbsize * sizeof (int)); \ 509 } \ 510 inv_lbreaks[++newlines] = out; \ 511 _rl_wrapped_line[newlines] = _rl_wrapped_multicolumn; \ 512 lpos = 0; \ 513 } \ 514 } while (0) 515#else 516#define CHECK_LPOS() \ 517 do { \ 518 lpos++; \ 519 if (lpos >= _rl_screenwidth) \ 520 { \ 521 if (newlines >= (inv_lbsize - 2)) \ 522 { \ 523 inv_lbsize *= 2; \ 524 inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \ 525 } \ 526 inv_lbreaks[++newlines] = out; \ 527 lpos = 0; \ 528 } \ 529 } while (0) 530#endif 531 532 /* inv_lbreaks[i] is where line i starts in the buffer. */ 533 inv_lbreaks[newlines = 0] = 0; 534 lpos = out - wrap_offset; 535#if defined (HANDLE_MULTIBYTE) 536 memset (_rl_wrapped_line, 0, vis_lbsize); 537#endif 538 539 /* prompt_invis_chars_first_line is the number of invisible characters in 540 the first physical line of the prompt. 541 wrap_offset - prompt_invis_chars_first_line is the number of invis 542 chars on the second line. */ 543 544 /* what if lpos is already >= _rl_screenwidth before we start drawing the 545 contents of the command line? */ 546 while (lpos >= _rl_screenwidth) 547 { 548 /* fix from Darin Johnson <darin@acuson.com> for prompt string with 549 invisible characters that is longer than the screen width. The 550 prompt_invis_chars_first_line variable could be made into an array 551 saying how many invisible characters there are per line, but that's 552 probably too much work for the benefit gained. How many people have 553 prompts that exceed two physical lines? */ 554 temp = ((newlines + 1) * _rl_screenwidth) + 555#if 0 556 ((newlines == 0) ? prompt_invis_chars_first_line : 0) + 557#else 558 ((newlines == 0 && local_prompt_prefix == 0) ? prompt_invis_chars_first_line : 0) + 559#endif 560 ((newlines == 1) ? wrap_offset : 0); 561 562 inv_lbreaks[++newlines] = temp; 563 lpos -= _rl_screenwidth; 564 } 565 566 prompt_last_screen_line = newlines; 567 568 /* Draw the rest of the line (after the prompt) into invisible_line, keeping 569 track of where the cursor is (c_pos), the number of the line containing 570 the cursor (lb_linenum), the last line number (lb_botlin and inv_botlin). 571 It maintains an array of line breaks for display (inv_lbreaks). 572 This handles expanding tabs for display and displaying meta characters. */ 573 lb_linenum = 0; 574#if defined (HANDLE_MULTIBYTE) 575 in = 0; 576 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 577 { 578 memset (&ps, 0, sizeof (mbstate_t)); 579 wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps); 580 } 581 else 582 wc_bytes = 1; 583 while (in < rl_end) 584#else 585 for (in = 0; in < rl_end; in++) 586#endif 587 { 588 c = (unsigned char)rl_line_buffer[in]; 589 590#if defined (HANDLE_MULTIBYTE) 591 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 592 { 593 if (wc_bytes == (size_t)-1 || wc_bytes == (size_t)-2) 594 { 595 /* Byte sequence is invalid or shortened. Assume that the 596 first byte represents a character. */ 597 wc_bytes = 1; 598 /* Assume that a character occupies a single column. */ 599 wc_width = 1; 600 memset (&ps, 0, sizeof (mbstate_t)); 601 } 602 else if (wc_bytes == (size_t)0) 603 break; /* Found '\0' */ 604 else 605 { 606 temp = wcwidth (wc); 607 wc_width = (temp < 0) ? 1 : temp; 608 } 609 } 610#endif 611 612 if (out + 8 >= line_size) /* XXX - 8 for \t */ 613 { 614 line_size *= 2; 615 visible_line = (char *)xrealloc (visible_line, line_size); 616 invisible_line = (char *)xrealloc (invisible_line, line_size); 617 line = invisible_line; 618 } 619 620 if (in == rl_point) 621 { 622 c_pos = out; 623 lb_linenum = newlines; 624 } 625 626#if defined (HANDLE_MULTIBYTE) 627 if (META_CHAR (c) && _rl_output_meta_chars == 0) /* XXX - clean up */ 628#else 629 if (META_CHAR (c)) 630#endif 631 { 632 if (_rl_output_meta_chars == 0) 633 { 634 sprintf (line + out, "\\%o", c); 635 636 if (lpos + 4 >= _rl_screenwidth) 637 { 638 temp = _rl_screenwidth - lpos; 639 CHECK_INV_LBREAKS (); 640 inv_lbreaks[++newlines] = out + temp; 641 lpos = 4 - temp; 642 } 643 else 644 lpos += 4; 645 646 out += 4; 647 } 648 else 649 { 650 line[out++] = c; 651 CHECK_LPOS(); 652 } 653 } 654#if defined (DISPLAY_TABS) 655 else if (c == '\t') 656 { 657 register int newout; 658 659#if 0 660 newout = (out | (int)7) + 1; 661#else 662 newout = out + 8 - lpos % 8; 663#endif 664 temp = newout - out; 665 if (lpos + temp >= _rl_screenwidth) 666 { 667 register int temp2; 668 temp2 = _rl_screenwidth - lpos; 669 CHECK_INV_LBREAKS (); 670 inv_lbreaks[++newlines] = out + temp2; 671 lpos = temp - temp2; 672 while (out < newout) 673 line[out++] = ' '; 674 } 675 else 676 { 677 while (out < newout) 678 line[out++] = ' '; 679 lpos += temp; 680 } 681 } 682#endif 683 else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up) 684 { 685 line[out++] = '\0'; /* XXX - sentinel */ 686 CHECK_INV_LBREAKS (); 687 inv_lbreaks[++newlines] = out; 688 lpos = 0; 689 } 690 else if (CTRL_CHAR (c) || c == RUBOUT) 691 { 692 line[out++] = '^'; 693 CHECK_LPOS(); 694 line[out++] = CTRL_CHAR (c) ? UNCTRL (c) : '?'; 695 CHECK_LPOS(); 696 } 697 else 698 { 699#if defined (HANDLE_MULTIBYTE) 700 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 701 { 702 register int i; 703 704 _rl_wrapped_multicolumn = 0; 705 706 if (_rl_screenwidth < lpos + wc_width) 707 for (i = lpos; i < _rl_screenwidth; i++) 708 { 709 /* The space will be removed in update_line() */ 710 line[out++] = ' '; 711 _rl_wrapped_multicolumn++; 712 CHECK_LPOS(); 713 } 714 if (in == rl_point) 715 { 716 c_pos = out; 717 lb_linenum = newlines; 718 } 719 for (i = in; i < in+wc_bytes; i++) 720 line[out++] = rl_line_buffer[i]; 721 for (i = 0; i < wc_width; i++) 722 CHECK_LPOS(); 723 } 724 else 725 { 726 line[out++] = c; 727 CHECK_LPOS(); 728 } 729#else 730 line[out++] = c; 731 CHECK_LPOS(); 732#endif 733 } 734 735#if defined (HANDLE_MULTIBYTE) 736 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 737 { 738 in += wc_bytes; 739 wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps); 740 } 741 else 742 in++; 743#endif 744 745 } 746 line[out] = '\0'; 747 if (c_pos < 0) 748 { 749 c_pos = out; 750 lb_linenum = newlines; 751 } 752 753 inv_botlin = lb_botlin = newlines; 754 CHECK_INV_LBREAKS (); 755 inv_lbreaks[newlines+1] = out; 756 cursor_linenum = lb_linenum; 757 758 /* C_POS == position in buffer where cursor should be placed. 759 CURSOR_LINENUM == line number where the cursor should be placed. */ 760 761 /* PWP: now is when things get a bit hairy. The visible and invisible 762 line buffers are really multiple lines, which would wrap every 763 (screenwidth - 1) characters. Go through each in turn, finding 764 the changed region and updating it. The line order is top to bottom. */ 765 766 /* If we can move the cursor up and down, then use multiple lines, 767 otherwise, let long lines display in a single terminal line, and 768 horizontally scroll it. */ 769 770 if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up) 771 { 772 int nleft, pos, changed_screen_line; 773 774 if (!rl_display_fixed || forced_display) 775 { 776 forced_display = 0; 777 778 /* If we have more than a screenful of material to display, then 779 only display a screenful. We should display the last screen, 780 not the first. */ 781 if (out >= _rl_screenchars) 782 { 783 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 784 out = _rl_find_prev_mbchar (line, _rl_screenchars, MB_FIND_ANY); 785 else 786 out = _rl_screenchars - 1; 787 } 788 789 /* The first line is at character position 0 in the buffer. The 790 second and subsequent lines start at inv_lbreaks[N], offset by 791 OFFSET (which has already been calculated above). */ 792 793#define W_OFFSET(line, offset) ((line) == 0 ? offset : 0) 794#define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l])) 795#define INV_LLEN(l) (inv_lbreaks[l+1] - inv_lbreaks[l]) 796#define VIS_CHARS(line) (visible_line + vis_lbreaks[line]) 797#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line) 798#define INV_LINE(line) (invisible_line + inv_lbreaks[line]) 799 800 /* For each line in the buffer, do the updating display. */ 801 for (linenum = 0; linenum <= inv_botlin; linenum++) 802 { 803 update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum, 804 VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin); 805 806 /* If this is the line with the prompt, we might need to 807 compensate for invisible characters in the new line. Do 808 this only if there is not more than one new line (which 809 implies that we completely overwrite the old visible line) 810 and the new line is shorter than the old. Make sure we are 811 at the end of the new line before clearing. */ 812 if (linenum == 0 && 813 inv_botlin == 0 && _rl_last_c_pos == out && 814 (wrap_offset > visible_wrap_offset) && 815 (_rl_last_c_pos < visible_first_line_len)) 816 { 817 nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos; 818 if (nleft) 819 _rl_clear_to_eol (nleft); 820 } 821 822 /* Since the new first line is now visible, save its length. */ 823 if (linenum == 0) 824 visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset; 825 } 826 827 /* We may have deleted some lines. If so, clear the left over 828 blank ones at the bottom out. */ 829 if (_rl_vis_botlin > inv_botlin) 830 { 831 char *tt; 832 for (; linenum <= _rl_vis_botlin; linenum++) 833 { 834 tt = VIS_CHARS (linenum); 835 _rl_move_vert (linenum); 836 _rl_move_cursor_relative (0, tt); 837 _rl_clear_to_eol 838 ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth); 839 } 840 } 841 _rl_vis_botlin = inv_botlin; 842 843 /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a 844 different screen line during this redisplay. */ 845 changed_screen_line = _rl_last_v_pos != cursor_linenum; 846 if (changed_screen_line) 847 { 848 _rl_move_vert (cursor_linenum); 849 /* If we moved up to the line with the prompt using _rl_term_up, 850 the physical cursor position on the screen stays the same, 851 but the buffer position needs to be adjusted to account 852 for invisible characters. */ 853 if (cursor_linenum == 0 && wrap_offset) 854 _rl_last_c_pos += wrap_offset; 855 } 856 857 /* We have to reprint the prompt if it contains invisible 858 characters, since it's not generally OK to just reprint 859 the characters from the current cursor position. But we 860 only need to reprint it if the cursor is before the last 861 invisible character in the prompt string. */ 862 nleft = prompt_visible_length + wrap_offset; 863 if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 && 864 _rl_last_c_pos <= prompt_last_invisible && local_prompt) 865 { 866#if defined (__MSDOS__) 867 putc ('\r', rl_outstream); 868#else 869 if (_rl_term_cr) 870 tputs (_rl_term_cr, 1, _rl_output_character_function); 871#endif 872 _rl_output_some_chars (local_prompt, nleft); 873 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 874 _rl_last_c_pos = _rl_col_width(local_prompt, 0, nleft); 875 else 876 _rl_last_c_pos = nleft; 877 } 878 879 /* Where on that line? And where does that line start 880 in the buffer? */ 881 pos = inv_lbreaks[cursor_linenum]; 882 /* nleft == number of characters in the line buffer between the 883 start of the line and the cursor position. */ 884 nleft = c_pos - pos; 885 886 /* Since _rl_backspace() doesn't know about invisible characters in the 887 prompt, and there's no good way to tell it, we compensate for 888 those characters here and call _rl_backspace() directly. */ 889 if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos) 890 { 891 _rl_backspace (_rl_last_c_pos - nleft); 892 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 893 _rl_last_c_pos = _rl_col_width (&visible_line[pos], 0, nleft); 894 else 895 _rl_last_c_pos = nleft; 896 } 897 898 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 899 _rl_move_cursor_relative (nleft, &invisible_line[pos]); 900 else if (nleft != _rl_last_c_pos) 901 _rl_move_cursor_relative (nleft, &invisible_line[pos]); 902 } 903 } 904 else /* Do horizontal scrolling. */ 905 { 906#define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0) 907 int lmargin, ndisp, nleft, phys_c_pos, t; 908 909 /* Always at top line. */ 910 _rl_last_v_pos = 0; 911 912 /* Compute where in the buffer the displayed line should start. This 913 will be LMARGIN. */ 914 915 /* The number of characters that will be displayed before the cursor. */ 916 ndisp = c_pos - wrap_offset; 917 nleft = prompt_visible_length + wrap_offset; 918 /* Where the new cursor position will be on the screen. This can be 919 longer than SCREENWIDTH; if it is, lmargin will be adjusted. */ 920 phys_c_pos = c_pos - (last_lmargin ? last_lmargin : wrap_offset); 921 t = _rl_screenwidth / 3; 922 923 /* If the number of characters had already exceeded the screenwidth, 924 last_lmargin will be > 0. */ 925 926 /* If the number of characters to be displayed is more than the screen 927 width, compute the starting offset so that the cursor is about 928 two-thirds of the way across the screen. */ 929 if (phys_c_pos > _rl_screenwidth - 2) 930 { 931 lmargin = c_pos - (2 * t); 932 if (lmargin < 0) 933 lmargin = 0; 934 /* If the left margin would be in the middle of a prompt with 935 invisible characters, don't display the prompt at all. */ 936 if (wrap_offset && lmargin > 0 && lmargin < nleft) 937 lmargin = nleft; 938 } 939 else if (ndisp < _rl_screenwidth - 2) /* XXX - was -1 */ 940 lmargin = 0; 941 else if (phys_c_pos < 1) 942 { 943 /* If we are moving back towards the beginning of the line and 944 the last margin is no longer correct, compute a new one. */ 945 lmargin = ((c_pos - 1) / t) * t; /* XXX */ 946 if (wrap_offset && lmargin > 0 && lmargin < nleft) 947 lmargin = nleft; 948 } 949 else 950 lmargin = last_lmargin; 951 952 /* If the first character on the screen isn't the first character 953 in the display line, indicate this with a special character. */ 954 if (lmargin > 0) 955 line[lmargin] = '<'; 956 957 /* If SCREENWIDTH characters starting at LMARGIN do not encompass 958 the whole line, indicate that with a special character at the 959 right edge of the screen. If LMARGIN is 0, we need to take the 960 wrap offset into account. */ 961 t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth; 962 if (t < out) 963 line[t - 1] = '>'; 964 965 if (!rl_display_fixed || forced_display || lmargin != last_lmargin) 966 { 967 forced_display = 0; 968 update_line (&visible_line[last_lmargin], 969 &invisible_line[lmargin], 970 0, 971 _rl_screenwidth + visible_wrap_offset, 972 _rl_screenwidth + (lmargin ? 0 : wrap_offset), 973 0); 974 975 /* If the visible new line is shorter than the old, but the number 976 of invisible characters is greater, and we are at the end of 977 the new line, we need to clear to eol. */ 978 t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset); 979 if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) && 980 (_rl_last_c_pos == out) && 981 t < visible_first_line_len) 982 { 983 nleft = _rl_screenwidth - t; 984 _rl_clear_to_eol (nleft); 985 } 986 visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset); 987 if (visible_first_line_len > _rl_screenwidth) 988 visible_first_line_len = _rl_screenwidth; 989 990 _rl_move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]); 991 last_lmargin = lmargin; 992 } 993 } 994 fflush (rl_outstream); 995 996 /* Swap visible and non-visible lines. */ 997 { 998 char *vtemp = visible_line; 999 int *itemp = vis_lbreaks, ntemp = vis_lbsize; 1000 1001 visible_line = invisible_line; 1002 invisible_line = vtemp; 1003 1004 vis_lbreaks = inv_lbreaks; 1005 inv_lbreaks = itemp; 1006 1007 vis_lbsize = inv_lbsize; 1008 inv_lbsize = ntemp; 1009 1010 rl_display_fixed = 0; 1011 /* If we are displaying on a single line, and last_lmargin is > 0, we 1012 are not displaying any invisible characters, so set visible_wrap_offset 1013 to 0. */ 1014 if (_rl_horizontal_scroll_mode && last_lmargin) 1015 visible_wrap_offset = 0; 1016 else 1017 visible_wrap_offset = wrap_offset; 1018 } 1019} 1020 1021/* PWP: update_line() is based on finding the middle difference of each 1022 line on the screen; vis: 1023 1024 /old first difference 1025 /beginning of line | /old last same /old EOL 1026 v v v v 1027old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as 1028new: eddie> Oh, my little buggy says to me, as lurgid as 1029 ^ ^ ^ ^ 1030 \beginning of line | \new last same \new end of line 1031 \new first difference 1032 1033 All are character pointers for the sake of speed. Special cases for 1034 no differences, as well as for end of line additions must be handled. 1035 1036 Could be made even smarter, but this works well enough */ 1037static void 1038update_line (old, new, current_line, omax, nmax, inv_botlin) 1039 register char *old, *new; 1040 int current_line, omax, nmax, inv_botlin; 1041{ 1042 register char *ofd, *ols, *oe, *nfd, *nls, *ne; 1043 int temp, lendiff, wsatend, od, nd; 1044 int current_invis_chars; 1045 int col_lendiff, col_temp; 1046#if defined (HANDLE_MULTIBYTE) 1047 mbstate_t ps_new, ps_old; 1048 int new_offset, old_offset, tmp; 1049#endif 1050 1051 /* If we're at the right edge of a terminal that supports xn, we're 1052 ready to wrap around, so do so. This fixes problems with knowing 1053 the exact cursor position and cut-and-paste with certain terminal 1054 emulators. In this calculation, TEMP is the physical screen 1055 position of the cursor. */ 1056 temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset); 1057 if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode 1058 && _rl_last_v_pos == current_line - 1) 1059 { 1060#if defined (HANDLE_MULTIBYTE) 1061 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1062 { 1063 wchar_t wc; 1064 mbstate_t ps; 1065 int tempwidth, bytes; 1066 size_t ret; 1067 1068 /* This fixes only double-column characters, but if the wrapped 1069 character comsumes more than three columns, spaces will be 1070 inserted in the string buffer. */ 1071 if (_rl_wrapped_line[current_line] > 0) 1072 _rl_clear_to_eol (_rl_wrapped_line[current_line]); 1073 1074 memset (&ps, 0, sizeof (mbstate_t)); 1075 ret = mbrtowc (&wc, new, MB_CUR_MAX, &ps); 1076 if (ret == (size_t)-1 || ret == (size_t)-2) 1077 { 1078 tempwidth = 1; 1079 ret = 1; 1080 } 1081 else if (ret == 0) 1082 tempwidth = 0; 1083 else 1084 tempwidth = wcwidth (wc); 1085 1086 if (tempwidth > 0) 1087 { 1088 int count; 1089 bytes = ret; 1090 for (count = 0; count < bytes; count++) 1091 putc (new[count], rl_outstream); 1092 _rl_last_c_pos = tempwidth; 1093 _rl_last_v_pos++; 1094 memset (&ps, 0, sizeof (mbstate_t)); 1095 ret = mbrtowc (&wc, old, MB_CUR_MAX, &ps); 1096 if (ret != 0 && bytes != 0) 1097 { 1098 if (ret == (size_t)-1 || ret == (size_t)-2) 1099 memmove (old+bytes, old+1, strlen (old+1)); 1100 else 1101 memmove (old+bytes, old+ret, strlen (old+ret)); 1102 memcpy (old, new, bytes); 1103 } 1104 } 1105 else 1106 { 1107 putc (' ', rl_outstream); 1108 _rl_last_c_pos = 1; 1109 _rl_last_v_pos++; 1110 if (old[0] && new[0]) 1111 old[0] = new[0]; 1112 } 1113 } 1114 else 1115#endif 1116 { 1117 if (new[0]) 1118 putc (new[0], rl_outstream); 1119 else 1120 putc (' ', rl_outstream); 1121 _rl_last_c_pos = 1; /* XXX */ 1122 _rl_last_v_pos++; 1123 if (old[0] && new[0]) 1124 old[0] = new[0]; 1125 } 1126 } 1127 1128 1129 /* Find first difference. */ 1130#if defined (HANDLE_MULTIBYTE) 1131 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1132 { 1133 memset (&ps_new, 0, sizeof(mbstate_t)); 1134 memset (&ps_old, 0, sizeof(mbstate_t)); 1135 1136 new_offset = old_offset = 0; 1137 for (ofd = old, nfd = new; 1138 (ofd - old < omax) && *ofd && 1139 _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new); ) 1140 { 1141 old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY); 1142 new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY); 1143 ofd = old + old_offset; 1144 nfd = new + new_offset; 1145 } 1146 } 1147 else 1148#endif 1149 for (ofd = old, nfd = new; 1150 (ofd - old < omax) && *ofd && (*ofd == *nfd); 1151 ofd++, nfd++) 1152 ; 1153 1154 /* Move to the end of the screen line. ND and OD are used to keep track 1155 of the distance between ne and new and oe and old, respectively, to 1156 move a subtraction out of each loop. */ 1157 for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++); 1158 for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++); 1159 1160 /* If no difference, continue to next line. */ 1161 if (ofd == oe && nfd == ne) 1162 return; 1163 1164 wsatend = 1; /* flag for trailing whitespace */ 1165 1166#if defined (HANDLE_MULTIBYTE) 1167 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1168 { 1169 ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY); 1170 nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY); 1171 while ((ols > ofd) && (nls > nfd)) 1172 { 1173 memset (&ps_old, 0, sizeof (mbstate_t)); 1174 memset (&ps_new, 0, sizeof (mbstate_t)); 1175 1176 _rl_adjust_point (old, ols - old, &ps_old); 1177 _rl_adjust_point (new, nls - new, &ps_new); 1178 1179 if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0) 1180 break; 1181 1182 if (*ols == ' ') 1183 wsatend = 0; 1184 1185 ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY); 1186 nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY); 1187 } 1188 } 1189 else 1190 { 1191#endif /* HANDLE_MULTIBYTE */ 1192 ols = oe - 1; /* find last same */ 1193 nls = ne - 1; 1194 while ((ols > ofd) && (nls > nfd) && (*ols == *nls)) 1195 { 1196 if (*ols != ' ') 1197 wsatend = 0; 1198 ols--; 1199 nls--; 1200 } 1201#if defined (HANDLE_MULTIBYTE) 1202 } 1203#endif 1204 1205 if (wsatend) 1206 { 1207 ols = oe; 1208 nls = ne; 1209 } 1210#if defined (HANDLE_MULTIBYTE) 1211 /* This may not work for stateful encoding, but who cares? To handle 1212 stateful encoding properly, we have to scan each string from the 1213 beginning and compare. */ 1214 else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0) 1215#else 1216 else if (*ols != *nls) 1217#endif 1218 { 1219 if (*ols) /* don't step past the NUL */ 1220 { 1221 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1222 ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY); 1223 else 1224 ols++; 1225 } 1226 if (*nls) 1227 { 1228 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1229 nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY); 1230 else 1231 nls++; 1232 } 1233 } 1234 1235 /* count of invisible characters in the current invisible line. */ 1236 current_invis_chars = W_OFFSET (current_line, wrap_offset); 1237 if (_rl_last_v_pos != current_line) 1238 { 1239 _rl_move_vert (current_line); 1240 if (current_line == 0 && visible_wrap_offset) 1241 _rl_last_c_pos += visible_wrap_offset; 1242 } 1243 1244 /* If this is the first line and there are invisible characters in the 1245 prompt string, and the prompt string has not changed, and the current 1246 cursor position is before the last invisible character in the prompt, 1247 and the index of the character to move to is past the end of the prompt 1248 string, then redraw the entire prompt string. We can only do this 1249 reliably if the terminal supports a `cr' capability. 1250 1251 This is not an efficiency hack -- there is a problem with redrawing 1252 portions of the prompt string if they contain terminal escape 1253 sequences (like drawing the `unbold' sequence without a corresponding 1254 `bold') that manifests itself on certain terminals. */ 1255 1256 lendiff = local_prompt ? strlen (local_prompt) : 0; 1257 od = ofd - old; /* index of first difference in visible line */ 1258 if (current_line == 0 && !_rl_horizontal_scroll_mode && 1259 _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 && 1260 od >= lendiff && _rl_last_c_pos <= prompt_last_invisible) 1261 { 1262#if defined (__MSDOS__) 1263 putc ('\r', rl_outstream); 1264#else 1265 tputs (_rl_term_cr, 1, _rl_output_character_function); 1266#endif 1267 _rl_output_some_chars (local_prompt, lendiff); 1268 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1269 _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff); 1270 else 1271 _rl_last_c_pos = lendiff; 1272 } 1273 1274 _rl_move_cursor_relative (od, old); 1275 1276 /* if (len (new) > len (old)) 1277 lendiff == difference in buffer 1278 col_lendiff == difference on screen 1279 When not using multibyte characters, these are equal */ 1280 lendiff = (nls - nfd) - (ols - ofd); 1281 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1282 col_lendiff = _rl_col_width (new, nfd - new, nls - new) - _rl_col_width (old, ofd - old, ols - old); 1283 else 1284 col_lendiff = lendiff; 1285 1286 /* If we are changing the number of invisible characters in a line, and 1287 the spot of first difference is before the end of the invisible chars, 1288 lendiff needs to be adjusted. */ 1289 if (current_line == 0 && !_rl_horizontal_scroll_mode && 1290 current_invis_chars != visible_wrap_offset) 1291 { 1292 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1293 { 1294 lendiff += visible_wrap_offset - current_invis_chars; 1295 col_lendiff += visible_wrap_offset - current_invis_chars; 1296 } 1297 else 1298 { 1299 lendiff += visible_wrap_offset - current_invis_chars; 1300 col_lendiff = lendiff; 1301 } 1302 } 1303 1304 /* Insert (diff (len (old), len (new)) ch. */ 1305 temp = ne - nfd; 1306 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1307 col_temp = _rl_col_width (new, nfd - new, ne - new); 1308 else 1309 col_temp = temp; 1310 1311 if (col_lendiff > 0) /* XXX - was lendiff */ 1312 { 1313 /* Non-zero if we're increasing the number of lines. */ 1314 int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin; 1315 /* Sometimes it is cheaper to print the characters rather than 1316 use the terminal's capabilities. If we're growing the number 1317 of lines, make sure we actually cause the new line to wrap 1318 around on auto-wrapping terminals. */ 1319 if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl)) 1320 { 1321 /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and 1322 _rl_horizontal_scroll_mode == 1, inserting the characters with 1323 _rl_term_IC or _rl_term_ic will screw up the screen because of the 1324 invisible characters. We need to just draw them. */ 1325 if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 || 1326 lendiff <= prompt_visible_length || !current_invis_chars)) 1327 { 1328 insert_some_chars (nfd, lendiff, col_lendiff); 1329 _rl_last_c_pos += col_lendiff; 1330 } 1331 else if (*ols == 0) 1332 { 1333 /* At the end of a line the characters do not have to 1334 be "inserted". They can just be placed on the screen. */ 1335 /* However, this screws up the rest of this block, which 1336 assumes you've done the insert because you can. */ 1337 _rl_output_some_chars (nfd, lendiff); 1338 _rl_last_c_pos += col_lendiff; 1339 } 1340 else 1341 { 1342 /* We have horizontal scrolling and we are not inserting at 1343 the end. We have invisible characters in this line. This 1344 is a dumb update. */ 1345 _rl_output_some_chars (nfd, temp); 1346 _rl_last_c_pos += col_temp; 1347 return; 1348 } 1349 /* Copy (new) chars to screen from first diff to last match. */ 1350 temp = nls - nfd; 1351 if ((temp - lendiff) > 0) 1352 { 1353 _rl_output_some_chars (nfd + lendiff, temp - lendiff); 1354#if 0 1355 _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-col_lendiff); 1356#else 1357 _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-lendiff); 1358#endif 1359 } 1360 } 1361 else 1362 { 1363 /* cannot insert chars, write to EOL */ 1364 _rl_output_some_chars (nfd, temp); 1365 _rl_last_c_pos += col_temp; 1366 } 1367 } 1368 else /* Delete characters from line. */ 1369 { 1370 /* If possible and inexpensive to use terminal deletion, then do so. */ 1371 if (_rl_term_dc && (2 * col_temp) >= -col_lendiff) 1372 { 1373 /* If all we're doing is erasing the invisible characters in the 1374 prompt string, don't bother. It screws up the assumptions 1375 about what's on the screen. */ 1376 if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 && 1377 -lendiff == visible_wrap_offset) 1378 col_lendiff = 0; 1379 1380 if (col_lendiff) 1381 delete_chars (-col_lendiff); /* delete (diff) characters */ 1382 1383 /* Copy (new) chars to screen from first diff to last match */ 1384 temp = nls - nfd; 1385 if (temp > 0) 1386 { 1387 _rl_output_some_chars (nfd, temp); 1388 _rl_last_c_pos += _rl_col_width (nfd, 0, temp);; 1389 } 1390 } 1391 /* Otherwise, print over the existing material. */ 1392 else 1393 { 1394 if (temp > 0) 1395 { 1396 _rl_output_some_chars (nfd, temp); 1397 _rl_last_c_pos += col_temp; 1398 } 1399 lendiff = (oe - old) - (ne - new); 1400 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1401 col_lendiff = _rl_col_width (old, 0, oe - old) - _rl_col_width (new, 0, ne - new); 1402 else 1403 col_lendiff = lendiff; 1404 1405 if (col_lendiff) 1406 { 1407 if (_rl_term_autowrap && current_line < inv_botlin) 1408 space_to_eol (col_lendiff); 1409 else 1410 _rl_clear_to_eol (col_lendiff); 1411 } 1412 } 1413 } 1414} 1415 1416/* Tell the update routines that we have moved onto a new (empty) line. */ 1417int 1418rl_on_new_line () 1419{ 1420 if (visible_line) 1421 visible_line[0] = '\0'; 1422 1423 _rl_last_c_pos = _rl_last_v_pos = 0; 1424 _rl_vis_botlin = last_lmargin = 0; 1425 if (vis_lbreaks) 1426 vis_lbreaks[0] = vis_lbreaks[1] = 0; 1427 visible_wrap_offset = 0; 1428 return 0; 1429} 1430 1431/* Tell the update routines that we have moved onto a new line with the 1432 prompt already displayed. Code originally from the version of readline 1433 distributed with CLISP. */ 1434int 1435rl_on_new_line_with_prompt () 1436{ 1437 int prompt_size, i, l, real_screenwidth, newlines; 1438 char *prompt_last_line; 1439 1440 /* Initialize visible_line and invisible_line to ensure that they can hold 1441 the already-displayed prompt. */ 1442 prompt_size = strlen (rl_prompt) + 1; 1443 init_line_structures (prompt_size); 1444 1445 /* Make sure the line structures hold the already-displayed prompt for 1446 redisplay. */ 1447 strcpy (visible_line, rl_prompt); 1448 strcpy (invisible_line, rl_prompt); 1449 1450 /* If the prompt contains newlines, take the last tail. */ 1451 prompt_last_line = strrchr (rl_prompt, '\n'); 1452 if (!prompt_last_line) 1453 prompt_last_line = rl_prompt; 1454 1455 l = strlen (prompt_last_line); 1456 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1457 _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l); 1458 else 1459 _rl_last_c_pos = l; 1460 1461 /* Dissect prompt_last_line into screen lines. Note that here we have 1462 to use the real screenwidth. Readline's notion of screenwidth might be 1463 one less, see terminal.c. */ 1464 real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1); 1465 _rl_last_v_pos = l / real_screenwidth; 1466 /* If the prompt length is a multiple of real_screenwidth, we don't know 1467 whether the cursor is at the end of the last line, or already at the 1468 beginning of the next line. Output a newline just to be safe. */ 1469 if (l > 0 && (l % real_screenwidth) == 0) 1470 _rl_output_some_chars ("\n", 1); 1471 last_lmargin = 0; 1472 1473 newlines = 0; i = 0; 1474 while (i <= l) 1475 { 1476 _rl_vis_botlin = newlines; 1477 vis_lbreaks[newlines++] = i; 1478 i += real_screenwidth; 1479 } 1480 vis_lbreaks[newlines] = l; 1481 visible_wrap_offset = 0; 1482 1483 return 0; 1484} 1485 1486/* Actually update the display, period. */ 1487int 1488rl_forced_update_display () 1489{ 1490 if (visible_line) 1491 { 1492 register char *temp = visible_line; 1493 1494 while (*temp) 1495 *temp++ = '\0'; 1496 } 1497 rl_on_new_line (); 1498 forced_display++; 1499 (*rl_redisplay_function) (); 1500 return 0; 1501} 1502 1503/* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices. 1504 DATA is the contents of the screen line of interest; i.e., where 1505 the movement is being done. */ 1506void 1507_rl_move_cursor_relative (new, data) 1508 int new; 1509 const char *data; 1510{ 1511 register int i; 1512 1513 /* If we don't have to do anything, then return. */ 1514#if defined (HANDLE_MULTIBYTE) 1515 /* If we have multibyte characters, NEW is indexed by the buffer point in 1516 a multibyte string, but _rl_last_c_pos is the display position. In 1517 this case, NEW's display position is not obvious and must be 1518 calculated. */ 1519 if (MB_CUR_MAX == 1 || rl_byte_oriented) 1520 { 1521 if (_rl_last_c_pos == new) 1522 return; 1523 } 1524 else if (_rl_last_c_pos == _rl_col_width (data, 0, new)) 1525 return; 1526#else 1527 if (_rl_last_c_pos == new) return; 1528#endif 1529 1530 /* It may be faster to output a CR, and then move forwards instead 1531 of moving backwards. */ 1532 /* i == current physical cursor position. */ 1533 i = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset); 1534 if (new == 0 || CR_FASTER (new, _rl_last_c_pos) || 1535 (_rl_term_autowrap && i == _rl_screenwidth)) 1536 { 1537#if defined (__MSDOS__) 1538 putc ('\r', rl_outstream); 1539#else 1540 tputs (_rl_term_cr, 1, _rl_output_character_function); 1541#endif /* !__MSDOS__ */ 1542 _rl_last_c_pos = 0; 1543 } 1544 1545 if (_rl_last_c_pos < new) 1546 { 1547 /* Move the cursor forward. We do it by printing the command 1548 to move the cursor forward if there is one, else print that 1549 portion of the output buffer again. Which is cheaper? */ 1550 1551 /* The above comment is left here for posterity. It is faster 1552 to print one character (non-control) than to print a control 1553 sequence telling the terminal to move forward one character. 1554 That kind of control is for people who don't know what the 1555 data is underneath the cursor. */ 1556#if defined (HACK_TERMCAP_MOTION) 1557 if (_rl_term_forward_char) 1558 { 1559 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1560 { 1561 int width; 1562 width = _rl_col_width (data, _rl_last_c_pos, new); 1563 for (i = 0; i < width; i++) 1564 tputs (_rl_term_forward_char, 1, _rl_output_character_function); 1565 } 1566 else 1567 { 1568 for (i = _rl_last_c_pos; i < new; i++) 1569 tputs (_rl_term_forward_char, 1, _rl_output_character_function); 1570 } 1571 } 1572 else if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1573 { 1574 tputs (_rl_term_cr, 1, _rl_output_character_function); 1575 for (i = 0; i < new; i++) 1576 putc (data[i], rl_outstream); 1577 } 1578 else 1579 for (i = _rl_last_c_pos; i < new; i++) 1580 putc (data[i], rl_outstream); 1581 1582#else /* !HACK_TERMCAP_MOTION */ 1583 1584 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1585 { 1586 tputs (_rl_term_cr, 1, _rl_output_character_function); 1587 for (i = 0; i < new; i++) 1588 putc (data[i], rl_outstream); 1589 } 1590 else 1591 for (i = _rl_last_c_pos; i < new; i++) 1592 putc (data[i], rl_outstream); 1593 1594#endif /* !HACK_TERMCAP_MOTION */ 1595 1596 } 1597#if defined (HANDLE_MULTIBYTE) 1598 /* NEW points to the buffer point, but _rl_last_c_pos is the display point. 1599 The byte length of the string is probably bigger than the column width 1600 of the string, which means that if NEW == _rl_last_c_pos, then NEW's 1601 display point is less than _rl_last_c_pos. */ 1602 else if (_rl_last_c_pos >= new) 1603#else 1604 else if (_rl_last_c_pos > new) 1605#endif 1606 { 1607 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1608 _rl_backspace (_rl_last_c_pos - _rl_col_width (data, 0, new)); 1609 else 1610 _rl_backspace (_rl_last_c_pos - new); 1611 } 1612 1613 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1614 _rl_last_c_pos = _rl_col_width (data, 0, new); 1615 else 1616 _rl_last_c_pos = new; 1617} 1618 1619/* PWP: move the cursor up or down. */ 1620void 1621_rl_move_vert (to) 1622 int to; 1623{ 1624 register int delta, i; 1625 1626 if (_rl_last_v_pos == to || to > _rl_screenheight) 1627 return; 1628 1629 if ((delta = to - _rl_last_v_pos) > 0) 1630 { 1631 for (i = 0; i < delta; i++) 1632 putc ('\n', rl_outstream); 1633#if defined (__MSDOS__) 1634 putc ('\r', rl_outstream); 1635#else 1636 tputs (_rl_term_cr, 1, _rl_output_character_function); 1637#endif 1638 _rl_last_c_pos = 0; 1639 } 1640 else 1641 { /* delta < 0 */ 1642#ifdef __MSDOS__ 1643 int row, col; 1644 1645 fflush (rl_outstream); /* make sure the cursor pos is current! */ 1646 ScreenGetCursor (&row, &col); 1647 ScreenSetCursor (row + delta, col); 1648 i = -delta; /* in case someone wants to use it after the loop */ 1649#else /* !__MSDOS__ */ 1650 if (_rl_term_up && *_rl_term_up) 1651 for (i = 0; i < -delta; i++) 1652 tputs (_rl_term_up, 1, _rl_output_character_function); 1653#endif /* !__MSDOS__ */ 1654 } 1655 1656 _rl_last_v_pos = to; /* Now TO is here */ 1657} 1658 1659/* Physically print C on rl_outstream. This is for functions which know 1660 how to optimize the display. Return the number of characters output. */ 1661int 1662rl_show_char (c) 1663 int c; 1664{ 1665 int n = 1; 1666 if (META_CHAR (c) && (_rl_output_meta_chars == 0)) 1667 { 1668 fprintf (rl_outstream, "M-"); 1669 n += 2; 1670 c = UNMETA (c); 1671 } 1672 1673#if defined (DISPLAY_TABS) 1674 if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT) 1675#else 1676 if (CTRL_CHAR (c) || c == RUBOUT) 1677#endif /* !DISPLAY_TABS */ 1678 { 1679 fprintf (rl_outstream, "C-"); 1680 n += 2; 1681 c = CTRL_CHAR (c) ? UNCTRL (c) : '?'; 1682 } 1683 1684 putc (c, rl_outstream); 1685 fflush (rl_outstream); 1686 return n; 1687} 1688 1689int 1690rl_character_len (c, pos) 1691 register int c, pos; 1692{ 1693 unsigned char uc; 1694 1695 uc = (unsigned char)c; 1696 1697 if (META_CHAR (uc)) 1698 return ((_rl_output_meta_chars == 0) ? 4 : 1); 1699 1700 if (uc == '\t') 1701 { 1702#if defined (DISPLAY_TABS) 1703 return (((pos | 7) + 1) - pos); 1704#else 1705 return (2); 1706#endif /* !DISPLAY_TABS */ 1707 } 1708 1709 if (CTRL_CHAR (c) || c == RUBOUT) 1710 return (2); 1711 1712 return ((ISPRINT (uc)) ? 1 : 2); 1713} 1714 1715/* How to print things in the "echo-area". The prompt is treated as a 1716 mini-modeline. */ 1717 1718#if defined (USE_VARARGS) 1719int 1720#if defined (PREFER_STDARG) 1721rl_message (const char *format, ...) 1722#else 1723rl_message (va_alist) 1724 va_dcl 1725#endif 1726{ 1727 va_list args; 1728#if defined (PREFER_VARARGS) 1729 char *format; 1730#endif 1731 1732#if defined (PREFER_STDARG) 1733 va_start (args, format); 1734#else 1735 va_start (args); 1736 format = va_arg (args, char *); 1737#endif 1738 1739#if defined (HAVE_VSNPRINTF) 1740 vsnprintf (msg_buf, sizeof (msg_buf) - 1, format, args); 1741#else 1742 vsprintf (msg_buf, format, args); 1743 msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */ 1744#endif 1745 va_end (args); 1746 1747 rl_display_prompt = msg_buf; 1748 (*rl_redisplay_function) (); 1749 return 0; 1750} 1751#else /* !USE_VARARGS */ 1752int 1753rl_message (format, arg1, arg2) 1754 char *format; 1755{ 1756 sprintf (msg_buf, format, arg1, arg2); 1757 msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */ 1758 rl_display_prompt = msg_buf; 1759 (*rl_redisplay_function) (); 1760 return 0; 1761} 1762#endif /* !USE_VARARGS */ 1763 1764/* How to clear things from the "echo-area". */ 1765int 1766rl_clear_message () 1767{ 1768 rl_display_prompt = rl_prompt; 1769 (*rl_redisplay_function) (); 1770 return 0; 1771} 1772 1773int 1774rl_reset_line_state () 1775{ 1776 rl_on_new_line (); 1777 1778 rl_display_prompt = rl_prompt ? rl_prompt : ""; 1779 forced_display = 1; 1780 return 0; 1781} 1782 1783static char *saved_local_prompt; 1784static char *saved_local_prefix; 1785static int saved_last_invisible; 1786static int saved_visible_length; 1787 1788void 1789rl_save_prompt () 1790{ 1791 saved_local_prompt = local_prompt; 1792 saved_local_prefix = local_prompt_prefix; 1793 saved_last_invisible = prompt_last_invisible; 1794 saved_visible_length = prompt_visible_length; 1795 1796 local_prompt = local_prompt_prefix = (char *)0; 1797 prompt_last_invisible = prompt_visible_length = 0; 1798} 1799 1800void 1801rl_restore_prompt () 1802{ 1803 FREE (local_prompt); 1804 FREE (local_prompt_prefix); 1805 1806 local_prompt = saved_local_prompt; 1807 local_prompt_prefix = saved_local_prefix; 1808 prompt_last_invisible = saved_last_invisible; 1809 prompt_visible_length = saved_visible_length; 1810} 1811 1812char * 1813_rl_make_prompt_for_search (pchar) 1814 int pchar; 1815{ 1816 int len; 1817 char *pmt; 1818 1819 rl_save_prompt (); 1820 1821 if (saved_local_prompt == 0) 1822 { 1823 len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0; 1824 pmt = (char *)xmalloc (len + 2); 1825 if (len) 1826 strcpy (pmt, rl_prompt); 1827 pmt[len] = pchar; 1828 pmt[len+1] = '\0'; 1829 } 1830 else 1831 { 1832 len = *saved_local_prompt ? strlen (saved_local_prompt) : 0; 1833 pmt = (char *)xmalloc (len + 2); 1834 if (len) 1835 strcpy (pmt, saved_local_prompt); 1836 pmt[len] = pchar; 1837 pmt[len+1] = '\0'; 1838 local_prompt = savestring (pmt); 1839 prompt_last_invisible = saved_last_invisible; 1840 prompt_visible_length = saved_visible_length + 1; 1841 } 1842 return pmt; 1843} 1844 1845/* Quick redisplay hack when erasing characters at the end of the line. */ 1846void 1847_rl_erase_at_end_of_line (l) 1848 int l; 1849{ 1850 register int i; 1851 1852 _rl_backspace (l); 1853 for (i = 0; i < l; i++) 1854 putc (' ', rl_outstream); 1855 _rl_backspace (l); 1856 for (i = 0; i < l; i++) 1857 visible_line[--_rl_last_c_pos] = '\0'; 1858 rl_display_fixed++; 1859} 1860 1861/* Clear to the end of the line. COUNT is the minimum 1862 number of character spaces to clear, */ 1863void 1864_rl_clear_to_eol (count) 1865 int count; 1866{ 1867#ifndef __MSDOS__ 1868 if (_rl_term_clreol) 1869 tputs (_rl_term_clreol, 1, _rl_output_character_function); 1870 else 1871#endif 1872 if (count) 1873 space_to_eol (count); 1874} 1875 1876/* Clear to the end of the line using spaces. COUNT is the minimum 1877 number of character spaces to clear, */ 1878static void 1879space_to_eol (count) 1880 int count; 1881{ 1882 register int i; 1883 1884 for (i = 0; i < count; i++) 1885 putc (' ', rl_outstream); 1886 1887 _rl_last_c_pos += count; 1888} 1889 1890void 1891_rl_clear_screen () 1892{ 1893#if defined (__GO32__) 1894 ScreenClear (); /* FIXME: only works in text modes */ 1895 ScreenSetCursor (0, 0); /* term_clrpag is "cl" which homes the cursor */ 1896#else 1897 if (_rl_term_clrpag) 1898 tputs (_rl_term_clrpag, 1, _rl_output_character_function); 1899 else 1900 rl_crlf (); 1901#endif 1902} 1903 1904/* Insert COUNT characters from STRING to the output stream at column COL. */ 1905static void 1906insert_some_chars (string, count, col) 1907 char *string; 1908 int count, col; 1909{ 1910#ifdef __MSDOS__ 1911 _rl_output_some_chars (string, count); 1912#else /* !__MSDOS__ */ 1913 /* DEBUGGING */ 1914 if (MB_CUR_MAX == 1 || rl_byte_oriented) 1915 if (count != col) 1916 fprintf(stderr, "readline: debug: insert_some_chars: count (%d) != col (%d)\n", count, col); 1917 1918 /* If IC is defined, then we do not have to "enter" insert mode. */ 1919 if (_rl_term_IC) 1920 { 1921 char *buffer; 1922 1923 buffer = tgoto (_rl_term_IC, 0, col); 1924 tputs (buffer, 1, _rl_output_character_function); 1925 _rl_output_some_chars (string, count); 1926 } 1927 else 1928 { 1929 register int i; 1930 1931 /* If we have to turn on insert-mode, then do so. */ 1932 if (_rl_term_im && *_rl_term_im) 1933 tputs (_rl_term_im, 1, _rl_output_character_function); 1934 1935 /* If there is a special command for inserting characters, then 1936 use that first to open up the space. */ 1937 if (_rl_term_ic && *_rl_term_ic) 1938 { 1939 for (i = col; i--; ) 1940 tputs (_rl_term_ic, 1, _rl_output_character_function); 1941 } 1942 1943 /* Print the text. */ 1944 _rl_output_some_chars (string, count); 1945 1946 /* If there is a string to turn off insert mode, we had best use 1947 it now. */ 1948 if (_rl_term_ei && *_rl_term_ei) 1949 tputs (_rl_term_ei, 1, _rl_output_character_function); 1950 } 1951#endif /* !__MSDOS__ */ 1952} 1953 1954/* Delete COUNT characters from the display line. */ 1955static void 1956delete_chars (count) 1957 int count; 1958{ 1959 if (count > _rl_screenwidth) /* XXX */ 1960 return; 1961 1962#ifndef __MSDOS__ 1963 if (_rl_term_DC && *_rl_term_DC) 1964 { 1965 char *buffer; 1966 buffer = tgoto (_rl_term_DC, count, count); 1967 tputs (buffer, count, _rl_output_character_function); 1968 } 1969 else 1970 { 1971 if (_rl_term_dc && *_rl_term_dc) 1972 while (count--) 1973 tputs (_rl_term_dc, 1, _rl_output_character_function); 1974 } 1975#endif /* !__MSDOS__ */ 1976} 1977 1978void 1979_rl_update_final () 1980{ 1981 int full_lines; 1982 1983 full_lines = 0; 1984 /* If the cursor is the only thing on an otherwise-blank last line, 1985 compensate so we don't print an extra CRLF. */ 1986 if (_rl_vis_botlin && _rl_last_c_pos == 0 && 1987 visible_line[vis_lbreaks[_rl_vis_botlin]] == 0) 1988 { 1989 _rl_vis_botlin--; 1990 full_lines = 1; 1991 } 1992 _rl_move_vert (_rl_vis_botlin); 1993 /* If we've wrapped lines, remove the final xterm line-wrap flag. */ 1994 if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth)) 1995 { 1996 char *last_line; 1997 1998 last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]]; 1999 _rl_move_cursor_relative (_rl_screenwidth - 1, last_line); 2000 _rl_clear_to_eol (0); 2001 putc (last_line[_rl_screenwidth - 1], rl_outstream); 2002 } 2003 _rl_vis_botlin = 0; 2004 rl_crlf (); 2005 fflush (rl_outstream); 2006 rl_display_fixed++; 2007} 2008 2009/* Move to the start of the current line. */ 2010static void 2011cr () 2012{ 2013 if (_rl_term_cr) 2014 { 2015#if defined (__MSDOS__) 2016 putc ('\r', rl_outstream); 2017#else 2018 tputs (_rl_term_cr, 1, _rl_output_character_function); 2019#endif 2020 _rl_last_c_pos = 0; 2021 } 2022} 2023 2024/* Redraw the last line of a multi-line prompt that may possibly contain 2025 terminal escape sequences. Called with the cursor at column 0 of the 2026 line to draw the prompt on. */ 2027static void 2028redraw_prompt (t) 2029 char *t; 2030{ 2031 char *oldp, *oldl, *oldlprefix; 2032 int oldlen, oldlast, oldplen, oldninvis; 2033 2034 /* Geez, I should make this a struct. */ 2035 oldp = rl_display_prompt; 2036 oldl = local_prompt; 2037 oldlprefix = local_prompt_prefix; 2038 oldlen = prompt_visible_length; 2039 oldplen = prompt_prefix_length; 2040 oldlast = prompt_last_invisible; 2041 oldninvis = prompt_invis_chars_first_line; 2042 2043 rl_display_prompt = t; 2044 local_prompt = expand_prompt (t, &prompt_visible_length, 2045 &prompt_last_invisible, 2046 &prompt_invis_chars_first_line); 2047 local_prompt_prefix = (char *)NULL; 2048 rl_forced_update_display (); 2049 2050 rl_display_prompt = oldp; 2051 local_prompt = oldl; 2052 local_prompt_prefix = oldlprefix; 2053 prompt_visible_length = oldlen; 2054 prompt_prefix_length = oldplen; 2055 prompt_last_invisible = oldlast; 2056 prompt_invis_chars_first_line = oldninvis; 2057} 2058 2059/* Redisplay the current line after a SIGWINCH is received. */ 2060void 2061_rl_redisplay_after_sigwinch () 2062{ 2063 char *t; 2064 2065 /* Clear the current line and put the cursor at column 0. Make sure 2066 the right thing happens if we have wrapped to a new screen line. */ 2067 if (_rl_term_cr) 2068 { 2069#if defined (__MSDOS__) 2070 putc ('\r', rl_outstream); 2071#else 2072 tputs (_rl_term_cr, 1, _rl_output_character_function); 2073#endif 2074 _rl_last_c_pos = 0; 2075#if defined (__MSDOS__) 2076 space_to_eol (_rl_screenwidth); 2077 putc ('\r', rl_outstream); 2078#else 2079 if (_rl_term_clreol) 2080 tputs (_rl_term_clreol, 1, _rl_output_character_function); 2081 else 2082 { 2083 space_to_eol (_rl_screenwidth); 2084 tputs (_rl_term_cr, 1, _rl_output_character_function); 2085 } 2086#endif 2087 if (_rl_last_v_pos > 0) 2088 _rl_move_vert (0); 2089 } 2090 else 2091 rl_crlf (); 2092 2093 /* Redraw only the last line of a multi-line prompt. */ 2094 t = strrchr (rl_display_prompt, '\n'); 2095 if (t) 2096 redraw_prompt (++t); 2097 else 2098 rl_forced_update_display (); 2099} 2100 2101void 2102_rl_clean_up_for_exit () 2103{ 2104 if (readline_echoing_p) 2105 { 2106 _rl_move_vert (_rl_vis_botlin); 2107 _rl_vis_botlin = 0; 2108 fflush (rl_outstream); 2109 rl_restart_output (1, 0); 2110 } 2111} 2112 2113void 2114_rl_erase_entire_line () 2115{ 2116 cr (); 2117 _rl_clear_to_eol (0); 2118 cr (); 2119 fflush (rl_outstream); 2120} 2121 2122/* return the `current display line' of the cursor -- the number of lines to 2123 move up to get to the first screen line of the current readline line. */ 2124int 2125_rl_current_display_line () 2126{ 2127 int ret, nleft; 2128 2129 /* Find out whether or not there might be invisible characters in the 2130 editing buffer. */ 2131 if (rl_display_prompt == rl_prompt) 2132 nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length; 2133 else 2134 nleft = _rl_last_c_pos - _rl_screenwidth; 2135 2136 if (nleft > 0) 2137 ret = 1 + nleft / _rl_screenwidth; 2138 else 2139 ret = 0; 2140 2141 return ret; 2142} 2143 2144#if defined (HANDLE_MULTIBYTE) 2145/* Calculate the number of screen columns occupied by STR from START to END. 2146 In the case of multibyte characters with stateful encoding, we have to 2147 scan from the beginning of the string to take the state into account. */ 2148static int 2149_rl_col_width (str, start, end) 2150 const char *str; 2151 int start, end; 2152{ 2153 wchar_t wc; 2154 mbstate_t ps = {0}; 2155 int tmp, point, width, max; 2156 2157 if (end <= start) 2158 return 0; 2159 2160 point = 0; 2161 max = end; 2162 2163 while (point < start) 2164 { 2165 tmp = mbrlen (str + point, max, &ps); 2166 if ((size_t)tmp == (size_t)-1 || (size_t)tmp == (size_t)-2) 2167 { 2168 /* In this case, the bytes are invalid or too short to compose a 2169 multibyte character, so we assume that the first byte represents 2170 a single character. */ 2171 point++; 2172 max--; 2173 2174 /* Clear the state of the byte sequence, because in this case the 2175 effect of mbstate is undefined. */ 2176 memset (&ps, 0, sizeof (mbstate_t)); 2177 } 2178 else if (tmp == 0) 2179 break; /* Found '\0' */ 2180 else 2181 { 2182 point += tmp; 2183 max -= tmp; 2184 } 2185 } 2186 2187 /* If START is not a byte that starts a character, then POINT will be 2188 greater than START. In this case, assume that (POINT - START) gives 2189 a byte count that is the number of columns of difference. */ 2190 width = point - start; 2191 2192 while (point < end) 2193 { 2194 tmp = mbrtowc (&wc, str + point, max, &ps); 2195 if ((size_t)tmp == (size_t)-1 || (size_t)tmp == (size_t)-2) 2196 { 2197 /* In this case, the bytes are invalid or too short to compose a 2198 multibyte character, so we assume that the first byte represents 2199 a single character. */ 2200 point++; 2201 max--; 2202 2203 /* and assume that the byte occupies a single column. */ 2204 width++; 2205 2206 /* Clear the state of the byte sequence, because in this case the 2207 effect of mbstate is undefined. */ 2208 memset (&ps, 0, sizeof (mbstate_t)); 2209 } 2210 else if (tmp == 0) 2211 break; /* Found '\0' */ 2212 else 2213 { 2214 point += tmp; 2215 max -= tmp; 2216 tmp = wcwidth(wc); 2217 width += (tmp >= 0) ? tmp : 1; 2218 } 2219 } 2220 2221 width += point - end; 2222 2223 return width; 2224} 2225#endif /* HANDLE_MULTIBYTE */ 2226