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