36 #if !defined(lint) && !defined(SCCSID)
38 static char sccsid[] =
"@(#)refresh.c 8.1 (Berkeley) 6/4/93";
53 private void re_nextline(
EditLine *);
54 private void re_addc(
EditLine *, Int);
55 private void re_update_line(
EditLine *, Char *, Char *,
int);
56 private void re_insert (
EditLine *, Char *,
int,
int, Char *,
int);
57 private void re_delete(
EditLine *, Char *,
int,
int,
int);
58 private void re_fastputc(
EditLine *, Int);
59 private void re_clear_eol(
EditLine *,
int,
int,
int);
60 private void re__strncopy(Char *, Char *,
size_t);
61 private void re__copy_and_pad(Char *,
const Char *,
size_t);
64 private void re_printstr(
EditLine *,
const char *,
char *,
char *);
65 #define __F el->el_errfile
66 #define ELRE_ASSERT(a, b, c) do \
72 #define ELRE_DEBUG(a, b) ELRE_ASSERT(a,b,;)
78 re_printstr(
EditLine *el,
const char *str,
char *f,
char *t)
81 ELRE_DEBUG(1, (__F,
"%s:\"", str));
83 ELRE_DEBUG(1, (__F,
"%c", *f++ & 0177));
84 ELRE_DEBUG(1, (__F,
"\"\r\n"));
87 #define ELRE_ASSERT(a, b, c)
88 #define ELRE_DEBUG(a, b)
97 el->el_refresh.r_cursor.h = 0;
105 if (el->el_refresh.r_cursor.v + 1 >= el->el_terminal.t_size.v) {
106 int i, lins = el->el_terminal.t_size.v;
107 Char *firstline = el->el_vdisplay[0];
109 for(i = 1; i < lins; i++)
110 el->el_vdisplay[i - 1] = el->el_vdisplay[i];
113 el->el_vdisplay[i - 1] = firstline;
115 el->el_refresh.r_cursor.v++;
117 ELRE_ASSERT(el->el_refresh.r_cursor.v >= el->el_terminal.t_size.v,
118 (__F,
"\r\nre_putc: overflow! r_cursor.v == %d > %d\r\n",
119 el->el_refresh.r_cursor.v, el->el_terminal.t_size.v),
129 switch (ct_chr_class((Char)c)) {
133 if ((el->el_refresh.r_cursor.h & 07) == 0)
138 int oldv = el->el_refresh.r_cursor.v;
139 re_putc(el,
'\0', 0);
140 if (oldv == el->el_refresh.r_cursor.v)
148 Char visbuf[VISUAL_WIDTH_MAX];
150 ct_visual_char(visbuf, VISUAL_WIDTH_MAX, (Char)c);
151 for (i = 0; n-- > 0; ++
i)
152 re_putc(el, visbuf[i], 1);
163 re_putc(
EditLine *el, Int c,
int shift)
166 ELRE_DEBUG(1, (__F,
"printing %5x '%c'\r\n", c, c));
168 while (shift && (el->el_refresh.r_cursor.h + w > el->el_terminal.t_size.h))
171 el->el_vdisplay[el->el_refresh.r_cursor.v]
172 [el->el_refresh.r_cursor.h] = c;
176 el->el_vdisplay[el->el_refresh.r_cursor.v]
177 [el->el_refresh.r_cursor.h +
i] = MB_FILL_CHAR;
182 el->el_refresh.r_cursor.h += w;
183 if (el->el_refresh.r_cursor.h >= el->el_terminal.t_size.h) {
185 el->el_vdisplay[el->el_refresh.r_cursor.v][el->el_terminal.t_size.h]
208 ELRE_DEBUG(1, (__F,
"el->el_line.buffer = :%s:\r\n",
209 el->el_line.buffer));
212 el->el_refresh.r_cursor.h = 0;
213 el->el_refresh.r_cursor.v = 0;
216 prompt_print(el, EL_RPROMPT);
219 el->el_refresh.r_cursor.h = 0;
220 el->el_refresh.r_cursor.v = 0;
222 if (el->el_line.cursor >= el->el_line.lastchar) {
223 if (el->el_map.current == el->el_map.alt
224 && el->el_line.lastchar != el->el_line.buffer)
225 el->el_line.cursor = el->el_line.lastchar - 1;
227 el->el_line.cursor = el->el_line.lastchar;
233 prompt_print(el, EL_PROMPT);
237 termsz = el->el_terminal.t_size.h * el->el_terminal.t_size.v;
238 if (el->el_line.lastchar - el->el_line.buffer > termsz) {
243 size_t rem = (el->el_line.lastchar-el->el_line.buffer)%termsz;
245 st = el->el_line.lastchar - rem
246 - (termsz - (((rem / el->el_terminal.t_size.v) - 1)
247 * el->el_terminal.t_size.v));
250 st = el->el_line.buffer;
252 for (cp = st; cp < el->el_line.lastchar; cp++) {
253 if (cp == el->el_line.cursor) {
256 cur.h = el->el_refresh.r_cursor.h;
257 cur.v = el->el_refresh.r_cursor.v;
259 if (w > 1 && el->el_refresh.r_cursor.h + w >
260 el->el_terminal.t_size.h) {
269 cur.h = el->el_refresh.r_cursor.h;
270 cur.v = el->el_refresh.r_cursor.v;
272 rhdiff = el->el_terminal.t_size.h - el->el_refresh.r_cursor.h -
273 el->el_rprompt.p_pos.h;
274 if (el->el_rprompt.p_pos.h && !el->el_rprompt.p_pos.v &&
275 !el->el_refresh.r_cursor.v && rhdiff > 1) {
283 prompt_print(el, EL_RPROMPT);
285 el->el_rprompt.p_pos.h = 0;
286 el->el_rprompt.p_pos.v = 0;
289 re_putc(el,
'\0', 0);
291 el->el_refresh.r_newcv = el->el_refresh.r_cursor.v;
294 "term.h=%d vcur.h=%d vcur.v=%d vdisplay[0]=\r\n:%80.80s:\r\n",
295 el->el_terminal.t_size.h, el->el_refresh.r_cursor.h,
296 el->el_refresh.r_cursor.v, ct_encode_string(el->el_vdisplay[0])));
298 ELRE_DEBUG(1, (__F,
"updating %d lines.\r\n", el->el_refresh.r_newcv));
299 for (i = 0; i <= el->el_refresh.r_newcv; i++) {
301 re_update_line(el, el->el_display[i], el->el_vdisplay[i], i);
310 re__copy_and_pad(el->el_display[i], el->el_vdisplay[i],
311 (
size_t) el->el_terminal.t_size.h);
314 "\r\nel->el_refresh.r_cursor.v=%d,el->el_refresh.r_oldcv=%d i=%d\r\n",
315 el->el_refresh.r_cursor.v, el->el_refresh.r_oldcv, i));
317 if (el->el_refresh.r_oldcv > el->el_refresh.r_newcv)
318 for (; i <= el->el_refresh.r_oldcv; i++) {
319 terminal_move_to_line(el, i);
320 terminal_move_to_char(el, 0);
322 terminal_clear_EOL(el, (
int) Strlen(el->el_display[i]));
324 terminal_overwrite(el,
"C\b", (
size_t)2);
326 el->el_display[
i][0] =
'\0';
329 el->el_refresh.r_oldcv = el->el_refresh.r_newcv;
331 "\r\ncursor.h = %d, cursor.v = %d, cur.h = %d, cur.v = %d\r\n",
332 el->el_refresh.r_cursor.h, el->el_refresh.r_cursor.v,
334 terminal_move_to_line(el, cur.v);
335 terminal_move_to_char(el, cur.h);
346 terminal_move_to_line(el, el->el_refresh.r_oldcv);
347 terminal__putc(el,
'\n');
348 re_clear_display(el);
359 re_insert(
EditLine *el __attribute__((__unused__)),
360 Char *d,
int dat,
int dlen, Char *s,
int num)
366 if (num > dlen - dat)
370 (__F,
"re_insert() starting: %d at %d max %d, d == \"%s\"\n",
371 num, dat, dlen, ct_encode_string(d)));
372 ELRE_DEBUG(1, (__F,
"s == \"%s\"\n", ct_encode_string(s)));
384 "re_insert() after insert: %d at %d max %d, d == \"%s\"\n",
385 num, dat, dlen, ct_encode_string(d)));
386 ELRE_DEBUG(1, (__F,
"s == \"%s\"\n", ct_encode_string(s)));
389 for (a = d + dat; (a < d + dlen) && (num > 0); num--)
396 (__F,
"re_insert() after copy: %d at %d max %d, %s == \"%s\"\n",
397 num, dat, dlen, d, s));
398 ELRE_DEBUG(1, (__F,
"s == \"%s\"\n", s));
408 re_delete(
EditLine *el __attribute__((__unused__)),
409 Char *d,
int dat,
int dlen,
int num)
415 if (dat + num >= dlen) {
420 (__F,
"re_delete() starting: %d at %d max %d, d == \"%s\"\n",
421 num, dat, dlen, ct_encode_string(d)));
432 (__F,
"re_delete() after delete: %d at %d max %d, d == \"%s\"\n",
433 num, dat, dlen, ct_encode_string(d)));
441 re__strncopy(Char *a, Char *b,
size_t n)
456 re_clear_eol(
EditLine *el,
int fx,
int sx,
int diff)
459 ELRE_DEBUG(1, (__F,
"re_clear_eol sx %d, fx %d, diff %d\n",
471 ELRE_DEBUG(1, (__F,
"re_clear_eol %d\n", diff));
472 terminal_clear_EOL(el, diff);
497 #define MIN_END_KEEP 4
500 re_update_line(
EditLine *el, Char *old, Char *
new,
int i)
503 Char *ofd, *ols, *oe, *nfd, *nls, *ne;
504 Char *osb, *ose, *nsb, *nse;
511 for (o = old, n =
new; *o && (*o == *
n); o++, n++)
548 if (*ofd ==
'\0' && *nfd ==
'\0') {
549 ELRE_DEBUG(1, (__F,
"no difference.\r\n"));
555 while ((o > ofd) && (n > nfd) && (*--o == *--n))
572 for (c = *ofd, n = nfd; n < nls; n++) {
575 p < nls && o < ols && *o == *p;
582 if (((nse - nsb) < (p - n)) &&
583 (2 * (p - n) > n - nfd)) {
596 for (c = *nfd, o = ofd; o < ols; o++) {
599 p < ols && n < nls && *p == *
n;
606 if (((ose - osb) < (p - o)) &&
607 (2 * (p - o) > o - ofd)) {
620 if ((oe - ols) < MIN_END_KEEP) {
633 fx = (int)((nsb - nfd) - (osb - ofd));
638 sx = (int)((nls - nse) - (ols - ose));
640 if (!EL_CAN_INSERT) {
651 if ((ols - ofd) < (nls - nfd)) {
656 if (!EL_CAN_DELETE) {
667 if ((ols - ofd) > (nls - nfd)) {
678 if ((ose - osb) < MIN_END_KEEP) {
687 fx = (int)((nsb - nfd) - (osb - ofd));
688 sx = (int)((nls - nse) - (ols - ose));
690 ELRE_DEBUG(1, (__F,
"fx %d, sx %d\n", fx, sx));
691 ELRE_DEBUG(1, (__F,
"ofd %d, osb %d, ose %d, ols %d, oe %d\n",
692 ofd - old, osb - old, ose - old, ols - old, oe - old));
693 ELRE_DEBUG(1, (__F,
"nfd %d, nsb %d, nse %d, nls %d, ne %d\n",
694 nfd -
new, nsb -
new, nse -
new, nls -
new, ne -
new));
696 "xxx-xxx:\"00000000001111111111222222222233333333334\"\r\n"));
698 "xxx-xxx:\"01234567890123456789012345678901234567890\"\r\n"));
700 re_printstr(el,
"old- oe", old, oe);
701 re_printstr(el,
"new- ne",
new, ne);
702 re_printstr(el,
"old-ofd", old, ofd);
703 re_printstr(el,
"new-nfd",
new, nfd);
704 re_printstr(el,
"ofd-osb", ofd, osb);
705 re_printstr(el,
"nfd-nsb", nfd, nsb);
706 re_printstr(el,
"osb-ose", osb, ose);
707 re_printstr(el,
"nsb-nse", nsb, nse);
708 re_printstr(el,
"ose-ols", ose, ols);
709 re_printstr(el,
"nse-nls", nse, nls);
710 re_printstr(el,
"ols- oe", ols, oe);
711 re_printstr(el,
"nls- ne", nls, ne);
719 terminal_move_to_line(el, i);
752 p = (ols != oe) ? oe : ose;
764 if ((nsb != nfd) && fx > 0 &&
765 ((p - old) + fx <= el->el_terminal.t_size.h)) {
767 (__F,
"first diff insert at %d...\r\n", nfd -
new));
771 terminal_move_to_char(el, (
int)(nfd -
new));
776 ELRE_DEBUG(1, (__F,
"with stuff to keep at end\r\n"));
781 ELRE_DEBUG(!EL_CAN_INSERT, (__F,
782 "ERROR: cannot insert in early first diff\n"));
783 terminal_insertwrite(el, nfd, fx);
784 re_insert(el, old, (
int)(ofd - old),
785 el->el_terminal.t_size.h, nfd, fx);
791 len = (size_t) ((nsb - nfd) - fx);
792 terminal_overwrite(el, (nfd + fx), len);
793 re__strncopy(ofd + fx, nfd + fx, len);
795 ELRE_DEBUG(1, (__F,
"without anything to save\r\n"));
796 len = (size_t)(nsb - nfd);
797 terminal_overwrite(el, nfd, len);
798 re__strncopy(ofd, nfd, len);
806 (__F,
"first diff delete at %d...\r\n", ofd - old));
810 terminal_move_to_char(el, (
int)(ofd - old));
815 ELRE_DEBUG(1, (__F,
"with stuff to save at end\r\n"));
821 ELRE_DEBUG(!EL_CAN_DELETE, (__F,
822 "ERROR: cannot delete in first diff\n"));
823 terminal_deletechars(el, -fx);
824 re_delete(el, old, (
int)(ofd - old),
825 el->el_terminal.t_size.h, -fx);
830 len = (size_t) (nsb - nfd);
831 terminal_overwrite(el, nfd, len);
832 re__strncopy(ofd, nfd, len);
836 "but with nothing left to save\r\n"));
840 terminal_overwrite(el, nfd, (
size_t)(nsb - nfd));
841 re_clear_eol(el, fx, sx,
842 (
int)((oe - old) - (ne -
new)));
851 if (sx < 0 && (ose - old) + fx < el->el_terminal.t_size.h) {
853 "second diff delete at %d...\r\n", (ose - old) + fx));
861 terminal_move_to_char(el, (
int)((ose - old) + fx));
866 ELRE_DEBUG(1, (__F,
"with stuff to save at end\r\n"));
871 ELRE_DEBUG(!EL_CAN_DELETE, (__F,
872 "ERROR: cannot delete in second diff\n"));
873 terminal_deletechars(el, -sx);
878 terminal_overwrite(el, nse, (
size_t)(nls - nse));
881 "but with nothing left to save\r\n"));
882 terminal_overwrite(el, nse, (
size_t)(nls - nse));
883 re_clear_eol(el, fx, sx,
884 (
int)((oe - old) - (ne -
new)));
890 if ((nsb != nfd) && (osb - ofd) <= (nsb - nfd) && (fx == 0)) {
891 ELRE_DEBUG(1, (__F,
"late first diff insert at %d...\r\n",
894 terminal_move_to_char(el, (
int)(nfd -
new));
899 ELRE_DEBUG(1, (__F,
"with stuff to keep at end\r\n"));
905 fx = (int)((nsb - nfd) - (osb - ofd));
910 ELRE_DEBUG(!EL_CAN_INSERT, (__F,
911 "ERROR: cannot insert in late first diff\n"));
912 terminal_insertwrite(el, nfd, fx);
913 re_insert(el, old, (
int)(ofd - old),
914 el->el_terminal.t_size.h, nfd, fx);
920 len = (size_t) ((nsb - nfd) - fx);
921 terminal_overwrite(el, (nfd + fx), len);
922 re__strncopy(ofd + fx, nfd + fx, len);
924 ELRE_DEBUG(1, (__F,
"without anything to save\r\n"));
925 len = (size_t) (nsb - nfd);
926 terminal_overwrite(el, nfd, len);
927 re__strncopy(ofd, nfd, len);
935 "second diff insert at %d...\r\n", (
int)(nse -
new)));
936 terminal_move_to_char(el, (
int)(nse -
new));
938 ELRE_DEBUG(1, (__F,
"with stuff to keep at end\r\n"));
941 ELRE_DEBUG(!EL_CAN_INSERT, (__F,
942 "ERROR: cannot insert in second diff\n"));
943 terminal_insertwrite(el, nse, sx);
949 terminal_overwrite(el, (nse + sx),
950 (
size_t)((nls - nse) - sx));
952 ELRE_DEBUG(1, (__F,
"without anything to save\r\n"));
953 terminal_overwrite(el, nse, (
size_t)(nls - nse));
962 ELRE_DEBUG(1, (__F,
"done.\r\n"));
970 re__copy_and_pad(Char *dst,
const Char *src,
size_t width)
974 for (i = 0; i < width; i++) {
980 for (; i < width; i++)
996 if (el->el_line.cursor >= el->el_line.lastchar) {
997 if (el->el_map.current == el->el_map.alt
998 && el->el_line.lastchar != el->el_line.buffer)
999 el->el_line.cursor = el->el_line.lastchar - 1;
1001 el->el_line.cursor = el->el_line.lastchar;
1005 h = el->el_prompt.p_pos.h;
1006 v = el->el_prompt.p_pos.v;
1007 th = el->el_terminal.t_size.h;
1010 for (cp = el->el_line.buffer; cp < el->el_line.cursor; cp++) {
1011 switch (ct_chr_class(*cp)) {
1022 if (w > 1 && h + w > th) {
1026 h += ct_visual_width(*cp);
1037 if (cp < el->el_line.lastchar && (w = Width(*cp)) > 1)
1044 terminal_move_to_line(el, v);
1045 terminal_move_to_char(el, h);
1046 terminal__flush(el);
1056 int w = Width((Char)c);
1057 while (w > 1 && el->el_cursor.h + w > el->el_terminal.t_size.h)
1058 re_fastputc(el,
' ');
1060 terminal__putc(el, c);
1061 el->el_display[el->el_cursor.v][el->el_cursor.h++] = c;
1063 el->el_display[el->el_cursor.v][el->el_cursor.h++]
1066 if (el->el_cursor.h >= el->el_terminal.t_size.h) {
1068 el->el_cursor.h = 0;
1076 if (el->el_cursor.v + 1 >= el->el_terminal.t_size.v) {
1077 int i, lins = el->el_terminal.t_size.v;
1078 Char *firstline = el->el_display[0];
1080 for(i = 1; i < lins; i++)
1081 el->el_display[i - 1] = el->el_display[i];
1083 re__copy_and_pad(firstline, STR(
""), (
size_t)0);
1084 el->el_display[i - 1] = firstline;
1087 el->el_refresh.r_oldcv++;
1089 if (EL_HAS_AUTO_MARGINS) {
1090 if (EL_HAS_MAGIC_MARGINS) {
1091 terminal__putc(el,
' ');
1092 terminal__putc(el,
'\b');
1095 terminal__putc(el,
'\r');
1096 terminal__putc(el,
'\n');
1112 c = el->el_line.cursor[-1];
1114 if (c ==
'\t' || el->el_line.cursor != el->el_line.lastchar) {
1118 rhdiff = el->el_terminal.t_size.h - el->el_cursor.h -
1119 el->el_rprompt.p_pos.h;
1120 if (el->el_rprompt.p_pos.h && rhdiff < 3) {
1124 switch (ct_chr_class(c)) {
1131 case CHTYPE_ASCIICTL:
1132 case CHTYPE_NONPRINT: {
1133 Char visbuf[VISUAL_WIDTH_MAX];
1135 ct_visual_char(visbuf, VISUAL_WIDTH_MAX, (Char)c);
1136 for (i = 0; n-- > 0; ++
i)
1137 re_fastputc(el, visbuf[i]);
1141 terminal__flush(el);
1153 el->el_cursor.v = 0;
1154 el->el_cursor.h = 0;
1155 for (i = 0; i < el->el_terminal.t_size.v; i++)
1156 el->el_display[i][0] =
'\0';
1157 el->el_refresh.r_oldcv = 0;
1170 for (i = el->el_refresh.r_oldcv; i >= 0; i--) {
1172 terminal_move_to_line(el, i);
1173 terminal_move_to_char(el, 0);
1174 terminal_clear_EOL(el, el->el_terminal.t_size.h);
1177 terminal_move_to_line(el, el->el_refresh.r_oldcv);
1179 terminal__putc(el,
'\r');
1180 terminal__putc(el,
'\n');