?? display.c
字號(hào):
otherwise, let long lines display in a single terminal line, and horizontally scroll it. */ if (!_rl_horizontal_scroll_mode && term_up && *term_up) { int total_screen_chars = screenchars; int nleft, cursor_linenum, pos, changed_screen_line; if (!rl_display_fixed || forced_display) { forced_display = 0; /* If we have more than a screenful of material to display, then only display a screenful. We should display the last screen, not the first. I'll fix this in a minute. */ if (out >= total_screen_chars) out = total_screen_chars - 1; /* Number of screen lines to display. The first line wraps at (screenwidth + wrap_offset) chars, the rest of the lines have screenwidth chars. */ nleft = out - wrap_offset + term_xn - 1; inv_botlin = (nleft > 0) ? nleft / screenwidth : 0; /* The first line is at character position 0 in the buffer. The second and subsequent lines start at N * screenwidth, offset by OFFSET. OFFSET is wrap_offset for the invisible line and visible_wrap_offset for the line currently displayed. */#define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)#define L_OFFSET(n, offset) ((n) > 0 ? ((n) * screenwidth) + (offset) : 0)#define VIS_CHARS(line) &visible_line[L_OFFSET((line), visible_wrap_offset)]#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)#define INV_LINE(line) &invisible_line[L_OFFSET((line), wrap_offset)] /* For each line in the buffer, do the updating display. */ for (linenum = 0; linenum <= inv_botlin; linenum++) { update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum, screenwidth + W_OFFSET(linenum, visible_wrap_offset), screenwidth + W_OFFSET(linenum, wrap_offset), inv_botlin); /* If this is the line with the prompt, we might need to compensate for invisible characters in the new line. Do this only if there is not more than one new line (which implies that we completely overwrite the old visible line) and the new line is shorter than the old. */ if (linenum == 0 && inv_botlin == 0 && (wrap_offset > visible_wrap_offset) && (_rl_last_c_pos < visible_first_line_len)) { nleft = screenwidth + wrap_offset - _rl_last_c_pos; clear_to_eol (nleft); } /* Since the new first line is now visible, save its length. */ if (linenum == 0) visible_first_line_len = (inv_botlin > 0) ? screenwidth : out - wrap_offset; } /* We may have deleted some lines. If so, clear the left over blank ones at the bottom out. */ if (_rl_vis_botlin > inv_botlin) { char *tt; for (; linenum <= _rl_vis_botlin; linenum++) { tt = VIS_CHARS (linenum); _rl_move_vert (linenum); _rl_move_cursor_relative (0, tt); clear_to_eol ((linenum == _rl_vis_botlin) ? strlen (tt) : screenwidth); } } _rl_vis_botlin = inv_botlin; /* Move the cursor where it should be. */ /* Which line? */ nleft = c_pos - wrap_offset - term_xn + 1; cursor_linenum = (nleft > 0) ? nleft / screenwidth : 0; /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a different screen line during this redisplay. */ changed_screen_line = _rl_last_v_pos != cursor_linenum; if (changed_screen_line) { _rl_move_vert (cursor_linenum); /* If we moved up to the line with the prompt using term_up, the physical cursor position on the screen stays the same, but the buffer position needs to be adjusted to account for invisible characters. */ if (cursor_linenum == 0 && wrap_offset) _rl_last_c_pos += wrap_offset; } /* We have to reprint the prompt if it contains invisible characters, since it's not generally OK to just reprint the characters from the current cursor position. */ nleft = visible_length + wrap_offset; if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 && _rl_last_c_pos <= nleft && local_prompt) { if (term_cr) tputs (term_cr, 1, _rl_output_character_function); _rl_output_some_chars (local_prompt, nleft); _rl_last_c_pos = nleft; } /* Where on that line? And where does that line start in the buffer? */ pos = L_OFFSET(cursor_linenum, wrap_offset); /* nleft == number of characters in the line buffer between the start of the line and the cursor position. */ nleft = c_pos - pos; /* Since backspace() doesn't know about invisible characters in the prompt, and there's no good way to tell it, we compensate for those characters here and call backspace() directly. */ if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos) { backspace (_rl_last_c_pos - nleft); _rl_last_c_pos = nleft; } if (nleft != _rl_last_c_pos) _rl_move_cursor_relative (nleft, &invisible_line[pos]); } } else /* Do horizontal scrolling. */ {#define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0) int lmargin, ndisp, nleft, phys_c_pos, t; /* Always at top line. */ _rl_last_v_pos = 0; /* Compute where in the buffer the displayed line should start. This will be LMARGIN. */ /* The number of characters that will be displayed before the cursor. */ ndisp = c_pos - wrap_offset; nleft = visible_length + wrap_offset; /* Where the new cursor position will be on the screen. This can be longer than SCREENWIDTH; if it is, lmargin will be adjusted. */ phys_c_pos = c_pos - (last_lmargin ? last_lmargin : wrap_offset); t = screenwidth / 3; /* If the number of characters had already exceeded the screenwidth, last_lmargin will be > 0. */ /* If the number of characters to be displayed is more than the screen width, compute the starting offset so that the cursor is about two-thirds of the way across the screen. */ if (phys_c_pos > screenwidth - 2) { lmargin = c_pos - (2 * t); if (lmargin < 0) lmargin = 0; /* If the left margin would be in the middle of a prompt with invisible characters, don't display the prompt at all. */ if (wrap_offset && lmargin > 0 && lmargin < nleft) lmargin = nleft; } else if (ndisp < screenwidth - 2) /* XXX - was -1 */ lmargin = 0; else if (phys_c_pos < 1) { /* If we are moving back towards the beginning of the line and the last margin is no longer correct, compute a new one. */ lmargin = ((c_pos - 1) / t) * t; /* XXX */ if (wrap_offset && lmargin > 0 && lmargin < nleft) lmargin = nleft; } else lmargin = last_lmargin; /* If the first character on the screen isn't the first character in the display line, indicate this with a special character. */ if (lmargin > 0) line[lmargin] = '<'; /* If SCREENWIDTH characters starting at LMARGIN do not encompass the whole line, indicate that with a special characters at the right edge of the screen. If LMARGIN is 0, we need to take the wrap offset into account. */ t = lmargin + M_OFFSET (lmargin, wrap_offset) + screenwidth; if (t < out) line[t - 1] = '>'; if (!rl_display_fixed || forced_display || lmargin != last_lmargin) { forced_display = 0; update_line (&visible_line[last_lmargin], &invisible_line[lmargin], 0, screenwidth + visible_wrap_offset, screenwidth + (lmargin ? 0 : wrap_offset), 0); /* If the visible new line is shorter than the old, but the number of invisible characters is greater, and we are at the end of the new line, we need to clear to eol. */ t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset); if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) && (_rl_last_c_pos == out) && t < visible_first_line_len) { nleft = screenwidth - t; clear_to_eol (nleft); } visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset); if (visible_first_line_len > screenwidth) visible_first_line_len = screenwidth; _rl_move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]); last_lmargin = lmargin; } } fflush (rl_outstream); /* Swap visible and non-visible lines. */ { char *temp = visible_line; visible_line = invisible_line; invisible_line = temp; rl_display_fixed = 0; /* If we are displaying on a single line, and last_lmargin is > 0, we are not displaying any invisible characters, so set visible_wrap_offset to 0. */ if (_rl_horizontal_scroll_mode && last_lmargin) visible_wrap_offset = 0; else visible_wrap_offset = wrap_offset; }}/* PWP: update_line() is based on finding the middle difference of each line on the screen; vis: /old first difference /beginning of line | /old last same /old EOL v v v vold: eddie> Oh, my little gruntle-buggy is to me, as lurgid asnew: eddie> Oh, my little buggy says to me, as lurgid as ^ ^ ^ ^ \beginning of line | \new last same \new end of line \new first difference All are character pointers for the sake of speed. Special cases for no differences, as well as for end of line additions must be handeled. Could be made even smarter, but this works well enough */static voidupdate_line (old, new, current_line, omax, nmax, inv_botlin) register char *old, *new; int current_line, omax, nmax;{ register char *ofd, *ols, *oe, *nfd, *nls, *ne; int temp, lendiff, wsatend, od, nd; /* If we're at the right edge of a terminal that supports xn, we're ready to wrap around, so do so. This fixes problems with knowing the exact cursor position and cut-and-paste with certain terminal emulators. In this calculation, TEMP is the physical screen position of the cursor. */ temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset); if (temp == screenwidth && term_xn && !_rl_horizontal_scroll_mode && _rl_last_v_pos == current_line - 1) { if (new[0]) putc (new[0], rl_outstream); else putc (' ', rl_outstream); _rl_last_c_pos = 1; /* XXX */ _rl_last_v_pos++; if (old[0]) old[0] = new[0]; } /* Find first difference. */ for (ofd = old, nfd = new; (ofd - old < omax) && *ofd && (*ofd == *nfd); ofd++, nfd++) ; /* Move to the end of the screen line. ND and OD are used to keep track of the distance between ne and new and oe and old, respectively, to move a subtraction out of each loop. */ for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++); for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++); /* If no difference, continue to next line. */ if (ofd == oe && nfd == ne) return; wsatend = 1; /* flag for trailing whitespace */ ols = oe - 1; /* find last same */ nls = ne - 1; while ((ols > ofd) && (nls > nfd) && (*ols == *nls)) { if (*ols != ' ') wsatend = 0; ols--; nls--; } if (wsatend) { ols = oe; nls = ne; } else if (*ols != *nls) { if (*ols) /* don't step past the NUL */ ols++; if (*nls) nls++; } _rl_move_vert (current_line); /* If this is the first line and there are invisible characters in the prompt string, and the prompt string has not changed, then redraw the entire prompt string. We can only do this reliably if the terminal supports a `cr' capability. This is more than just an efficiency hack -- there is a problem with redrawing portions of the prompt string if they contain terminal escape sequences (like drawing the `unbold' sequence without a corresponding `bold') that manifests itself on certain terminals. */ lendiff = strlen (local_prompt); if (current_line == 0 && !_rl_horizontal_scroll_mode && lendiff > visible_length && _rl_last_c_pos > 0 && (ofd - old) >= lendiff && term_cr) { tputs (term_cr, 1, _rl_output_character_function); _rl_output_some_chars (local_prompt, lendiff); _rl_last_c_pos = lendiff; } _rl_move_cursor_relative (ofd - old, old); /* if (len (new) > len (old)) */ lendiff = (nls - nfd) - (ols - ofd); /* Insert (diff (len (old), len (new)) ch. */ temp = ne - nfd; if (lendiff > 0) { /* Non-zero if we're increasing the number of lines. */ int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin; /* 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. */ if (terminal_can_insert && ((2 * temp) >= lendiff || term_IC) && (!term_xn || !gl)) { /* If lendiff > visible_length and _rl_last_c_pos == 0 and _rl_horizontal_scroll_mode == 1, inserting the characters with term_IC or term_ic will screw up the screen because of the invisible characters. We need to just draw them. */ if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 || lendiff <= visible_length)) { insert_some_chars (nfd, lendiff); _rl_last_c_pos += lendiff; } else { /* At the end of a line the characters do not have to be "inserted". They can just be placed on the screen. */ _rl_output_some_chars (nfd, lendiff); _rl_last_c_pos += lendiff; } /* 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); _rl_last_c_pos += temp - lendiff; } } else { /* cannot insert chars, write to EOL */ _rl_output_some_chars (nfd, temp); _rl_last_c_pos += temp; } } else /* Delete characters from line. */ { /* If possible and inexpensive to use terminal deletion, then do so. */ if (term_dc && (2 * temp) >= -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) lendiff = 0; if (lendiff) delete_chars (-lendiff); /* delete (diff) characters */
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -