1 /* $MirOS: contrib/code/jupp/tw.c,v 1.12 2017/03/19 18:53:02 tg Exp $ */
5 * (C) 1992 Joseph H. Allen
7 * This file is part of JOE (Joe's Own Editor)
19 #ifdef HAVE_BSD_STRING_H
20 #include <bsd/string.h>
39 char *ctime(const time_t *);
47 /* Move text window */
49 static void movetw(BW *bw, int x, int y)
51 TW *tw = (TW *) bw->object;
54 if (!tw->staon) { /* Scroll down and shrink */
55 nscrldn(bw->parent->t->t, y, bw->parent->nh + y, 1);
57 bwmove(bw, x + (bw->o.linums ? LINCOLS : 0), y + 1);
60 if (tw->staon) { /* Scroll up and grow */
61 nscrlup(bw->parent->t->t, y, bw->parent->nh + y, 1);
63 bwmove(bw, x + (bw->o.linums ? LINCOLS : 0), y);
68 /* Resize text window */
70 static void resizetw(BW *bw, int wi, int he)
72 if (bw->parent->ny || !staen)
73 bwresz(bw, wi - (bw->o.linums ? LINCOLS : 0), he - 1);
75 bwresz(bw, wi - (bw->o.linums ? LINCOLS : 0), he);
78 /* Get current context */
80 /* Find first line (going backwards) which has 0 indentation level
81 * and is not a comment, blank, or block structuring line. This is
82 * likely to be the line with the function name.
84 * There are actually two possibilities:
86 * We want the first line-
93 * We want the last line-
95 * program foo(input,output);
101 unsigned char *get_context(BW *bw)
103 P *p = pdup(bw->cursor);
104 static unsigned char buf1[stdsiz];
108 /* Find first line with 0 indentation which is not a comment line */
111 if (!pisindent(p) && !pisblank(p)) {
112 /* Uncomment to get the last line instead of the first line (see above)
115 brzs(p,stdbuf,stdsiz-1);
116 /* Ignore comment and block structuring lines */
117 if (!(stdbuf[0]=='{' ||
118 (stdbuf[0]=='/' && stdbuf[1]=='*') ||
120 (stdbuf[0]=='/' && stdbuf[1]=='/') ||
122 (stdbuf[0]=='b' && stdbuf[1]=='e' && stdbuf[2]=='g' && stdbuf[3]=='i' && stdbuf[4]=='n') ||
123 (stdbuf[0]=='B' && stdbuf[1]=='E' && stdbuf[2]=='G' && stdbuf[3]=='I' && stdbuf[4]=='N') ||
124 (stdbuf[0]=='-' && stdbuf[1]=='-') ||
126 strlcpy(buf1,stdbuf,stdsiz);
127 /* Uncomment to get the last line instead of the first line (see above)
130 if (!pisindent(p) && !pisblank(p))
138 } while (!buf1[0] && pprevl(p));
145 static unsigned char *stagen(unsigned char *stalin, BW *bw, unsigned char *s, int fill)
147 unsigned char *cp, *cp2, uc;
148 unsigned char buf[80];
155 while ((cp2 = strstr(cp, "%a")) != NULL) {
159 if (cp2[0] == '%' && cp2[1] == 'A') {
164 if (!special_aA) while ((cp2 = strstr(cp, "%A")) != NULL) {
168 if (cp2[0] == '%' && cp2[1] == 'a') {
174 stalin = vstrunc(stalin, 0);
176 if (*s == '%' && s[1]) {
179 /* Context (but only if autoindent is enabled) */
180 if (bw->o.autoindent) {
181 cp = get_context(bw);
182 stalin = vsncpy(sv(stalin), sz(cp));
188 joe_snprintf_1((char *)buf, sizeof(buf), "(%s)", bw->o.syntax->name);
189 stalin = vsncpy(sv(stalin), sz(buf));
194 cp = (unsigned char *)ctime(&tt);
196 x = (cp[11] - '0') * 10 + cp[12] - '0';
199 joe_snprintf_1((char *)buf, sizeof(buf), "%2.2d", x);
202 stalin = vsncpy(sv(stalin), buf, 2);
203 stalin = vsncpy(sv(stalin), cp + 13, 3);
207 cp = (unsigned char *)ctime(&tt);
208 stalin = vsncpy(sv(stalin), cp + 11, 5);
212 stalin = vsadd(stalin, 'O');
214 stalin = vsadd(stalin, 'I');
218 stalin = vsadd(stalin, 'W');
220 stalin = vsadd(stalin, fill);
223 if (bw->o.autoindent)
224 stalin = vsadd(stalin, 'A');
226 stalin = vsadd(stalin, fill);
230 stalin = vsadd(stalin, 'X');
232 stalin = vsadd(stalin, fill);
236 stalin = vsncpy(sv(stalin), sc("Unnamed"));
241 switch ((uc = *cp++)) {
243 stalin = vsadd(stalin, uc);
246 stalin = vsadd(stalin, uc);
254 stalin = vsncpy(sv(stalin), sc("(Modified)"));
258 stalin = vsncpy(sv(stalin), sc("(Read only)"));
262 stalin = vsadd(stalin, '*');
264 stalin = vsadd(stalin, fill);
267 joe_snprintf_1((char *)buf, sizeof(buf), "%-4ld", bw->cursor->line + 1);
268 for (x = 0; buf[x]; ++x)
271 stalin = vsncpy(sv(stalin), sz(buf));
274 joe_snprintf_1((char *)buf, sizeof(buf), "%-4ld", bw->cursor->byte);
275 for (x = 0; buf[x]; ++x)
278 stalin = vsncpy(sv(stalin), sz(buf));
281 joe_snprintf_1((char *)buf, sizeof(buf), "%-4lX", bw->cursor->byte);
282 for (x = 0; buf[x]; ++x)
285 stalin = vsncpy(sv(stalin), sz(buf));
288 if (bw->b->o.charmap->type && !(special_aA && brch(bw->cursor) == 0x1000FFFE)) {
289 /* UTF-8: don't display decimal value */
293 if (!piseof(bw->cursor))
294 joe_snprintf_1((char *)buf, sizeof(buf), "%3d", 255 & brc(bw->cursor));
296 joe_snprintf_0((char *)buf, sizeof(buf), " ");
297 for (x = 0; buf[x]; ++x)
301 stalin = vsncpy(sv(stalin), sz(buf));
304 if (bw->b->o.charmap->type) {
305 /* UTF-8, display UCS-2 value */
306 if (!piseof(bw->cursor)) {
307 int uch = brch(bw->cursor);
308 if (uch == 0x1000FFFE)
309 joe_snprintf_1((char *)buf, sizeof(buf), special_aA ? "%02X" : " %02X", 255 & brc(bw->cursor));
310 else if (uch == 0x1000FFFF)
311 joe_snprintf_0((char *)buf, sizeof(buf), "<-2>");
313 joe_snprintf_1((char *)buf, sizeof(buf), "%04X", uch);
315 joe_snprintf_0((char *)buf, sizeof(buf), " ");
317 if (!piseof(bw->cursor))
318 joe_snprintf_1((char *)buf, sizeof(buf), "%2.2X", 255 & brc(bw->cursor));
320 joe_snprintf_0((char *)buf, sizeof(buf), " ");
322 for (x = 0; buf[x]; ++x)
325 stalin = vsncpy(sv(stalin), sz(buf));
328 joe_snprintf_1((char *)buf, sizeof(buf), "%-3ld", piscol(bw->cursor) + 1);
329 for (x = 0; buf[x]; ++x)
332 stalin = vsncpy(sv(stalin), sz(buf));
335 if (bw->b->eof->byte)
336 joe_snprintf_1((char *)buf, sizeof(buf), "%3ld", bw->cursor->byte * 100 / bw->b->eof->byte);
338 joe_snprintf_0((char *)buf, sizeof(buf), "100");
339 for (x = 0; buf[x]; ++x)
342 stalin = vsncpy(sv(stalin), sz(buf));
345 joe_snprintf_1((char *)buf, sizeof(buf), "%-4ld", bw->b->eof->line + 1);
346 for (x = 0; buf[x]; ++x)
349 stalin = vsncpy(sv(stalin), sz(buf));
354 if (w->kbd->x && w->kbd->seq[0])
355 for (x = 0; x != w->kbd->x; ++x) {
356 uc = w->kbd->seq[x] & 127;
362 } else if (uc == 127) {
374 stalin = vsncpy(sv(stalin), buf, cp - buf);
378 stalin = vsncpy(sv(stalin), sc("*SHELL*"));
382 joe_snprintf_1((char *)buf, sizeof(buf), "(Macro %d recording...)", recmac->n);
383 stalin = vsncpy(sv(stalin), sz(buf));
387 stalin = vsadd(stalin, *s);
390 stalin = vsadd(stalin, *s);
396 static void disptw(BW *bw, int flg)
399 TW *tw = (TW *) bw->object;
401 if (bw->o.linums != bw->linums) {
402 bw->linums = bw->o.linums;
403 resizetw(bw, w->w, w->h);
404 movetw(bw, w->x, w->y);
409 w->cury = (bw->cursor->byte-bw->top->byte)/16 + bw->y - w->y;
410 w->curx = (bw->cursor->byte-bw->top->byte)%16 + 60 - bw->offset;
412 w->cury = bw->cursor->line - bw->top->line + bw->y - w->y;
413 w->curx = bw->cursor->xcol - bw->offset + (bw->o.linums ? LINCOLS : 0);
416 if ((staupd || keepup || bw->cursor->line != tw->prevline || bw->b->changed != tw->changed || bw->b != tw->prev_b) && (w->y || !staen)) {
419 tw->prevline = bw->cursor->line;
420 tw->changed = bw->b->changed;
423 fill = bw->o.rmsg[0];
426 tw->stalin = stagen(tw->stalin, bw, bw->o.lmsg, fill);
427 tw->staright = stagen(tw->staright, bw, bw->o.rmsg, fill);
428 if (fmtlen(tw->staright) < w->w) {
429 int x = fmtpos(tw->stalin, w->w - fmtlen(tw->staright));
431 if (x > sLEN(tw->stalin))
432 tw->stalin = vsfill(sv(tw->stalin), fill, x - sLEN(tw->stalin));
433 tw->stalin = vsncpy(tw->stalin, fmtpos(tw->stalin, w->w - fmtlen(tw->staright)), sv(tw->staright));
435 tw->stalin = vstrunc(tw->stalin, fmtpos(tw->stalin, w->w));
436 genfmt(w->t->t, w->x, w->y, 0, tw->stalin, 0);
437 w->t->t->updtab[w->y] = 0;
444 bwgen(bw, bw->o.linums);
448 /* Split current window */
450 static void iztw(TW *tw, int y)
456 tw->staon = (!staen || y);
465 int newh = getgrouph(w);
471 if (newh / 2 < FITHEIGHT)
473 new = wcreate(w->t, w->watom, findbotw(w), NULL, w, newh / 2 + (newh & 1), NULL, NULL);
477 new->object = (void *) (newbw = bwmk(new, bw->b, 0));
479 newbw->offset = bw->offset;
480 newbw->object = (void *) (newtw = (TW *) joe_malloc(sizeof(TW)));
482 pset(newbw->top, bw->top);
483 pset(newbw->cursor, bw->cursor);
484 newbw->cursor->xcol = bw->cursor->xcol;
485 new->t->curwin = new;
492 int newh = getgrouph(w);
498 new = wcreate(w->t, w->watom, findbotw(w), NULL, NULL, newh, NULL, NULL);
502 new->t->topwin = new;
503 new->object = (void *) (newbw = bwmk(new, bw->b, 0));
505 newbw->offset = bw->offset;
506 newbw->object = (void *) (newtw = (TW *) joe_malloc(sizeof(TW)));
508 pset(newbw->top, bw->top);
509 pset(newbw->cursor, bw->cursor);
510 newbw->cursor->xcol = bw->cursor->xcol;
511 new->t->curwin = new;
516 static void instw(BW *bw, B *b, long int l, long int n, int flg)
519 bwins(bw, l, n, flg);
522 static void deltw(BW *bw, B *b, long int l, long int n, int flg)
525 bwdel(bw, l, n, flg);
547 if (bw->parent->watom != &watomtw)
548 return wabort(bw->parent);
549 if (bw->b->pid && bw->b->count==1)
552 tw = (TW *) bw->object;
553 /* If only one main window on the screen... */
554 if (countmain(w->t) == 1)
555 /* Replace it with an orphaned buffer if there are any */
556 if ((b = borphan()) != NULL) {
557 void *object = bw->object;
558 /* FIXME: Shouldn't we wabort() and wcreate here to kill
559 any prompt windows? */
562 w->object = (void *) (bw = bwmk(w, b, 0));
571 wabort(w); /* Eliminate this window and it's children */
575 /* User routine for aborting a text window */
577 static int naborttw(BW *bw, int k, void *object, int *notify)
581 if (k != 'y' && k != 'Y')
584 genexmsg(bw, 0, NULL);
588 static int naborttw1(BW *bw, int k, void *object, int *notify)
592 if (k != 'y' && k != 'Y')
595 if (!exmsg) genexmsg(bw, 0, NULL);
599 /* k is last character types which lead to uabort. If k is -1, it means uabort
600 was called internally, and not by the user: which means uabort will not send
602 int uabort(BW *bw, int k)
604 if (bw->parent->watom != &watomtw)
605 return wabort(bw->parent);
606 if (bw->b->pid && bw->b->count==1)
608 if (bw->b->changed && bw->b->count == 1 && !bw->b->scratch)
609 if (mkqw(bw->parent, sc("Lose changes to this file (y,n,^C)? "), naborttw, NULL, NULL, NULL))
614 return naborttw(bw, 'y', NULL, NULL);
617 int ucancel(BW *bw, int k)
619 if (bw->parent->watom != &watomtw) {
626 /* Same as above, but only calls genexmsg if nobody else has */
628 int uabort1(BW *bw, int k)
630 if (bw->parent->watom != &watomtw)
631 return wabort(bw->parent);
632 if (bw->b->pid && bw->b->count==1)
634 if (bw->b->changed && bw->b->count == 1 && !bw->b->scratch)
635 if (mkqw(bw->parent, sc("Lose changes to this file (y,n,^C)? "), naborttw1, NULL, NULL, NULL))
640 return naborttw1(bw, 'y', NULL, NULL);
643 /* Abort buffer without prompting: just fail if this is last window on buffer */
645 int uabortbuf(BW *bw)
650 if (bw->b->pid && bw->b->count==1)
656 if ((b = borphan()) != NULL) {
657 void *object = bw->object;
660 w->object = (void *) (bw = bwmk(w, b, 0));
666 return naborttw(bw, 'y', NULL, NULL);
669 /* Kill current window (orphans buffer) */
673 BW *bw = b->parent->main->object;
675 if (countmain(b->parent->t) == 1)
677 if (bw->b->count == 1)
679 return uabort(bw, -1);
682 /* Kill all other windows (orphans buffers) */
686 W *starting = b->parent;
687 W *mainw = starting->main;
688 SCREEN *t = mainw->t;
696 } while (t->curwin->main == mainw && t->curwin != starting);
697 if (t->curwin->main != mainw) {
698 BW *bw = t->curwin->main->object;
707 void setline(B *b, long int line)
709 W *w = maint->curwin;
712 if (w->watom->what == TYPETW) {
716 long oline = bw->top->line;
718 pline(bw->top, line);
719 pline(bw->cursor, line);
720 if (w->y >= 0 && bw->top->line > oline && bw->top->line - oline < bw->h)
721 nscrlup(w->t->t, bw->y, bw->y + bw->h, (int) (bw->top->line - oline));
722 else if (w->y >= 0 && bw->top->line < oline && oline - bw->top->line < bw->h)
723 nscrldn(w->t->t, bw->y, bw->y + bw->h, (int) (oline - bw->top->line));
726 } while ((w = w->link.next) != maint->curwin);
729 /* Create a text window. It becomes the last window on the screen */
731 BW *wmktw(SCREEN *t, B *b)
737 w = wcreate(t, &watomtw, NULL, NULL, NULL, t->h, NULL, NULL);
739 w->object = (void *) (bw = bwmk(w, b, 0));
740 bw->object = (void *) (tw = (TW *) joe_malloc(sizeof(TW)));