4 * (C) 1992 Joseph H. Allen
6 * This file is part of JOE (Joe's Own Editor)
11 __RCSID("$MirOS: contrib/code/jupp/tw.c,v 1.20 2017/12/08 03:24:15 tg Exp $");
19 #ifdef HAVE_BSD_STRING_H
20 #include <bsd/string.h>
40 char *ctime(const time_t *);
48 /* Move text window */
50 static void movetw(jobject jO, int x, int y)
53 TW *tw = (TW *) bw->object;
56 if (!tw->staon) { /* Scroll down and shrink */
57 nscrldn(bw->parent->t->t, y, bw->parent->nh + y, 1);
59 bwmove(bw, x + (bw->o.linums ? LINCOLS : 0), y + 1);
62 if (tw->staon) { /* Scroll up and grow */
63 nscrlup(bw->parent->t->t, y, bw->parent->nh + y, 1);
65 bwmove(bw, x + (bw->o.linums ? LINCOLS : 0), y);
70 /* Resize text window */
72 static void resizetw(jobject jO, int wi, int he)
76 if (bw->parent->ny || !staen)
77 bwresz(bw, wi - (bw->o.linums ? LINCOLS : 0), he - 1);
79 bwresz(bw, wi - (bw->o.linums ? LINCOLS : 0), he);
82 /* Get current context */
84 /* Find first line (going backwards) which has 0 indentation level
85 * and is not a comment, blank, or block structuring line. This is
86 * likely to be the line with the function name.
88 * There are actually two possibilities:
90 * We want the first line-
97 * We want the last line-
99 * program foo(input,output);
100 * var a, b, c : real;
105 static unsigned char *
108 P *p = pdup(bw->cursor);
109 static unsigned char buf1[stdsiz];
113 /* Find first line with 0 indentation which is not a comment line */
116 if (!pisindent(p) && !pisblank(p)) {
117 /* Uncomment to get the last line instead of the first line (see above)
120 brzs(p,stdbuf,stdsiz-1);
121 /* Ignore comment and block structuring lines */
122 if (!(stdbuf[0]=='{' ||
123 (stdbuf[0]=='/' && stdbuf[1]=='*') ||
125 (stdbuf[0]=='/' && stdbuf[1]=='/') ||
127 ((stdbuf[0] | 0x20) == 'b' && (stdbuf[1] | 0x20) == 'e' && (stdbuf[2] | 0x20) == 'g' && (stdbuf[3] | 0x20) == 'i' && (stdbuf[4] | 0x20) == 'n') ||
128 (stdbuf[0]=='-' && stdbuf[1]=='-') ||
130 strlcpy(buf1,stdbuf,stdsiz);
131 /* Uncomment to get the last line instead of the first line (see above)
134 if (!pisindent(p) && !pisblank(p))
142 } while (!buf1[0] && pprevl(p));
149 static unsigned char *stagen(unsigned char *stalin, BW *bw, unsigned char *s, int fill)
151 unsigned char *cp, *cp2, uc;
152 unsigned char buf[80];
159 while ((cp2 = strstr(cp, "%a")) != NULL) {
163 if (cp2[0] == '%' && cp2[1] == 'A') {
168 if (!special_aA) while ((cp2 = strstr(cp, "%A")) != NULL) {
172 if (cp2[0] == '%' && cp2[1] == 'a') {
178 stalin = vstrunc(stalin, 0);
180 if (*s == '%' && s[1]) {
183 /* Context (but only if autoindent is enabled) */
184 if (bw->o.autoindent) {
185 cp = get_context(bw);
186 stalin = vsncpy(sv(stalin), sz(cp));
192 joe_snprintf_1((char *)buf, sizeof(buf), "(%s)", bw->o.syntax->name);
193 stalin = vsncpy(sv(stalin), sz(buf));
198 cp = (unsigned char *)ctime(&tt);
200 x = (cp[11] - '0') * 10 + cp[12] - '0';
203 joe_snprintf_1((char *)buf, sizeof(buf), "%2.2d", x);
206 stalin = vsncpy(sv(stalin), buf, 2);
207 stalin = vsncpy(sv(stalin), cp + 13, 3);
211 cp = (unsigned char *)ctime(&tt);
212 stalin = vsncpy(sv(stalin), cp + 11, 5);
216 stalin = vsadd(stalin, 'O');
218 stalin = vsadd(stalin, 'I');
222 stalin = vsadd(stalin, 'W');
224 stalin = vsadd(stalin, fill);
227 if (bw->o.autoindent)
228 stalin = vsadd(stalin, 'A');
230 stalin = vsadd(stalin, fill);
234 stalin = vsadd(stalin, 'X');
236 stalin = vsadd(stalin, fill);
240 stalin = vsncpy(sv(stalin), sc("Unnamed"));
245 switch ((uc = *cp++)) {
247 stalin = vsadd(stalin, uc);
250 stalin = vsadd(stalin, uc);
258 stalin = vsncpy(sv(stalin), sc("(Modified)"));
262 stalin = vsncpy(sv(stalin), sc("(Read only)"));
266 stalin = vsadd(stalin, '*');
268 stalin = vsadd(stalin, fill);
271 joe_snprintf_1((char *)buf, sizeof(buf), "%-4ld", bw->cursor->line + 1);
272 for (x = 0; buf[x]; ++x)
275 stalin = vsncpy(sv(stalin), sz(buf));
278 joe_snprintf_1((char *)buf, sizeof(buf), "%-4ld", bw->cursor->byte);
279 for (x = 0; buf[x]; ++x)
282 stalin = vsncpy(sv(stalin), sz(buf));
285 joe_snprintf_1((char *)buf, sizeof(buf), "%-4lX", bw->cursor->byte);
286 for (x = 0; buf[x]; ++x)
289 stalin = vsncpy(sv(stalin), sz(buf));
292 if (bw->b->o.charmap->type && !(special_aA && brch(bw->cursor) == 0x1000FFFE)) {
293 /* UTF-8: don't display decimal value */
297 if (!piseof(bw->cursor))
298 joe_snprintf_1((char *)buf, sizeof(buf), "%3d", 255 & brc(bw->cursor));
300 joe_snprintf_0((char *)buf, sizeof(buf), " ");
301 for (x = 0; buf[x]; ++x)
305 stalin = vsncpy(sv(stalin), sz(buf));
308 if (bw->b->o.charmap->type) {
309 /* UTF-8, display UCS-2 value */
310 if (!piseof(bw->cursor)) {
311 int uch = brch(bw->cursor);
312 if (uch == 0x1000FFFE)
313 joe_snprintf_1((char *)buf, sizeof(buf), special_aA ? "%02X" : " %02X", 255 & brc(bw->cursor));
314 else if (uch == 0x1000FFFF)
315 joe_snprintf_0((char *)buf, sizeof(buf), "<-2>");
317 joe_snprintf_1((char *)buf, sizeof(buf), "%04X", uch);
319 joe_snprintf_0((char *)buf, sizeof(buf), " ");
321 if (!piseof(bw->cursor))
322 joe_snprintf_1((char *)buf, sizeof(buf), "%2.2X", 255 & brc(bw->cursor));
324 joe_snprintf_0((char *)buf, sizeof(buf), " ");
326 for (x = 0; buf[x]; ++x)
329 stalin = vsncpy(sv(stalin), sz(buf));
332 joe_snprintf_1((char *)buf, sizeof(buf), "%-3ld", piscol(bw->cursor) + 1);
333 for (x = 0; buf[x]; ++x)
336 stalin = vsncpy(sv(stalin), sz(buf));
339 if (bw->b->eof->byte)
340 joe_snprintf_1((char *)buf, sizeof(buf), "%3ld", bw->cursor->byte * 100 / bw->b->eof->byte);
342 joe_snprintf_0((char *)buf, sizeof(buf), "100");
343 for (x = 0; buf[x]; ++x)
346 stalin = vsncpy(sv(stalin), sz(buf));
349 joe_snprintf_1((char *)buf, sizeof(buf), "%-4ld", bw->b->eof->line + 1);
350 for (x = 0; buf[x]; ++x)
353 stalin = vsncpy(sv(stalin), sz(buf));
358 if (w->kbd->x && w->kbd->seq[0])
359 for (x = 0; x != w->kbd->x; ++x) {
360 uc = w->kbd->seq[x] & 127;
366 } else if (uc == 127) {
378 stalin = vsncpy(sv(stalin), buf, cp - buf);
382 stalin = vsncpy(sv(stalin), sc("*SHELL*"));
386 joe_snprintf_1((char *)buf, sizeof(buf), "(Macro %d recording...)", recmac->n);
387 stalin = vsncpy(sv(stalin), sz(buf));
391 stalin = vsadd(stalin, *s);
394 stalin = vsadd(stalin, *s);
400 static void disptw(jobject jO, int flg)
404 TW *tw = (TW *) bw->object;
406 if (bw->o.linums != bw->linums) {
407 bw->linums = bw->o.linums;
408 resizetw(jO, w->w, w->h);
409 movetw(jO, w->x, w->y);
414 w->cury = (bw->cursor->byte-bw->top->byte)/16 + bw->y - w->y;
415 w->curx = (bw->cursor->byte-bw->top->byte)%16 + 60 - bw->offset;
417 w->cury = bw->cursor->line - bw->top->line + bw->y - w->y;
418 w->curx = bw->cursor->xcol - bw->offset + (bw->o.linums ? LINCOLS : 0);
421 if ((staupd || keepup || bw->cursor->line != tw->prevline || bw->b->changed != tw->changed || bw->b != tw->prev_b) && (w->y || !staen)) {
424 tw->prevline = bw->cursor->line;
425 tw->changed = bw->b->changed;
428 fill = bw->o.rmsg[0];
431 tw->stalin = stagen(tw->stalin, bw, bw->o.lmsg, fill);
432 tw->staright = stagen(tw->staright, bw, bw->o.rmsg, fill);
433 if (fmtlen(tw->staright) < w->w) {
434 int x = fmtpos(tw->stalin, w->w - fmtlen(tw->staright));
436 if (x > sLEN(tw->stalin))
437 tw->stalin = vsfill(sv(tw->stalin), fill, x - sLEN(tw->stalin));
438 tw->stalin = vsncpy(tw->stalin, fmtpos(tw->stalin, w->w - fmtlen(tw->staright)), sv(tw->staright));
440 tw->stalin = vstrunc(tw->stalin, fmtpos(tw->stalin, w->w));
441 genfmt(w->t->t, w->x, w->y, 0, tw->stalin, 0);
442 w->t->t->updtab[w->y] = 0;
449 bwgen(bw, bw->o.linums);
453 /* Split current window */
455 static void iztw(TW *tw, int y)
461 tw->staon = (!staen || y);
470 int newh = getgrouph(w);
476 if (newh / 2 < FITHEIGHT)
478 new = wcreate(w->t, w->watom, findbotw(w), NULL, w, newh / 2 + (newh & 1), NULL, NULL);
482 new->object.bw = newbw = bwmk(new, bw->b, 0);
484 newbw->offset = bw->offset;
485 newbw->object = newtw = malloc(sizeof(TW));
487 pset(newbw->top, bw->top);
488 pset(newbw->cursor, bw->cursor);
489 newbw->cursor->xcol = bw->cursor->xcol;
490 new->t->curwin = new;
497 int newh = getgrouph(w);
503 new = wcreate(w->t, w->watom, findbotw(w), NULL, NULL, newh, NULL, NULL);
507 new->t->topwin = new;
508 new->object.bw = newbw = bwmk(new, bw->b, 0);
510 newbw->offset = bw->offset;
511 newbw->object = newtw = malloc(sizeof(TW));
513 pset(newbw->top, bw->top);
514 pset(newbw->cursor, bw->cursor);
515 newbw->cursor->xcol = bw->cursor->xcol;
516 new->t->curwin = new;
521 static void instw(BW *bw, B *b, long int l, long int n, int flg)
524 bwins(bw, l, n, flg);
527 static void deltw(BW *bw, B *b, long int l, long int n, int flg)
530 bwdel(bw, l, n, flg);
552 if (bw->parent->watom != &watomtw)
553 return wabort(bw->parent);
554 if (bw->b->pid && bw->b->count==1)
557 tw = (TW *) bw->object;
558 /* If only one main window on the screen... */
559 if (countmain(w->t) == 1)
560 /* Replace it with an orphaned buffer if there are any */
561 if ((b = borphan()) != NULL) {
562 void *object = bw->object;
563 /* FIXME: Shouldn't we wabort() and wcreate here to kill
564 any prompt windows? */
567 w->object.bw = bw = bwmk(w, b, 0);
575 w->object.base = NULL;
576 wabort(w); /* Eliminate this window and it's children */
580 /* User routine for aborting a text window */
582 static int naborttw(BW *bw, int k, void *object, int *notify)
586 if ((k | 0x20) != 'y')
589 genexmsg(bw, 0, NULL);
593 static int naborttw1(BW *bw, int k, void *object, int *notify)
597 if ((k | 0x20) != 'y')
600 if (!exmsg) genexmsg(bw, 0, NULL);
604 /* k is last character types which lead to uabort. If k is -1, it means uabort
605 was called internally, and not by the user: which means uabort will not send
607 int uabort(BW *bw, int k)
609 if (bw->parent->watom != &watomtw)
610 return wabort(bw->parent);
611 if (bw->b->pid && bw->b->count==1)
613 if (bw->b->changed && bw->b->count == 1 && !bw->b->scratch)
614 if (mkqw(bw->parent, sc("Lose changes to this file (y,n,^C)? "), naborttw, NULL, NULL, NULL))
619 return naborttw(bw, 'y', NULL, NULL);
622 int ucancel(BW *bw, int k)
624 if (bw->parent->watom != &watomtw) {
631 /* Same as above, but only calls genexmsg if nobody else has */
633 int uabort1(BW *bw, int k)
635 if (bw->parent->watom != &watomtw)
636 return wabort(bw->parent);
637 if (bw->b->pid && bw->b->count==1)
639 if (bw->b->changed && bw->b->count == 1 && !bw->b->scratch)
640 if (mkqw(bw->parent, sc("Lose changes to this file (y,n,^C)? "), naborttw1, NULL, NULL, NULL))
645 return naborttw1(bw, 'y', NULL, NULL);
648 /* Abort buffer without prompting: just fail if this is last window on buffer */
650 int uabortbuf(BW *bw)
655 if (bw->b->pid && bw->b->count==1)
661 if ((b = borphan()) != NULL) {
662 void *object = bw->object;
665 w->object.bw = bw = bwmk(w, b, 0);
671 return naborttw(bw, 'y', NULL, NULL);
674 /* Kill current window (orphans buffer) */
678 BW *bw = b->parent->main->object.bw;
680 if (countmain(b->parent->t) == 1)
682 if (bw->b->count == 1)
684 return uabort(bw, -1);
687 /* Kill all other windows (orphans buffers) */
691 W *starting = b->parent;
692 W *mainw = starting->main;
693 SCREEN *t = mainw->t;
701 } while (t->curwin->main == mainw && t->curwin != starting);
702 if (t->curwin->main != mainw) {
703 BW *bw = t->curwin->main->object.bw;
712 void setline(B *b, long int line)
714 W *w = maint->curwin;
717 if (w->watom->what == TYPETW) {
718 BW *bw = w->object.bw;
721 long oline = bw->top->line;
723 pline(bw->top, line);
724 pline(bw->cursor, line);
725 if (w->y >= 0 && bw->top->line > oline && bw->top->line - oline < bw->h)
726 nscrlup(w->t->t, bw->y, bw->y + bw->h, (int) (bw->top->line - oline));
727 else if (w->y >= 0 && bw->top->line < oline && oline - bw->top->line < bw->h)
728 nscrldn(w->t->t, bw->y, bw->y + bw->h, (int) (oline - bw->top->line));
731 } while ((w = w->link.next) != maint->curwin);
734 /* Create a text window. It becomes the last window on the screen */
736 BW *wmktw(SCREEN *t, B *b)
742 w = wcreate(t, &watomtw, NULL, NULL, NULL, t->h, NULL, NULL);
744 w->object.bw = bw = bwmk(w, b, 0);
745 bw->object = tw = malloc(sizeof(TW));