joe-3.1jupp31.tgz (die zweite Klappeā€¦)
[alioth/jupp.git] / bw.c
1 /* $MirOS: contrib/code/jupp/bw.c,v 1.22 2017/07/09 01:15:51 tg Exp $ */
2 /*
3  *      Edit buffer window generation
4  *      Copyright
5  *              (C) 1992 Joseph H. Allen
6  *
7  *      This file is part of JOE (Joe's Own Editor)
8  */
9 #include "config.h"
10 #include "types.h"
11
12 #include <string.h>
13 #include <stdio.h>
14 #ifdef HAVE_STDLIB_H
15 #include <stdlib.h>
16 #endif
17
18 #ifdef HAVE_BSD_STRING_H
19 #include <bsd/string.h>
20 #endif
21
22 #include "b.h"
23 #include "bw.h"
24 #include "blocks.h"
25 #include "kbd.h"
26 #include "rc.h"
27 #include "scrn.h"
28 #include "ublock.h"
29 #include "utils.h"
30 #include "syntax.h"
31 #include "utf8.h"
32 #include "charmap.h"
33 #include "w.h"
34
35 /* Display modes */
36 int dspasis = 0;
37 int marking = 0;
38 extern int staen;
39 extern SCREEN *maint;
40
41 static P *getto(P *p, P *cur, P *top, long int line)
42 {
43
44         if (p == NULL) {
45                 P *best = cur;
46                 long dist = MAXLONG;
47                 long d;
48
49                 d = (line >= cur->line ? line - cur->line : cur->line - line);
50                 if (d < dist) {
51                         dist = d;
52                         best = cur;
53                 }
54                 d = (line >= top->line ? line - top->line : top->line - line);
55                 if (d < dist) {
56                         /* dead store: dist = d; */
57                         best = top;
58                 }
59                 p = pdup(best);
60                 p_goto_bol(p);
61         }
62         while (line > p->line)
63                 if (!pnextl(p))
64                         break;
65         if (line < p->line) {
66                 while (line < p->line)
67                         pprevl(p);
68                 p_goto_bol(p);
69         }
70         return p;
71 }
72
73 /* Scroll window to follow cursor */
74
75 int mid = 0;
76
77 /* For hex */
78
79 static void bwfllwh(BW *w)
80 {
81         /* Top must be a muliple of 16 bytes */
82         if (w->top->byte%16) {
83                 pbkwd(w->top,w->top->byte%16);
84         }
85
86         /* Move backward */
87         if (w->cursor->byte < w->top->byte) {
88                 long new_top = w->cursor->byte/16;
89                 if (mid) {
90                         if (new_top >= w->h / 2)
91                                 new_top -= w->h / 2;
92                         else
93                                 new_top = 0;
94                 }
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));
97                 else
98                         msetI(w->t->t->updtab + w->y, 1, w->h);
99                 pgoto(w->top,new_top*16);
100         }
101
102         /* Move forward */
103         if (w->cursor->byte >= w->top->byte+(w->h*16)) {
104                 long new_top;
105                 if (mid) {
106                         new_top = w->cursor->byte/16 - w->h / 2;
107                 } else {
108                         new_top = w->cursor->byte/16 - (w->h - 1);
109                 }
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));
112                 else {
113                         msetI(w->t->t->updtab + w->y, 1, w->h);
114                 }
115                 pgoto(w->top, new_top*16);
116         }
117
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);
125         }
126 }
127
128 /* For text */
129
130 static void bwfllwt(BW *w)
131 {
132         P *newtop;
133
134         if (w->cursor->line < w->top->line) {
135                 newtop = pdup(w->cursor);
136                 p_goto_bol(newtop);
137                 if (mid) {
138                         if (newtop->line >= w->h / 2)
139                                 pline(newtop, newtop->line - w->h / 2);
140                         else
141                                 pset(newtop, newtop->b->bof);
142                 }
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));
145                 else {
146                         msetI(w->t->t->updtab + w->y, 1, w->h);
147                         msetI(w->t->t->syntab + w->y, -1, w->h);
148                 }
149                 pset(w->top, newtop);
150                 prm(newtop);
151         } else if (w->cursor->line >= w->top->line + w->h) {
152                 pdup(w->top);
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));
157                 else {
158                         msetI(w->t->t->updtab + w->y, 1, w->h);
159                         msetI(w->t->t->syntab + w->y, -1, w->h);
160                 }
161                 pset(w->top, newtop);
162                 prm(newtop);
163         }
164
165 /* Adjust column */
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);
172         }
173 }
174
175 /* For either */
176
177 void bwfllw(BW *w)
178 {
179         if (w->o.hex)
180                 bwfllwh(w);
181         else
182                 bwfllwt(w);
183 }
184
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. */
188
189 int get_highlight_state(BW *w,int line)
190 {
191         P *tmp = 0;
192         int state;
193
194         /* Screen y position of requested line */
195         int y = line-w->top->line+w->y;
196
197         if(!w->o.highlight || !w->o.syntax)
198                 return -1;
199
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];
203
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;
207
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 */
211                 state = 0;
212                 tmp = pdup(w->top);
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);
215                 else
216                         p_goto_bof(tmp);
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;
221                 prm(tmp);
222         }
223
224         /* Color to end of screen */
225         tmp = pdup(w->top);
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 */
232                 }
233         prm(tmp);
234         while(y<w->y+w->h-1) {
235                 w->parent->t->t->syntab[++y] = state;
236                 }
237
238         /* Line after window */
239         /* state = parse_c(state,syn,tmp); */
240
241         /* If we changed, fix other windows */
242         /* w->state = state; */
243
244         /* Return state of requested line */
245         y = line - w->top->line + w->y;
246         return w->parent->t->t->syntab[y];
247 }
248
249 /* Scroll a buffer window after an insert occurred.  'flg' is set to 1 if
250  * the first line was split
251  */
252
253 void bwins(BW *w, long int l, long int n, int flg)
254 {
255         if (l + flg + n < w->top->line + w->h && l + flg >= w->top->line && l + flg <= w->b->eof->line) {
256                 if (flg)
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);
259         }
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));
264                 } else {
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);
267                 }
268         }
269 }
270
271 /* Scroll current windows after a delete */
272
273 void bwdel(BW *w, long int l, long int n, int flg)
274 {
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;
278
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;
283                 }
284
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;
288
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));
293                 else
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);
300                 else
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);
306                 else
307                         nscrlup(w->t->t, w->y, w->y + w->h, (int) (l + n - w->top->line));
308         }
309 }
310
311 /* Update a single line */
312
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)
314         
315       
316                                 /* Screen line address */
317                                 /* Window */
318                                 /* Buffer pointer */
319                                 /* Starting column to display */
320                                 /* Range for marked block */
321 {
322         int ox = x;
323         int tach, tach1;
324         int done = 1;
325         long col = 0;
326         long byte = p->byte;
327         unsigned char *bp;      /* Buffer pointer, 0 if not set */
328         int amnt;               /* Amount left in this segment of the buffer */
329         int c, ta, c1;
330         unsigned char bc;
331         int ungetit = -1;
332
333         struct utf8_sm utf8_sm;
334
335         int *syn = NULL;
336         P *tmp;
337         int idx=0;
338         int atr = 0;
339
340         utf8_init(&utf8_sm);
341
342         if(st!=-1) {
343                 tmp=pdup(p);
344                 p_goto_bol(tmp);
345                 parse(bw->o.syntax,tmp,st);
346                 syn = attr_buf;
347                 prm(tmp);
348         }
349
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);
354         } else {
355                 bp = p->ptr + p->ofst;
356                 amnt = p->hdr->hole - p->ofst;
357         }
358
359         if (col == scr)
360                 goto loop;
361       lp:                       /* Display next character */
362         if (amnt)
363                 do {
364                         if (ungetit== -1)
365                                 bc = *bp++;
366                         else {
367                                 bc = ungetit;
368                                 ungetit = -1;
369                         }
370                         if(st!=-1)
371                                 atr = syn[idx++];
372                         if (p->b->o.crlf && bc == '\r') {
373                                 ++byte;
374                                 if (!--amnt) {
375                                       pppl:
376                                         if (bp == p->ptr + SEGSIZ) {
377                                                 if (pnext(p)) {
378                                                         bp = p->ptr;
379                                                         amnt = p->hdr->hole;
380                                                 } else
381                                                         goto nnnl;
382                                         } else {
383                                                 bp = p->ptr + p->hdr->ehole;
384                                                 amnt = SEGSIZ - p->hdr->ehole;
385                                                 if (!amnt)
386                                                         goto pppl;
387                                         }
388                                 }
389                                 if (*bp == '\n') {
390                                         ++bp;
391                                         ++byte;
392                                         ++amnt;
393                                         goto eobl;
394                                 }
395                               nnnl:
396                                 --byte;
397                                 ++amnt;
398                         }
399                         if (square)
400                                 if (bc == '\t') {
401                                         long tcol = col + p->b->o.tab - col % p->b->o.tab;
402
403                                         if (tcol > from && tcol <= to)
404                                                 c1 = INVERSE;
405                                         else
406                                                 c1 = 0;
407                                 } else if (col >= from && col < to)
408                                         c1 = INVERSE;
409                                 else
410                                         c1 = 0;
411                         else if (byte >= from && byte < to)
412                                 c1 = INVERSE;
413                         else
414                                 c1 = 0;
415                         ++byte;
416                         if (bc == '\t') {
417                                 ta = p->b->o.tab - col % p->b->o.tab;
418                                 if (ta + col > scr) {
419                                         ta -= scr - col;
420                                         goto dota_tab;
421                                 }
422                                 if ((col += ta) == scr) {
423                                         --amnt;
424                                         goto loop;
425                                 }
426                         } else if (bc == '\n')
427                                 goto eobl;
428                         else {
429                                 int wid = 1;
430                                 if (p->b->o.charmap->type) {
431                                         c = utf8_decode(&utf8_sm,bc);
432
433                                         if (c>=0) /* Normal decoded character */
434                                                 wid = joe_wcwidth(1,c);
435                                         else if(c== -1) /* Character taken */
436                                                 wid = -1;
437                                         else if(c== -2) { /* Incomplete sequence */
438                                                 wid = 1;
439                                                 ungetit = c;
440                                                 ++amnt;
441                                                 --byte;
442                                         }
443                                         else if(c== -3) /* Control character 128-191, 254, 255 */
444                                                 wid = 1;
445                                 }
446
447                                 if (wid >= 0) {
448                                         col += wid;
449                                         if (col == scr) {
450                                                 --amnt;
451                                                 goto loop;
452                                         } else if (col > scr) {
453                                                 ta = col - scr;
454                                                 tach1 = tach = '<';
455                                                 goto dota_gen;
456                                         }
457                                 } else
458                                         --idx;  /* Get highlighting character again.. */
459                         }
460                 } while (--amnt);
461         if (bp == p->ptr + SEGSIZ) {
462                 if (pnext(p)) {
463                         bp = p->ptr;
464                         amnt = p->hdr->hole;
465                         goto lp;
466                 }
467         } else {
468                 bp = p->ptr + p->hdr->ehole;
469                 amnt = SEGSIZ - p->hdr->ehole;
470                 goto lp;
471         }
472         goto eof;
473
474       loop:                     /* Display next character */
475         if (amnt)
476                 do {
477                         if (ungetit== -1)
478                                 bc = *bp++;
479                         else {
480                                 bc = ungetit;
481                                 ungetit = -1;
482                         }
483                         if(st!=-1)
484                                 atr=syn[idx++];
485                         if (p->b->o.crlf && bc == '\r') {
486                                 ++byte;
487                                 if (!--amnt) {
488                                       ppl:
489                                         if (bp == p->ptr + SEGSIZ) {
490                                                 if (pnext(p)) {
491                                                         bp = p->ptr;
492                                                         amnt = p->hdr->hole;
493                                                 } else
494                                                         goto nnl;
495                                         } else {
496                                                 bp = p->ptr + p->hdr->ehole;
497                                                 amnt = SEGSIZ - p->hdr->ehole;
498                                                 if (!amnt)
499                                                         goto ppl;
500                                         }
501                                 }
502                                 if (*bp == '\n') {
503                                         ++bp;
504                                         ++byte;
505                                         ++amnt;
506                                         goto eobl;
507                                 }
508                               nnl:
509                                 --byte;
510                                 ++amnt;
511                         }
512                         if (square)
513                                 if (bc == '\t') {
514                                         long tcol = scr + x - ox + p->b->o.tab - (scr + x - ox) % p->b->o.tab;
515
516                                         if (tcol > from && tcol <= to)
517                                                 c1 = INVERSE;
518                                         else
519                                                 c1 = 0;
520                                 } else if (scr + x - ox >= from && scr + x - ox < to)
521                                         c1 = INVERSE;
522                                 else
523                                         c1 = 0;
524                         else if (byte >= from && byte < to)
525                                 c1 = INVERSE;
526                         else
527                                 c1 = 0;
528                         ++byte;
529                         if (bc == '\t') {
530                                 ta = p->b->o.tab - ((x - ox + scr) % p->b->o.tab);
531  dota_tab:
532                                 tach1 = tach = ' ';
533                                 if (bw->o.vispace)
534                                         tach = 0x2192;
535  dota_gen:
536                                 do {
537                                         outatr(utf8_map, t, screen + x, attr + x, x, y, tach, c1|atr);
538                                         tach = tach1;
539                                         if (ifhave)
540                                                 goto bye;
541                                         if (++x == w)
542                                                 goto eosl;
543                                 } while (--ta);
544                         } else if (bc == '\n') {
545                                 if (utf8_sm.state)
546                                         goto unget_cch;
547                                 goto eobl;
548                         } else {
549                                 int wid = -1;
550                                 int utf8_char;
551                                 if (p->b->o.charmap->type) { /* UTF-8 */
552
553                                         utf8_char = utf8_decode(&utf8_sm,bc);
554
555                                         if (utf8_char >= 0) { /* Normal decoded character */
556                                                 wid = joe_wcwidth(1,utf8_char);
557                                         } else if(utf8_char== -1) { /* Character taken */
558                                                 wid = -1;
559                                         } else if(utf8_char== -2) { /* Incomplete sequence (FIXME: do something better here) */
560  unget_cch:
561                                                 ungetit = bc;
562                                                 ++amnt;
563                                                 --byte;
564                                                 utf8_char = 0x1000FFFE;
565                                                 wid = utf8_sm.ptr;
566                                                 utf8_init(&utf8_sm);
567                                         } else if(utf8_char== -3) { /* Invalid UTF-8 start character 128-191, 254, 255 */
568                                                 /* Show as control character */
569                                                 wid = 1;
570                                                 utf8_char = 0x1000FFFE;
571                                         }
572                                 } else { /* Regular */
573                                         utf8_char = bc;
574                                         wid = 1;
575                                 }
576
577                                 if(wid>=0) {
578                                         if (x+wid > w) {
579                                                 /* If character hits right most column, don't display it */
580                                                 while (x < w) {
581                                                         outatr(bw->b->o.charmap, t, screen + x, attr + x, x, y, '>', c1|atr);
582                                                         x++;
583                                                 }
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);
586                                                 x++;
587                                         } else if (bw->o.vispace && (utf8_char == 0x20)) {
588                                                 outatr(utf8_map, t, screen + x, attr + x, x, y, 0xB7, c1|atr);
589                                                 x += wid;
590                                         } else {
591                                                 outatr(bw->b->o.charmap, t, screen + x, attr + x, x, y, utf8_char, c1|atr);
592                                                 x += wid;
593                                         }
594                                 } else
595                                         --idx;
596
597                                 if (ifhave)
598                                         goto bye;
599                                 if (x >= w)
600                                         goto eosl;
601                         }
602                 } while (--amnt);
603         if (bp == p->ptr + SEGSIZ) {
604                 if (pnext(p)) {
605                         bp = p->ptr;
606                         amnt = p->hdr->hole;
607                         goto loop;
608                 }
609         } else {
610                 bp = p->ptr + p->hdr->ehole;
611                 amnt = SEGSIZ - p->hdr->ehole;
612                 goto loop;
613         }
614         goto eof;
615
616       eobl:                     /* End of buffer line found.  Erase to end of screen line */
617         ++p->line;
618       eof:
619         if (x != w)
620                 done = eraeol(t, x, y);
621         else
622                 done = 0;
623
624 /* Set p to bp/amnt */
625       bye:
626         if (bp - p->ptr <= p->hdr->hole)
627                 p->ofst = bp - p->ptr;
628         else
629                 p->ofst = bp - p->ptr - (p->hdr->ehole - p->hdr->hole);
630         p->byte = byte;
631         return done;
632
633       eosl:
634         if (bp - p->ptr <= p->hdr->hole)
635                 p->ofst = bp - p->ptr;
636         else
637                 p->ofst = bp - p->ptr - (p->hdr->ehole - p->hdr->hole);
638         p->byte = byte;
639         pnextl(p);
640         return 0;
641 }
642
643 static void gennum(BW *w, int *screen, int *attr, SCRN *t, int y, int *comp)
644 {
645         unsigned char buf[12];
646         int z;
647         int lin = w->top->line + y - w->y;
648
649         if (lin <= w->b->eof->line)
650                 joe_snprintf_1((char *)buf, sizeof(buf), "%5ld ", w->top->line + y - w->y + 1);
651         else
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);
655                 if (ifhave)
656                         return;
657                 comp[z] = buf[z];
658         }
659 }
660
661 void bwgenh(BW *w)
662 {
663         int *screen;
664         int *attr;
665         P *q = pdup(w->top);
666         int bot = w->h + w->y;
667         int y;
668         SCRN *t = w->t->t;
669         int flg = 0;
670         long from;
671         long to;
672         int dosquare = 0;
673
674         from = to = 0;
675
676         if (markv(0) && markk->b == w->b)
677                 if (square) {
678                         from = markb->xcol;
679                         to = markk->xcol;
680                         dosquare = 1;
681                 } else {
682                         from = markb->byte;
683                         to = markk->byte;
684                 }
685         else if (marking && w == (BW *)maint->curwin->object && markb && markb->b == w->b && w->cursor->byte != markb->byte && !from) {
686                 if (square) {
687                         from = long_min(w->cursor->xcol, markb->xcol);
688                         to = long_max(w->cursor->xcol, markb->xcol);
689                         dosquare = 1;
690                 } else {
691                         from = long_min(w->cursor->byte, markb->byte);
692                         to = long_max(w->cursor->byte, markb->byte);
693                 }
694         }
695
696         if (marking && w == (BW *)maint->curwin->object)
697                 msetI(t->updtab + w->y, 1, w->h);
698
699         if (dosquare) {
700                 from = 0;
701                 to = 0;
702         }
703
704         y=w->y;
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];
708                 int fmt[80];
709                 unsigned char bf[16];
710                 int x;
711                 memset(txt,' ',76);
712                 msetI(fmt, /* BG_COLOR(bg_text) */ 0,76);
713                 txt[76]=0;
714                 if (!flg) {
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);
717 #else
718                         joe_snprintf_1((char *)bf,sizeof(bf),"%8lX ",(unsigned long)q->byte);
719 #endif
720                         memcpy(txt,bf,9);
721                         for (x=0; x!=8; ++x) {
722                                 int c;
723                                 if (q->byte==w->cursor->byte && !flg) {
724                                         fmt[10+x*3] |= INVERSE;
725                                         fmt[10+x*3+1] |= INVERSE;
726                                 }
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;
731                                 }
732                                 c = pgetb(q);
733                                 if (c >= 0) {
734                                         joe_snprintf_1((char *)bf,sizeof(bf),"%2.2X",c);
735                                         txt[10+x*3] = bf[0];
736                                         txt[10+x*3+1] = bf[1];
737                                         if (c >= 0x20 && c <= 0x7E)
738                                                 txt[60+x] = c;
739                                         else
740                                                 txt[60+x] = '.';
741                                 } else
742                                         flg = 1;
743                         }
744                         for (x=8; x!=16; ++x) {
745                                 int c;
746                                 if (q->byte==w->cursor->byte && !flg) {
747                                         fmt[11+x*3] |= INVERSE;
748                                         fmt[11+x*3+1] |= INVERSE;
749                                 }
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;
754                                 }
755                                 c = pgetb(q);
756                                 if (c >= 0) {
757                                         joe_snprintf_1((char *)bf,sizeof(bf),"%2.2X",c);
758                                         txt[11+x*3] = bf[0];
759                                         txt[11+x*3+1] = bf[1];
760                                         if (c >= 0x20 && c <= 0x7E)
761                                                 txt[60+x] = c;
762                                         else
763                                                 txt[60+x] = '.';
764                                 } else
765                                         flg = 1;
766                         }
767                 }
768                 genfield(t, screen, attr, 0, y, w->offset, txt, 76, 0, w->w, 1, fmt);
769         }
770         prm(q);
771 }
772
773 void bwgen(BW *w, int linums)
774 {
775         int *screen;
776         int *attr;
777         P *p = NULL;
778         P *q = pdup(w->cursor);
779         int bot = w->h + w->y;
780         int y;
781         int dosquare = 0;
782         long from, to;
783         long fromline, toline;
784         SCRN *t = w->t->t;
785
786         fromline = toline = from = to = 0;
787
788         if (markv(0) && markk->b == w->b)
789                 if (square) {
790                         from = markb->xcol;
791                         to = markk->xcol;
792                         dosquare = 1;
793                         fromline = markb->line;
794                         toline = markk->line;
795                 } else {
796                         from = markb->byte;
797                         to = markk->byte;
798                 }
799         else if (marking && w==maint->curwin->object && markb && markb->b == w->b && w->cursor->byte != markb->byte && !from) {
800                 if (square) {
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);
805                         dosquare = 1;
806                 } else {
807                         from = long_min(w->cursor->byte, markb->byte);
808                         to = long_max(w->cursor->byte, markb->byte);
809                 }
810         }
811
812         if (marking && w==maint->curwin->object)
813                 msetI(t->updtab + w->y, 1, w->h);
814
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)
819                         break;
820                 if (linums)
821                         gennum(w, screen, attr, t, y, t->compose);
822                 if (t->updtab[y]) {
823                         p = getto(p, w->cursor, w->top, w->top->line + y - w->y);
824 /*                      if (t->insdel && !w->x) {
825                                 pset(q, p);
826                                 if (dosquare)
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);
829                                         else
830                                                 lgena(t, y, t->compose, w->x, w->x + w->w, q, w->offset, 0L, 0L);
831                                 else
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));
834                         } */
835                         if (dosquare)
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);
838                                 else
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);
840                         else
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);
842                 }
843         }
844
845         y = w->y;
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)
849                         break;
850                 if (linums)
851                         gennum(w, screen, attr, t, y, t->compose);
852                 if (t->updtab[y]) {
853                         p = getto(p, w->cursor, w->top, w->top->line + y - w->y);
854 /*                      if (t->insdel && !w->x) {
855                                 pset(q, p);
856                                 if (dosquare)
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);
859                                         else
860                                                 lgena(t, y, t->compose, w->x, w->x + w->w, q, w->offset, 0L, 0L);
861                                 else
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));
864                         } */
865                         if (dosquare)
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);
868                                 else
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);
870                         else
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);
872                 }
873         }
874         prm(q);
875         if (p)
876                 prm(p);
877 }
878
879 void bwmove(BW *w, int x, int y)
880 {
881         w->x = x;
882         w->y = y;
883 }
884
885 void bwresz(BW *w, int wi, int he)
886 {
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);
890                 }
891         w->w = wi;
892         w->h = he;
893 }
894
895 BW *bwmk(W *window, B *b, int prompt)
896 {
897         BW *w = (BW *) joe_malloc(sizeof(BW));
898
899         w->parent = window;
900         w->b = b;
901         if (prompt || (!window->y && staen)) {
902                 w->y = window->y;
903                 w->h = window->h;
904         } else {
905                 w->y = window->y + 1;
906                 w->h = window->h - 1;
907         }
908         if (b->oldcur) {
909                 w->top = b->oldtop;
910                 b->oldtop = NULL;
911                 w->top->owner = NULL;
912                 w->cursor = b->oldcur;
913                 b->oldcur = NULL;
914                 w->cursor->owner = NULL;
915         } else {
916                 w->top = pdup(b->bof);
917                 w->cursor = pdup(b->bof);
918         }
919         w->t = window->t;
920         w->object = NULL;
921         w->offset = 0;
922         w->o = w->b->o;
923         if ((w->linums = w->o.linums)) {
924                 w->x = window->x + LINCOLS;
925                 w->w = window->w - LINCOLS;
926         } else {
927                 w->x = window->x;
928                 w->w = window->w;
929         }
930         if (window == window->main) {
931                 rmkbd(window->kbd);
932                 window->kbd = mkkbd(kmap_getcontext(w->o.context, 1));
933         }
934         w->top->xcol = 0;
935         w->cursor->xcol = 0;
936         w->top_changed = 1;
937         return w;
938 }
939
940 void bwrm(BW *w)
941 {
942         prm(w->top);
943         prm(w->cursor);
944         brm(w->b);
945         joe_free(w);
946 }
947
948 int ustat(BW *bw)
949 {
950         static unsigned char buf[80];
951         int c = brch(bw->cursor);
952
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);
955         else
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);
958         return 0;
959 }
960
961 int ucrawlr(BW *bw)
962 {
963         int amnt = bw->w / 2;
964
965         pcol(bw->cursor, bw->cursor->xcol + amnt);
966         bw->cursor->xcol += amnt;
967         bw->offset += amnt;
968         updall();
969         return 0;
970 }
971
972 int ucrawll(BW *bw)
973 {
974         int amnt = bw->w / 2;
975         int curamnt = bw->w / 2;
976
977         if (amnt > bw->offset) {
978                 amnt = bw->offset;
979                 curamnt = bw->offset;
980         }
981         if (!bw->offset)
982                 curamnt = bw->cursor->xcol;
983         if (!curamnt)
984                 return -1;
985         pcol(bw->cursor, bw->cursor->xcol - curamnt);
986         bw->cursor->xcol -= curamnt;
987         bw->offset -= amnt;
988         updall();
989         return 0;
990 }
991
992 void orphit(BW *bw)
993 {
994         ++bw->b->count;
995         bw->b->orphan = 1;
996         pdupown(bw->cursor, &bw->b->oldcur);
997         pdupown(bw->top, &bw->b->oldtop);
998 }