2 * Edit buffer window generation
4 * (C) 1992 Joseph H. Allen
6 * This file is part of JOE (Joe's Own Editor)
11 __RCSID("$MirOS: contrib/code/jupp/bw.c,v 1.33 2017/12/08 02:28:04 tg Exp $");
17 #ifdef HAVE_BSD_STRING_H
18 #include <bsd/string.h>
39 static P *getto(P *p, P *cur, P *top, long int line)
47 d = (line >= cur->line ? line - cur->line : cur->line - line);
52 d = (line >= top->line ? line - top->line : top->line - line);
54 /* dead store: dist = d; */
60 while (line > p->line)
64 while (line < p->line)
71 /* Scroll window to follow cursor */
77 static void bwfllwh(BW *w)
79 /* Top must be a muliple of 16 bytes */
80 if (w->top->byte%16) {
81 pbkwd(w->top,w->top->byte%16);
85 if (w->cursor->byte < w->top->byte) {
86 long new_top = w->cursor->byte/16;
88 if (new_top >= w->h / 2)
93 if (w->top->byte/16 - new_top < w->h)
94 nscrldn(w->t->t, w->y, w->y + w->h, (int) (w->top->byte/16 - new_top));
96 msetI(w->t->t->updtab + w->y, 1, w->h);
97 pgoto(w->top,new_top*16);
101 if (w->cursor->byte >= w->top->byte+(w->h*16)) {
104 new_top = w->cursor->byte/16 - w->h / 2;
106 new_top = w->cursor->byte/16 - (w->h - 1);
108 if (new_top - w->top->byte/16 < w->h)
109 nscrlup(w->t->t, w->y, w->y + w->h, (int) (new_top - w->top->byte/16));
111 msetI(w->t->t->updtab + w->y, 1, w->h);
113 pgoto(w->top, new_top*16);
116 /* Adjust scroll offset */
117 if (w->cursor->byte%16+60 < w->offset) {
118 w->offset = w->cursor->byte%16+60;
119 msetI(w->t->t->updtab + w->y, 1, w->h);
120 } else if (w->cursor->byte%16+60 >= w->offset + w->w) {
121 w->offset = w->cursor->byte%16+60 - (w->w - 1);
122 msetI(w->t->t->updtab + w->y, 1, w->h);
128 static void bwfllwt(BW *w)
132 if (w->cursor->line < w->top->line) {
133 newtop = pdup(w->cursor);
136 if (newtop->line >= w->h / 2)
137 pline(newtop, newtop->line - w->h / 2);
139 pset(newtop, newtop->b->bof);
141 if (w->top->line - newtop->line < w->h)
142 nscrldn(w->t->t, w->y, w->y + w->h, (int) (w->top->line - newtop->line));
144 msetI(w->t->t->updtab + w->y, 1, w->h);
145 msetI(w->t->t->syntab + w->y, -1, w->h);
147 pset(w->top, newtop);
149 } else if (w->cursor->line >= w->top->line + w->h) {
151 newtop = getto(NULL, w->cursor, w->top, w->cursor->line -
152 (mid ? (w->h / 2) : (w->h - 1)));
153 if (newtop->line - w->top->line < w->h)
154 nscrlup(w->t->t, w->y, w->y + w->h, (int) (newtop->line - w->top->line));
156 msetI(w->t->t->updtab + w->y, 1, w->h);
157 msetI(w->t->t->syntab + w->y, -1, w->h);
159 pset(w->top, newtop);
164 if (w->cursor->xcol < w->offset) {
165 w->offset = w->cursor->xcol;
166 msetI(w->t->t->updtab + w->y, 1, w->h);
167 } else if (w->cursor->xcol >= w->offset + w->w) {
168 w->offset = w->cursor->xcol - (w->w - 1);
169 msetI(w->t->t->updtab + w->y, 1, w->h);
175 void bwfllw(jobject jO)
184 /* Determine highlighting state of a particular line on the window.
185 If the state is not known, it is computed and the state for all
186 of the remaining lines of the window are also recalculated. */
189 get_highlight_state(BW *w, int line)
194 /* Screen y position of requested line */
195 int y = line-w->top->line+w->y;
197 if(!w->o.highlight || !w->o.syntax)
200 /* If we know the state, just return it */
201 if (w->parent->t->t->syntab[y]>=0)
202 return w->parent->t->t->syntab[y];
204 /* Scan upwards until we have a line with known state or
205 we're on the first line */
206 while (y > w->y && w->parent->t->t->syntab[y] < 0) --y;
208 /* If we don't have state for this line, calculate by going 100 lines back */
209 if (w->parent->t->t->syntab[y]<0) {
210 /* We must be on the top line */
213 if(w->o.syntax->sync_lines >= 0 && tmp->line > w->o.syntax->sync_lines)
214 pline(tmp, tmp->line-w->o.syntax->sync_lines);
217 while(tmp->line!=y-w->y+w->top->line)
218 state = parse(w->o.syntax,tmp,state);
219 w->parent->t->t->syntab[y] = state;
220 w->parent->t->t->updtab[y] = 1;
224 /* Color to end of screen */
226 pline(tmp, y-w->y+w->top->line);
227 state = w->parent->t->t->syntab[y];
228 while(tmp->line!=w->top->line+w->h-1 && !piseof(tmp)) {
229 state = parse(w->o.syntax,tmp,state);
230 w->parent->t->t->syntab[++y] = state;
231 w->parent->t->t->updtab[y] = 1; /* This could be smarter: update only if we changed what was there before */
234 while(y<w->y+w->h-1) {
235 w->parent->t->t->syntab[++y] = state;
238 /* Line after window */
239 /* state = parse_c(state,syn,tmp); */
241 /* If we changed, fix other windows */
242 /* w->state = state; */
244 /* Return state of requested line */
245 y = line - w->top->line + w->y;
246 return w->parent->t->t->syntab[y];
249 /* Scroll a buffer window after an insert occurred. 'flg' is set to 1 if
250 * the first line was split
253 void bwins(BW *w, long int l, long int n, int flg)
255 if (l + flg + n < w->top->line + w->h && l + flg >= w->top->line && l + flg <= w->b->eof->line) {
257 w->t->t->sary[w->y + l - w->top->line] = w->t->t->li;
258 nscrldn(w->t->t, (int) (w->y + l + flg - w->top->line), w->y + w->h, (int) n);
260 if (l < w->top->line + w->h && l >= w->top->line) {
261 if (n >= w->h - (l - w->top->line)) {
262 msetI(w->t->t->updtab + w->y + l - w->top->line, 1, w->h - (int) (l - w->top->line));
263 msetI(w->t->t->syntab + w->y + l - w->top->line, -1, w->h - (int) (l - w->top->line));
265 msetI(w->t->t->updtab + w->y + l - w->top->line, 1, (int) n + 1);
266 msetI(w->t->t->syntab + w->y + l - w->top->line, -1, (int) n + 1);
271 /* Scroll current windows after a delete */
273 void bwdel(BW *w, long int l, long int n, int flg)
275 /* Update the line where the delete began */
276 if (l < w->top->line + w->h && l >= w->top->line)
277 w->t->t->updtab[w->y + l - w->top->line] = 1;
279 /* Update highlight for line after first one which changed */
280 if ((l+1) < w->top->line + w->h && (l+1) >= w->top->line) {
281 w->t->t->syntab[w->y + (l+1) - w->top->line] = -1;
282 w->t->t->updtab[w->y + (l+1) - w->top->line] = 1;
285 /* Update the line where the delete ended */
286 if (l + n < w->top->line + w->h && l + n >= w->top->line)
287 w->t->t->updtab[w->y + l + n - w->top->line] = 1;
289 if (l < w->top->line + w->h && (l + n >= w->top->line + w->h || (l + n == w->b->eof->line && w->b->eof->line >= w->top->line + w->h))) {
290 if (l >= w->top->line)
291 /* Update window from l to end */
292 msetI(w->t->t->updtab + w->y + l - w->top->line, 1, w->h - (int) (l - w->top->line));
294 /* Update entire window */
295 msetI(w->t->t->updtab + w->y, 1, w->h);
296 } else if (l < w->top->line + w->h && l + n == w->b->eof->line && w->b->eof->line < w->top->line + w->h) {
297 if (l >= w->top->line)
298 /* Update window from l to end of file */
299 msetI(w->t->t->updtab + w->y + l - w->top->line, 1, (int) n);
301 /* Update from beginning of window to end of file */
302 msetI(w->t->t->updtab + w->y, 1, (int) (w->b->eof->line - w->top->line));
303 } else if (l + n < w->top->line + w->h && l + n > w->top->line && l + n < w->b->eof->line) {
304 if (l + flg >= w->top->line)
305 nscrlup(w->t->t, (int) (w->y + l + flg - w->top->line), w->y + w->h, (int) n);
307 nscrlup(w->t->t, w->y, w->y + w->h, (int) (l + n - w->top->line));
311 /* Update a single line */
313 static int lgen(SCRN *t, int y, int *screen, int *attr, int x, int w, P *p, long int scr, long int from, long int to,int st,BW *bw)
316 /* Screen line address */
319 /* Starting column to display */
320 /* Range for marked block */
327 unsigned char *bp; /* Buffer pointer, 0 if not set */
328 int amnt; /* Amount left in this segment of the buffer */
333 struct utf8_sm utf8_sm;
345 parse(bw->o.syntax,tmp,st);
350 /* Initialize bp and amnt from p */
351 if (p->ofst >= p->hdr->hole) {
352 bp = p->ptr + p->hdr->ehole + p->ofst - p->hdr->hole;
353 amnt = SEGSIZ - p->hdr->ehole - (p->ofst - p->hdr->hole);
355 bp = p->ptr + p->ofst;
356 amnt = p->hdr->hole - p->ofst;
362 /* Display next character */
373 if (p->b->o.crlf && bc == '\r') {
377 if (bp == p->ptr + SEGSIZ) {
384 bp = p->ptr + p->hdr->ehole;
385 amnt = SEGSIZ - p->hdr->ehole;
402 long tcol = col + p->b->o.tab - col % p->b->o.tab;
404 if (tcol > from && tcol <= to)
408 } else if (col >= from && col < to)
412 else if (byte >= from && byte < to)
418 ta = p->b->o.tab - col % p->b->o.tab;
419 if (ta + col > scr) {
423 if ((col += ta) == scr) {
427 } else if (bc == '\n')
431 if (p->b->o.charmap->type) {
432 c = utf8_decode(&utf8_sm,bc);
434 if (c>=0) /* Normal decoded character */
435 wid = joe_wcwidth(1,c);
436 else if(c== -1) /* Character taken */
438 else if(c== -2) { /* Incomplete sequence */
444 else if(c== -3) /* Control character 128-191, 254, 255 */
453 } else if (col > scr) {
459 --idx; /* Get highlighting character again.. */
462 if (bp == p->ptr + SEGSIZ) {
469 bp = p->ptr + p->hdr->ehole;
470 amnt = SEGSIZ - p->hdr->ehole;
475 /* Display next character */
486 if (p->b->o.crlf && bc == '\r') {
490 if (bp == p->ptr + SEGSIZ) {
497 bp = p->ptr + p->hdr->ehole;
498 amnt = SEGSIZ - p->hdr->ehole;
515 long tcol = scr + x - ox + p->b->o.tab - (scr + x - ox) % p->b->o.tab;
517 if (tcol > from && tcol <= to)
521 } else if (scr + x - ox >= from && scr + x - ox < to)
525 else if (byte >= from && byte < to)
531 ta = p->b->o.tab - ((x - ox + scr) % p->b->o.tab);
538 outatr(utf8_map, t, screen + x, attr + x, x, y, tach, c1|atr);
545 } else if (bc == '\n') {
552 if (p->b->o.charmap->type) { /* UTF-8 */
554 utf8_char = utf8_decode(&utf8_sm,bc);
556 if (utf8_char >= 0) { /* Normal decoded character */
557 wid = joe_wcwidth(1,utf8_char);
558 } else if(utf8_char== -1) { /* Character taken */
560 } else if(utf8_char== -2) { /* Incomplete sequence (FIXME: do something better here) */
565 utf8_char = 0x1000FFFE;
568 } else if(utf8_char== -3) { /* Invalid UTF-8 start character 128-191, 254, 255 */
569 /* Show as control character */
571 utf8_char = 0x1000FFFE;
573 } else { /* Regular */
580 /* If character hits right most column, don't display it */
582 outatr(bw->b->o.charmap, t, screen + x, attr + x, x, y, '>', c1|atr);
585 } else if (utf8_char == 0x1000FFFE) while (wid--) {
586 outatr(bw->b->o.charmap, t, screen + x, attr + x, x, y, 0xFFFD, (c1|atr|UNDERLINE)^INVERSE);
588 } else if (bw->o.vispace && (utf8_char == 0x20)) {
589 outatr(utf8_map, t, screen + x, attr + x, x, y, 0xB7, c1|atr);
592 outatr(bw->b->o.charmap, t, screen + x, attr + x, x, y, utf8_char, c1|atr);
604 if (bp == p->ptr + SEGSIZ) {
611 bp = p->ptr + p->hdr->ehole;
612 amnt = SEGSIZ - p->hdr->ehole;
617 /* End of buffer line found. Erase to end of screen line */
621 done = eraeol(t, x, y);
625 /* Set p to bp/amnt */
627 if (bp - p->ptr <= p->hdr->hole)
628 p->ofst = bp - p->ptr;
630 p->ofst = bp - p->ptr - (p->hdr->ehole - p->hdr->hole);
635 if (bp - p->ptr <= p->hdr->hole)
636 p->ofst = bp - p->ptr;
638 p->ofst = bp - p->ptr - (p->hdr->ehole - p->hdr->hole);
644 static void gennum(BW *w, int *screen, int *attr, SCRN *t, int y, int *comp)
646 unsigned char buf[12];
648 int lin = w->top->line + y - w->y;
650 if (lin <= w->b->eof->line)
651 joe_snprintf_1((char *)buf, sizeof(buf), "%5ld ", w->top->line + y - w->y + 1);
653 strlcpy((char *)buf, " ",12);
654 for (z = 0; buf[z]; ++z) {
655 outatr(w->b->o.charmap, t, screen + z, attr + z, z, y, buf[z], 0);
667 int bot = w->h + w->y;
677 if (markv(0) && markk->b == w->b)
686 else if (marking && w == maint->curwin->object.bw && markb && markb->b == w->b && w->cursor->byte != markb->byte && !from) {
688 from = long_min(w->cursor->xcol, markb->xcol);
689 to = long_max(w->cursor->xcol, markb->xcol);
692 from = long_min(w->cursor->byte, markb->byte);
693 to = long_max(w->cursor->byte, markb->byte);
697 if (marking && w == maint->curwin->object.bw)
698 msetI(t->updtab + w->y, 1, w->h);
706 attr = t->attr + y*w->t->w;
707 for (screen = t->scrn + y * w->t->w; y != bot; ++y, (screen += w->t->w), (attr += w->t->w)) {
708 unsigned char txt[80];
710 unsigned char bf[16];
713 msetI(fmt, /* BG_COLOR(bg_text) */ 0,76);
716 #if SIZEOF_LONG_LONG && SIZEOF_LONG_LONG == SIZEOF_OFF_T
717 joe_snprintf_1((char *)bf,sizeof(bf),"%8llX ",(unsigned long long)q->byte);
719 joe_snprintf_1((char *)bf,sizeof(bf),"%8lX ",(unsigned long)q->byte);
722 for (x=0; x!=8; ++x) {
724 if (q->byte==w->cursor->byte && !flg) {
725 fmt[10+x*3] |= INVERSE;
726 fmt[10+x*3+1] |= INVERSE;
728 if (q->byte>=from && q->byte<to && !flg) {
729 fmt[10+x*3] |= UNDERLINE;
730 fmt[10+x*3+1] |= UNDERLINE;
731 fmt[60+x] |= INVERSE;
735 joe_snprintf_1((char *)bf,sizeof(bf),"%2.2X",c);
737 txt[10+x*3+1] = bf[1];
738 if (c >= 0x20 && c <= 0x7E)
745 for (x=8; x!=16; ++x) {
747 if (q->byte==w->cursor->byte && !flg) {
748 fmt[11+x*3] |= INVERSE;
749 fmt[11+x*3+1] |= INVERSE;
751 if (q->byte>=from && q->byte<to && !flg) {
752 fmt[11+x*3] |= UNDERLINE;
753 fmt[11+x*3+1] |= UNDERLINE;
754 fmt[60+x] |= INVERSE;
758 joe_snprintf_1((char *)bf,sizeof(bf),"%2.2X",c);
760 txt[11+x*3+1] = bf[1];
761 if (c >= 0x20 && c <= 0x7E)
769 genfield(t, screen, attr, 0, y, w->offset, txt, 76, 0, w->w, 1, fmt);
774 void bwgen(BW *w, int linums)
779 P *q = pdup(w->cursor);
780 int bot = w->h + w->y;
784 long fromline, toline;
787 fromline = toline = from = to = 0;
789 if (markv(0) && markk->b == w->b)
794 fromline = markb->line;
795 toline = markk->line;
800 else if (marking && w == maint->curwin->object.bw && markb && markb->b == w->b && w->cursor->byte != markb->byte && !from) {
802 from = long_min(w->cursor->xcol, markb->xcol);
803 to = long_max(w->cursor->xcol, markb->xcol);
804 fromline = long_min(w->cursor->line, markb->line);
805 toline = long_max(w->cursor->line, markb->line);
808 from = long_min(w->cursor->byte, markb->byte);
809 to = long_max(w->cursor->byte, markb->byte);
813 if (marking && w == maint->curwin->object.bw)
814 msetI(t->updtab + w->y, 1, w->h);
816 y = w->cursor->line - w->top->line + w->y;
817 attr = t->attr + y*w->t->w;
818 for (screen = t->scrn + y * w->t->w; y != bot; ++y, (screen += w->t->w), (attr += w->t->w)) {
822 gennum(w, screen, attr, t, y, t->compose);
824 p = getto(p, w->cursor, w->top, w->top->line + y - w->y);
825 /* if (t->insdel && !w->x) {
828 if (w->top->line + y - w->y >= fromline && w->top->line + y - w->y <= toline)
829 lgena(t, y, t->compose, w->x, w->x + w->w, q, w->offset, from, to);
831 lgena(t, y, t->compose, w->x, w->x + w->w, q, w->offset, 0L, 0L);
833 lgena(t, y, t->compose, w->x, w->x + w->w, q, w->offset, from, to);
834 magic(t, y, screen, attr, t->compose, (int) (w->cursor->xcol - w->offset + w->x));
837 if (w->top->line + y - w->y >= fromline && w->top->line + y - w->y <= toline)
838 t->updtab[y] = lgen(t, y, screen, attr, w->x, w->x + w->w, p, w->offset, from, to, get_highlight_state(w,w->top->line+y-w->y),w);
840 t->updtab[y] = lgen(t, y, screen, attr, w->x, w->x + w->w, p, w->offset, 0L, 0L, get_highlight_state(w,w->top->line+y-w->y),w);
842 t->updtab[y] = lgen(t, y, screen, attr, w->x, w->x + w->w, p, w->offset, from, to, get_highlight_state(w,w->top->line+y-w->y),w);
847 attr = t->attr + w->y * w->t->w;
848 for (screen = t->scrn + w->y * w->t->w; y != w->y + w->cursor->line - w->top->line; ++y, (screen += w->t->w), (attr += w->t->w)) {
852 gennum(w, screen, attr, t, y, t->compose);
854 p = getto(p, w->cursor, w->top, w->top->line + y - w->y);
855 /* if (t->insdel && !w->x) {
858 if (w->top->line + y - w->y >= fromline && w->top->line + y - w->y <= toline)
859 lgena(t, y, t->compose, w->x, w->x + w->w, q, w->offset, from, to);
861 lgena(t, y, t->compose, w->x, w->x + w->w, q, w->offset, 0L, 0L);
863 lgena(t, y, t->compose, w->x, w->x + w->w, q, w->offset, from, to);
864 magic(t, y, screen, attr, t->compose, (int) (w->cursor->xcol - w->offset + w->x));
867 if (w->top->line + y - w->y >= fromline && w->top->line + y - w->y <= toline)
868 t->updtab[y] = lgen(t, y, screen, attr, w->x, w->x + w->w, p, w->offset, from, to, get_highlight_state(w,w->top->line+y-w->y),w);
870 t->updtab[y] = lgen(t, y, screen, attr, w->x, w->x + w->w, p, w->offset, 0L, 0L, get_highlight_state(w,w->top->line+y-w->y),w);
872 t->updtab[y] = lgen(t, y, screen, attr, w->x, w->x + w->w, p, w->offset, from, to, get_highlight_state(w,w->top->line+y-w->y),w);
880 void bwmove(BW *w, int x, int y)
886 void bwresz(BW *w, int wi, int he)
888 if (he > w->h && w->y != -1) {
889 msetI(w->t->t->updtab + w->y + w->h, 1, he - w->h);
890 msetI(w->t->t->syntab + w->y + w->h, -1, he - w->h);
896 BW *bwmk(W *window, B *b, int prompt)
898 BW *w = malloc(sizeof(BW));
902 if (prompt || (!window->y && staen)) {
906 w->y = window->y + 1;
907 w->h = window->h - 1;
912 w->top->owner = NULL;
913 w->cursor = b->oldcur;
915 w->cursor->owner = NULL;
917 w->top = pdup(b->bof);
918 w->cursor = pdup(b->bof);
924 if ((w->linums = w->o.linums)) {
925 w->x = window->x + LINCOLS;
926 w->w = window->w - LINCOLS;
931 if (window == window->main) {
933 window->kbd = mkkbd(kmap_getcontext(w->o.context, 1));
951 static unsigned char buf[80];
952 int c = brch(bw->cursor);
954 if (c == NO_MORE_DATA)
955 joe_snprintf_4((char *)buf, sizeof(buf), "** Line %ld Col %ld Offset %ld(0x%lX) **", bw->cursor->line + 1, piscol(bw->cursor) + 1, bw->cursor->byte, bw->cursor->byte);
957 joe_snprintf_9((char *)buf, sizeof(buf), "** Line %ld Col %ld Offset %ld(0x%lX) %s %d(0%o/0x%X) Width %d **", bw->cursor->line + 1, piscol(bw->cursor) + 1, bw->cursor->byte, bw->cursor->byte, bw->b->o.charmap->name, c, c, c, joe_wcwidth(bw->o.charmap->type,c));
958 msgnw(bw->parent, buf);
964 int amnt = bw->w / 2;
966 pcol(bw->cursor, bw->cursor->xcol + amnt);
967 bw->cursor->xcol += amnt;
975 int amnt = bw->w / 2;
976 int curamnt = bw->w / 2;
978 if (amnt > bw->offset) {
980 curamnt = bw->offset;
983 curamnt = bw->cursor->xcol;
986 pcol(bw->cursor, bw->cursor->xcol - curamnt);
987 bw->cursor->xcol -= curamnt;
997 pdupown(bw->cursor, &bw->b->oldcur);
998 pdupown(bw->top, &bw->b->oldtop);