📄 display.c
字号:
if (col_lendiff > 0) /* XXX - was lendiff */ { /* Non-zero if we're increasing the number of lines. */ int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin; /* If col_lendiff is > 0, implying that the new string takes up more screen real estate than the old, but lendiff is < 0, meaning that it takes fewer bytes, we need to just output the characters starting from the first difference. These will overwrite what is on the display, so there's no reason to do a smart update. This can really only happen in a multibyte environment. */ if (lendiff < 0) { _rl_output_some_chars (nfd, temp); _rl_last_c_pos += _rl_col_width (nfd, 0, temp, 1); /* If nfd begins before any invisible characters in the prompt, adjust _rl_last_c_pos to account for wrap_offset and set cpos_adjusted to let the caller know. */ if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible)) { _rl_last_c_pos -= wrap_offset; cpos_adjusted = 1; } return; } /* Sometimes it is cheaper to print the characters rather than use the terminal's capabilities. If we're growing the number of lines, make sure we actually cause the new line to wrap around on auto-wrapping terminals. */ else if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl)) { /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and _rl_horizontal_scroll_mode == 1, inserting the characters with _rl_term_IC or _rl_term_ic will screw up the screen because of the invisible characters. We need to just draw them. */ /* The same thing happens if we're trying to draw before the last invisible character in the prompt string or we're increasing the number of invisible characters in the line and we're not drawing the entire prompt string. */ if (*ols && ((_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 && lendiff > prompt_visible_length && current_invis_chars > 0) == 0) && (((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible) && (col_lendiff < prompt_visible_length)) == 0) && (visible_wrap_offset >= current_invis_chars)) { insert_some_chars (nfd, lendiff, col_lendiff); _rl_last_c_pos += col_lendiff; }#if 0 /* XXX - for now */ else if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && _rl_last_c_pos == 0 && wrap_offset && (nfd-new) <= prompt_last_invisible && col_lendiff < prompt_visible_length && visible_wrap_offset >= current_invis_chars) { _rl_output_some_chars (nfd, lendiff); _rl_last_c_pos += col_lendiff; }#endif else if ((MB_CUR_MAX == 1 || rl_byte_oriented != 0) && *ols == 0 && lendiff > 0) { /* At the end of a line the characters do not have to be "inserted". They can just be placed on the screen. */ /* However, this screws up the rest of this block, which assumes you've done the insert because you can. */ _rl_output_some_chars (nfd, lendiff); _rl_last_c_pos += col_lendiff; } else { _rl_output_some_chars (nfd, temp); _rl_last_c_pos += col_temp; /* If nfd begins before the last invisible character in the prompt, adjust _rl_last_c_pos to account for wrap_offset and set cpos_adjusted to let the caller know. */ if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible)) { _rl_last_c_pos -= wrap_offset; cpos_adjusted = 1; } return; } /* Copy (new) chars to screen from first diff to last match. */ temp = nls - nfd; if ((temp - lendiff) > 0) { _rl_output_some_chars (nfd + lendiff, temp - lendiff); /* XXX -- this bears closer inspection. Fixes a redisplay bug reported against bash-3.0-alpha by Andreas Schwab involving multibyte characters and prompt strings with invisible characters, but was previously disabled. */ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) twidth = _rl_col_width (nfd+lendiff, 0, temp-col_lendiff, 1); else twidth = temp - lendiff; _rl_last_c_pos += twidth; /* If nfd begins before the last invisible character in the prompt, adjust _rl_last_c_pos to account for wrap_offset and set cpos_adjusted to let the caller know. */ if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible)) { _rl_last_c_pos -= wrap_offset; cpos_adjusted = 1; } } } else { /* cannot insert chars, write to EOL */ _rl_output_some_chars (nfd, temp); _rl_last_c_pos += col_temp; /* If we're in a multibyte locale and were before the last invisible char in the current line (which implies we just output some invisible characters) we need to adjust _rl_last_c_pos, since it represents a physical character position. */ if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == prompt_last_screen_line && wrap_offset && wrap_offset != prompt_invis_chars_first_line && ((nfd-new) < (prompt_last_invisible-(current_line*_rl_screenwidth)))) { _rl_last_c_pos -= wrap_offset - prompt_invis_chars_first_line; cpos_adjusted = 1; } } } else /* Delete characters from line. */ { /* If possible and inexpensive to use terminal deletion, then do so. */ if (_rl_term_dc && (2 * col_temp) >= -col_lendiff) { /* If all we're doing is erasing the invisible characters in the prompt string, don't bother. It screws up the assumptions about what's on the screen. */ if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 && -lendiff == visible_wrap_offset) col_lendiff = 0; if (col_lendiff) delete_chars (-col_lendiff); /* delete (diff) characters */ /* Copy (new) chars to screen from first diff to last match */ temp = nls - nfd; if (temp > 0) { /* If nfd begins at the prompt, or before the invisible characters in the prompt, we need to adjust _rl_last_c_pos in a multibyte locale to account for the wrap offset and set cpos_adjusted accordingly. */ _rl_output_some_chars (nfd, temp); if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) { _rl_last_c_pos += _rl_col_width (nfd, 0, temp, 1); if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible)) { _rl_last_c_pos -= wrap_offset; cpos_adjusted = 1; } } else _rl_last_c_pos += temp; } } /* Otherwise, print over the existing material. */ else { if (temp > 0) { /* If nfd begins at the prompt, or before the invisible characters in the prompt, we need to adjust _rl_last_c_pos in a multibyte locale to account for the wrap offset and set cpos_adjusted accordingly. */ _rl_output_some_chars (nfd, temp); _rl_last_c_pos += col_temp; /* XXX */ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) { if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible)) { _rl_last_c_pos -= wrap_offset; cpos_adjusted = 1; } } } lendiff = (oe - old) - (ne - new); if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) col_lendiff = _rl_col_width (old, 0, oe - old, 1) - _rl_col_width (new, 0, ne - new, 1); else col_lendiff = lendiff;#if 0 if (col_lendiff)#else /* If we've already printed over the entire width of the screen, including the old material, then col_lendiff doesn't matter and space_to_eol will insert too many spaces. XXX - maybe we should adjust col_lendiff based on the difference between _rl_last_c_pos and _rl_screenwidth */ if (col_lendiff && ((MB_CUR_MAX == 1 || rl_byte_oriented) || (_rl_last_c_pos < _rl_screenwidth)))#endif { if (_rl_term_autowrap && current_line < inv_botlin) space_to_eol (col_lendiff); else _rl_clear_to_eol (col_lendiff); } } }}/* Tell the update routines that we have moved onto a new (empty) line. */intrl_on_new_line (){ if (visible_line) visible_line[0] = '\0'; _rl_last_c_pos = _rl_last_v_pos = 0; _rl_vis_botlin = last_lmargin = 0; if (vis_lbreaks) vis_lbreaks[0] = vis_lbreaks[1] = 0; visible_wrap_offset = 0; return 0;}/* Tell the update routines that we have moved onto a new line with the prompt already displayed. Code originally from the version of readline distributed with CLISP. rl_expand_prompt must have already been called (explicitly or implicitly). This still doesn't work exactly right. */intrl_on_new_line_with_prompt (){ int prompt_size, i, l, real_screenwidth, newlines; char *prompt_last_line, *lprompt; /* Initialize visible_line and invisible_line to ensure that they can hold the already-displayed prompt. */ prompt_size = strlen (rl_prompt) + 1; init_line_structures (prompt_size); /* Make sure the line structures hold the already-displayed prompt for redisplay. */ lprompt = local_prompt ? local_prompt : rl_prompt; strcpy (visible_line, lprompt); strcpy (invisible_line, lprompt); /* If the prompt contains newlines, take the last tail. */ prompt_last_line = strrchr (rl_prompt, '\n'); if (!prompt_last_line) prompt_last_line = rl_prompt; l = strlen (prompt_last_line); if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l, 1); /* XXX */ else _rl_last_c_pos = l; /* Dissect prompt_last_line into screen lines. Note that here we have to use the real screenwidth. Readline's notion of screenwidth might be one less, see terminal.c. */ real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1); _rl_last_v_pos = l / real_screenwidth; /* If the prompt length is a multiple of real_screenwidth, we don't know whether the cursor is at the end of the last line, or already at the beginning of the next line. Output a newline just to be safe. */ if (l > 0 && (l % real_screenwidth) == 0) _rl_output_some_chars ("\n", 1); last_lmargin = 0; newlines = 0; i = 0; while (i <= l) { _rl_vis_botlin = newlines; vis_lbreaks[newlines++] = i; i += real_screenwidth; } vis_lbreaks[newlines] = l; visible_wrap_offset = 0; rl_display_prompt = rl_prompt; /* XXX - make sure it's set */ return 0;}/* Actually update the display, period. */intrl_forced_update_display (){ register char *temp; if (visible_line) { temp = visible_line; while (*temp) *temp++ = '\0'; } rl_on_new_line (); forced_display++; (*rl_redisplay_function) (); return 0;}/* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices. (Well, when we don't have multibyte characters, _rl_last_c_pos is a buffer index.) DATA is the contents of the screen line of interest; i.e., where the movement is being done. */void_rl_move_cursor_relative (new, data) int new; const char *data;{ register int i; int woff; /* number of invisible chars on current line */ int cpos, dpos; /* current and desired cursor positions */ int adjust; woff = WRAP_OFFSET (_rl_last_v_pos, wrap_offset); cpos = _rl_last_c_pos; if (cpos == 0 && cpos == new) return;#if defined (HANDLE_MULTIBYTE) /* If we have multibyte characters, NEW is indexed by the buffer point in a multibyte string, but _rl_last_c_pos is the display position. In this case, NEW's display position is not obvious and must be calculated. We need to account for invisible characters in this line, as long as we are past them and they are counted by _rl_col_width. */ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) { adjust = 1; /* Try to short-circuit common cases and eliminate a bunch of multibyte character function calls. */ /* 1. prompt string */ if (new == local_prompt_len && memcmp (data, local_prompt, new) == 0) { dpos = prompt_physical_chars; cpos_adjusted = 1; adjust = 0; } /* 2. prompt_string + line contents */ else if (new > local_prompt_len && local_prompt && memcmp (data, local_prompt, local_prompt_len) == 0) { dpos = prompt_physical_chars + _rl_col_width (data, local_prompt_len, new, 1); cpos_adjusted = 1; adjust = 0; } else dpos = _rl_col_width (data, 0, new, 1); /* Use NEW when comparing against the last invisible character in the prompt string, since they're both buffer indices and DPOS is a desired display position. */ if (adjust && ((new > prompt_last_invisible) || /* XXX - don't use woff here */ (prompt_physical_chars >= _rl_screenwidth && _rl_last_v_pos == prompt_last_screen_line && wrap_offset >= woff && dpos >= woff && new > (prompt_last_invisible-(_rl_screenwidth*_rl_last_v_pos)-wrap_offset)))) /* XXX last comparison might need to be >= */ { dpos -= woff; /* Since this will be assigned to _rl_last_c_pos at the end (more precisely, _rl_last_c_pos == dpos when this function returns), let the caller know. */ cpos_adjusted = 1; } } else#endif dpos = new; /* If we don't have to do anything, then return. */ if (cpos == dpos) return; /* It may be faster to output a CR, and then move forwards instead of moving backwards. */ /* i == current physical cursor position. */#if defined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) i = _rl_last_c_pos; else#endif i = _rl_last_c_pos - woff; if (dpos == 0 || CR_FASTER (dpos, _rl_last_c_pos) || (_rl_term_autowrap && i == _rl_screenwidth)) {#if defined (__MSDOS__) putc ('\r', rl_outstream);#else tputs (_rl_term_cr, 1, _rl_output_character_function);#endif /* !__MSDOS__ */ cpos = _rl_last_c_pos = 0; } if (cpos < dpos) { /* Move the cursor forward. We do it by printing the command to move the cursor forward if the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -