1 /* $MirOS: contrib/code/jupp/bw.c,v 1.22 2017/07/09 01:15:51 tg Exp $ */
3 * Edit buffer window generation
5 * (C) 1992 Joseph H. Allen
7 * This file is part of JOE (Joe's Own Editor)
18 #ifdef HAVE_BSD_STRING_H
19 #include <bsd/string.h>
41 static P *getto(P *p, P *cur, P *top, long int line)
49 d = (line >= cur->line ? line - cur->line : cur->line - line);
54 d = (line >= top->line ? line - top->line : top->line - line);
56 /* dead store: dist = d; */
62 while (line > p->line)
66 while (line < p->line)
73 /* Scroll window to follow cursor */
79 static void bwfllwh(BW *w)
81 /* Top must be a muliple of 16 bytes */
82 if (w->top->byte%16) {
83 pbkwd(w->top,w->top->byte%16);
87 if (w->cursor->byte < w->top->byte) {
88 long new_top = w->cursor->byte/16;
90 if (new_top >= w->h / 2)
95 if (w->top->byte/16 - new_top < w->h)
96 nscrldn(w->t->t, w->y, w->y + w->h, (int) (w->top->byte/16 - new_top));
98 msetI(w->t->t->updtab + w->y, 1, w->h);
99 pgoto(w->top,new_top*16);
103 if (w->cursor->byte >= w->top->byte+(w->h*16)) {
106 new_top = w->cursor->byte/16 - w->h / 2;
108 new_top = w->cursor->byte/16 - (w->h - 1);
110 if (new_top - w->top->byte/16 < w->h)
111 nscrlup(w->t->t, w->y, w->y + w->h, (int) (new_top - w->top->byte/16));
113 msetI(w->t->t->updtab + w->y, 1, w->h);
115 pgoto(w->top, new_top*16);
118 /* Adjust scroll offset */
119 if (w->cursor->byte%16+60 < w->offset) {
120 w->offset = w->cursor->byte%16+60;
121 msetI(w->t->t->updtab + w->y, 1, w->h);
122 } else if (w->cursor->byte%16+60 >= w->offset + w->w) {
123 w->offset = w->cursor->byte%16+60 - (w->w - 1);
124 msetI(w->t->t->updtab + w->y, 1, w->h);
130 static void bwfllwt(BW *w)
134 if (w->cursor->line < w->top->line) {
135 newtop = pdup(w->cursor);
138 if (newtop->line >= w->h / 2)
139 pline(newtop, newtop->line - w->h / 2);
141 pset(newtop, newtop->b->bof);
143 if (w->top->line - newtop->line < w->h)
144 nscrldn(w->t->t, w->y, w->y + w->h, (int) (w->top->line - newtop->line));
146 msetI(w->t->t->updtab + w->y, 1, w->h);
147 msetI(w->t->t->syntab + w->y, -1, w->h);
149 pset(w->top, newtop);
151 } else if (w->cursor->line >= w->top->line + w->h) {
153 newtop = getto(NULL, w->cursor, w->top, w->cursor->line -
154 (mid ? (w->h / 2) : (w->h - 1)));
155 if (newtop->line - w->top->line < w->h)
156 nscrlup(w->t->t, w->y, w->y + w->h, (int) (newtop->line - w->top->line));
158 msetI(w->t->t->updtab + w->y, 1, w->h);
159 msetI(w->t->t->syntab + w->y, -1, w->h);
161 pset(w->top, newtop);
166 if (w->cursor->xcol < w->offset) {
167 w->offset = w->cursor->xcol;
168 msetI(w->t->t->updtab + w->y, 1, w->h);
169 } else if (w->cursor->xcol >= w->offset + w->w) {
170 w->offset = w->cursor->xcol - (w->w - 1);
171 msetI(w->t->t->updtab + w->y, 1, w->h);
185 /* Determine highlighting state of a particular line on the window.
186 If the state is not known, it is computed and the state for all
187 of the remaining lines of the window are also recalculated. */
189 int 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;
361 lp: /* Display next character */
372 if (p->b->o.crlf && bc == '\r') {
376 if (bp == p->ptr + SEGSIZ) {
383 bp = p->ptr + p->hdr->ehole;
384 amnt = SEGSIZ - p->hdr->ehole;
401 long tcol = col + p->b->o.tab - col % p->b->o.tab;
403 if (tcol > from && tcol <= to)
407 } else if (col >= from && col < to)
411 else if (byte >= from && byte < to)
417 ta = p->b->o.tab - col % p->b->o.tab;
418 if (ta + col > scr) {
422 if ((col += ta) == scr) {
426 } else if (bc == '\n')
430 if (p->b->o.charmap->type) {
431 c = utf8_decode(&utf8_sm,bc);
433 if (c>=0) /* Normal decoded character */
434 wid = joe_wcwidth(1,c);
435 else if(c== -1) /* Character taken */
437 else if(c== -2) { /* Incomplete sequence */
443 else if(c== -3) /* Control character 128-191, 254, 255 */
452 } else if (col > scr) {
458 --idx; /* Get highlighting character again.. */
461 if (bp == p->ptr + SEGSIZ) {
468 bp = p->ptr + p->hdr->ehole;
469 amnt = SEGSIZ - p->hdr->ehole;
474 loop: /* Display next character */
485 if (p->b->o.crlf && bc == '\r') {
489 if (bp == p->ptr + SEGSIZ) {
496 bp = p->ptr + p->hdr->ehole;
497 amnt = SEGSIZ - p->hdr->ehole;
514 long tcol = scr + x - ox + p->b->o.tab - (scr + x - ox) % p->b->o.tab;
516 if (tcol > from && tcol <= to)
520 } else if (scr + x - ox >= from && scr + x - ox < to)
524 else if (byte >= from && byte < to)
530 ta = p->b->o.tab - ((x - ox + scr) % p->b->o.tab);
537 outatr(utf8_map, t, screen + x, attr + x, x, y, tach, c1|atr);
544 } else if (bc == '\n') {
551 if (p->b->o.charmap->type) { /* UTF-8 */
553 utf8_char = utf8_decode(&utf8_sm,bc);
555 if (utf8_char >= 0) { /* Normal decoded character */
556 wid = joe_wcwidth(1,utf8_char);
557 } else if(utf8_char== -1) { /* Character taken */
559 } else if(utf8_char== -2) { /* Incomplete sequence (FIXME: do something better here) */
564 utf8_char = 0x1000FFFE;
567 } else if(utf8_char== -3) { /* Invalid UTF-8 start character 128-191, 254, 255 */
568 /* Show as control character */
570 utf8_char = 0x1000FFFE;
572 } else { /* Regular */
579 /* If character hits right most column, don't display it */
581 outatr(bw->b->o.charmap, t, screen + x, attr + x, x, y, '>', c1|atr);
584 } else if (utf8_char == 0x1000FFFE) while (wid--) {
585 outatr(bw->b->o.charmap, t, screen + x, attr + x, x, y, 0xFFFD, (c1|atr|UNDERLINE)^INVERSE);
587 } else if (bw->o.vispace && (utf8_char == 0x20)) {
588 outatr(utf8_map, t, screen + x, attr + x, x, y, 0xB7, c1|atr);
591 outatr(bw->b->o.charmap, t, screen + x, attr + x, x, y, utf8_char, c1|atr);
603 if (bp == p->ptr + SEGSIZ) {
610 bp = p->ptr + p->hdr->ehole;
611 amnt = SEGSIZ - p->hdr->ehole;
616 eobl: /* End of buffer line found. Erase to end of screen line */
620 done = eraeol(t, x, y);
624 /* Set p to bp/amnt */
626 if (bp - p->ptr <= p->hdr->hole)
627 p->ofst = bp - p->ptr;
629 p->ofst = bp - p->ptr - (p->hdr->ehole - p->hdr->hole);
634 if (bp - p->ptr <= p->hdr->hole)
635 p->ofst = bp - p->ptr;
637 p->ofst = bp - p->ptr - (p->hdr->ehole - p->hdr->hole);
643 static void gennum(BW *w, int *screen, int *attr, SCRN *t, int y, int *comp)
645 unsigned char buf[12];
647 int lin = w->top->line + y - w->y;
649 if (lin <= w->b->eof->line)
650 joe_snprintf_1((char *)buf, sizeof(buf), "%5ld ", w->top->line + y - w->y + 1);
652 strlcpy((char *)buf, " ",12);
653 for (z = 0; buf[z]; ++z) {
654 outatr(w->b->o.charmap, t, screen + z, attr + z, z, y, buf[z], 0);
666 int bot = w->h + w->y;
676 if (markv(0) && markk->b == w->b)
685 else if (marking && w == (BW *)maint->curwin->object && markb && markb->b == w->b && w->cursor->byte != markb->byte && !from) {
687 from = long_min(w->cursor->xcol, markb->xcol);
688 to = long_max(w->cursor->xcol, markb->xcol);
691 from = long_min(w->cursor->byte, markb->byte);
692 to = long_max(w->cursor->byte, markb->byte);
696 if (marking && w == (BW *)maint->curwin->object)
697 msetI(t->updtab + w->y, 1, w->h);
705 attr = t->attr + y*w->t->w;
706 for (screen = t->scrn + y * w->t->w; y != bot; ++y, (screen += w->t->w), (attr += w->t->w)) {
707 unsigned char txt[80];
709 unsigned char bf[16];
712 msetI(fmt, /* BG_COLOR(bg_text) */ 0,76);
715 #if SIZEOF_LONG_LONG && SIZEOF_LONG_LONG == SIZEOF_OFF_T
716 joe_snprintf_1((char *)bf,sizeof(bf),"%8llX ",(unsigned long long)q->byte);
718 joe_snprintf_1((char *)bf,sizeof(bf),"%8lX ",(unsigned long)q->byte);
721 for (x=0; x!=8; ++x) {
723 if (q->byte==w->cursor->byte && !flg) {
724 fmt[10+x*3] |= INVERSE;
725 fmt[10+x*3+1] |= INVERSE;
727 if (q->byte>=from && q->byte<to && !flg) {
728 fmt[10+x*3] |= UNDERLINE;
729 fmt[10+x*3+1] |= UNDERLINE;
730 fmt[60+x] |= INVERSE;
734 joe_snprintf_1((char *)bf,sizeof(bf),"%2.2X",c);
736 txt[10+x*3+1] = bf[1];
737 if (c >= 0x20 && c <= 0x7E)
744 for (x=8; x!=16; ++x) {
746 if (q->byte==w->cursor->byte && !flg) {
747 fmt[11+x*3] |= INVERSE;
748 fmt[11+x*3+1] |= INVERSE;
750 if (q->byte>=from && q->byte<to && !flg) {
751 fmt[11+x*3] |= UNDERLINE;
752 fmt[11+x*3+1] |= UNDERLINE;
753 fmt[60+x] |= INVERSE;
757 joe_snprintf_1((char *)bf,sizeof(bf),"%2.2X",c);
759 txt[11+x*3+1] = bf[1];
760 if (c >= 0x20 && c <= 0x7E)
768 genfield(t, screen, attr, 0, y, w->offset, txt, 76, 0, w->w, 1, fmt);
773 void bwgen(BW *w, int linums)
778 P *q = pdup(w->cursor);
779 int bot = w->h + w->y;
783 long fromline, toline;
786 fromline = toline = from = to = 0;
788 if (markv(0) && markk->b == w->b)
793 fromline = markb->line;
794 toline = markk->line;
799 else if (marking && w==maint->curwin->object && markb && markb->b == w->b && w->cursor->byte != markb->byte && !from) {
801 from = long_min(w->cursor->xcol, markb->xcol);
802 to = long_max(w->cursor->xcol, markb->xcol);
803 fromline = long_min(w->cursor->line, markb->line);
804 toline = long_max(w->cursor->line, markb->line);
807 from = long_min(w->cursor->byte, markb->byte);
808 to = long_max(w->cursor->byte, markb->byte);
812 if (marking && w==maint->curwin->object)
813 msetI(t->updtab + w->y, 1, w->h);
815 y = w->cursor->line - w->top->line + w->y;
816 attr = t->attr + y*w->t->w;
817 for (screen = t->scrn + y * w->t->w; y != bot; ++y, (screen += w->t->w), (attr += w->t->w)) {
818 if (ifhave && !linums)
821 gennum(w, screen, attr, t, y, t->compose);
823 p = getto(p, w->cursor, w->top, w->top->line + y - w->y);
824 /* if (t->insdel && !w->x) {
827 if (w->top->line + y - w->y >= fromline && w->top->line + y - w->y <= toline)
828 lgena(t, y, t->compose, w->x, w->x + w->w, q, w->offset, from, to);
830 lgena(t, y, t->compose, w->x, w->x + w->w, q, w->offset, 0L, 0L);
832 lgena(t, y, t->compose, w->x, w->x + w->w, q, w->offset, from, to);
833 magic(t, y, screen, attr, t->compose, (int) (w->cursor->xcol - w->offset + w->x));
836 if (w->top->line + y - w->y >= fromline && w->top->line + y - w->y <= toline)
837 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);
839 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);
841 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);
846 attr = t->attr + w->y * w->t->w;
847 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)) {
848 if (ifhave && !linums)
851 gennum(w, screen, attr, t, y, t->compose);
853 p = getto(p, w->cursor, w->top, w->top->line + y - w->y);
854 /* if (t->insdel && !w->x) {
857 if (w->top->line + y - w->y >= fromline && w->top->line + y - w->y <= toline)
858 lgena(t, y, t->compose, w->x, w->x + w->w, q, w->offset, from, to);
860 lgena(t, y, t->compose, w->x, w->x + w->w, q, w->offset, 0L, 0L);
862 lgena(t, y, t->compose, w->x, w->x + w->w, q, w->offset, from, to);
863 magic(t, y, screen, attr, t->compose, (int) (w->cursor->xcol - w->offset + w->x));
866 if (w->top->line + y - w->y >= fromline && w->top->line + y - w->y <= toline)
867 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);
869 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);
871 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);
879 void bwmove(BW *w, int x, int y)
885 void bwresz(BW *w, int wi, int he)
887 if (he > w->h && w->y != -1) {
888 msetI(w->t->t->updtab + w->y + w->h, 1, he - w->h);
889 msetI(w->t->t->syntab + w->y + w->h, -1, he - w->h);
895 BW *bwmk(W *window, B *b, int prompt)
897 BW *w = (BW *) joe_malloc(sizeof(BW));
901 if (prompt || (!window->y && staen)) {
905 w->y = window->y + 1;
906 w->h = window->h - 1;
911 w->top->owner = NULL;
912 w->cursor = b->oldcur;
914 w->cursor->owner = NULL;
916 w->top = pdup(b->bof);
917 w->cursor = pdup(b->bof);
923 if ((w->linums = w->o.linums)) {
924 w->x = window->x + LINCOLS;
925 w->w = window->w - LINCOLS;
930 if (window == window->main) {
932 window->kbd = mkkbd(kmap_getcontext(w->o.context, 1));
950 static unsigned char buf[80];
951 int c = brch(bw->cursor);
953 if (c == NO_MORE_DATA)
954 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);
956 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));
957 msgnw(bw->parent, buf);
963 int amnt = bw->w / 2;
965 pcol(bw->cursor, bw->cursor->xcol + amnt);
966 bw->cursor->xcol += amnt;
974 int amnt = bw->w / 2;
975 int curamnt = bw->w / 2;
977 if (amnt > bw->offset) {
979 curamnt = bw->offset;
982 curamnt = bw->cursor->xcol;
985 pcol(bw->cursor, bw->cursor->xcol - curamnt);
986 bw->cursor->xcol -= curamnt;
996 pdupown(bw->cursor, &bw->b->oldcur);
997 pdupown(bw->top, &bw->b->oldtop);