/* After a resize, clear all the lines that were occupied by prompt + line buffer before the resize */ static void wipe_textarea(struct winsize *old_winsize) { int point, lineheight, linelength, cursor_height, i, promptlength; if (!prompt_is_single_line()) { /* Don't need to do anything in horizontal_scroll_mode */ promptlength = colourless_strlen((saved_rl_state.cooked_prompt ? saved_rl_state.cooked_prompt: saved_rl_state.raw_prompt), NULL, old_winsize -> ws_col); linelength = (within_line_edit ? strlen(rl_line_buffer) : 0) + promptlength; point = (within_line_edit ? rl_point : 0) + promptlength; assert(old_winsize -> ws_col > 0); lineheight = (linelength == 0 ? 0 : (1 + (max(point, (linelength - 1)) / old_winsize -> ws_col))); if (lineheight > 1 && term_cursor_up != NULL && term_cursor_down != NULL) { /* i.e. if we have multiple rows displayed, and we can clean them up first */ cr(); cursor_height = point / old_winsize -> ws_col; /* cursor is still on old line */ DPRINTF2(DEBUG_SIGNALS, "lineheight: %d, cursor_height: %d", lineheight, cursor_height); for (i = 1 + cursor_height; i < lineheight; i++) curs_down(); /* ...move it down to last line */ for (i = lineheight; i > 1; i--) { /* go up again, erasing every line */ clear_line(); curs_up(); } } clear_line(); cr(); } }
int colourless_strlen_unmarked (const char *str, int termwidth) { char *marked_str = mark_invisible(str); int colourless_length = colourless_strlen(marked_str, NULL, termwidth); free(marked_str); return colourless_length; }
static void my_homegrown_redisplay(int hide_passwords) { static int line_start = 0; /* at which position of prompt_plus_line does the printed line start? */ static int line_extends_right = 0; static int line_extends_left = 0; static char *previous_line = NULL; int width = winsize.ws_col; int skip = max(1, min(width / 5, 10)); /* jumpscroll this many positions when cursor reaches edge of terminal */ char *prompt_without_ignore_markers; int colourless_promptlen = colourless_strlen(rl_prompt, &prompt_without_ignore_markers,0); int promptlen = strlen(prompt_without_ignore_markers); int invisible_chars_in_prompt = promptlen - colourless_promptlen; char *prompt_plus_line = add2strings(prompt_without_ignore_markers, rl_line_buffer); char *new_line; int total_length = strlen(prompt_plus_line); int curpos = promptlen + rl_point; /* cursor position within prompt_plus_line */ int i, printed_length, new_curpos, /* cursor position on screen */ keep_old_line, vlinestart, printwidth, last_column; DPRINTF3(DEBUG_AD_HOC,"rl_prompt: <%s>, prompt_without_ignore_markers: <%s>, prompt_plus_line: <%s>", rl_prompt, prompt_without_ignore_markers, prompt_plus_line); /* In order to handle prompt with colour we either print the whole prompt, or start past it: starting in the middle is too difficult (i.e. I am too lazy) to get it right. We use a "virtual line start" vlinestart, which is the number of invisible chars in prompt in the former case, or linestart in the latter (which then must be >= strlen(prompt)) At all times (before redisplay and after) the following is true: - the cursor is at column (curpos - vlinestart) (may be < 0 or > width) - the character under the cursor is prompt_plus_line[curpos] - the character at column 0 is prompt_plus_line[linestart] - the last column is at <number of printed visible or invisible chars> - vlinestart the goal of this function is to display (part of) prompt_plus_line such that the cursor is visible again */ if (hide_passwords) for (i = promptlen; i < total_length; i++) prompt_plus_line[i] = '*'; /* hide a pasword by making user input unreadable */ if (rl_point == 0) /* (re)set at program start and after accept_line (where rl_point is zeroed) */ line_start = 0; assert(line_start == 0 || line_start >= promptlen); /* the line *never* starts in the middle of the prompt (too complicated to handle)*/ vlinestart = (line_start > promptlen ? line_start : invisible_chars_in_prompt); if (curpos - vlinestart > width - line_extends_right) /* cursor falls off right edge ? */ vlinestart = (curpos - width + line_extends_right) + skip; /* jumpscroll left */ else if (curpos < vlinestart + line_extends_left) { /* cursor falls off left edge ? */ if (curpos == total_length) /* .. but still at end of line? */ vlinestart = max(0, total_length - width); /* .. try to display entire line */ else /* in not at end of line .. */ vlinestart = curpos - line_extends_left - skip; /* ... jumpscroll right .. */ } if (vlinestart <= invisible_chars_in_prompt) { line_start = 0; /* ... but not past start of line! */ vlinestart = invisible_chars_in_prompt; } else if (vlinestart > invisible_chars_in_prompt && vlinestart <= promptlen) { line_start = vlinestart = promptlen; } else { line_start = vlinestart; } printwidth = (line_start > 0 ? width : width + invisible_chars_in_prompt); printed_length = min(printwidth, total_length - line_start); /* never print more than width */ last_column = printed_length - vlinestart; /* some invariants : 0 <= line_start <= curpos <= line_start + printed_length <= total_length */ /* these are interesting: ^ ^ */ assert(0 <= line_start); assert(line_start <= curpos); assert(curpos <= line_start + printed_length); /* <=, rather than <, as cursor may be past eol */ assert(line_start + printed_length <= total_length); new_line = prompt_plus_line + line_start; new_line[printed_length] = '\0'; new_curpos = curpos - vlinestart; /* indicate whether line extends past right or left edge (i.e. whether the "interesting inequalities marked ^ above are really unequal) */ line_extends_left = (line_start > 0 ? 1 : 0); line_extends_right = (total_length - vlinestart > width ? 1 : 0); if (line_extends_left) new_line[0] = '<'; if (line_extends_right) new_line[printwidth - 1] = '>'; keep_old_line = FALSE; if (term_cursor_hpos) { if (previous_line && strcmp(new_line, previous_line) == 0) { keep_old_line = TRUE; } else { if (previous_line) free(previous_line); previous_line = mysavestring(new_line); } } /* DPRINTF2(DEBUG_AD_HOC, "keep_old_line=%d, new_line=<%s>", keep_old_line, new_line); */ /* keep_old_line = TRUE; */ if (!keep_old_line) { clear_line(); cr(); write_patiently(STDOUT_FILENO, new_line, printed_length, "to stdout"); } assert(term_cursor_hpos || !keep_old_line); /* if we cannot position cursor, we must have reprinted ... */ if (term_cursor_hpos) cursor_hpos(new_curpos); else /* ... so we know we're 1 past last position on line */ backspace(last_column - new_curpos); free(prompt_plus_line); free(prompt_without_ignore_markers); }