📄 refresh.c
字号:
} } } /* * Pragmatics I: If old trailing whitespace or not enough characters to * save to be worth it, then don't save the last same info. */ if ((oe - ols) < MIN_END_KEEP) { ols = oe; nls = ne; } /* * Pragmatics II: if the terminal isn't smart enough, make the data * dumber so the smart update doesn't try anything fancy */ /* * fx is the number of characters we need to insert/delete: in the * beginning to bring the two same begins together */ fx = (nsb - nfd) - (osb - ofd); /* * sx is the number of characters we need to insert/delete: in the * end to bring the two same last parts together */ sx = (nls - nse) - (ols - ose); if (!EL_CAN_INSERT) { if (fx > 0) { osb = ols; ose = ols; nsb = nls; nse = nls; } if (sx > 0) { ols = oe; nls = ne; } if ((ols - ofd) < (nls - nfd)) { ols = oe; nls = ne; } } if (!EL_CAN_DELETE) { if (fx < 0) { osb = ols; ose = ols; nsb = nls; nse = nls; } if (sx < 0) { ols = oe; nls = ne; } if ((ols - ofd) > (nls - nfd)) { ols = oe; nls = ne; } } /* * Pragmatics III: make sure the middle shifted pointers are correct if * they don't point to anything (we may have moved ols or nls). */ /* if the change isn't worth it, don't bother */ /* was: if (osb == ose) */ if ((ose - osb) < MIN_END_KEEP) { osb = ols; ose = ols; nsb = nls; nse = nls; } /* * Now that we are done with pragmatics we recompute fx, sx */ fx = (nsb - nfd) - (osb - ofd); sx = (nls - nse) - (ols - ose); ELRE_DEBUG(1, (__F, "\n")); ELRE_DEBUG(1, (__F, "ofd %d, osb %d, ose %d, ols %d, oe %d\n", ofd - old, osb - old, ose - old, ols - old, oe - old)); ELRE_DEBUG(1, (__F, "nfd %d, nsb %d, nse %d, nls %d, ne %d\n", nfd - new, nsb - new, nse - new, nls - new, ne - new)); ELRE_DEBUG(1, (__F, "xxx-xxx:\"00000000001111111111222222222233333333334\"\r\n")); ELRE_DEBUG(1, (__F, "xxx-xxx:\"01234567890123456789012345678901234567890\"\r\n"));#ifdef DEBUG_REFRESH re_printstr(el, "old- oe", old, oe); re_printstr(el, "new- ne", new, ne); re_printstr(el, "old-ofd", old, ofd); re_printstr(el, "new-nfd", new, nfd); re_printstr(el, "ofd-osb", ofd, osb); re_printstr(el, "nfd-nsb", nfd, nsb); re_printstr(el, "osb-ose", osb, ose); re_printstr(el, "nsb-nse", nsb, nse); re_printstr(el, "ose-ols", ose, ols); re_printstr(el, "nse-nls", nse, nls); re_printstr(el, "ols- oe", ols, oe); re_printstr(el, "nls- ne", nls, ne);#endif /* DEBUG_REFRESH */ /* * el_cursor.v to this line i MUST be in this routine so that if we * don't have to change the line, we don't move to it. el_cursor.h to * first diff char */ term_move_to_line(el, i); /* * at this point we have something like this: * * /old /ofd /osb /ose /ols /oe * v.....................v v..................v v........v * eddie> Oh, my fredded gruntle-buggy is to me, as foo var lurgid as * eddie> Oh, my fredded quiux buggy is to me, as gruntle-lurgid as * ^.....................^ ^..................^ ^........^ * \new \nfd \nsb \nse \nls \ne * * fx is the difference in length between the chars between nfd and * nsb, and the chars between ofd and osb, and is thus the number of * characters to delete if < 0 (new is shorter than old, as above), * or insert (new is longer than short). * * sx is the same for the second differences. */ /* * if we have a net insert on the first difference, AND inserting the * net amount ((nsb-nfd) - (osb-ofd)) won't push the last useful * character (which is ne if nls != ne, otherwise is nse) off the edge * of the screen (el->el_term.t_size.h) else we do the deletes first * so that we keep everything we need to. */ /* * if the last same is the same like the end, there is no last same * part, otherwise we want to keep the last same part set p to the * last useful old character */ p = (ols != oe) ? oe : ose; /* * if (There is a diffence in the beginning) && (we need to insert * characters) && (the number of characters to insert is less than * the term width) * We need to do an insert! * else if (we need to delete characters) * We need to delete characters! * else * No insert or delete */ if ((nsb != nfd) && fx > 0 && ((p - old) + fx <= el->el_term.t_size.h)) { ELRE_DEBUG(1, (__F, "first diff insert at %d...\r\n", nfd - new)); /* * Move to the first char to insert, where the first diff is. */ term_move_to_char(el, nfd - new); /* * Check if we have stuff to keep at end */ if (nsb != ne) { ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n")); /* * insert fx chars of new starting at nfd */ if (fx > 0) { ELRE_DEBUG(!EL_CAN_INSERT, (__F, "ERROR: cannot insert in early first diff\n")); term_insertwrite(el, nfd, fx); re_insert(el, old, ofd - old, el->el_term.t_size.h, nfd, fx); } /* * write (nsb-nfd) - fx chars of new starting at * (nfd + fx) */ term_overwrite(el, nfd + fx, (nsb - nfd) - fx); re__strncopy(ofd + fx, nfd + fx, (size_t) ((nsb - nfd) - fx)); } else { ELRE_DEBUG(1, (__F, "without anything to save\r\n")); term_overwrite(el, nfd, (nsb - nfd)); re__strncopy(ofd, nfd, (size_t) (nsb - nfd)); /* * Done */ return; } } else if (fx < 0) { ELRE_DEBUG(1, (__F, "first diff delete at %d...\r\n", ofd - old)); /* * move to the first char to delete where the first diff is */ term_move_to_char(el, ofd - old); /* * Check if we have stuff to save */ if (osb != oe) { ELRE_DEBUG(1, (__F, "with stuff to save at end\r\n")); /* * fx is less than zero *always* here but we check * for code symmetry */ if (fx < 0) { ELRE_DEBUG(!EL_CAN_DELETE, (__F, "ERROR: cannot delete in first diff\n")); term_deletechars(el, -fx); re_delete(el, old, ofd - old, el->el_term.t_size.h, -fx); } /* * write (nsb-nfd) chars of new starting at nfd */ term_overwrite(el, nfd, (nsb - nfd)); re__strncopy(ofd, nfd, (size_t) (nsb - nfd)); } else { ELRE_DEBUG(1, (__F, "but with nothing left to save\r\n")); /* * write (nsb-nfd) chars of new starting at nfd */ term_overwrite(el, nfd, (nsb - nfd)); ELRE_DEBUG(1, (__F, "cleareol %d\n", (oe - old) - (ne - new))); term_clear_EOL(el, (oe - old) - (ne - new)); /* * Done */ return; } } else fx = 0; if (sx < 0 && (ose - old) + fx < el->el_term.t_size.h) { ELRE_DEBUG(1, (__F, "second diff delete at %d...\r\n", (ose - old) + fx)); /* * Check if we have stuff to delete */ /* * fx is the number of characters inserted (+) or deleted (-) */ term_move_to_char(el, (ose - old) + fx); /* * Check if we have stuff to save */ if (ols != oe) { ELRE_DEBUG(1, (__F, "with stuff to save at end\r\n")); /* * Again a duplicate test. */ if (sx < 0) { ELRE_DEBUG(!EL_CAN_DELETE, (__F, "ERROR: cannot delete in second diff\n")); term_deletechars(el, -sx); } /* * write (nls-nse) chars of new starting at nse */ term_overwrite(el, nse, (nls - nse)); } else { ELRE_DEBUG(1, (__F, "but with nothing left to save\r\n")); term_overwrite(el, nse, (nls - nse)); ELRE_DEBUG(1, (__F, "cleareol %d\n", (oe - old) - (ne - new))); if ((oe - old) - (ne - new) != 0) term_clear_EOL(el, (oe - old) - (ne - new)); } } /* * if we have a first insert AND WE HAVEN'T ALREADY DONE IT... */ if ((nsb != nfd) && (osb - ofd) <= (nsb - nfd) && (fx == 0)) { ELRE_DEBUG(1, (__F, "late first diff insert at %d...\r\n", nfd - new)); term_move_to_char(el, nfd - new); /* * Check if we have stuff to keep at the end */ if (nsb != ne) { ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n")); /* * We have to recalculate fx here because we set it * to zero above as a flag saying that we hadn't done * an early first insert. */ fx = (nsb - nfd) - (osb - ofd); if (fx > 0) { /* * insert fx chars of new starting at nfd */ ELRE_DEBUG(!EL_CAN_INSERT, (__F, "ERROR: cannot insert in late first diff\n")); term_insertwrite(el, nfd, fx); re_insert(el, old, ofd - old, el->el_term.t_size.h, nfd, fx); } /* * write (nsb-nfd) - fx chars of new starting at * (nfd + fx) */ term_overwrite(el, nfd + fx, (nsb - nfd) - fx); re__strncopy(ofd + fx, nfd + fx, (size_t) ((nsb - nfd) - fx)); } else { ELRE_DEBUG(1, (__F, "without anything to save\r\n")); term_overwrite(el, nfd, (nsb - nfd)); re__strncopy(ofd, nfd, (size_t) (nsb - nfd)); } } /* * line is now NEW up to nse */ if (sx >= 0) { ELRE_DEBUG(1, (__F, "second diff insert at %d...\r\n", nse - new)); term_move_to_char(el, nse - new); if (ols != oe) { ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n")); if (sx > 0) { /* insert sx chars of new starting at nse */ ELRE_DEBUG(!EL_CAN_INSERT, (__F, "ERROR: cannot insert in second diff\n")); term_insertwrite(el, nse, sx); } /* * write (nls-nse) - sx chars of new starting at * (nse + sx) */ term_overwrite(el, nse + sx, (nls - nse) - sx); } else { ELRE_DEBUG(1, (__F, "without anything to save\r\n")); term_overwrite(el, nse, (nls - nse)); /* * No need to do a clear-to-end here because we were * doing a second insert, so we will have over * written all of the old string. */ } } ELRE_DEBUG(1, (__F, "done.\r\n"));}/* re__copy_and_pad(): * Copy string and pad with spaces */private voidre__copy_and_pad(char *dst, const char *src, size_t width){ int i; for (i = 0; i < width; i++) { if (*src == '\0') break; *dst++ = *src++; } for (; i < width; i++) *dst++ = ' '; *dst = '\0';}/* re_refresh_cursor(): * Move to the new cursor position */protected voidre_refresh_cursor(EditLine *el){ char *cp, c; int h, v, th; /* first we must find where the cursor is... */ h = el->el_prompt.p_pos.h; v = el->el_prompt.p_pos.v; th = el->el_term.t_size.h; /* optimize for speed */ /* do input buffer to el->el_line.cursor */ for (cp = el->el_line.buffer; cp < el->el_line.cursor; cp++) { c = *cp; h++; /* all chars at least this long */ if (c == '\n') {/* handle newline in data part too */ h = 0; v++; } else { if (c == '\t') { /* if a tab, to next tab stop */ while (h & 07) { h++; } } else if (iscntrl((unsigned char) c)) { /* if control char */ h++; if (h > th) { /* if overflow, compensate */ h = 1; v++; } } else if (!isprint((unsigned char) c)) { h += 3; if (h > th) { /* if overflow, compensate */ h = h - th; v++; } } } if (h >= th) { /* check, extra long tabs picked up here also */ h = 0; v++; } } /* now go there */ term_move_to_line(el, v); term_move_to_char(el, h); term__flush();}/* re_fastputc(): * Add a character fast. */private voidre_fastputc(EditLine *el, int c){ term__putc(c); el->el_display[el->el_cursor.v][el->el_cursor.h++] = c; if (el->el_cursor.h >= el->el_term.t_size.h) { /* if we must overflow */ el->el_cursor.h = 0; /* * If we would overflow (input is longer than terminal size), * emulate scroll by dropping first line and shuffling the rest. * We do this via pointer shuffling - it's safe in this case * and we avoid memcpy(). */ if (el->el_cursor.v + 1 >= el->el_term.t_size.v) { int i, lins = el->el_term.t_size.v; char *firstline = el->el_display[0]; for(i=1; i < lins; i++) el->el_display[i-1] = el->el_display[i]; re__copy_and_pad(firstline, "", 0); el->el_display[i-1] = firstline; } else { el->el_cursor.v++; el->el_refresh.r_oldcv++; } if (EL_HAS_AUTO_MARGINS) { if (EL_HAS_MAGIC_MARGINS) { term__putc(' '); term__putc('\b'); } } else { term__putc('\r'); term__putc('\n'); } }}/* re_fastaddc(): * we added just one char, handle it fast. * Assumes that screen cursor == real cursor */protected voidre_fastaddc(EditLine *el){ char c; int rhdiff; c = el->el_line.cursor[-1]; if (c == '\t' || el->el_line.cursor != el->el_line.lastchar) { re_refresh(el); /* too hard to handle */ return; } rhdiff = el->el_term.t_size.h - el->el_cursor.h - el->el_rprompt.p_pos.h; if (el->el_rprompt.p_pos.h && rhdiff < 3) { re_refresh(el); /* clear out rprompt if less than 1 char gap */ return; } /* else (only do at end of line, no TAB) */ if (iscntrl((unsigned char) c)) { /* if control char, do caret */ char mc = (c == '\177') ? '?' : (c | 0100); re_fastputc(el, '^'); re_fastputc(el, mc); } else if (isprint((unsigned char) c)) { /* normal char */ re_fastputc(el, c); } else { re_fastputc(el, '\\'); re_fastputc(el, (int) ((((unsigned int) c >> 6) & 7) + '0')); re_fastputc(el, (int) ((((unsigned int) c >> 3) & 7) + '0')); re_fastputc(el, (c & 7) + '0'); } term__flush();}/* re_clear_display(): * clear the screen buffers so that new new prompt starts fresh. */protected voidre_clear_display(EditLine *el){ int i; el->el_cursor.v = 0; el->el_cursor.h = 0; for (i = 0; i < el->el_term.t_size.v; i++) el->el_display[i][0] = '\0'; el->el_refresh.r_oldcv = 0;}/* re_clear_lines(): * Make sure all lines are *really* blank */protected voidre_clear_lines(EditLine *el){ if (EL_CAN_CEOL) { int i; term_move_to_char(el, 0); for (i = 0; i <= el->el_refresh.r_oldcv; i++) { /* for each line on the screen */ term_move_to_line(el, i); term_clear_EOL(el, el->el_term.t_size.h); } term_move_to_line(el, 0); } else { term_move_to_line(el, el->el_refresh.r_oldcv); /* go to last line */ term__putc('\r'); /* go to BOL */ term__putc('\n'); /* go to new line */ }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -