Annotation of embedaddon/readline/display.c, revision 1.1
1.1 ! misho 1: /* display.c -- readline redisplay facility. */
! 2:
! 3: /* Copyright (C) 1987-2013 Free Software Foundation, Inc.
! 4:
! 5: This file is part of the GNU Readline Library (Readline), a library
! 6: for reading lines of text with interactive input and history editing.
! 7:
! 8: Readline is free software: you can redistribute it and/or modify
! 9: it under the terms of the GNU General Public License as published by
! 10: the Free Software Foundation, either version 3 of the License, or
! 11: (at your option) any later version.
! 12:
! 13: Readline is distributed in the hope that it will be useful,
! 14: but WITHOUT ANY WARRANTY; without even the implied warranty of
! 15: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 16: GNU General Public License for more details.
! 17:
! 18: You should have received a copy of the GNU General Public License
! 19: along with Readline. If not, see <http://www.gnu.org/licenses/>.
! 20: */
! 21:
! 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__)
! 63: extern char *strchr (), *strrchr ();
! 64: #endif /* !strchr && !__STDC__ */
! 65:
! 66: static void update_line PARAMS((char *, char *, int, int, int, int));
! 67: static void space_to_eol PARAMS((int));
! 68: static void delete_chars PARAMS((int));
! 69: static void insert_some_chars PARAMS((char *, int, int));
! 70: static void open_some_spaces PARAMS((int));
! 71: static void cr PARAMS((void));
! 72:
! 73: /* State of visible and invisible lines. */
! 74: struct line_state
! 75: {
! 76: char *line;
! 77: int *lbreaks;
! 78: int lbsize;
! 79: #if defined (HANDLE_MULTIBYTE)
! 80: int *wrapped_line;
! 81: int wbsize;
! 82: #endif
! 83: };
! 84:
! 85: /* The line display buffers. One is the line currently displayed on
! 86: the screen. The other is the line about to be displayed. */
! 87: static struct line_state line_state_array[2];
! 88: static struct line_state *line_state_visible = &line_state_array[0];
! 89: static struct line_state *line_state_invisible = &line_state_array[1];
! 90: static int line_structures_initialized = 0;
! 91:
! 92: /* Backwards-compatible names. */
! 93: #define inv_lbreaks (line_state_invisible->lbreaks)
! 94: #define inv_lbsize (line_state_invisible->lbsize)
! 95: #define vis_lbreaks (line_state_visible->lbreaks)
! 96: #define vis_lbsize (line_state_visible->lbsize)
! 97:
! 98: #define visible_line (line_state_visible->line)
! 99: #define invisible_line (line_state_invisible->line)
! 100:
! 101: #if defined (HANDLE_MULTIBYTE)
! 102: static int _rl_col_width PARAMS((const char *, int, int, int));
! 103: #else
! 104: # define _rl_col_width(l, s, e, f) (((e) <= (s)) ? 0 : (e) - (s))
! 105: #endif
! 106:
! 107: /* Heuristic used to decide whether it is faster to move from CUR to NEW
! 108: by backing up or outputting a carriage return and moving forward. CUR
! 109: and NEW are either both buffer positions or absolute screen positions. */
! 110: #define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new)))
! 111:
! 112: /* _rl_last_c_pos is an absolute cursor position in multibyte locales and a
! 113: buffer index in others. This macro is used when deciding whether the
! 114: current cursor position is in the middle of a prompt string containing
! 115: invisible characters. XXX - might need to take `modmark' into account. */
! 116: #define PROMPT_ENDING_INDEX \
! 117: ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) ? prompt_physical_chars : prompt_last_invisible+1)
! 118:
! 119:
! 120: /* **************************************************************** */
! 121: /* */
! 122: /* Display stuff */
! 123: /* */
! 124: /* **************************************************************** */
! 125:
! 126: /* This is the stuff that is hard for me. I never seem to write good
! 127: display routines in C. Let's see how I do this time. */
! 128:
! 129: /* (PWP) Well... Good for a simple line updater, but totally ignores
! 130: the problems of input lines longer than the screen width.
! 131:
! 132: update_line and the code that calls it makes a multiple line,
! 133: automatically wrapping line update. Careful attention needs
! 134: to be paid to the vertical position variables. */
! 135:
! 136: /* Keep two buffers; one which reflects the current contents of the
! 137: screen, and the other to draw what we think the new contents should
! 138: be. Then compare the buffers, and make whatever changes to the
! 139: screen itself that we should. Finally, make the buffer that we
! 140: just drew into be the one which reflects the current contents of the
! 141: screen, and place the cursor where it belongs.
! 142:
! 143: Commands that want to can fix the display themselves, and then let
! 144: this function know that the display has been fixed by setting the
! 145: RL_DISPLAY_FIXED variable. This is good for efficiency. */
! 146:
! 147: /* Application-specific redisplay function. */
! 148: rl_voidfunc_t *rl_redisplay_function = rl_redisplay;
! 149:
! 150: /* Global variables declared here. */
! 151: /* What YOU turn on when you have handled all redisplay yourself. */
! 152: int rl_display_fixed = 0;
! 153:
! 154: int _rl_suppress_redisplay = 0;
! 155: int _rl_want_redisplay = 0;
! 156:
! 157: /* The stuff that gets printed out before the actual text of the line.
! 158: This is usually pointing to rl_prompt. */
! 159: char *rl_display_prompt = (char *)NULL;
! 160:
! 161: /* Pseudo-global variables declared here. */
! 162:
! 163: /* The visible cursor position. If you print some text, adjust this. */
! 164: /* NOTE: _rl_last_c_pos is used as a buffer index when not in a locale
! 165: supporting multibyte characters, and an absolute cursor position when
! 166: in such a locale. This is an artifact of the donated multibyte support.
! 167: Care must be taken when modifying its value. */
! 168: int _rl_last_c_pos = 0;
! 169: int _rl_last_v_pos = 0;
! 170:
! 171: static int cpos_adjusted;
! 172: static int cpos_buffer_position;
! 173: static int displaying_prompt_first_line;
! 174: static int prompt_multibyte_chars;
! 175:
! 176: /* Number of lines currently on screen minus 1. */
! 177: int _rl_vis_botlin = 0;
! 178:
! 179: /* Variables used only in this file. */
! 180: /* The last left edge of text that was displayed. This is used when
! 181: doing horizontal scrolling. It shifts in thirds of a screenwidth. */
! 182: static int last_lmargin;
! 183:
! 184: /* A buffer for `modeline' messages. */
! 185: static char *msg_buf = 0;
! 186: static int msg_bufsiz = 0;
! 187:
! 188: /* Non-zero forces the redisplay even if we thought it was unnecessary. */
! 189: static int forced_display;
! 190:
! 191: /* Default and initial buffer size. Can grow. */
! 192: static int line_size = 1024;
! 193:
! 194: /* Variables to keep track of the expanded prompt string, which may
! 195: include invisible characters. */
! 196:
! 197: static char *local_prompt, *local_prompt_prefix;
! 198: static int local_prompt_len;
! 199: static int prompt_visible_length, prompt_prefix_length;
! 200:
! 201: /* The number of invisible characters in the line currently being
! 202: displayed on the screen. */
! 203: static int visible_wrap_offset;
! 204:
! 205: /* The number of invisible characters in the prompt string. Static so it
! 206: can be shared between rl_redisplay and update_line */
! 207: static int wrap_offset;
! 208:
! 209: /* The index of the last invisible character in the prompt string. */
! 210: static int prompt_last_invisible;
! 211:
! 212: /* The length (buffer offset) of the first line of the last (possibly
! 213: multi-line) buffer displayed on the screen. */
! 214: static int visible_first_line_len;
! 215:
! 216: /* Number of invisible characters on the first physical line of the prompt.
! 217: Only valid when the number of physical characters in the prompt exceeds
! 218: (or is equal to) _rl_screenwidth. */
! 219: static int prompt_invis_chars_first_line;
! 220:
! 221: static int prompt_last_screen_line;
! 222:
! 223: static int prompt_physical_chars;
! 224:
! 225: /* set to a non-zero value by rl_redisplay if we are marking modified history
! 226: lines and the current line is so marked. */
! 227: static int modmark;
! 228:
! 229: /* Variables to save and restore prompt and display information. */
! 230:
! 231: /* These are getting numerous enough that it's time to create a struct. */
! 232:
! 233: static char *saved_local_prompt;
! 234: static char *saved_local_prefix;
! 235: static int saved_last_invisible;
! 236: static int saved_visible_length;
! 237: static int saved_prefix_length;
! 238: static int saved_local_length;
! 239: static int saved_invis_chars_first_line;
! 240: static int saved_physical_chars;
! 241:
! 242: /* Return a character indicating the editing mode, for use in the prompt. */
! 243: static int
! 244: prompt_modechar ()
! 245: {
! 246: if (rl_editing_mode == emacs_mode)
! 247: return '@';
! 248: else if (_rl_keymap == vi_insertion_keymap)
! 249: return '+'; /* vi insert mode */
! 250: else
! 251: return ':'; /* vi command mode */
! 252: }
! 253:
! 254: /* Expand the prompt string S and return the number of visible
! 255: characters in *LP, if LP is not null. This is currently more-or-less
! 256: a placeholder for expansion. LIP, if non-null is a place to store the
! 257: index of the last invisible character in the returned string. NIFLP,
! 258: if non-zero, is a place to store the number of invisible characters in
! 259: the first prompt line. The previous are used as byte counts -- indexes
! 260: into a character buffer. */
! 261:
! 262: /* Current implementation:
! 263: \001 (^A) start non-visible characters
! 264: \002 (^B) end non-visible characters
! 265: all characters except \001 and \002 (following a \001) are copied to
! 266: the returned string; all characters except those between \001 and
! 267: \002 are assumed to be `visible'. */
! 268:
! 269: static char *
! 270: expand_prompt (pmt, lp, lip, niflp, vlp)
! 271: char *pmt;
! 272: int *lp, *lip, *niflp, *vlp;
! 273: {
! 274: char *r, *ret, *p, *igstart;
! 275: int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars;
! 276:
! 277: /* Short-circuit if we can. */
! 278: if ((MB_CUR_MAX <= 1 || rl_byte_oriented) && strchr (pmt, RL_PROMPT_START_IGNORE) == 0)
! 279: {
! 280: if (pmt == rl_prompt && _rl_show_mode_in_prompt)
! 281: {
! 282: l = strlen (pmt);
! 283: r = (char *)xmalloc (l + 2);
! 284: r[0] = prompt_modechar ();
! 285: strcpy (r + 1, pmt);
! 286: }
! 287: else
! 288: r = savestring (pmt);
! 289:
! 290: if (lp)
! 291: *lp = strlen (r);
! 292: if (lip)
! 293: *lip = 0;
! 294: if (niflp)
! 295: *niflp = 0;
! 296: if (vlp)
! 297: *vlp = lp ? *lp : strlen (r);
! 298: return r;
! 299: }
! 300:
! 301: l = strlen (pmt);
! 302: r = ret = (char *)xmalloc (l + 2);
! 303:
! 304: rl = physchars = 0; /* move up here so mode show can set them */
! 305: if (pmt == rl_prompt && _rl_show_mode_in_prompt)
! 306: {
! 307: *r++ = prompt_modechar ();
! 308: rl = physchars = 1;
! 309: }
! 310:
! 311: invfl = 0; /* invisible chars in first line of prompt */
! 312: invflset = 0; /* we only want to set invfl once */
! 313:
! 314: igstart = 0;
! 315: for (ignoring = last = ninvis = 0, p = pmt; p && *p; p++)
! 316: {
! 317: /* This code strips the invisible character string markers
! 318: RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
! 319: if (ignoring == 0 && *p == RL_PROMPT_START_IGNORE) /* XXX - check ignoring? */
! 320: {
! 321: ignoring = 1;
! 322: igstart = p;
! 323: continue;
! 324: }
! 325: else if (ignoring && *p == RL_PROMPT_END_IGNORE)
! 326: {
! 327: ignoring = 0;
! 328: if (p != (igstart + 1))
! 329: last = r - ret - 1;
! 330: continue;
! 331: }
! 332: else
! 333: {
! 334: #if defined (HANDLE_MULTIBYTE)
! 335: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
! 336: {
! 337: pind = p - pmt;
! 338: ind = _rl_find_next_mbchar (pmt, pind, 1, MB_FIND_NONZERO);
! 339: l = ind - pind;
! 340: while (l--)
! 341: *r++ = *p++;
! 342: if (!ignoring)
! 343: {
! 344: /* rl ends up being assigned to prompt_visible_length,
! 345: which is the number of characters in the buffer that
! 346: contribute to characters on the screen, which might
! 347: not be the same as the number of physical characters
! 348: on the screen in the presence of multibyte characters */
! 349: rl += ind - pind;
! 350: physchars += _rl_col_width (pmt, pind, ind, 0);
! 351: }
! 352: else
! 353: ninvis += ind - pind;
! 354: p--; /* compensate for later increment */
! 355: }
! 356: else
! 357: #endif
! 358: {
! 359: *r++ = *p;
! 360: if (!ignoring)
! 361: {
! 362: rl++; /* visible length byte counter */
! 363: physchars++;
! 364: }
! 365: else
! 366: ninvis++; /* invisible chars byte counter */
! 367: }
! 368:
! 369: if (invflset == 0 && rl >= _rl_screenwidth)
! 370: {
! 371: invfl = ninvis;
! 372: invflset = 1;
! 373: }
! 374: }
! 375: }
! 376:
! 377: if (rl < _rl_screenwidth)
! 378: invfl = ninvis;
! 379:
! 380: *r = '\0';
! 381: if (lp)
! 382: *lp = rl;
! 383: if (lip)
! 384: *lip = last;
! 385: if (niflp)
! 386: *niflp = invfl;
! 387: if (vlp)
! 388: *vlp = physchars;
! 389: return ret;
! 390: }
! 391:
! 392: /* Just strip out RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE from
! 393: PMT and return the rest of PMT. */
! 394: char *
! 395: _rl_strip_prompt (pmt)
! 396: char *pmt;
! 397: {
! 398: char *ret;
! 399:
! 400: ret = expand_prompt (pmt, (int *)NULL, (int *)NULL, (int *)NULL, (int *)NULL);
! 401: return ret;
! 402: }
! 403:
! 404: void
! 405: _rl_reset_prompt ()
! 406: {
! 407: rl_visible_prompt_length = rl_expand_prompt (rl_prompt);
! 408: }
! 409:
! 410: /*
! 411: * Expand the prompt string into the various display components, if
! 412: * necessary.
! 413: *
! 414: * local_prompt = expanded last line of string in rl_display_prompt
! 415: * (portion after the final newline)
! 416: * local_prompt_prefix = portion before last newline of rl_display_prompt,
! 417: * expanded via expand_prompt
! 418: * prompt_visible_length = number of visible characters in local_prompt
! 419: * prompt_prefix_length = number of visible characters in local_prompt_prefix
! 420: *
! 421: * This function is called once per call to readline(). It may also be
! 422: * called arbitrarily to expand the primary prompt.
! 423: *
! 424: * The return value is the number of visible characters on the last line
! 425: * of the (possibly multi-line) prompt.
! 426: */
! 427: int
! 428: rl_expand_prompt (prompt)
! 429: char *prompt;
! 430: {
! 431: char *p, *t;
! 432: int c;
! 433:
! 434: /* Clear out any saved values. */
! 435: FREE (local_prompt);
! 436: FREE (local_prompt_prefix);
! 437:
! 438: local_prompt = local_prompt_prefix = (char *)0;
! 439: local_prompt_len = 0;
! 440: prompt_last_invisible = prompt_invis_chars_first_line = 0;
! 441: prompt_visible_length = prompt_physical_chars = 0;
! 442:
! 443: if (prompt == 0 || *prompt == 0)
! 444: return (0);
! 445:
! 446: p = strrchr (prompt, '\n');
! 447: if (!p)
! 448: {
! 449: /* The prompt is only one logical line, though it might wrap. */
! 450: local_prompt = expand_prompt (prompt, &prompt_visible_length,
! 451: &prompt_last_invisible,
! 452: &prompt_invis_chars_first_line,
! 453: &prompt_physical_chars);
! 454: local_prompt_prefix = (char *)0;
! 455: local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
! 456: return (prompt_visible_length);
! 457: }
! 458: else
! 459: {
! 460: /* The prompt spans multiple lines. */
! 461: t = ++p;
! 462: local_prompt = expand_prompt (p, &prompt_visible_length,
! 463: &prompt_last_invisible,
! 464: &prompt_invis_chars_first_line,
! 465: &prompt_physical_chars);
! 466: c = *t; *t = '\0';
! 467: /* The portion of the prompt string up to and including the
! 468: final newline is now null-terminated. */
! 469: local_prompt_prefix = expand_prompt (prompt, &prompt_prefix_length,
! 470: (int *)NULL,
! 471: (int *)NULL,
! 472: (int *)NULL);
! 473: *t = c;
! 474: local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
! 475: return (prompt_prefix_length);
! 476: }
! 477: }
! 478:
! 479: /* Initialize the VISIBLE_LINE and INVISIBLE_LINE arrays, and their associated
! 480: arrays of line break markers. MINSIZE is the minimum size of VISIBLE_LINE
! 481: and INVISIBLE_LINE; if it is greater than LINE_SIZE, LINE_SIZE is
! 482: increased. If the lines have already been allocated, this ensures that
! 483: they can hold at least MINSIZE characters. */
! 484: static void
! 485: init_line_structures (minsize)
! 486: int minsize;
! 487: {
! 488: register int n;
! 489:
! 490: if (invisible_line == 0) /* initialize it */
! 491: {
! 492: if (line_size < minsize)
! 493: line_size = minsize;
! 494: visible_line = (char *)xmalloc (line_size);
! 495: invisible_line = (char *)xmalloc (line_size);
! 496: }
! 497: else if (line_size < minsize) /* ensure it can hold MINSIZE chars */
! 498: {
! 499: line_size *= 2;
! 500: if (line_size < minsize)
! 501: line_size = minsize;
! 502: visible_line = (char *)xrealloc (visible_line, line_size);
! 503: invisible_line = (char *)xrealloc (invisible_line, line_size);
! 504: }
! 505:
! 506: for (n = minsize; n < line_size; n++)
! 507: {
! 508: visible_line[n] = 0;
! 509: invisible_line[n] = 1;
! 510: }
! 511:
! 512: if (vis_lbreaks == 0)
! 513: {
! 514: /* should be enough. */
! 515: inv_lbsize = vis_lbsize = 256;
! 516:
! 517: #if defined (HANDLE_MULTIBYTE)
! 518: line_state_visible->wbsize = vis_lbsize;
! 519: line_state_visible->wrapped_line = (int *)xmalloc (line_state_visible->wbsize * sizeof (int));
! 520:
! 521: line_state_invisible->wbsize = inv_lbsize;
! 522: line_state_invisible->wrapped_line = (int *)xmalloc (line_state_invisible->wbsize * sizeof (int));
! 523: #endif
! 524:
! 525: inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int));
! 526: vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int));
! 527: inv_lbreaks[0] = vis_lbreaks[0] = 0;
! 528: }
! 529:
! 530: line_structures_initialized = 1;
! 531: }
! 532:
! 533: /* Basic redisplay algorithm. */
! 534: void
! 535: rl_redisplay ()
! 536: {
! 537: register int in, out, c, linenum, cursor_linenum;
! 538: register char *line;
! 539: int inv_botlin, lb_botlin, lb_linenum, o_cpos;
! 540: int newlines, lpos, temp, n0, num, prompt_lines_estimate;
! 541: char *prompt_this_line;
! 542: #if defined (HANDLE_MULTIBYTE)
! 543: wchar_t wc;
! 544: size_t wc_bytes;
! 545: int wc_width;
! 546: mbstate_t ps;
! 547: int _rl_wrapped_multicolumn = 0;
! 548: #endif
! 549:
! 550: if (_rl_echoing_p == 0)
! 551: return;
! 552:
! 553: /* Block keyboard interrupts because this function manipulates global
! 554: data structures. */
! 555: _rl_block_sigint ();
! 556: RL_SETSTATE (RL_STATE_REDISPLAYING);
! 557:
! 558: if (!rl_display_prompt)
! 559: rl_display_prompt = "";
! 560:
! 561: if (line_structures_initialized == 0)
! 562: {
! 563: init_line_structures (0);
! 564: rl_on_new_line ();
! 565: }
! 566:
! 567: /* Draw the line into the buffer. */
! 568: cpos_buffer_position = -1;
! 569:
! 570: prompt_multibyte_chars = prompt_visible_length - prompt_physical_chars;
! 571:
! 572: line = invisible_line;
! 573: out = inv_botlin = 0;
! 574:
! 575: /* Mark the line as modified or not. We only do this for history
! 576: lines. */
! 577: modmark = 0;
! 578: if (_rl_mark_modified_lines && current_history () && rl_undo_list)
! 579: {
! 580: line[out++] = '*';
! 581: line[out] = '\0';
! 582: modmark = 1;
! 583: }
! 584:
! 585: /* If someone thought that the redisplay was handled, but the currently
! 586: visible line has a different modification state than the one about
! 587: to become visible, then correct the caller's misconception. */
! 588: if (visible_line[0] != invisible_line[0])
! 589: rl_display_fixed = 0;
! 590:
! 591: /* If the prompt to be displayed is the `primary' readline prompt (the
! 592: one passed to readline()), use the values we have already expanded.
! 593: If not, use what's already in rl_display_prompt. WRAP_OFFSET is the
! 594: number of non-visible characters in the prompt string. */
! 595: if (rl_display_prompt == rl_prompt || local_prompt)
! 596: {
! 597: if (local_prompt_prefix && forced_display)
! 598: _rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix));
! 599:
! 600: if (local_prompt_len > 0)
! 601: {
! 602: temp = local_prompt_len + out + 2;
! 603: if (temp >= line_size)
! 604: {
! 605: line_size = (temp + 1024) - (temp % 1024);
! 606: visible_line = (char *)xrealloc (visible_line, line_size);
! 607: line = invisible_line = (char *)xrealloc (invisible_line, line_size);
! 608: }
! 609: strncpy (line + out, local_prompt, local_prompt_len);
! 610: out += local_prompt_len;
! 611: }
! 612: line[out] = '\0';
! 613: wrap_offset = local_prompt_len - prompt_visible_length;
! 614: }
! 615: else
! 616: {
! 617: int pmtlen;
! 618: prompt_this_line = strrchr (rl_display_prompt, '\n');
! 619: if (!prompt_this_line)
! 620: prompt_this_line = rl_display_prompt;
! 621: else
! 622: {
! 623: prompt_this_line++;
! 624: pmtlen = prompt_this_line - rl_display_prompt; /* temp var */
! 625: if (forced_display)
! 626: {
! 627: _rl_output_some_chars (rl_display_prompt, pmtlen);
! 628: /* Make sure we are at column zero even after a newline,
! 629: regardless of the state of terminal output processing. */
! 630: if (pmtlen < 2 || prompt_this_line[-2] != '\r')
! 631: cr ();
! 632: }
! 633: }
! 634:
! 635: prompt_physical_chars = pmtlen = strlen (prompt_this_line);
! 636: temp = pmtlen + out + 2;
! 637: if (temp >= line_size)
! 638: {
! 639: line_size = (temp + 1024) - (temp % 1024);
! 640: visible_line = (char *)xrealloc (visible_line, line_size);
! 641: line = invisible_line = (char *)xrealloc (invisible_line, line_size);
! 642: }
! 643: strncpy (line + out, prompt_this_line, pmtlen);
! 644: out += pmtlen;
! 645: line[out] = '\0';
! 646: wrap_offset = prompt_invis_chars_first_line = 0;
! 647: }
! 648:
! 649: #define CHECK_INV_LBREAKS() \
! 650: do { \
! 651: if (newlines >= (inv_lbsize - 2)) \
! 652: { \
! 653: inv_lbsize *= 2; \
! 654: inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
! 655: } \
! 656: } while (0)
! 657:
! 658: #if defined (HANDLE_MULTIBYTE)
! 659: #define CHECK_LPOS() \
! 660: do { \
! 661: lpos++; \
! 662: if (lpos >= _rl_screenwidth) \
! 663: { \
! 664: if (newlines >= (inv_lbsize - 2)) \
! 665: { \
! 666: inv_lbsize *= 2; \
! 667: inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
! 668: } \
! 669: inv_lbreaks[++newlines] = out; \
! 670: if (newlines >= (line_state_invisible->wbsize - 1)) \
! 671: { \
! 672: line_state_invisible->wbsize *= 2; \
! 673: line_state_invisible->wrapped_line = (int *)xrealloc (line_state_invisible->wrapped_line, line_state_invisible->wbsize * sizeof(int)); \
! 674: } \
! 675: line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn; \
! 676: lpos = 0; \
! 677: } \
! 678: } while (0)
! 679: #else
! 680: #define CHECK_LPOS() \
! 681: do { \
! 682: lpos++; \
! 683: if (lpos >= _rl_screenwidth) \
! 684: { \
! 685: if (newlines >= (inv_lbsize - 2)) \
! 686: { \
! 687: inv_lbsize *= 2; \
! 688: inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
! 689: } \
! 690: inv_lbreaks[++newlines] = out; \
! 691: lpos = 0; \
! 692: } \
! 693: } while (0)
! 694: #endif
! 695:
! 696: /* inv_lbreaks[i] is where line i starts in the buffer. */
! 697: inv_lbreaks[newlines = 0] = 0;
! 698: lpos = prompt_physical_chars + modmark;
! 699:
! 700: #if defined (HANDLE_MULTIBYTE)
! 701: memset (line_state_invisible->wrapped_line, 0, line_state_invisible->wbsize * sizeof (int));
! 702: num = 0;
! 703: #endif
! 704:
! 705: /* prompt_invis_chars_first_line is the number of invisible characters in
! 706: the first physical line of the prompt.
! 707: wrap_offset - prompt_invis_chars_first_line is the number of invis
! 708: chars on the second (or, more generally, last) line. */
! 709:
! 710: /* This is zero-based, used to set the newlines */
! 711: prompt_lines_estimate = lpos / _rl_screenwidth;
! 712:
! 713: /* what if lpos is already >= _rl_screenwidth before we start drawing the
! 714: contents of the command line? */
! 715: while (lpos >= _rl_screenwidth)
! 716: {
! 717: int z;
! 718: /* fix from Darin Johnson <darin@acuson.com> for prompt string with
! 719: invisible characters that is longer than the screen width. The
! 720: prompt_invis_chars_first_line variable could be made into an array
! 721: saying how many invisible characters there are per line, but that's
! 722: probably too much work for the benefit gained. How many people have
! 723: prompts that exceed two physical lines?
! 724: Additional logic fix from Edward Catmur <ed@catmur.co.uk> */
! 725: #if defined (HANDLE_MULTIBYTE)
! 726: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0)
! 727: {
! 728: n0 = num;
! 729: temp = local_prompt_len;
! 730: while (num < temp)
! 731: {
! 732: z = _rl_col_width (local_prompt, n0, num, 1);
! 733: if (z > _rl_screenwidth)
! 734: {
! 735: num = _rl_find_prev_mbchar (local_prompt, num, MB_FIND_ANY);
! 736: break;
! 737: }
! 738: else if (z == _rl_screenwidth)
! 739: break;
! 740: num++;
! 741: }
! 742: temp = num;
! 743: }
! 744: else
! 745: #endif /* !HANDLE_MULTIBYTE */
! 746: temp = ((newlines + 1) * _rl_screenwidth);
! 747:
! 748: /* Now account for invisible characters in the current line. */
! 749: /* XXX - this assumes that the invisible characters may be split, but only
! 750: between the first and the last lines. */
! 751: temp += (newlines == 0) ? prompt_invis_chars_first_line
! 752: : ((newlines == prompt_lines_estimate) ? wrap_offset : prompt_invis_chars_first_line);
! 753:
! 754: inv_lbreaks[++newlines] = temp;
! 755: #if defined (HANDLE_MULTIBYTE)
! 756: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0)
! 757: lpos -= _rl_col_width (local_prompt, n0, num, 1);
! 758: else
! 759: #endif
! 760: lpos -= _rl_screenwidth;
! 761: }
! 762:
! 763: prompt_last_screen_line = newlines;
! 764:
! 765: /* Draw the rest of the line (after the prompt) into invisible_line, keeping
! 766: track of where the cursor is (cpos_buffer_position), the number of the line containing
! 767: the cursor (lb_linenum), the last line number (lb_botlin and inv_botlin).
! 768: It maintains an array of line breaks for display (inv_lbreaks).
! 769: This handles expanding tabs for display and displaying meta characters. */
! 770: lb_linenum = 0;
! 771: #if defined (HANDLE_MULTIBYTE)
! 772: in = 0;
! 773: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
! 774: {
! 775: memset (&ps, 0, sizeof (mbstate_t));
! 776: /* XXX - what if wc_bytes ends up <= 0? check for MB_INVALIDCH */
! 777: wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps);
! 778: }
! 779: else
! 780: wc_bytes = 1;
! 781: while (in < rl_end)
! 782: #else
! 783: for (in = 0; in < rl_end; in++)
! 784: #endif
! 785: {
! 786: c = (unsigned char)rl_line_buffer[in];
! 787:
! 788: #if defined (HANDLE_MULTIBYTE)
! 789: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
! 790: {
! 791: if (MB_INVALIDCH (wc_bytes))
! 792: {
! 793: /* Byte sequence is invalid or shortened. Assume that the
! 794: first byte represents a character. */
! 795: wc_bytes = 1;
! 796: /* Assume that a character occupies a single column. */
! 797: wc_width = 1;
! 798: memset (&ps, 0, sizeof (mbstate_t));
! 799: }
! 800: else if (MB_NULLWCH (wc_bytes))
! 801: break; /* Found '\0' */
! 802: else
! 803: {
! 804: temp = WCWIDTH (wc);
! 805: wc_width = (temp >= 0) ? temp : 1;
! 806: }
! 807: }
! 808: #endif
! 809:
! 810: if (out + 8 >= line_size) /* XXX - 8 for \t */
! 811: {
! 812: line_size *= 2;
! 813: visible_line = (char *)xrealloc (visible_line, line_size);
! 814: invisible_line = (char *)xrealloc (invisible_line, line_size);
! 815: line = invisible_line;
! 816: }
! 817:
! 818: if (in == rl_point)
! 819: {
! 820: cpos_buffer_position = out;
! 821: lb_linenum = newlines;
! 822: }
! 823:
! 824: #if defined (HANDLE_MULTIBYTE)
! 825: if (META_CHAR (c) && _rl_output_meta_chars == 0) /* XXX - clean up */
! 826: #else
! 827: if (META_CHAR (c))
! 828: #endif
! 829: {
! 830: if (_rl_output_meta_chars == 0)
! 831: {
! 832: sprintf (line + out, "\\%o", c);
! 833:
! 834: if (lpos + 4 >= _rl_screenwidth)
! 835: {
! 836: temp = _rl_screenwidth - lpos;
! 837: CHECK_INV_LBREAKS ();
! 838: inv_lbreaks[++newlines] = out + temp;
! 839: lpos = 4 - temp;
! 840: }
! 841: else
! 842: lpos += 4;
! 843:
! 844: out += 4;
! 845: }
! 846: else
! 847: {
! 848: line[out++] = c;
! 849: CHECK_LPOS();
! 850: }
! 851: }
! 852: #if defined (DISPLAY_TABS)
! 853: else if (c == '\t')
! 854: {
! 855: register int newout;
! 856:
! 857: #if 0
! 858: newout = (out | (int)7) + 1;
! 859: #else
! 860: newout = out + 8 - lpos % 8;
! 861: #endif
! 862: temp = newout - out;
! 863: if (lpos + temp >= _rl_screenwidth)
! 864: {
! 865: register int temp2;
! 866: temp2 = _rl_screenwidth - lpos;
! 867: CHECK_INV_LBREAKS ();
! 868: inv_lbreaks[++newlines] = out + temp2;
! 869: lpos = temp - temp2;
! 870: while (out < newout)
! 871: line[out++] = ' ';
! 872: }
! 873: else
! 874: {
! 875: while (out < newout)
! 876: line[out++] = ' ';
! 877: lpos += temp;
! 878: }
! 879: }
! 880: #endif
! 881: else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
! 882: {
! 883: line[out++] = '\0'; /* XXX - sentinel */
! 884: CHECK_INV_LBREAKS ();
! 885: inv_lbreaks[++newlines] = out;
! 886: lpos = 0;
! 887: }
! 888: else if (CTRL_CHAR (c) || c == RUBOUT)
! 889: {
! 890: line[out++] = '^';
! 891: CHECK_LPOS();
! 892: line[out++] = CTRL_CHAR (c) ? UNCTRL (c) : '?';
! 893: CHECK_LPOS();
! 894: }
! 895: else
! 896: {
! 897: #if defined (HANDLE_MULTIBYTE)
! 898: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
! 899: {
! 900: register int i;
! 901:
! 902: _rl_wrapped_multicolumn = 0;
! 903:
! 904: if (_rl_screenwidth < lpos + wc_width)
! 905: for (i = lpos; i < _rl_screenwidth; i++)
! 906: {
! 907: /* The space will be removed in update_line() */
! 908: line[out++] = ' ';
! 909: _rl_wrapped_multicolumn++;
! 910: CHECK_LPOS();
! 911: }
! 912: if (in == rl_point)
! 913: {
! 914: cpos_buffer_position = out;
! 915: lb_linenum = newlines;
! 916: }
! 917: for (i = in; i < in+wc_bytes; i++)
! 918: line[out++] = rl_line_buffer[i];
! 919: for (i = 0; i < wc_width; i++)
! 920: CHECK_LPOS();
! 921: }
! 922: else
! 923: {
! 924: line[out++] = c;
! 925: CHECK_LPOS();
! 926: }
! 927: #else
! 928: line[out++] = c;
! 929: CHECK_LPOS();
! 930: #endif
! 931: }
! 932:
! 933: #if defined (HANDLE_MULTIBYTE)
! 934: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
! 935: {
! 936: in += wc_bytes;
! 937: /* XXX - what if wc_bytes ends up <= 0? check for MB_INVALIDCH */
! 938: wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps);
! 939: }
! 940: else
! 941: in++;
! 942: #endif
! 943:
! 944: }
! 945: line[out] = '\0';
! 946: if (cpos_buffer_position < 0)
! 947: {
! 948: cpos_buffer_position = out;
! 949: lb_linenum = newlines;
! 950: }
! 951:
! 952: inv_botlin = lb_botlin = newlines;
! 953: CHECK_INV_LBREAKS ();
! 954: inv_lbreaks[newlines+1] = out;
! 955: cursor_linenum = lb_linenum;
! 956:
! 957: /* CPOS_BUFFER_POSITION == position in buffer where cursor should be placed.
! 958: CURSOR_LINENUM == line number where the cursor should be placed. */
! 959:
! 960: /* PWP: now is when things get a bit hairy. The visible and invisible
! 961: line buffers are really multiple lines, which would wrap every
! 962: (screenwidth - 1) characters. Go through each in turn, finding
! 963: the changed region and updating it. The line order is top to bottom. */
! 964:
! 965: /* If we can move the cursor up and down, then use multiple lines,
! 966: otherwise, let long lines display in a single terminal line, and
! 967: horizontally scroll it. */
! 968: displaying_prompt_first_line = 1;
! 969: if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
! 970: {
! 971: int nleft, pos, changed_screen_line, tx;
! 972:
! 973: if (!rl_display_fixed || forced_display)
! 974: {
! 975: forced_display = 0;
! 976:
! 977: /* If we have more than a screenful of material to display, then
! 978: only display a screenful. We should display the last screen,
! 979: not the first. */
! 980: if (out >= _rl_screenchars)
! 981: {
! 982: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
! 983: out = _rl_find_prev_mbchar (line, _rl_screenchars, MB_FIND_ANY);
! 984: else
! 985: out = _rl_screenchars - 1;
! 986: }
! 987:
! 988: /* The first line is at character position 0 in the buffer. The
! 989: second and subsequent lines start at inv_lbreaks[N], offset by
! 990: OFFSET (which has already been calculated above). */
! 991:
! 992: #define INVIS_FIRST() (prompt_physical_chars > _rl_screenwidth ? prompt_invis_chars_first_line : wrap_offset)
! 993: #define WRAP_OFFSET(line, offset) ((line == 0) \
! 994: ? (offset ? INVIS_FIRST() : 0) \
! 995: : ((line == prompt_last_screen_line) ? wrap_offset-prompt_invis_chars_first_line : 0))
! 996: #define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
! 997: #define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
! 998: #define INV_LLEN(l) (inv_lbreaks[l+1] - inv_lbreaks[l])
! 999: #define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
! 1000: #define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
! 1001: #define INV_LINE(line) (invisible_line + inv_lbreaks[line])
! 1002:
! 1003: #define OLD_CPOS_IN_PROMPT() (cpos_adjusted == 0 && \
! 1004: _rl_last_c_pos != o_cpos && \
! 1005: _rl_last_c_pos > wrap_offset && \
! 1006: o_cpos < prompt_last_invisible)
! 1007:
! 1008: /* For each line in the buffer, do the updating display. */
! 1009: for (linenum = 0; linenum <= inv_botlin; linenum++)
! 1010: {
! 1011: /* This can lead us astray if we execute a program that changes
! 1012: the locale from a non-multibyte to a multibyte one. */
! 1013: o_cpos = _rl_last_c_pos;
! 1014: cpos_adjusted = 0;
! 1015: update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum,
! 1016: VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin);
! 1017:
! 1018: /* update_line potentially changes _rl_last_c_pos, but doesn't
! 1019: take invisible characters into account, since _rl_last_c_pos
! 1020: is an absolute cursor position in a multibyte locale. See
! 1021: if compensating here is the right thing, or if we have to
! 1022: change update_line itself. There are several cases in which
! 1023: update_line adjusts _rl_last_c_pos itself (so it can pass
! 1024: _rl_move_cursor_relative accurate values); it communicates
! 1025: this back by setting cpos_adjusted. If we assume that
! 1026: _rl_last_c_pos is correct (an absolute cursor position) each
! 1027: time update_line is called, then we can assume in our
! 1028: calculations that o_cpos does not need to be adjusted by
! 1029: wrap_offset. */
! 1030: if (linenum == 0 && (MB_CUR_MAX > 1 && rl_byte_oriented == 0) && OLD_CPOS_IN_PROMPT())
! 1031: _rl_last_c_pos -= prompt_invis_chars_first_line; /* XXX - was wrap_offset */
! 1032: else if (linenum == prompt_last_screen_line && prompt_physical_chars > _rl_screenwidth &&
! 1033: (MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
! 1034: cpos_adjusted == 0 &&
! 1035: _rl_last_c_pos != o_cpos &&
! 1036: _rl_last_c_pos > (prompt_last_invisible - _rl_screenwidth - prompt_invis_chars_first_line))
! 1037: _rl_last_c_pos -= (wrap_offset-prompt_invis_chars_first_line);
! 1038:
! 1039: /* If this is the line with the prompt, we might need to
! 1040: compensate for invisible characters in the new line. Do
! 1041: this only if there is not more than one new line (which
! 1042: implies that we completely overwrite the old visible line)
! 1043: and the new line is shorter than the old. Make sure we are
! 1044: at the end of the new line before clearing. */
! 1045: if (linenum == 0 &&
! 1046: inv_botlin == 0 && _rl_last_c_pos == out &&
! 1047: (wrap_offset > visible_wrap_offset) &&
! 1048: (_rl_last_c_pos < visible_first_line_len))
! 1049: {
! 1050: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
! 1051: nleft = _rl_screenwidth - _rl_last_c_pos;
! 1052: else
! 1053: nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos;
! 1054: if (nleft)
! 1055: _rl_clear_to_eol (nleft);
! 1056: }
! 1057: #if 0
! 1058: /* This segment is intended to handle the case where the prompt
! 1059: has invisible characters on the second line and the new line
! 1060: to be displayed needs to clear the rest of the old characters
! 1061: out (e.g., when printing the i-search prompt). In general,
! 1062: the case of the new line being shorter than the old.
! 1063: Incomplete */
! 1064: else if (linenum == prompt_last_screen_line &&
! 1065: prompt_physical_chars > _rl_screenwidth &&
! 1066: wrap_offset != prompt_invis_chars_first_line &&
! 1067: _rl_last_c_pos == out &&
! 1068: #endif
! 1069:
! 1070:
! 1071: /* Since the new first line is now visible, save its length. */
! 1072: if (linenum == 0)
! 1073: visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset;
! 1074: }
! 1075:
! 1076: /* We may have deleted some lines. If so, clear the left over
! 1077: blank ones at the bottom out. */
! 1078: if (_rl_vis_botlin > inv_botlin)
! 1079: {
! 1080: char *tt;
! 1081: for (; linenum <= _rl_vis_botlin; linenum++)
! 1082: {
! 1083: tt = VIS_CHARS (linenum);
! 1084: _rl_move_vert (linenum);
! 1085: _rl_move_cursor_relative (0, tt);
! 1086: _rl_clear_to_eol
! 1087: ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth);
! 1088: }
! 1089: }
! 1090: _rl_vis_botlin = inv_botlin;
! 1091:
! 1092: /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
! 1093: different screen line during this redisplay. */
! 1094: changed_screen_line = _rl_last_v_pos != cursor_linenum;
! 1095: if (changed_screen_line)
! 1096: {
! 1097: _rl_move_vert (cursor_linenum);
! 1098: /* If we moved up to the line with the prompt using _rl_term_up,
! 1099: the physical cursor position on the screen stays the same,
! 1100: but the buffer position needs to be adjusted to account
! 1101: for invisible characters. */
! 1102: if ((MB_CUR_MAX == 1 || rl_byte_oriented) && cursor_linenum == 0 && wrap_offset)
! 1103: _rl_last_c_pos += wrap_offset;
! 1104: }
! 1105:
! 1106: /* We have to reprint the prompt if it contains invisible
! 1107: characters, since it's not generally OK to just reprint
! 1108: the characters from the current cursor position. But we
! 1109: only need to reprint it if the cursor is before the last
! 1110: invisible character in the prompt string. */
! 1111: nleft = prompt_visible_length + wrap_offset;
! 1112: if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
! 1113: #if 0
! 1114: _rl_last_c_pos <= PROMPT_ENDING_INDEX && local_prompt)
! 1115: #else
! 1116: _rl_last_c_pos < PROMPT_ENDING_INDEX && local_prompt)
! 1117: #endif
! 1118: {
! 1119: #if defined (__MSDOS__)
! 1120: putc ('\r', rl_outstream);
! 1121: #else
! 1122: if (_rl_term_cr)
! 1123: tputs (_rl_term_cr, 1, _rl_output_character_function);
! 1124: #endif
! 1125: if (modmark)
! 1126: _rl_output_some_chars ("*", 1);
! 1127:
! 1128: _rl_output_some_chars (local_prompt, nleft);
! 1129: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
! 1130: _rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft, 1) - wrap_offset + modmark;
! 1131: else
! 1132: _rl_last_c_pos = nleft + modmark;
! 1133: }
! 1134:
! 1135: /* Where on that line? And where does that line start
! 1136: in the buffer? */
! 1137: pos = inv_lbreaks[cursor_linenum];
! 1138: /* nleft == number of characters in the line buffer between the
! 1139: start of the line and the desired cursor position. */
! 1140: nleft = cpos_buffer_position - pos;
! 1141:
! 1142: /* NLEFT is now a number of characters in a buffer. When in a
! 1143: multibyte locale, however, _rl_last_c_pos is an absolute cursor
! 1144: position that doesn't take invisible characters in the prompt
! 1145: into account. We use a fudge factor to compensate. */
! 1146:
! 1147: /* Since _rl_backspace() doesn't know about invisible characters in the
! 1148: prompt, and there's no good way to tell it, we compensate for
! 1149: those characters here and call _rl_backspace() directly. */
! 1150: if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
! 1151: {
! 1152: /* TX == new physical cursor position in multibyte locale. */
! 1153: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
! 1154: tx = _rl_col_width (&visible_line[pos], 0, nleft, 1) - visible_wrap_offset;
! 1155: else
! 1156: tx = nleft;
! 1157: if (tx >= 0 && _rl_last_c_pos > tx)
! 1158: {
! 1159: _rl_backspace (_rl_last_c_pos - tx); /* XXX */
! 1160: _rl_last_c_pos = tx;
! 1161: }
! 1162: }
! 1163:
! 1164: /* We need to note that in a multibyte locale we are dealing with
! 1165: _rl_last_c_pos as an absolute cursor position, but moving to a
! 1166: point specified by a buffer position (NLEFT) that doesn't take
! 1167: invisible characters into account. */
! 1168: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
! 1169: _rl_move_cursor_relative (nleft, &invisible_line[pos]);
! 1170: else if (nleft != _rl_last_c_pos)
! 1171: _rl_move_cursor_relative (nleft, &invisible_line[pos]);
! 1172: }
! 1173: }
! 1174: else /* Do horizontal scrolling. */
! 1175: {
! 1176: #define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
! 1177: int lmargin, ndisp, nleft, phys_c_pos, t;
! 1178:
! 1179: /* Always at top line. */
! 1180: _rl_last_v_pos = 0;
! 1181:
! 1182: /* Compute where in the buffer the displayed line should start. This
! 1183: will be LMARGIN. */
! 1184:
! 1185: /* The number of characters that will be displayed before the cursor. */
! 1186: ndisp = cpos_buffer_position - wrap_offset;
! 1187: nleft = prompt_visible_length + wrap_offset;
! 1188: /* Where the new cursor position will be on the screen. This can be
! 1189: longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
! 1190: phys_c_pos = cpos_buffer_position - (last_lmargin ? last_lmargin : wrap_offset);
! 1191: t = _rl_screenwidth / 3;
! 1192:
! 1193: /* If the number of characters had already exceeded the screenwidth,
! 1194: last_lmargin will be > 0. */
! 1195:
! 1196: /* If the number of characters to be displayed is more than the screen
! 1197: width, compute the starting offset so that the cursor is about
! 1198: two-thirds of the way across the screen. */
! 1199: if (phys_c_pos > _rl_screenwidth - 2)
! 1200: {
! 1201: lmargin = cpos_buffer_position - (2 * t);
! 1202: if (lmargin < 0)
! 1203: lmargin = 0;
! 1204: /* If the left margin would be in the middle of a prompt with
! 1205: invisible characters, don't display the prompt at all. */
! 1206: if (wrap_offset && lmargin > 0 && lmargin < nleft)
! 1207: lmargin = nleft;
! 1208: }
! 1209: else if (ndisp < _rl_screenwidth - 2) /* XXX - was -1 */
! 1210: lmargin = 0;
! 1211: else if (phys_c_pos < 1)
! 1212: {
! 1213: /* If we are moving back towards the beginning of the line and
! 1214: the last margin is no longer correct, compute a new one. */
! 1215: lmargin = ((cpos_buffer_position - 1) / t) * t; /* XXX */
! 1216: if (wrap_offset && lmargin > 0 && lmargin < nleft)
! 1217: lmargin = nleft;
! 1218: }
! 1219: else
! 1220: lmargin = last_lmargin;
! 1221:
! 1222: displaying_prompt_first_line = lmargin < nleft;
! 1223:
! 1224: /* If the first character on the screen isn't the first character
! 1225: in the display line, indicate this with a special character. */
! 1226: if (lmargin > 0)
! 1227: line[lmargin] = '<';
! 1228:
! 1229: /* If SCREENWIDTH characters starting at LMARGIN do not encompass
! 1230: the whole line, indicate that with a special character at the
! 1231: right edge of the screen. If LMARGIN is 0, we need to take the
! 1232: wrap offset into account. */
! 1233: t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth;
! 1234: if (t < out)
! 1235: line[t - 1] = '>';
! 1236:
! 1237: if (rl_display_fixed == 0 || forced_display || lmargin != last_lmargin)
! 1238: {
! 1239: forced_display = 0;
! 1240: o_cpos = _rl_last_c_pos;
! 1241: cpos_adjusted = 0;
! 1242: update_line (&visible_line[last_lmargin],
! 1243: &invisible_line[lmargin],
! 1244: 0,
! 1245: _rl_screenwidth + visible_wrap_offset,
! 1246: _rl_screenwidth + (lmargin ? 0 : wrap_offset),
! 1247: 0);
! 1248:
! 1249: if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
! 1250: displaying_prompt_first_line && OLD_CPOS_IN_PROMPT())
! 1251: _rl_last_c_pos -= prompt_invis_chars_first_line; /* XXX - was wrap_offset */
! 1252:
! 1253: /* If the visible new line is shorter than the old, but the number
! 1254: of invisible characters is greater, and we are at the end of
! 1255: the new line, we need to clear to eol. */
! 1256: t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
! 1257: if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
! 1258: (_rl_last_c_pos == out) && displaying_prompt_first_line &&
! 1259: t < visible_first_line_len)
! 1260: {
! 1261: nleft = _rl_screenwidth - t;
! 1262: _rl_clear_to_eol (nleft);
! 1263: }
! 1264: visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
! 1265: if (visible_first_line_len > _rl_screenwidth)
! 1266: visible_first_line_len = _rl_screenwidth;
! 1267:
! 1268: _rl_move_cursor_relative (cpos_buffer_position - lmargin, &invisible_line[lmargin]);
! 1269: last_lmargin = lmargin;
! 1270: }
! 1271: }
! 1272: fflush (rl_outstream);
! 1273:
! 1274: /* Swap visible and non-visible lines. */
! 1275: {
! 1276: struct line_state *vtemp = line_state_visible;
! 1277:
! 1278: line_state_visible = line_state_invisible;
! 1279: line_state_invisible = vtemp;
! 1280:
! 1281: rl_display_fixed = 0;
! 1282: /* If we are displaying on a single line, and last_lmargin is > 0, we
! 1283: are not displaying any invisible characters, so set visible_wrap_offset
! 1284: to 0. */
! 1285: if (_rl_horizontal_scroll_mode && last_lmargin)
! 1286: visible_wrap_offset = 0;
! 1287: else
! 1288: visible_wrap_offset = wrap_offset;
! 1289: }
! 1290:
! 1291: RL_UNSETSTATE (RL_STATE_REDISPLAYING);
! 1292: _rl_release_sigint ();
! 1293: }
! 1294:
! 1295: /* PWP: update_line() is based on finding the middle difference of each
! 1296: line on the screen; vis:
! 1297:
! 1298: /old first difference
! 1299: /beginning of line | /old last same /old EOL
! 1300: v v v v
! 1301: old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as
! 1302: new: eddie> Oh, my little buggy says to me, as lurgid as
! 1303: ^ ^ ^ ^
! 1304: \beginning of line | \new last same \new end of line
! 1305: \new first difference
! 1306:
! 1307: All are character pointers for the sake of speed. Special cases for
! 1308: no differences, as well as for end of line additions must be handled.
! 1309:
! 1310: Could be made even smarter, but this works well enough */
! 1311: static void
! 1312: update_line (old, new, current_line, omax, nmax, inv_botlin)
! 1313: register char *old, *new;
! 1314: int current_line, omax, nmax, inv_botlin;
! 1315: {
! 1316: register char *ofd, *ols, *oe, *nfd, *nls, *ne;
! 1317: int temp, lendiff, wsatend, od, nd, twidth, o_cpos;
! 1318: int current_invis_chars;
! 1319: int col_lendiff, col_temp;
! 1320: int bytes_to_insert;
! 1321: #if defined (HANDLE_MULTIBYTE)
! 1322: mbstate_t ps_new, ps_old;
! 1323: int new_offset, old_offset;
! 1324: #endif
! 1325:
! 1326: /* If we're at the right edge of a terminal that supports xn, we're
! 1327: ready to wrap around, so do so. This fixes problems with knowing
! 1328: the exact cursor position and cut-and-paste with certain terminal
! 1329: emulators. In this calculation, TEMP is the physical screen
! 1330: position of the cursor. */
! 1331: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
! 1332: temp = _rl_last_c_pos;
! 1333: else
! 1334: temp = _rl_last_c_pos - WRAP_OFFSET (_rl_last_v_pos, visible_wrap_offset);
! 1335: if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
! 1336: && _rl_last_v_pos == current_line - 1)
! 1337: {
! 1338: #if defined (HANDLE_MULTIBYTE)
! 1339: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
! 1340: {
! 1341: wchar_t wc;
! 1342: mbstate_t ps;
! 1343: int tempwidth, bytes;
! 1344: size_t ret;
! 1345:
! 1346: /* This fixes only double-column characters, but if the wrapped
! 1347: character consumes more than three columns, spaces will be
! 1348: inserted in the string buffer. */
! 1349: if (current_line < line_state_visible->wbsize && line_state_visible->wrapped_line[current_line] > 0)
! 1350: _rl_clear_to_eol (line_state_visible->wrapped_line[current_line]);
! 1351:
! 1352: memset (&ps, 0, sizeof (mbstate_t));
! 1353: ret = mbrtowc (&wc, new, MB_CUR_MAX, &ps);
! 1354: if (MB_INVALIDCH (ret))
! 1355: {
! 1356: tempwidth = 1;
! 1357: ret = 1;
! 1358: }
! 1359: else if (MB_NULLWCH (ret))
! 1360: tempwidth = 0;
! 1361: else
! 1362: tempwidth = WCWIDTH (wc);
! 1363:
! 1364: if (tempwidth > 0)
! 1365: {
! 1366: int count, i;
! 1367: bytes = ret;
! 1368: for (count = 0; count < bytes; count++)
! 1369: putc (new[count], rl_outstream);
! 1370: _rl_last_c_pos = tempwidth;
! 1371: _rl_last_v_pos++;
! 1372: memset (&ps, 0, sizeof (mbstate_t));
! 1373: ret = mbrtowc (&wc, old, MB_CUR_MAX, &ps);
! 1374: if (ret != 0 && bytes != 0)
! 1375: {
! 1376: if (MB_INVALIDCH (ret))
! 1377: ret = 1;
! 1378: memmove (old+bytes, old+ret, strlen (old+ret));
! 1379: memcpy (old, new, bytes);
! 1380: /* Fix up indices if we copy data from one line to another */
! 1381: omax += bytes - ret;
! 1382: for (i = current_line+1; i <= inv_botlin+1; i++)
! 1383: vis_lbreaks[i] += bytes - ret;
! 1384: }
! 1385: }
! 1386: else
! 1387: {
! 1388: putc (' ', rl_outstream);
! 1389: _rl_last_c_pos = 1;
! 1390: _rl_last_v_pos++;
! 1391: if (old[0] && new[0])
! 1392: old[0] = new[0];
! 1393: }
! 1394: }
! 1395: else
! 1396: #endif
! 1397: {
! 1398: if (new[0])
! 1399: putc (new[0], rl_outstream);
! 1400: else
! 1401: putc (' ', rl_outstream);
! 1402: _rl_last_c_pos = 1;
! 1403: _rl_last_v_pos++;
! 1404: if (old[0] && new[0])
! 1405: old[0] = new[0];
! 1406: }
! 1407: }
! 1408:
! 1409:
! 1410: /* Find first difference. */
! 1411: #if defined (HANDLE_MULTIBYTE)
! 1412: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
! 1413: {
! 1414: /* See if the old line is a subset of the new line, so that the
! 1415: only change is adding characters. */
! 1416: temp = (omax < nmax) ? omax : nmax;
! 1417: if (memcmp (old, new, temp) == 0) /* adding at the end */
! 1418: {
! 1419: new_offset = old_offset = temp;
! 1420: ofd = old + temp;
! 1421: nfd = new + temp;
! 1422: }
! 1423: else
! 1424: {
! 1425: memset (&ps_new, 0, sizeof(mbstate_t));
! 1426: memset (&ps_old, 0, sizeof(mbstate_t));
! 1427:
! 1428: if (omax == nmax && STREQN (new, old, omax))
! 1429: {
! 1430: old_offset = omax;
! 1431: new_offset = nmax;
! 1432: ofd = old + omax;
! 1433: nfd = new + nmax;
! 1434: }
! 1435: else
! 1436: {
! 1437: new_offset = old_offset = 0;
! 1438: for (ofd = old, nfd = new;
! 1439: (ofd - old < omax) && *ofd &&
! 1440: _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new); )
! 1441: {
! 1442: old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY);
! 1443: new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY);
! 1444:
! 1445: ofd = old + old_offset;
! 1446: nfd = new + new_offset;
! 1447: }
! 1448: }
! 1449: }
! 1450: }
! 1451: else
! 1452: #endif
! 1453: for (ofd = old, nfd = new;
! 1454: (ofd - old < omax) && *ofd && (*ofd == *nfd);
! 1455: ofd++, nfd++)
! 1456: ;
! 1457:
! 1458: /* Move to the end of the screen line. ND and OD are used to keep track
! 1459: of the distance between ne and new and oe and old, respectively, to
! 1460: move a subtraction out of each loop. */
! 1461: for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
! 1462: for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
! 1463:
! 1464: /* If no difference, continue to next line. */
! 1465: if (ofd == oe && nfd == ne)
! 1466: return;
! 1467:
! 1468: #if defined (HANDLE_MULTIBYTE)
! 1469: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0 && _rl_utf8locale)
! 1470: {
! 1471: wchar_t wc;
! 1472: mbstate_t ps = { 0 };
! 1473: int t;
! 1474:
! 1475: /* If the first character in the difference is a zero-width character,
! 1476: assume it's a combining character and back one up so the two base
! 1477: characters no longer compare equivalently. */
! 1478: t = mbrtowc (&wc, ofd, MB_CUR_MAX, &ps);
! 1479: if (t > 0 && UNICODE_COMBINING_CHAR (wc) && WCWIDTH (wc) == 0)
! 1480: {
! 1481: old_offset = _rl_find_prev_mbchar (old, ofd - old, MB_FIND_ANY);
! 1482: new_offset = _rl_find_prev_mbchar (new, nfd - new, MB_FIND_ANY);
! 1483: ofd = old + old_offset; /* equal by definition */
! 1484: nfd = new + new_offset;
! 1485: }
! 1486: }
! 1487: #endif
! 1488:
! 1489: wsatend = 1; /* flag for trailing whitespace */
! 1490:
! 1491: #if defined (HANDLE_MULTIBYTE)
! 1492: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
! 1493: {
! 1494: ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY);
! 1495: nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY);
! 1496:
! 1497: while ((ols > ofd) && (nls > nfd))
! 1498: {
! 1499: memset (&ps_old, 0, sizeof (mbstate_t));
! 1500: memset (&ps_new, 0, sizeof (mbstate_t));
! 1501:
! 1502: #if 0
! 1503: /* On advice from jir@yamato.ibm.com */
! 1504: _rl_adjust_point (old, ols - old, &ps_old);
! 1505: _rl_adjust_point (new, nls - new, &ps_new);
! 1506: #endif
! 1507:
! 1508: if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0)
! 1509: break;
! 1510:
! 1511: if (*ols == ' ')
! 1512: wsatend = 0;
! 1513:
! 1514: ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY);
! 1515: nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY);
! 1516: }
! 1517: }
! 1518: else
! 1519: {
! 1520: #endif /* HANDLE_MULTIBYTE */
! 1521: ols = oe - 1; /* find last same */
! 1522: nls = ne - 1;
! 1523: while ((ols > ofd) && (nls > nfd) && (*ols == *nls))
! 1524: {
! 1525: if (*ols != ' ')
! 1526: wsatend = 0;
! 1527: ols--;
! 1528: nls--;
! 1529: }
! 1530: #if defined (HANDLE_MULTIBYTE)
! 1531: }
! 1532: #endif
! 1533:
! 1534: if (wsatend)
! 1535: {
! 1536: ols = oe;
! 1537: nls = ne;
! 1538: }
! 1539: #if defined (HANDLE_MULTIBYTE)
! 1540: /* This may not work for stateful encoding, but who cares? To handle
! 1541: stateful encoding properly, we have to scan each string from the
! 1542: beginning and compare. */
! 1543: else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0)
! 1544: #else
! 1545: else if (*ols != *nls)
! 1546: #endif
! 1547: {
! 1548: if (*ols) /* don't step past the NUL */
! 1549: {
! 1550: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
! 1551: ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY);
! 1552: else
! 1553: ols++;
! 1554: }
! 1555: if (*nls)
! 1556: {
! 1557: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
! 1558: nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY);
! 1559: else
! 1560: nls++;
! 1561: }
! 1562: }
! 1563:
! 1564: /* count of invisible characters in the current invisible line. */
! 1565: current_invis_chars = W_OFFSET (current_line, wrap_offset);
! 1566: if (_rl_last_v_pos != current_line)
! 1567: {
! 1568: _rl_move_vert (current_line);
! 1569: if ((MB_CUR_MAX == 1 || rl_byte_oriented) && current_line == 0 && visible_wrap_offset)
! 1570: _rl_last_c_pos += visible_wrap_offset;
! 1571: }
! 1572:
! 1573: /* If this is the first line and there are invisible characters in the
! 1574: prompt string, and the prompt string has not changed, and the current
! 1575: cursor position is before the last invisible character in the prompt,
! 1576: and the index of the character to move to is past the end of the prompt
! 1577: string, then redraw the entire prompt string. We can only do this
! 1578: reliably if the terminal supports a `cr' capability.
! 1579:
! 1580: This is not an efficiency hack -- there is a problem with redrawing
! 1581: portions of the prompt string if they contain terminal escape
! 1582: sequences (like drawing the `unbold' sequence without a corresponding
! 1583: `bold') that manifests itself on certain terminals. */
! 1584:
! 1585: lendiff = local_prompt_len;
! 1586: od = ofd - old; /* index of first difference in visible line */
! 1587: if (current_line == 0 && !_rl_horizontal_scroll_mode &&
! 1588: _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 &&
! 1589: od >= lendiff && _rl_last_c_pos < PROMPT_ENDING_INDEX)
! 1590: {
! 1591: #if defined (__MSDOS__)
! 1592: putc ('\r', rl_outstream);
! 1593: #else
! 1594: tputs (_rl_term_cr, 1, _rl_output_character_function);
! 1595: #endif
! 1596: if (modmark)
! 1597: _rl_output_some_chars ("*", 1);
! 1598: _rl_output_some_chars (local_prompt, lendiff);
! 1599: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
! 1600: {
! 1601: /* We take wrap_offset into account here so we can pass correct
! 1602: information to _rl_move_cursor_relative. */
! 1603: _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff, 1) - wrap_offset + modmark;
! 1604: cpos_adjusted = 1;
! 1605: }
! 1606: else
! 1607: _rl_last_c_pos = lendiff + modmark;
! 1608: }
! 1609:
! 1610: o_cpos = _rl_last_c_pos;
! 1611:
! 1612: /* When this function returns, _rl_last_c_pos is correct, and an absolute
! 1613: cursor position in multibyte mode, but a buffer index when not in a
! 1614: multibyte locale. */
! 1615: _rl_move_cursor_relative (od, old);
! 1616:
! 1617: #if defined (HANDLE_MULTIBYTE)
! 1618: /* We need to indicate that the cursor position is correct in the presence of
! 1619: invisible characters in the prompt string. Let's see if setting this when
! 1620: we make sure we're at the end of the drawn prompt string works. */
! 1621: if (current_line == 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0 &&
! 1622: (_rl_last_c_pos > 0 || o_cpos > 0) &&
! 1623: _rl_last_c_pos == prompt_physical_chars)
! 1624: cpos_adjusted = 1;
! 1625: #endif
! 1626:
! 1627: /* if (len (new) > len (old))
! 1628: lendiff == difference in buffer (bytes)
! 1629: col_lendiff == difference on screen (columns)
! 1630: When not using multibyte characters, these are equal */
! 1631: lendiff = (nls - nfd) - (ols - ofd);
! 1632: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
! 1633: col_lendiff = _rl_col_width (new, nfd - new, nls - new, 1) - _rl_col_width (old, ofd - old, ols - old, 1);
! 1634: else
! 1635: col_lendiff = lendiff;
! 1636:
! 1637: /* If we are changing the number of invisible characters in a line, and
! 1638: the spot of first difference is before the end of the invisible chars,
! 1639: lendiff needs to be adjusted. */
! 1640: if (current_line == 0 && !_rl_horizontal_scroll_mode &&
! 1641: current_invis_chars != visible_wrap_offset)
! 1642: {
! 1643: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
! 1644: {
! 1645: lendiff += visible_wrap_offset - current_invis_chars;
! 1646: col_lendiff += visible_wrap_offset - current_invis_chars;
! 1647: }
! 1648: else
! 1649: {
! 1650: lendiff += visible_wrap_offset - current_invis_chars;
! 1651: col_lendiff = lendiff;
! 1652: }
! 1653: }
! 1654:
! 1655: /* We use temp as a count of the number of bytes from the first difference
! 1656: to the end of the new line. col_temp is the corresponding number of
! 1657: screen columns. A `dumb' update moves to the spot of first difference
! 1658: and writes TEMP bytes. */
! 1659: /* Insert (diff (len (old), len (new)) ch. */
! 1660: temp = ne - nfd;
! 1661: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
! 1662: col_temp = _rl_col_width (new, nfd - new, ne - new, 1);
! 1663: else
! 1664: col_temp = temp;
! 1665:
! 1666: /* how many bytes from the new line buffer to write to the display */
! 1667: bytes_to_insert = nls - nfd;
! 1668:
! 1669: /* col_lendiff > 0 if we are adding characters to the line */
! 1670: if (col_lendiff > 0) /* XXX - was lendiff */
! 1671: {
! 1672: /* Non-zero if we're increasing the number of lines. */
! 1673: int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
! 1674: /* If col_lendiff is > 0, implying that the new string takes up more
! 1675: screen real estate than the old, but lendiff is < 0, meaning that it
! 1676: takes fewer bytes, we need to just output the characters starting
! 1677: from the first difference. These will overwrite what is on the
! 1678: display, so there's no reason to do a smart update. This can really
! 1679: only happen in a multibyte environment. */
! 1680: if (lendiff < 0)
! 1681: {
! 1682: _rl_output_some_chars (nfd, temp);
! 1683: _rl_last_c_pos += col_temp; /* XXX - was _rl_col_width (nfd, 0, temp, 1); */
! 1684: /* If nfd begins before any invisible characters in the prompt,
! 1685: adjust _rl_last_c_pos to account for wrap_offset and set
! 1686: cpos_adjusted to let the caller know. */
! 1687: if (current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
! 1688: {
! 1689: _rl_last_c_pos -= wrap_offset;
! 1690: cpos_adjusted = 1;
! 1691: }
! 1692: return;
! 1693: }
! 1694: /* Sometimes it is cheaper to print the characters rather than
! 1695: use the terminal's capabilities. If we're growing the number
! 1696: of lines, make sure we actually cause the new line to wrap
! 1697: around on auto-wrapping terminals. */
! 1698: else if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
! 1699: {
! 1700: /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
! 1701: _rl_horizontal_scroll_mode == 1, inserting the characters with
! 1702: _rl_term_IC or _rl_term_ic will screw up the screen because of the
! 1703: invisible characters. We need to just draw them. */
! 1704: /* The same thing happens if we're trying to draw before the last
! 1705: invisible character in the prompt string or we're increasing the
! 1706: number of invisible characters in the line and we're not drawing
! 1707: the entire prompt string. */
! 1708: if (*ols && ((_rl_horizontal_scroll_mode &&
! 1709: _rl_last_c_pos == 0 &&
! 1710: lendiff > prompt_visible_length &&
! 1711: current_invis_chars > 0) == 0) &&
! 1712: (((MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
! 1713: current_line == 0 && wrap_offset &&
! 1714: ((nfd - new) <= prompt_last_invisible) &&
! 1715: (col_lendiff < prompt_visible_length)) == 0) &&
! 1716: (visible_wrap_offset >= current_invis_chars))
! 1717: {
! 1718: open_some_spaces (col_lendiff);
! 1719: _rl_output_some_chars (nfd, bytes_to_insert);
! 1720: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
! 1721: _rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
! 1722: else
! 1723: _rl_last_c_pos += bytes_to_insert;
! 1724: }
! 1725: else if ((MB_CUR_MAX == 1 || rl_byte_oriented != 0) && *ols == 0 && lendiff > 0)
! 1726: {
! 1727: /* At the end of a line the characters do not have to
! 1728: be "inserted". They can just be placed on the screen. */
! 1729: _rl_output_some_chars (nfd, temp);
! 1730: _rl_last_c_pos += col_temp;
! 1731: return;
! 1732: }
! 1733: else /* just write from first difference to end of new line */
! 1734: {
! 1735: _rl_output_some_chars (nfd, temp);
! 1736: _rl_last_c_pos += col_temp;
! 1737: /* If nfd begins before the last invisible character in the
! 1738: prompt, adjust _rl_last_c_pos to account for wrap_offset
! 1739: and set cpos_adjusted to let the caller know. */
! 1740: if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
! 1741: {
! 1742: _rl_last_c_pos -= wrap_offset;
! 1743: cpos_adjusted = 1;
! 1744: }
! 1745: return;
! 1746: }
! 1747:
! 1748: if (bytes_to_insert > lendiff)
! 1749: {
! 1750: /* If nfd begins before the last invisible character in the
! 1751: prompt, adjust _rl_last_c_pos to account for wrap_offset
! 1752: and set cpos_adjusted to let the caller know. */
! 1753: if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
! 1754: {
! 1755: _rl_last_c_pos -= wrap_offset;
! 1756: cpos_adjusted = 1;
! 1757: }
! 1758: }
! 1759: }
! 1760: else
! 1761: {
! 1762: /* cannot insert chars, write to EOL */
! 1763: _rl_output_some_chars (nfd, temp);
! 1764: _rl_last_c_pos += col_temp;
! 1765: /* If we're in a multibyte locale and were before the last invisible
! 1766: char in the current line (which implies we just output some invisible
! 1767: characters) we need to adjust _rl_last_c_pos, since it represents
! 1768: a physical character position. */
! 1769: if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
! 1770: current_line == prompt_last_screen_line && wrap_offset &&
! 1771: displaying_prompt_first_line &&
! 1772: wrap_offset != prompt_invis_chars_first_line &&
! 1773: ((nfd-new) < (prompt_last_invisible-(current_line*_rl_screenwidth))))
! 1774: {
! 1775: _rl_last_c_pos -= wrap_offset - prompt_invis_chars_first_line;
! 1776: cpos_adjusted = 1;
! 1777: }
! 1778: }
! 1779: }
! 1780: else /* Delete characters from line. */
! 1781: {
! 1782: /* If possible and inexpensive to use terminal deletion, then do so. */
! 1783: if (_rl_term_dc && (2 * col_temp) >= -col_lendiff)
! 1784: {
! 1785: /* If all we're doing is erasing the invisible characters in the
! 1786: prompt string, don't bother. It screws up the assumptions
! 1787: about what's on the screen. */
! 1788: if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
! 1789: displaying_prompt_first_line &&
! 1790: -lendiff == visible_wrap_offset)
! 1791: col_lendiff = 0;
! 1792:
! 1793: /* If we have moved lmargin and we're shrinking the line, we've
! 1794: already moved the cursor to the first character of the new line,
! 1795: so deleting -col_lendiff characters will mess up the cursor
! 1796: position calculation */
! 1797: if (_rl_horizontal_scroll_mode && displaying_prompt_first_line == 0 &&
! 1798: col_lendiff && _rl_last_c_pos < -col_lendiff)
! 1799: col_lendiff = 0;
! 1800:
! 1801: if (col_lendiff)
! 1802: delete_chars (-col_lendiff); /* delete (diff) characters */
! 1803:
! 1804: /* Copy (new) chars to screen from first diff to last match,
! 1805: overwriting what is there. */
! 1806: if (bytes_to_insert > 0)
! 1807: {
! 1808: /* If nfd begins at the prompt, or before the invisible
! 1809: characters in the prompt, we need to adjust _rl_last_c_pos
! 1810: in a multibyte locale to account for the wrap offset and
! 1811: set cpos_adjusted accordingly. */
! 1812: _rl_output_some_chars (nfd, bytes_to_insert);
! 1813: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
! 1814: {
! 1815: _rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
! 1816: if (current_line == 0 && wrap_offset &&
! 1817: displaying_prompt_first_line &&
! 1818: _rl_last_c_pos > wrap_offset &&
! 1819: ((nfd - new) <= prompt_last_invisible))
! 1820: {
! 1821: _rl_last_c_pos -= wrap_offset;
! 1822: cpos_adjusted = 1;
! 1823: }
! 1824: }
! 1825: else
! 1826: _rl_last_c_pos += bytes_to_insert;
! 1827:
! 1828: if (_rl_horizontal_scroll_mode && ((oe-old) > (ne-new)))
! 1829: goto clear_rest_of_line;
! 1830: }
! 1831: }
! 1832: /* Otherwise, print over the existing material. */
! 1833: else
! 1834: {
! 1835: if (temp > 0)
! 1836: {
! 1837: /* If nfd begins at the prompt, or before the invisible
! 1838: characters in the prompt, we need to adjust _rl_last_c_pos
! 1839: in a multibyte locale to account for the wrap offset and
! 1840: set cpos_adjusted accordingly. */
! 1841: _rl_output_some_chars (nfd, temp);
! 1842: _rl_last_c_pos += col_temp; /* XXX */
! 1843: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
! 1844: {
! 1845: if (current_line == 0 && wrap_offset &&
! 1846: displaying_prompt_first_line &&
! 1847: _rl_last_c_pos > wrap_offset &&
! 1848: ((nfd - new) <= prompt_last_invisible))
! 1849: {
! 1850: _rl_last_c_pos -= wrap_offset;
! 1851: cpos_adjusted = 1;
! 1852: }
! 1853: }
! 1854: }
! 1855: clear_rest_of_line:
! 1856: lendiff = (oe - old) - (ne - new);
! 1857: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
! 1858: col_lendiff = _rl_col_width (old, 0, oe - old, 1) - _rl_col_width (new, 0, ne - new, 1);
! 1859: else
! 1860: col_lendiff = lendiff;
! 1861:
! 1862: /* If we've already printed over the entire width of the screen,
! 1863: including the old material, then col_lendiff doesn't matter and
! 1864: space_to_eol will insert too many spaces. XXX - maybe we should
! 1865: adjust col_lendiff based on the difference between _rl_last_c_pos
! 1866: and _rl_screenwidth */
! 1867: if (col_lendiff && ((MB_CUR_MAX == 1 || rl_byte_oriented) || (_rl_last_c_pos < _rl_screenwidth)))
! 1868: {
! 1869: if (_rl_term_autowrap && current_line < inv_botlin)
! 1870: space_to_eol (col_lendiff);
! 1871: else
! 1872: _rl_clear_to_eol (col_lendiff);
! 1873: }
! 1874: }
! 1875: }
! 1876: }
! 1877:
! 1878: /* Tell the update routines that we have moved onto a new (empty) line. */
! 1879: int
! 1880: rl_on_new_line ()
! 1881: {
! 1882: if (visible_line)
! 1883: visible_line[0] = '\0';
! 1884:
! 1885: _rl_last_c_pos = _rl_last_v_pos = 0;
! 1886: _rl_vis_botlin = last_lmargin = 0;
! 1887: if (vis_lbreaks)
! 1888: vis_lbreaks[0] = vis_lbreaks[1] = 0;
! 1889: visible_wrap_offset = 0;
! 1890: return 0;
! 1891: }
! 1892:
! 1893: /* Tell the update routines that we have moved onto a new line with the
! 1894: prompt already displayed. Code originally from the version of readline
! 1895: distributed with CLISP. rl_expand_prompt must have already been called
! 1896: (explicitly or implicitly). This still doesn't work exactly right. */
! 1897: int
! 1898: rl_on_new_line_with_prompt ()
! 1899: {
! 1900: int prompt_size, i, l, real_screenwidth, newlines;
! 1901: char *prompt_last_line, *lprompt;
! 1902:
! 1903: /* Initialize visible_line and invisible_line to ensure that they can hold
! 1904: the already-displayed prompt. */
! 1905: prompt_size = strlen (rl_prompt) + 1;
! 1906: init_line_structures (prompt_size);
! 1907:
! 1908: /* Make sure the line structures hold the already-displayed prompt for
! 1909: redisplay. */
! 1910: lprompt = local_prompt ? local_prompt : rl_prompt;
! 1911: strcpy (visible_line, lprompt);
! 1912: strcpy (invisible_line, lprompt);
! 1913:
! 1914: /* If the prompt contains newlines, take the last tail. */
! 1915: prompt_last_line = strrchr (rl_prompt, '\n');
! 1916: if (!prompt_last_line)
! 1917: prompt_last_line = rl_prompt;
! 1918:
! 1919: l = strlen (prompt_last_line);
! 1920: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
! 1921: _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l, 1); /* XXX */
! 1922: else
! 1923: _rl_last_c_pos = l;
! 1924:
! 1925: /* Dissect prompt_last_line into screen lines. Note that here we have
! 1926: to use the real screenwidth. Readline's notion of screenwidth might be
! 1927: one less, see terminal.c. */
! 1928: real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1);
! 1929: _rl_last_v_pos = l / real_screenwidth;
! 1930: /* If the prompt length is a multiple of real_screenwidth, we don't know
! 1931: whether the cursor is at the end of the last line, or already at the
! 1932: beginning of the next line. Output a newline just to be safe. */
! 1933: if (l > 0 && (l % real_screenwidth) == 0)
! 1934: _rl_output_some_chars ("\n", 1);
! 1935: last_lmargin = 0;
! 1936:
! 1937: newlines = 0; i = 0;
! 1938: while (i <= l)
! 1939: {
! 1940: _rl_vis_botlin = newlines;
! 1941: vis_lbreaks[newlines++] = i;
! 1942: i += real_screenwidth;
! 1943: }
! 1944: vis_lbreaks[newlines] = l;
! 1945: visible_wrap_offset = 0;
! 1946:
! 1947: rl_display_prompt = rl_prompt; /* XXX - make sure it's set */
! 1948:
! 1949: return 0;
! 1950: }
! 1951:
! 1952: /* Actually update the display, period. */
! 1953: int
! 1954: rl_forced_update_display ()
! 1955: {
! 1956: register char *temp;
! 1957:
! 1958: if (visible_line)
! 1959: {
! 1960: temp = visible_line;
! 1961: while (*temp)
! 1962: *temp++ = '\0';
! 1963: }
! 1964: rl_on_new_line ();
! 1965: forced_display++;
! 1966: (*rl_redisplay_function) ();
! 1967: return 0;
! 1968: }
! 1969:
! 1970: /* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
! 1971: (Well, when we don't have multibyte characters, _rl_last_c_pos is a
! 1972: buffer index.)
! 1973: DATA is the contents of the screen line of interest; i.e., where
! 1974: the movement is being done. */
! 1975: void
! 1976: _rl_move_cursor_relative (new, data)
! 1977: int new;
! 1978: const char *data;
! 1979: {
! 1980: register int i;
! 1981: int woff; /* number of invisible chars on current line */
! 1982: int cpos, dpos; /* current and desired cursor positions */
! 1983: int adjust;
! 1984:
! 1985: woff = WRAP_OFFSET (_rl_last_v_pos, wrap_offset);
! 1986: cpos = _rl_last_c_pos;
! 1987:
! 1988: if (cpos == 0 && cpos == new)
! 1989: return;
! 1990:
! 1991: #if defined (HANDLE_MULTIBYTE)
! 1992: /* If we have multibyte characters, NEW is indexed by the buffer point in
! 1993: a multibyte string, but _rl_last_c_pos is the display position. In
! 1994: this case, NEW's display position is not obvious and must be
! 1995: calculated. We need to account for invisible characters in this line,
! 1996: as long as we are past them and they are counted by _rl_col_width. */
! 1997: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
! 1998: {
! 1999: adjust = 1;
! 2000: /* Try to short-circuit common cases and eliminate a bunch of multibyte
! 2001: character function calls. */
! 2002: /* 1. prompt string */
! 2003: if (new == local_prompt_len && memcmp (data, local_prompt, new) == 0)
! 2004: {
! 2005: dpos = prompt_physical_chars;
! 2006: cpos_adjusted = 1;
! 2007: adjust = 0;
! 2008: }
! 2009: /* 2. prompt_string + line contents */
! 2010: else if (new > local_prompt_len && local_prompt && memcmp (data, local_prompt, local_prompt_len) == 0)
! 2011: {
! 2012: dpos = prompt_physical_chars + _rl_col_width (data, local_prompt_len, new, 1);
! 2013: cpos_adjusted = 1;
! 2014: adjust = 0;
! 2015: }
! 2016: else
! 2017: dpos = _rl_col_width (data, 0, new, 1);
! 2018:
! 2019: if (displaying_prompt_first_line == 0)
! 2020: adjust = 0;
! 2021:
! 2022: /* Use NEW when comparing against the last invisible character in the
! 2023: prompt string, since they're both buffer indices and DPOS is a
! 2024: desired display position. */
! 2025: if (adjust && ((new > prompt_last_invisible) || /* XXX - don't use woff here */
! 2026: (prompt_physical_chars >= _rl_screenwidth &&
! 2027: _rl_last_v_pos == prompt_last_screen_line &&
! 2028: wrap_offset >= woff && dpos >= woff &&
! 2029: new > (prompt_last_invisible-(_rl_screenwidth*_rl_last_v_pos)-wrap_offset))))
! 2030: /* XXX last comparison might need to be >= */
! 2031: {
! 2032: dpos -= woff;
! 2033: /* Since this will be assigned to _rl_last_c_pos at the end (more
! 2034: precisely, _rl_last_c_pos == dpos when this function returns),
! 2035: let the caller know. */
! 2036: cpos_adjusted = 1;
! 2037: }
! 2038: }
! 2039: else
! 2040: #endif
! 2041: dpos = new;
! 2042:
! 2043: /* If we don't have to do anything, then return. */
! 2044: if (cpos == dpos)
! 2045: return;
! 2046:
! 2047: /* It may be faster to output a CR, and then move forwards instead
! 2048: of moving backwards. */
! 2049: /* i == current physical cursor position. */
! 2050: #if defined (HANDLE_MULTIBYTE)
! 2051: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
! 2052: i = _rl_last_c_pos;
! 2053: else
! 2054: #endif
! 2055: i = _rl_last_c_pos - woff;
! 2056: if (dpos == 0 || CR_FASTER (dpos, _rl_last_c_pos) ||
! 2057: (_rl_term_autowrap && i == _rl_screenwidth))
! 2058: {
! 2059: #if defined (__MSDOS__)
! 2060: putc ('\r', rl_outstream);
! 2061: #else
! 2062: tputs (_rl_term_cr, 1, _rl_output_character_function);
! 2063: #endif /* !__MSDOS__ */
! 2064: cpos = _rl_last_c_pos = 0;
! 2065: }
! 2066:
! 2067: if (cpos < dpos)
! 2068: {
! 2069: /* Move the cursor forward. We do it by printing the command
! 2070: to move the cursor forward if there is one, else print that
! 2071: portion of the output buffer again. Which is cheaper? */
! 2072:
! 2073: /* The above comment is left here for posterity. It is faster
! 2074: to print one character (non-control) than to print a control
! 2075: sequence telling the terminal to move forward one character.
! 2076: That kind of control is for people who don't know what the
! 2077: data is underneath the cursor. */
! 2078:
! 2079: /* However, we need a handle on where the current display position is
! 2080: in the buffer for the immediately preceding comment to be true.
! 2081: In multibyte locales, we don't currently have that info available.
! 2082: Without it, we don't know where the data we have to display begins
! 2083: in the buffer and we have to go back to the beginning of the screen
! 2084: line. In this case, we can use the terminal sequence to move forward
! 2085: if it's available. */
! 2086: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
! 2087: {
! 2088: if (_rl_term_forward_char)
! 2089: {
! 2090: for (i = cpos; i < dpos; i++)
! 2091: tputs (_rl_term_forward_char, 1, _rl_output_character_function);
! 2092: }
! 2093: else
! 2094: {
! 2095: tputs (_rl_term_cr, 1, _rl_output_character_function);
! 2096: for (i = 0; i < new; i++)
! 2097: putc (data[i], rl_outstream);
! 2098: }
! 2099: }
! 2100: else
! 2101: for (i = cpos; i < new; i++)
! 2102: putc (data[i], rl_outstream);
! 2103: }
! 2104:
! 2105: #if defined (HANDLE_MULTIBYTE)
! 2106: /* NEW points to the buffer point, but _rl_last_c_pos is the display point.
! 2107: The byte length of the string is probably bigger than the column width
! 2108: of the string, which means that if NEW == _rl_last_c_pos, then NEW's
! 2109: display point is less than _rl_last_c_pos. */
! 2110: #endif
! 2111: else if (cpos > dpos)
! 2112: _rl_backspace (cpos - dpos);
! 2113:
! 2114: _rl_last_c_pos = dpos;
! 2115: }
! 2116:
! 2117: /* PWP: move the cursor up or down. */
! 2118: void
! 2119: _rl_move_vert (to)
! 2120: int to;
! 2121: {
! 2122: register int delta, i;
! 2123:
! 2124: if (_rl_last_v_pos == to || to > _rl_screenheight)
! 2125: return;
! 2126:
! 2127: if ((delta = to - _rl_last_v_pos) > 0)
! 2128: {
! 2129: for (i = 0; i < delta; i++)
! 2130: putc ('\n', rl_outstream);
! 2131: #if defined (__MSDOS__)
! 2132: putc ('\r', rl_outstream);
! 2133: #else
! 2134: tputs (_rl_term_cr, 1, _rl_output_character_function);
! 2135: #endif
! 2136: _rl_last_c_pos = 0;
! 2137: }
! 2138: else
! 2139: { /* delta < 0 */
! 2140: #ifdef __DJGPP__
! 2141: int row, col;
! 2142:
! 2143: fflush (rl_outstream);
! 2144: ScreenGetCursor (&row, &col);
! 2145: ScreenSetCursor (row + delta, col);
! 2146: i = -delta;
! 2147: #else
! 2148: if (_rl_term_up && *_rl_term_up)
! 2149: for (i = 0; i < -delta; i++)
! 2150: tputs (_rl_term_up, 1, _rl_output_character_function);
! 2151: #endif /* !__DJGPP__ */
! 2152: }
! 2153:
! 2154: _rl_last_v_pos = to; /* Now TO is here */
! 2155: }
! 2156:
! 2157: /* Physically print C on rl_outstream. This is for functions which know
! 2158: how to optimize the display. Return the number of characters output. */
! 2159: int
! 2160: rl_show_char (c)
! 2161: int c;
! 2162: {
! 2163: int n = 1;
! 2164: if (META_CHAR (c) && (_rl_output_meta_chars == 0))
! 2165: {
! 2166: fprintf (rl_outstream, "M-");
! 2167: n += 2;
! 2168: c = UNMETA (c);
! 2169: }
! 2170:
! 2171: #if defined (DISPLAY_TABS)
! 2172: if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
! 2173: #else
! 2174: if (CTRL_CHAR (c) || c == RUBOUT)
! 2175: #endif /* !DISPLAY_TABS */
! 2176: {
! 2177: fprintf (rl_outstream, "C-");
! 2178: n += 2;
! 2179: c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
! 2180: }
! 2181:
! 2182: putc (c, rl_outstream);
! 2183: fflush (rl_outstream);
! 2184: return n;
! 2185: }
! 2186:
! 2187: int
! 2188: rl_character_len (c, pos)
! 2189: register int c, pos;
! 2190: {
! 2191: unsigned char uc;
! 2192:
! 2193: uc = (unsigned char)c;
! 2194:
! 2195: if (META_CHAR (uc))
! 2196: return ((_rl_output_meta_chars == 0) ? 4 : 1);
! 2197:
! 2198: if (uc == '\t')
! 2199: {
! 2200: #if defined (DISPLAY_TABS)
! 2201: return (((pos | 7) + 1) - pos);
! 2202: #else
! 2203: return (2);
! 2204: #endif /* !DISPLAY_TABS */
! 2205: }
! 2206:
! 2207: if (CTRL_CHAR (c) || c == RUBOUT)
! 2208: return (2);
! 2209:
! 2210: return ((ISPRINT (uc)) ? 1 : 2);
! 2211: }
! 2212: /* How to print things in the "echo-area". The prompt is treated as a
! 2213: mini-modeline. */
! 2214: static int msg_saved_prompt = 0;
! 2215:
! 2216: #if defined (USE_VARARGS)
! 2217: int
! 2218: #if defined (PREFER_STDARG)
! 2219: rl_message (const char *format, ...)
! 2220: #else
! 2221: rl_message (va_alist)
! 2222: va_dcl
! 2223: #endif
! 2224: {
! 2225: va_list args;
! 2226: #if defined (PREFER_VARARGS)
! 2227: char *format;
! 2228: #endif
! 2229: #if defined (HAVE_VSNPRINTF)
! 2230: int bneed;
! 2231: #endif
! 2232:
! 2233: #if defined (PREFER_STDARG)
! 2234: va_start (args, format);
! 2235: #else
! 2236: va_start (args);
! 2237: format = va_arg (args, char *);
! 2238: #endif
! 2239:
! 2240: if (msg_buf == 0)
! 2241: msg_buf = xmalloc (msg_bufsiz = 128);
! 2242:
! 2243: #if defined (HAVE_VSNPRINTF)
! 2244: bneed = vsnprintf (msg_buf, msg_bufsiz - 1, format, args);
! 2245: if (bneed >= msg_bufsiz - 1)
! 2246: {
! 2247: msg_bufsiz = bneed + 1;
! 2248: msg_buf = xrealloc (msg_buf, msg_bufsiz);
! 2249: va_end (args);
! 2250:
! 2251: #if defined (PREFER_STDARG)
! 2252: va_start (args, format);
! 2253: #else
! 2254: va_start (args);
! 2255: format = va_arg (args, char *);
! 2256: #endif
! 2257: vsnprintf (msg_buf, msg_bufsiz - 1, format, args);
! 2258: }
! 2259: #else
! 2260: vsprintf (msg_buf, format, args);
! 2261: msg_buf[msg_bufsiz - 1] = '\0'; /* overflow? */
! 2262: #endif
! 2263: va_end (args);
! 2264:
! 2265: if (saved_local_prompt == 0)
! 2266: {
! 2267: rl_save_prompt ();
! 2268: msg_saved_prompt = 1;
! 2269: }
! 2270: else if (local_prompt != saved_local_prompt)
! 2271: {
! 2272: FREE (local_prompt);
! 2273: FREE (local_prompt_prefix);
! 2274: local_prompt = (char *)NULL;
! 2275: }
! 2276: rl_display_prompt = msg_buf;
! 2277: local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
! 2278: &prompt_last_invisible,
! 2279: &prompt_invis_chars_first_line,
! 2280: &prompt_physical_chars);
! 2281: local_prompt_prefix = (char *)NULL;
! 2282: local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
! 2283: (*rl_redisplay_function) ();
! 2284:
! 2285: return 0;
! 2286: }
! 2287: #else /* !USE_VARARGS */
! 2288: int
! 2289: rl_message (format, arg1, arg2)
! 2290: char *format;
! 2291: {
! 2292: if (msg_buf == 0)
! 2293: msg_buf = xmalloc (msg_bufsiz = 128);
! 2294:
! 2295: sprintf (msg_buf, format, arg1, arg2);
! 2296: msg_buf[msg_bufsiz - 1] = '\0'; /* overflow? */
! 2297:
! 2298: rl_display_prompt = msg_buf;
! 2299: if (saved_local_prompt == 0)
! 2300: {
! 2301: rl_save_prompt ();
! 2302: msg_saved_prompt = 1;
! 2303: }
! 2304: else if (local_prompt != saved_local_prompt)
! 2305: {
! 2306: FREE (local_prompt);
! 2307: FREE (local_prompt_prefix);
! 2308: local_prompt = (char *)NULL;
! 2309: }
! 2310: local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
! 2311: &prompt_last_invisible,
! 2312: &prompt_invis_chars_first_line,
! 2313: &prompt_physical_chars);
! 2314: local_prompt_prefix = (char *)NULL;
! 2315: local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
! 2316: (*rl_redisplay_function) ();
! 2317:
! 2318: return 0;
! 2319: }
! 2320: #endif /* !USE_VARARGS */
! 2321:
! 2322: /* How to clear things from the "echo-area". */
! 2323: int
! 2324: rl_clear_message ()
! 2325: {
! 2326: rl_display_prompt = rl_prompt;
! 2327: if (msg_saved_prompt)
! 2328: {
! 2329: rl_restore_prompt ();
! 2330: msg_saved_prompt = 0;
! 2331: }
! 2332: (*rl_redisplay_function) ();
! 2333: return 0;
! 2334: }
! 2335:
! 2336: int
! 2337: rl_reset_line_state ()
! 2338: {
! 2339: rl_on_new_line ();
! 2340:
! 2341: rl_display_prompt = rl_prompt ? rl_prompt : "";
! 2342: forced_display = 1;
! 2343: return 0;
! 2344: }
! 2345:
! 2346: void
! 2347: rl_save_prompt ()
! 2348: {
! 2349: saved_local_prompt = local_prompt;
! 2350: saved_local_prefix = local_prompt_prefix;
! 2351: saved_prefix_length = prompt_prefix_length;
! 2352: saved_local_length = local_prompt_len;
! 2353: saved_last_invisible = prompt_last_invisible;
! 2354: saved_visible_length = prompt_visible_length;
! 2355: saved_invis_chars_first_line = prompt_invis_chars_first_line;
! 2356: saved_physical_chars = prompt_physical_chars;
! 2357:
! 2358: local_prompt = local_prompt_prefix = (char *)0;
! 2359: local_prompt_len = 0;
! 2360: prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0;
! 2361: prompt_invis_chars_first_line = prompt_physical_chars = 0;
! 2362: }
! 2363:
! 2364: void
! 2365: rl_restore_prompt ()
! 2366: {
! 2367: FREE (local_prompt);
! 2368: FREE (local_prompt_prefix);
! 2369:
! 2370: local_prompt = saved_local_prompt;
! 2371: local_prompt_prefix = saved_local_prefix;
! 2372: local_prompt_len = saved_local_length;
! 2373: prompt_prefix_length = saved_prefix_length;
! 2374: prompt_last_invisible = saved_last_invisible;
! 2375: prompt_visible_length = saved_visible_length;
! 2376: prompt_invis_chars_first_line = saved_invis_chars_first_line;
! 2377: prompt_physical_chars = saved_physical_chars;
! 2378:
! 2379: /* can test saved_local_prompt to see if prompt info has been saved. */
! 2380: saved_local_prompt = saved_local_prefix = (char *)0;
! 2381: saved_local_length = 0;
! 2382: saved_last_invisible = saved_visible_length = saved_prefix_length = 0;
! 2383: saved_invis_chars_first_line = saved_physical_chars = 0;
! 2384: }
! 2385:
! 2386: char *
! 2387: _rl_make_prompt_for_search (pchar)
! 2388: int pchar;
! 2389: {
! 2390: int len;
! 2391: char *pmt, *p;
! 2392:
! 2393: rl_save_prompt ();
! 2394:
! 2395: /* We've saved the prompt, and can do anything with the various prompt
! 2396: strings we need before they're restored. We want the unexpanded
! 2397: portion of the prompt string after any final newline. */
! 2398: p = rl_prompt ? strrchr (rl_prompt, '\n') : 0;
! 2399: if (p == 0)
! 2400: {
! 2401: len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
! 2402: pmt = (char *)xmalloc (len + 2);
! 2403: if (len)
! 2404: strcpy (pmt, rl_prompt);
! 2405: pmt[len] = pchar;
! 2406: pmt[len+1] = '\0';
! 2407: }
! 2408: else
! 2409: {
! 2410: p++;
! 2411: len = strlen (p);
! 2412: pmt = (char *)xmalloc (len + 2);
! 2413: if (len)
! 2414: strcpy (pmt, p);
! 2415: pmt[len] = pchar;
! 2416: pmt[len+1] = '\0';
! 2417: }
! 2418:
! 2419: /* will be overwritten by expand_prompt, called from rl_message */
! 2420: prompt_physical_chars = saved_physical_chars + 1;
! 2421: return pmt;
! 2422: }
! 2423:
! 2424: /* Quick redisplay hack when erasing characters at the end of the line. */
! 2425: void
! 2426: _rl_erase_at_end_of_line (l)
! 2427: int l;
! 2428: {
! 2429: register int i;
! 2430:
! 2431: _rl_backspace (l);
! 2432: for (i = 0; i < l; i++)
! 2433: putc (' ', rl_outstream);
! 2434: _rl_backspace (l);
! 2435: for (i = 0; i < l; i++)
! 2436: visible_line[--_rl_last_c_pos] = '\0';
! 2437: rl_display_fixed++;
! 2438: }
! 2439:
! 2440: /* Clear to the end of the line. COUNT is the minimum
! 2441: number of character spaces to clear, */
! 2442: void
! 2443: _rl_clear_to_eol (count)
! 2444: int count;
! 2445: {
! 2446: #ifndef __MSDOS__
! 2447: if (_rl_term_clreol)
! 2448: tputs (_rl_term_clreol, 1, _rl_output_character_function);
! 2449: else
! 2450: #endif
! 2451: if (count)
! 2452: space_to_eol (count);
! 2453: }
! 2454:
! 2455: /* Clear to the end of the line using spaces. COUNT is the minimum
! 2456: number of character spaces to clear, */
! 2457: static void
! 2458: space_to_eol (count)
! 2459: int count;
! 2460: {
! 2461: register int i;
! 2462:
! 2463: for (i = 0; i < count; i++)
! 2464: putc (' ', rl_outstream);
! 2465:
! 2466: _rl_last_c_pos += count;
! 2467: }
! 2468:
! 2469: void
! 2470: _rl_clear_screen ()
! 2471: {
! 2472: #ifndef __DJGPP__
! 2473: if (_rl_term_clrpag)
! 2474: tputs (_rl_term_clrpag, 1, _rl_output_character_function);
! 2475: else
! 2476: rl_crlf ();
! 2477: #else
! 2478: ScreenClear ();
! 2479: ScreenSetCursor (0, 0);
! 2480: #endif /* __DJGPP__ */
! 2481: }
! 2482:
! 2483: /* Insert COUNT characters from STRING to the output stream at column COL. */
! 2484: static void
! 2485: insert_some_chars (string, count, col)
! 2486: char *string;
! 2487: int count, col;
! 2488: {
! 2489: open_some_spaces (col);
! 2490: _rl_output_some_chars (string, count);
! 2491: }
! 2492:
! 2493: /* Insert COL spaces, keeping the cursor at the same position. We follow the
! 2494: ncurses documentation and use either im/ei with explicit spaces, or IC/ic
! 2495: by itself. We assume there will either be ei or we don't need to use it. */
! 2496: static void
! 2497: open_some_spaces (col)
! 2498: int col;
! 2499: {
! 2500: #if !defined (__MSDOS__) && !defined (__MINGW32__)
! 2501: char *buffer;
! 2502: register int i;
! 2503:
! 2504: /* If IC is defined, then we do not have to "enter" insert mode. */
! 2505: if (_rl_term_IC)
! 2506: {
! 2507: buffer = tgoto (_rl_term_IC, 0, col);
! 2508: tputs (buffer, 1, _rl_output_character_function);
! 2509: }
! 2510: else if (_rl_term_im && *_rl_term_im)
! 2511: {
! 2512: tputs (_rl_term_im, 1, _rl_output_character_function);
! 2513: /* just output the desired number of spaces */
! 2514: for (i = col; i--; )
! 2515: _rl_output_character_function (' ');
! 2516: /* If there is a string to turn off insert mode, use it now. */
! 2517: if (_rl_term_ei && *_rl_term_ei)
! 2518: tputs (_rl_term_ei, 1, _rl_output_character_function);
! 2519: /* and move back the right number of spaces */
! 2520: _rl_backspace (col);
! 2521: }
! 2522: else if (_rl_term_ic && *_rl_term_ic)
! 2523: {
! 2524: /* If there is a special command for inserting characters, then
! 2525: use that first to open up the space. */
! 2526: for (i = col; i--; )
! 2527: tputs (_rl_term_ic, 1, _rl_output_character_function);
! 2528: }
! 2529: #endif /* !__MSDOS__ && !__MINGW32__ */
! 2530: }
! 2531:
! 2532: /* Delete COUNT characters from the display line. */
! 2533: static void
! 2534: delete_chars (count)
! 2535: int count;
! 2536: {
! 2537: if (count > _rl_screenwidth) /* XXX */
! 2538: return;
! 2539:
! 2540: #if !defined (__MSDOS__) && !defined (__MINGW32__)
! 2541: if (_rl_term_DC && *_rl_term_DC)
! 2542: {
! 2543: char *buffer;
! 2544: buffer = tgoto (_rl_term_DC, count, count);
! 2545: tputs (buffer, count, _rl_output_character_function);
! 2546: }
! 2547: else
! 2548: {
! 2549: if (_rl_term_dc && *_rl_term_dc)
! 2550: while (count--)
! 2551: tputs (_rl_term_dc, 1, _rl_output_character_function);
! 2552: }
! 2553: #endif /* !__MSDOS__ && !__MINGW32__ */
! 2554: }
! 2555:
! 2556: void
! 2557: _rl_update_final ()
! 2558: {
! 2559: int full_lines;
! 2560:
! 2561: full_lines = 0;
! 2562: /* If the cursor is the only thing on an otherwise-blank last line,
! 2563: compensate so we don't print an extra CRLF. */
! 2564: if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
! 2565: visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
! 2566: {
! 2567: _rl_vis_botlin--;
! 2568: full_lines = 1;
! 2569: }
! 2570: _rl_move_vert (_rl_vis_botlin);
! 2571: /* If we've wrapped lines, remove the final xterm line-wrap flag. */
! 2572: if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth))
! 2573: {
! 2574: char *last_line;
! 2575:
! 2576: last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]];
! 2577: cpos_buffer_position = -1; /* don't know where we are in buffer */
! 2578: _rl_move_cursor_relative (_rl_screenwidth - 1, last_line); /* XXX */
! 2579: _rl_clear_to_eol (0);
! 2580: putc (last_line[_rl_screenwidth - 1], rl_outstream);
! 2581: }
! 2582: _rl_vis_botlin = 0;
! 2583: rl_crlf ();
! 2584: fflush (rl_outstream);
! 2585: rl_display_fixed++;
! 2586: }
! 2587:
! 2588: /* Move to the start of the current line. */
! 2589: static void
! 2590: cr ()
! 2591: {
! 2592: if (_rl_term_cr)
! 2593: {
! 2594: #if defined (__MSDOS__)
! 2595: putc ('\r', rl_outstream);
! 2596: #else
! 2597: tputs (_rl_term_cr, 1, _rl_output_character_function);
! 2598: #endif
! 2599: _rl_last_c_pos = 0;
! 2600: }
! 2601: }
! 2602:
! 2603: /* Redraw the last line of a multi-line prompt that may possibly contain
! 2604: terminal escape sequences. Called with the cursor at column 0 of the
! 2605: line to draw the prompt on. */
! 2606: static void
! 2607: redraw_prompt (t)
! 2608: char *t;
! 2609: {
! 2610: char *oldp;
! 2611:
! 2612: oldp = rl_display_prompt;
! 2613: rl_save_prompt ();
! 2614:
! 2615: rl_display_prompt = t;
! 2616: local_prompt = expand_prompt (t, &prompt_visible_length,
! 2617: &prompt_last_invisible,
! 2618: &prompt_invis_chars_first_line,
! 2619: &prompt_physical_chars);
! 2620: local_prompt_prefix = (char *)NULL;
! 2621: local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
! 2622:
! 2623: rl_forced_update_display ();
! 2624:
! 2625: rl_display_prompt = oldp;
! 2626: rl_restore_prompt();
! 2627: }
! 2628:
! 2629: /* Redisplay the current line after a SIGWINCH is received. */
! 2630: void
! 2631: _rl_redisplay_after_sigwinch ()
! 2632: {
! 2633: char *t;
! 2634:
! 2635: /* Clear the last line (assuming that the screen size change will result in
! 2636: either more or fewer characters on that line only) and put the cursor at
! 2637: column 0. Make sure the right thing happens if we have wrapped to a new
! 2638: screen line. */
! 2639: if (_rl_term_cr)
! 2640: {
! 2641: _rl_move_vert (_rl_vis_botlin);
! 2642:
! 2643: #if defined (__MSDOS__)
! 2644: putc ('\r', rl_outstream);
! 2645: #else
! 2646: tputs (_rl_term_cr, 1, _rl_output_character_function);
! 2647: #endif
! 2648: _rl_last_c_pos = 0;
! 2649: #if defined (__MSDOS__)
! 2650: space_to_eol (_rl_screenwidth);
! 2651: putc ('\r', rl_outstream);
! 2652: #else
! 2653: if (_rl_term_clreol)
! 2654: tputs (_rl_term_clreol, 1, _rl_output_character_function);
! 2655: else
! 2656: {
! 2657: space_to_eol (_rl_screenwidth);
! 2658: tputs (_rl_term_cr, 1, _rl_output_character_function);
! 2659: }
! 2660: #endif
! 2661: if (_rl_last_v_pos > 0)
! 2662: _rl_move_vert (0);
! 2663: }
! 2664: else
! 2665: rl_crlf ();
! 2666:
! 2667: /* Redraw only the last line of a multi-line prompt. */
! 2668: t = strrchr (rl_display_prompt, '\n');
! 2669: if (t)
! 2670: redraw_prompt (++t);
! 2671: else
! 2672: rl_forced_update_display ();
! 2673: }
! 2674:
! 2675: void
! 2676: _rl_clean_up_for_exit ()
! 2677: {
! 2678: if (_rl_echoing_p)
! 2679: {
! 2680: _rl_move_vert (_rl_vis_botlin);
! 2681: _rl_vis_botlin = 0;
! 2682: fflush (rl_outstream);
! 2683: rl_restart_output (1, 0);
! 2684: }
! 2685: }
! 2686:
! 2687: void
! 2688: _rl_erase_entire_line ()
! 2689: {
! 2690: cr ();
! 2691: _rl_clear_to_eol (0);
! 2692: cr ();
! 2693: fflush (rl_outstream);
! 2694: }
! 2695:
! 2696: /* return the `current display line' of the cursor -- the number of lines to
! 2697: move up to get to the first screen line of the current readline line. */
! 2698: int
! 2699: _rl_current_display_line ()
! 2700: {
! 2701: int ret, nleft;
! 2702:
! 2703: /* Find out whether or not there might be invisible characters in the
! 2704: editing buffer. */
! 2705: if (rl_display_prompt == rl_prompt)
! 2706: nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length;
! 2707: else
! 2708: nleft = _rl_last_c_pos - _rl_screenwidth;
! 2709:
! 2710: if (nleft > 0)
! 2711: ret = 1 + nleft / _rl_screenwidth;
! 2712: else
! 2713: ret = 0;
! 2714:
! 2715: return ret;
! 2716: }
! 2717:
! 2718: #if defined (HANDLE_MULTIBYTE)
! 2719: /* Calculate the number of screen columns occupied by STR from START to END.
! 2720: In the case of multibyte characters with stateful encoding, we have to
! 2721: scan from the beginning of the string to take the state into account. */
! 2722: static int
! 2723: _rl_col_width (str, start, end, flags)
! 2724: const char *str;
! 2725: int start, end, flags;
! 2726: {
! 2727: wchar_t wc;
! 2728: mbstate_t ps;
! 2729: int tmp, point, width, max;
! 2730:
! 2731: if (end <= start)
! 2732: return 0;
! 2733: if (MB_CUR_MAX == 1 || rl_byte_oriented)
! 2734: /* this can happen in some cases where it's inconvenient to check */
! 2735: return (end - start);
! 2736:
! 2737: memset (&ps, 0, sizeof (mbstate_t));
! 2738:
! 2739: point = 0;
! 2740: max = end;
! 2741:
! 2742: /* Try to short-circuit common cases. The adjustment to remove wrap_offset
! 2743: is done by the caller. */
! 2744: /* 1. prompt string */
! 2745: if (flags && start == 0 && end == local_prompt_len && memcmp (str, local_prompt, local_prompt_len) == 0)
! 2746: return (prompt_physical_chars + wrap_offset);
! 2747: /* 2. prompt string + line contents */
! 2748: else if (flags && start == 0 && local_prompt_len > 0 && end > local_prompt_len && local_prompt && memcmp (str, local_prompt, local_prompt_len) == 0)
! 2749: {
! 2750: tmp = prompt_physical_chars + wrap_offset;
! 2751: /* XXX - try to call ourselves recursively with non-prompt portion */
! 2752: tmp += _rl_col_width (str, local_prompt_len, end, flags);
! 2753: return (tmp);
! 2754: }
! 2755:
! 2756: while (point < start)
! 2757: {
! 2758: tmp = mbrlen (str + point, max, &ps);
! 2759: if (MB_INVALIDCH ((size_t)tmp))
! 2760: {
! 2761: /* In this case, the bytes are invalid or too short to compose a
! 2762: multibyte character, so we assume that the first byte represents
! 2763: a single character. */
! 2764: point++;
! 2765: max--;
! 2766:
! 2767: /* Clear the state of the byte sequence, because in this case the
! 2768: effect of mbstate is undefined. */
! 2769: memset (&ps, 0, sizeof (mbstate_t));
! 2770: }
! 2771: else if (MB_NULLWCH (tmp))
! 2772: break; /* Found '\0' */
! 2773: else
! 2774: {
! 2775: point += tmp;
! 2776: max -= tmp;
! 2777: }
! 2778: }
! 2779:
! 2780: /* If START is not a byte that starts a character, then POINT will be
! 2781: greater than START. In this case, assume that (POINT - START) gives
! 2782: a byte count that is the number of columns of difference. */
! 2783: width = point - start;
! 2784:
! 2785: while (point < end)
! 2786: {
! 2787: tmp = mbrtowc (&wc, str + point, max, &ps);
! 2788: if (MB_INVALIDCH ((size_t)tmp))
! 2789: {
! 2790: /* In this case, the bytes are invalid or too short to compose a
! 2791: multibyte character, so we assume that the first byte represents
! 2792: a single character. */
! 2793: point++;
! 2794: max--;
! 2795:
! 2796: /* and assume that the byte occupies a single column. */
! 2797: width++;
! 2798:
! 2799: /* Clear the state of the byte sequence, because in this case the
! 2800: effect of mbstate is undefined. */
! 2801: memset (&ps, 0, sizeof (mbstate_t));
! 2802: }
! 2803: else if (MB_NULLWCH (tmp))
! 2804: break; /* Found '\0' */
! 2805: else
! 2806: {
! 2807: point += tmp;
! 2808: max -= tmp;
! 2809: tmp = WCWIDTH(wc);
! 2810: width += (tmp >= 0) ? tmp : 1;
! 2811: }
! 2812: }
! 2813:
! 2814: width += point - end;
! 2815:
! 2816: return width;
! 2817: }
! 2818: #endif /* HANDLE_MULTIBYTE */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>