1 /* $MirOS: contrib/code/jupp/w.c,v 1.7 2017/01/11 22:56:50 tg Exp $ */
5 * (C) 1992 Joseph H. Allen
7 * This file is part of JOE (Joe's Own Editor)
26 extern int dspasis; /* Set to display chars above 127 as-is */
27 extern int staen; /* 0 if top-most status line not displayed */
29 /* Count no. of main windows */
31 int countmain(SCREEN *t)
34 W *m = t->curwin->main;
37 for (q = t->curwin->link.next; q != t->curwin; q = q->link.next)
49 msetI(w->t->t->updtab + w->y, 1, w->h);
50 msetI(w->t->t->syntab + w->y, -1, w->h);
53 /* Find first window in a group */
59 for (x = w; x->link.prev->main == w->main && x->link.prev != w; x = x->link.prev) ;
63 /* Determine height of a window. Returns reqh if it is set, otherwise
64 * used fixed or hh scaled to the current screen size */
73 return (((long) w->t->h - w->t->wind) * w->hh) / 1000;
76 /* Set the height of a window */
78 static void seth(W *w, int h)
85 tmpb = w->t->h - w->t->wind;
86 w->hh = (tmp + (tmpb - 1)) / tmpb;
89 /* Determine height of a family of windows. Uses 'reqh' if it's set */
96 /* Find first window in family */
99 /* Add heights of all windows in family */
100 for (w = x, h = geth(w); w->link.next != x && w->link.next->main == x->main; w = w->link.next, h += geth(w)) ;
105 /* Determine minimum height of a family */
107 static int getminh(W *w)
113 for (w = x, h = (w->fixed ? w->fixed : 2); w->link.next != x && w->link.next->main == x->main; w = w->link.next, h += (w->fixed ? w->fixed : 2)) ;
118 /* Find last window in a group */
124 for (x = w; x->link.next->main == w->main && x->link.next != w; x = x->link.next) ;
128 /* Demote group of window to end of window list. Returns true if top window
131 int demotegroup(W *w)
133 W *top = findtopw(w);
134 W *bot = findbotw(w);
138 for (w = top; w != bot; w = next) {
140 if (w == w->t->topwin) {
144 demote(W, link, w->t->topwin, w);
147 if (w == w->t->topwin)
150 demote(W, link, w->t->topwin, w);
155 /* Find last window on the screen */
161 for (x = t->topwin; x->link.next != t->topwin && x->link.next->y >= 0; x = x->link.next) ;
165 /* Create a screen object */
169 SCREEN *screate(SCRN *scrn)
171 SCREEN *t = (SCREEN *) joe_malloc(sizeof(SCREEN));
183 void sresize(SCREEN *t)
190 if (t->h - t->wind < FITHEIGHT)
191 t->wind = t->h - FITHEIGHT;
199 } while (w != t->topwin);
208 for (y = 0; y != scr->h; ++y) {
209 scr->t->updtab[y] = 1;
210 scr->t->syntab[y] = -1;
214 void scrins(B *b, long l, long n, int flg)
218 if ((w = scr->topwin) != NULL) {
221 if (w->object && w->watom->ins)
222 w->watom->ins(w->object, b, l, n, flg);
225 } while (w != scr->topwin);
229 void scrdel(B *b, long l, long n, int flg)
233 if ((w = scr->topwin) != NULL) {
236 if (w->object && w->watom->del)
237 w->watom->del(w->object, b, l, n, flg);
240 } while (w != scr->topwin);
244 /* Fit as many windows on the screen as is possible beginning with the window
245 * at topwin. Give any extra space which couldn't be used to fit in another
246 * window to the last text window on the screen. This function guarentees
247 * to fit on the window with the cursor in it (moves topwin to next group
248 * of windows until window with cursor fits on screen).
251 static int doabort(W *w, int *ret);
252 extern volatile int dostaupd;
256 int y; /* Where next window goes */
257 int left; /* Lines left on screen */
258 W *w; /* Current window we're fitting */
259 W *pw; /* Main window of previous family */
260 int req; /* Amount this family needs */
261 int adj; /* Amount family needs to be adjusted */
262 int flg = 0; /* Set if cursor window was placed on screen */
277 } while (w != t->topwin);
279 /* Fit a group of windows on the screen */
283 if (req > left) /* If group is taller than lines left */
284 adj = req - left; /* then family gets shorter */
288 /* Fit a family of windows on the screen */
290 w->ny = y; /* Set window's y position */
293 w->nh -= adj; /* Adjust main window of the group */
295 if (!w->win && w->nh < 2)
297 w->nh += doabort(w->link.next, &ret);
299 flg = 1; /* Set if we got window with cursor */
301 left -= w->nh; /* Increment y value by height of window */
302 w = w->link.next; /* Next window */
303 } while (w != t->topwin && w->main == w->link.prev->main);
304 } while (w != t->topwin && left >= FITHEIGHT);
309 /* We can't use extra space to fit a new family on, so give space to parent of
313 /* Adjust that family's children which are below the parent */
314 while ((pw = pw->link.next) != w)
317 /* Make sure the cursor window got on the screen */
319 t->topwin = findbotw(t->topwin)->link.next;
323 /* All of the windows are now on the screen. Scroll the screen to reflect what
328 if (w->y >= 0 && w->ny >= 0)
332 while (pw->link.next != t->topwin && (pw->link.next->y < 0 || pw->link.next->ny < 0 || pw->link.next->ny > pw->link.next->y)) {
334 if (pw->ny >= 0 && pw->y >= 0)
337 /* Scroll windows between l and w */
339 if (l->ny >= 0 && l->y >= 0)
340 nscrldn(t->t, l->y, l->ny + uns_min(l->h, l->nh), l->ny - l->y);
346 } else if (w->ny < w->y) {
349 while (pw->link.next != t->topwin && (pw->link.next->y < 0 || pw->link.next->ny < 0 || pw->link.next->ny < pw->link.next->y)) {
351 if (pw->ny >= 0 && pw->y >= 0)
354 /* Scroll windows between l and w */
356 if (w->ny >= 0 && w->y >= 0)
357 nscrlup(t->t, w->ny, w->y + uns_min(w->h, w->nh), w->y - w->ny);
367 } while (w != t->topwin);
369 /* Update current height and position values */
375 w->watom->move(w->object, w->x, w->ny);
376 if (w->watom->resize)
377 w->watom->resize(w->object, w->w, w->nh);
380 msetI(t->t->updtab + w->ny, 1, w->nh);
381 msetI(t->t->syntab + w->ny, -1, w->nh);
389 } while (w != t->topwin);
392 /* Goto next window */
396 if (t->curwin->link.next != t->curwin) {
397 t->curwin = t->curwin->link.next;
398 if (t->curwin->y == -1)
405 /* Goto previous window */
409 if (t->curwin->link.prev != t->curwin) {
410 t->curwin = t->curwin->link.prev;
411 if (t->curwin->y == -1) {
412 t->topwin = findtopw(t->curwin);
426 /* If we're the last window on the screen, shrink the previous window */
427 if ((w->link.next == w->t->topwin || w->link.next->y == -1) && w != w->t->topwin)
428 return wshrink(w->link.prev->main);
430 /* Get to next variable size window */
431 for (nextw = w->link.next; nextw->fixed && nextw != w->t->topwin; nextw = nextw->link.next) ;
433 /* Is it below us, on screen and big enough to take space from? */
434 if (nextw == w->t->topwin || nextw->y == -1 || nextw->h <= FITHEIGHT)
437 /* Increase this window's height */
440 /* Decrease next window's height */
441 seth(nextw, nextw->h - 1);
455 /* If we're the last window on the screen, grow the previous window */
456 if ((w->link.next == w->t->topwin || w->link.next->y == -1) && w != w->t->topwin)
457 return wgrow(w->link.prev->main);
459 /* Is this window too small already? */
460 if (w->h <= FITHEIGHT)
463 /* Get to window below us */
464 for (nextw = w->link.next; nextw != w->t->topwin && nextw->fixed; nextw = nextw->link.next) ;
465 if (nextw == w->t->topwin)
468 /* Decrease the size of this window */
471 /* Increase the size of next window */
472 seth(nextw, nextw->h + 1);
480 /* Show all windows */
482 void wshowall(SCREEN *t)
488 /* Count no. of main windows */
494 } while (w != t->topwin);
496 /* Compute size to set each window */
497 if ((set = (t->h - t->wind) / (n ? n : 1)) < FITHEIGHT)
500 /* Set size of each variable size window */
509 seth(w, set - (h - 2));
513 } while (w != t->topwin);
519 static void wspread(SCREEN *t)
525 if (w->y >= 0 && !w->win)
528 } while (w != t->topwin);
533 if ((t->h - t->wind) / n >= FITHEIGHT)
534 n = (t->h - t->wind) / n;
545 seth(w, n - (h - 2));
549 } while (w != t->topwin);
553 /* Show just one family of windows */
561 seth(q, w->t->h - w->t->wind - (getminh(q) - 2));
565 } while (q != w->t->topwin);
569 /* Create a window */
571 W *wcreate(SCREEN *t, WATOM *watom, W *where, W *target, W *original, int height, const unsigned char *huh, int *notify)
578 /* Create the window */
579 new = (W *) joe_malloc(sizeof(W));
580 new->notify = notify;
590 new->orgwin = original;
595 /* Set window's target and family */
596 /* was: if (new->win = target) { which may be mistyped == */
597 if ((new->win = target) != NULL) { /* A subwindow */
598 new->main = target->main;
600 } else { /* A parent window */
605 /* Get space for window */
607 if (original->h - height <= 2) {
608 /* Not enough space for window */
612 seth(original, original->h - height);
615 /* Create new keyboard handler for window */
617 new->kbd = mkkbd(kmap_getcontext(watom->context, 1));
621 /* Put window on the screen */
623 enquef(W, link, where, new);
626 enqueb(W, link, t->topwin, new);
629 t->curwin = t->topwin = new;
636 /* Abort group of windows */
638 static int doabort(W *w, int *ret)
644 if (w->t->topwin == w)
645 w->t->topwin = w->link.next;
651 if ((z->win == w || z->main == w) && z->y != -2) {
652 amnt += doabort(z, ret);
655 } while (z = z->link.next, z != w->t->topwin);
657 seth(w->orgwin, geth(w->orgwin) + geth(w));
658 if (w->t->curwin == w) {
659 if (w->t->curwin->win)
660 w->t->curwin = w->t->curwin->win;
662 w->t->curwin = w->orgwin;
664 w->t->curwin = w->link.next;
666 if (qempty(W, link, w)) {
671 if (w->watom->abort && w->object) {
672 *ret = w->watom->abort(w->object);
686 /* Abort a window and its children */
700 if (lastw(t)->link.next != t->topwin)
709 /* Display a message and skip the next key */
711 static void mdisp(SCRN *t, int y, const unsigned char *s)
717 if (len <= (t->co - 1))
720 ofst = len - (t->co - 1);
721 genfmt(t, 0, y, ofst, s, 1);
730 mdisp(t, w->y + w->h - 1, w->msgb);
734 mdisp(t, w->y + ((w->h > 1 && (w->y || !staen)) ? 1 : 0), w->msgt);
739 /* Set temporary message */
741 unsigned char msgbuf[JOE_MSGBUFSIZE];
743 /* display message on bottom line of window */
744 void msgnw(W *w, const unsigned char *s)
749 void msgnwt(W *w, const unsigned char *s)
754 int urtn(BASE *b, int k)
756 if (b->parent->watom->rtn)
757 return b->parent->watom->rtn(b, k);
762 int utype(BASE *b, int k)
764 if (b->parent->watom->type)
765 return b->parent->watom->type(b, k);
770 /* Window user commands */
774 return wprev(bw->parent->t);
779 return wnext(bw->parent->t);
784 return wgrow(bw->parent);
789 return wshrink(bw->parent);
794 if (bw->parent->t->h - bw->parent->t->wind == getgrouph(bw->parent))
795 wshowall(bw->parent->t);
797 wshowone(bw->parent);
803 nredraw(bw->parent->t->t);