Start refactoring.
[screen-lua.git] / src / canvas.c
blob50752f0f8d5ce8915d14a95d95539e0c70729627
1 /* Copyright (c) 2008, 2009
2 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4 * Micah Cowan (micah@cowan.name)
5 * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
6 * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
7 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
8 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
9 * Copyright (c) 1987 Oliver Laumann
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3, or (at your option)
14 * any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program (see the file COPYING); if not, see
23 * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
26 ****************************************************************
29 #include "config.h"
30 #include "screen.h"
31 #include "extern.h"
32 #include "canvas.h"
34 extern struct display *display;
35 extern struct win *fore, *windows;
36 extern struct layer *flayer;
37 extern int captionalways;
38 extern struct LayFuncs BlankLf;
39 extern int focusminwidth, focusminheight;
41 static void
42 CanvasInitBlank(cv)
43 struct canvas *cv;
45 cv->c_blank.l_cvlist = cv;
46 cv->c_blank.l_width = cv->c_xe - cv->c_xs + 1;
47 cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1;
48 cv->c_blank.l_x = cv->c_blank.l_y = 0;
49 cv->c_blank.l_layfn = &BlankLf;
50 cv->c_blank.l_data = 0;
51 cv->c_blank.l_next = 0;
52 cv->c_blank.l_bottom = &cv->c_blank;
53 cv->c_blank.l_blocking = 0;
54 cv->c_layer = &cv->c_blank;
57 static void
58 FreePerp(pcv)
59 struct canvas *pcv;
61 struct canvas *cv;
63 if (!pcv->c_slperp)
64 return;
65 cv = pcv->c_slperp;
66 cv->c_slprev = pcv->c_slprev;
67 if (cv->c_slprev)
68 cv->c_slprev->c_slnext = cv;
69 cv->c_slback = pcv->c_slback;
70 if (cv->c_slback && cv->c_slback->c_slperp == pcv)
71 cv->c_slback->c_slperp = cv;
72 cv->c_slorient = pcv->c_slorient;
73 cv->c_slweight = pcv->c_slweight;
74 while (cv->c_slnext)
76 cv = cv->c_slnext;
77 cv->c_slorient = pcv->c_slorient;
78 cv->c_slback = pcv->c_slback;
79 cv->c_slweight = pcv->c_slweight;
81 cv->c_slnext = pcv->c_slnext;
82 if (cv->c_slnext)
83 cv->c_slnext->c_slprev = cv;
84 free(pcv);
87 void
88 FreeCanvas(cv)
89 struct canvas *cv;
91 struct viewport *vp, *nvp;
92 struct canvas **cvp;
93 struct win *p;
95 if (cv->c_slprev)
96 cv->c_slprev->c_slnext = cv->c_slnext;
97 if (cv->c_slnext)
98 cv->c_slnext->c_slprev = cv->c_slprev;
99 if (cv->c_slback && cv->c_slback->c_slperp == cv)
100 cv->c_slback->c_slperp = cv->c_slnext ? cv->c_slnext : cv->c_slprev;
101 if (cv->c_slperp)
103 while (cv->c_slperp)
104 FreeCanvas(cv->c_slperp);
105 free(cv);
106 return;
109 if (display)
111 if (D_forecv == cv)
112 D_forecv = 0;
113 /* remove from canvas chain as SetCanvasWindow might call
114 * some layer function */
115 for (cvp = &D_cvlist; *cvp ; cvp = &(*cvp)->c_next)
116 if (*cvp == cv)
118 *cvp = cv->c_next;
119 break;
122 p = cv->c_layer ? Layer2Window(cv->c_layer) : 0;
123 SetCanvasWindow(cv, 0);
124 if (p)
125 WindowChanged(p, 'u');
126 if (flayer == cv->c_layer)
127 flayer = 0;
128 for (vp = cv->c_vplist; vp; vp = nvp)
130 vp->v_canvas = 0;
131 nvp = vp->v_next;
132 vp->v_next = 0;
133 free(vp);
135 evdeq(&cv->c_captev);
136 free(cv);
140 CountCanvas(cv)
141 struct canvas *cv;
143 int num = 0;
144 for (; cv; cv = cv->c_slnext)
146 if (cv->c_slperp)
148 struct canvas *cvp;
149 int nump = 1, n;
150 for (cvp = cv->c_slperp; cvp; cvp = cvp->c_slnext)
151 if (cvp->c_slperp)
153 n = CountCanvas(cvp->c_slperp);
154 if (n > nump)
155 nump = n;
157 num += nump;
159 else
160 num++;
162 return num;
166 CountCanvasPerp(cv)
167 struct canvas *cv;
169 struct canvas *cvp;
170 int num = 1, n;
171 for (cvp = cv->c_slperp; cvp; cvp = cvp->c_slnext)
172 if (cvp->c_slperp)
174 n = CountCanvas(cvp->c_slperp);
175 if (n > num)
176 num = n;
178 return num;
181 struct canvas *
182 FindCanvas(x, y)
183 int x, y;
185 struct canvas *cv, *mcv = 0;
186 int m, mm = 0;
188 for (cv = D_cvlist; cv; cv = cv->c_next)
190 /* ye + 1 because of caption line */
191 if (x >= cv->c_xs && x <= cv->c_xe && y >= cv->c_ys && y <= cv->c_ye + 1)
192 return cv;
193 if (cv == D_forecv)
194 continue;
195 m = 0;
196 if (x >= D_forecv->c_xs && x <= D_forecv->c_xe)
198 if (x < cv->c_xs || x > cv->c_xe)
199 continue;
200 if (y < D_forecv->c_ys && y < cv->c_ys)
201 continue;
202 if (y > D_forecv->c_ye + 1 && y > cv->c_ye + 1)
203 continue;
204 if (y < cv->c_ys)
205 m = cv->c_ys - y;
206 if (y > cv->c_ye + 1)
207 m = y - (cv->c_ye + 1);
209 if (y >= D_forecv->c_ys && y <= D_forecv->c_ye + 1)
211 if (y < cv->c_ys || y > cv->c_ye + 1)
212 continue;
213 if (x < D_forecv->c_xs && x < cv->c_xs)
214 continue;
215 if (x > D_forecv->c_xe && x > cv->c_xe)
216 continue;
217 if (x < cv->c_xs)
218 m = cv->c_xs - x;
219 if (x > cv->c_xe)
220 m = x - cv->c_xe;
222 if (m && (!mm || m < mm))
224 mcv = cv;
225 mm = m;
228 return mcv ? mcv : D_forecv;
231 void
232 SetCanvasWindow(cv, wi)
233 struct canvas *cv;
234 struct win *wi;
236 struct win *p = 0, **pp;
237 struct layer *l;
238 struct canvas *cvp, **cvpp;
240 l = cv->c_layer;
241 display = cv->c_display;
243 if (l)
245 /* remove old layer */
246 for (cvpp = &l->l_cvlist; (cvp = *cvpp); cvpp = &cvp->c_lnext)
247 if (cvp == cv)
248 break;
249 ASSERT(cvp);
250 *cvpp = cvp->c_lnext;
252 p = Layer2Window(l);
253 l = cv->c_layer;
254 cv->c_layer = 0;
256 if (p && cv == D_forecv)
258 #ifdef MULTIUSER
259 ReleaseAutoWritelock(display, p);
260 #endif
261 if (p->w_silence)
263 SetTimeout(&p->w_silenceev, p->w_silencewait * 1000);
264 evenq(&p->w_silenceev);
266 D_other = fore;
267 D_fore = 0;
269 if (l->l_cvlist == 0 && (p == 0 || l != p->w_savelayer))
270 KillLayerChain(l);
273 /* find right layer to display on canvas */
274 if (wi && wi->w_type != W_TYPE_GROUP)
276 l = &wi->w_layer;
277 if (wi->w_savelayer && (wi->w_blocked || wi->w_savelayer->l_cvlist == 0))
278 l = wi->w_savelayer;
280 else
282 l = &cv->c_blank;
283 if (wi)
284 l->l_data = (char *)wi;
285 else
286 l->l_data = 0;
289 /* add our canvas to the layer's canvaslist */
290 ASSERT(l->l_cvlist != cv);
291 cv->c_lnext = l->l_cvlist;
292 l->l_cvlist = cv;
293 cv->c_layer = l;
294 cv->c_xoff = cv->c_xs;
295 cv->c_yoff = cv->c_ys;
296 RethinkViewportOffsets(cv);
298 if (flayer == 0)
299 flayer = l;
301 if (wi && wi->w_type == W_TYPE_GROUP)
303 /* auto-start windowlist on groups */
304 struct display *d = display;
305 struct layer *oldflayer = flayer;
306 flayer = l;
307 display_wlist(0, 0, wi);
308 flayer = oldflayer;
309 display = d;
312 if (wi && D_other == wi)
313 D_other = wi->w_next; /* Might be 0, but that's OK. */
314 if (cv == D_forecv)
316 D_fore = wi;
317 fore = D_fore; /* XXX ? */
318 if (wi)
320 #ifdef MULTIUSER
321 ObtainAutoWritelock(display, wi);
322 #endif
324 * Place the window at the head of the most-recently-used list
326 if (windows != wi)
328 for (pp = &windows; (p = *pp); pp = &p->w_next)
329 if (p == wi)
330 break;
331 ASSERT(p);
332 *pp = p->w_next;
333 p->w_next = windows;
334 windows = p;
335 WListLinkChanged();
341 static void
342 cv_winid_fn(ev, data)
343 struct event *ev;
344 char *data;
346 int ox, oy;
347 struct canvas *cv = (struct canvas *)data;
349 display = cv->c_display;
350 if (D_status == STATUS_ON_WIN)
352 SetTimeout(ev, 1);
353 evenq(ev);
354 return;
356 ox = D_x;
357 oy = D_y;
358 if (cv->c_ye + 1 < D_height)
359 RefreshLine(cv->c_ye + 1, 0, D_width - 1, 0);
360 if (ox != -1 && oy != -1)
361 GotoPos(ox, oy);
365 MakeDefaultCanvas()
367 struct canvas *cv;
369 ASSERT(display);
370 if ((cv = (struct canvas *)calloc(1, sizeof *cv)) == 0)
371 return -1;
372 cv->c_xs = 0;
373 cv->c_xe = D_width - 1;
374 cv->c_ys = 0;
375 cv->c_ye = D_height - 1 - (D_has_hstatus == HSTATUS_LASTLINE) - captionalways;
376 debug2("MakeDefaultCanvas 0,0 %d,%d\n", cv->c_xe, cv->c_ye);
377 cv->c_xoff = 0;
378 cv->c_yoff = 0;
379 cv->c_next = 0;
380 cv->c_display = display;
381 cv->c_vplist = 0;
382 cv->c_slnext = 0;
383 cv->c_slprev = 0;
384 cv->c_slperp = 0;
385 cv->c_slweight = 1;
386 cv->c_slback = &D_canvas;
387 D_canvas.c_slperp = cv;
388 D_canvas.c_xs = cv->c_xs;
389 D_canvas.c_xe = cv->c_xe;
390 D_canvas.c_ys = cv->c_ys;
391 D_canvas.c_ye = cv->c_ye;
392 cv->c_slorient = SLICE_UNKN;
393 cv->c_captev.type = EV_TIMEOUT;
394 cv->c_captev.data = (char *)cv;
395 cv->c_captev.handler = cv_winid_fn;
397 CanvasInitBlank(cv);
398 cv->c_lnext = 0;
400 D_cvlist = cv;
401 RethinkDisplayViewports();
402 D_forecv = cv; /* default input focus */
403 return 0;
406 static struct canvas **
407 CreateCanvasChainRec(cv, cvp)
408 struct canvas *cv;
409 struct canvas **cvp;
411 for (; cv; cv = cv->c_slnext)
413 if (cv->c_slperp)
414 cvp = CreateCanvasChainRec(cv->c_slperp, cvp);
415 else
417 *cvp = cv;
418 cvp = &cv->c_next;
421 return cvp;
424 void
425 RecreateCanvasChain()
427 struct canvas **cvp;
428 cvp = CreateCanvasChainRec(D_canvas.c_slperp, &D_cvlist);
429 *cvp = 0;
432 void
433 EqualizeCanvas(cv, gflag)
434 struct canvas *cv;
435 int gflag;
437 struct canvas *cv2;
438 for (; cv; cv = cv->c_slnext)
440 if (cv->c_slperp && gflag)
442 cv->c_slweight = CountCanvasPerp(cv);
443 for (cv2 = cv->c_slperp; cv2; cv2 = cv2->c_slnext)
444 if (cv2->c_slperp)
445 EqualizeCanvas(cv2->c_slperp, gflag);
447 else
448 cv->c_slweight = 1;
452 void
453 ResizeCanvas(cv)
454 struct canvas *cv;
456 struct canvas *cv2, *cvn, *fcv;
457 int nh, i, maxi, hh, m, w, wsum;
458 int need, got;
459 int xs, ys, xe, ye;
460 int focusmin = 0;
462 xs = cv->c_xs;
463 ys = cv->c_ys;
464 xe = cv->c_xe;
465 ye = cv->c_ye;
466 cv = cv->c_slperp;
467 debug2("ResizeCanvas: %d,%d", xs, ys);
468 debug2(" %d,%d\n", xe, ye);
469 if (cv == 0)
470 return;
471 if (cv->c_slorient == SLICE_UNKN)
473 ASSERT(!cv->c_slnext && !cv->c_slperp);
474 cv->c_xs = xs;
475 cv->c_xe = xe;
476 cv->c_ys = ys;
477 cv->c_ye = ye;
478 cv->c_xoff = cv->c_xs;
479 cv->c_yoff = cv->c_ys;
480 cv->c_blank.l_width = cv->c_xe - cv->c_xs + 1;
481 cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1;
482 return;
485 fcv = 0;
486 if (focusminwidth || focusminheight)
488 debug("searching for focus canvas\n");
489 cv2 = D_forecv;
490 while (cv2->c_slback)
492 if (cv2->c_slback == cv->c_slback)
494 fcv = cv2;
495 focusmin = cv->c_slorient == SLICE_VERT ? focusminheight : focusminwidth;
496 if (focusmin > 0)
497 focusmin--;
498 else if (focusmin < 0)
499 focusmin = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2;
500 debug1("found, focusmin=%d\n", focusmin);
502 cv2 = cv2->c_slback;
505 if (focusmin)
507 m = CountCanvas(cv) * 2;
508 nh = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2;
509 nh -= m;
510 if (nh < 0)
511 nh = 0;
512 if (focusmin > nh)
513 focusmin = nh;
514 debug1("corrected to %d\n", focusmin);
517 /* pass 1: calculate weight sum */
518 for (cv2 = cv, wsum = 0; cv2; cv2 = cv2->c_slnext)
520 debug1(" weight %d\n", cv2->c_slweight);
521 wsum += cv2->c_slweight;
523 debug1("wsum = %d\n", wsum);
524 if (wsum == 0)
525 wsum = 1;
526 w = wsum;
528 /* pass 2: calculate need/excess space */
529 nh = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2;
530 for (cv2 = cv, need = got = 0; cv2; cv2 = cv2->c_slnext)
532 m = cv2->c_slperp ? CountCanvasPerp(cv2) * 2 - 1 : 1;
533 if (cv2 == fcv)
534 m += focusmin;
535 hh = cv2->c_slweight ? nh * cv2->c_slweight / w : 0;
536 w -= cv2->c_slweight;
537 nh -= hh;
538 debug2(" should %d min %d\n", hh, m);
539 if (hh <= m + 1)
540 need += m + 1 - hh;
541 else
542 got += hh - m - 1;
544 debug2("need: %d, got %d\n", need, got);
545 if (need > got)
546 need = got;
548 /* pass 3: distribute space */
549 nh = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2;
550 i = cv->c_slorient == SLICE_VERT ? ys : xs;
551 maxi = cv->c_slorient == SLICE_VERT ? ye : xe;
552 w = wsum;
553 for (; cv; cv = cvn)
555 cvn = cv->c_slnext;
556 if (i > maxi)
558 if (cv->c_slprev && !cv->c_slback->c_slback && !cv->c_slprev->c_slperp && !cv->c_slprev->c_slprev)
560 cv->c_slprev->c_slorient = SLICE_UNKN;
561 if (!captionalways)
563 cv->c_slback->c_ye++;
564 cv->c_slprev->c_ye++;
567 SetCanvasWindow(cv, 0);
568 FreeCanvas(cv);
569 continue;
571 m = cv->c_slperp ? CountCanvasPerp(cv) * 2 - 1 : 1;
572 if (cv == fcv)
573 m += focusmin;
574 hh = cv->c_slweight ? nh * cv->c_slweight / w : 0;
575 w -= cv->c_slweight;
576 nh -= hh;
577 debug2(" should %d min %d\n", hh, m);
578 if (hh <= m + 1)
580 hh = m + 1;
581 debug1(" -> %d\n", hh);
583 else
585 int hx = need * (hh - m - 1) / got;
586 debug3(" -> %d - %d = %d\n", hh, hx, hh - hx);
587 got -= (hh - m - 1);
588 hh -= hx;
589 need -= hx;
590 debug2(" now need=%d got=%d\n", need, got);
592 ASSERT(hh >= m + 1);
593 /* hh is window size plus pation line */
594 if (i + hh > maxi + 2)
596 hh = maxi + 2 - i;
597 debug1(" not enough space, reducing to %d\n", hh);
599 if (i + hh == maxi + 1)
601 hh++;
602 debug(" incrementing as no other canvas will fit\n");
604 if (cv->c_slorient == SLICE_VERT)
606 cv->c_xs = xs;
607 cv->c_xe = xe;
608 cv->c_ys = i;
609 cv->c_ye = i + hh - 2;
610 cv->c_xoff = xs;
611 cv->c_yoff = i;
613 else
615 cv->c_xs = i;
616 cv->c_xe = i + hh - 2;
617 cv->c_ys = ys;
618 cv->c_ye = ye;
619 cv->c_xoff = i;
620 cv->c_yoff = ys;
622 cv->c_xoff = cv->c_xs;
623 cv->c_yoff = cv->c_ys;
624 cv->c_blank.l_width = cv->c_xe - cv->c_xs + 1;
625 cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1;
626 if (cv->c_slperp)
628 ResizeCanvas(cv);
629 if (!cv->c_slperp->c_slnext)
631 debug("deleting perp node\n");
632 FreePerp(cv->c_slperp);
633 FreePerp(cv);
636 i += hh;
640 static struct canvas *
641 AddPerp(cv)
642 struct canvas *cv;
644 struct canvas *pcv;
645 debug("Creating new perp node\n");
647 if ((pcv = (struct canvas *)calloc(1, sizeof *cv)) == 0)
648 return 0;
649 pcv->c_next = 0;
650 pcv->c_display = cv->c_display;
651 pcv->c_slnext = cv->c_slnext;
652 pcv->c_slprev = cv->c_slprev;
653 pcv->c_slperp = cv;
654 pcv->c_slback = cv->c_slback;
655 if (cv->c_slback && cv->c_slback->c_slperp == cv)
656 cv->c_slback->c_slperp = pcv;
657 pcv->c_slorient = cv->c_slorient;
658 pcv->c_xoff = 0;
659 pcv->c_yoff = 0;
660 pcv->c_xs = cv->c_xs;
661 pcv->c_xe = cv->c_xe;
662 pcv->c_ys = cv->c_ys;
663 pcv->c_ye = cv->c_ye;
664 if (pcv->c_slnext)
665 pcv->c_slnext->c_slprev = pcv;
666 if (pcv->c_slprev)
667 pcv->c_slprev->c_slnext = pcv;
668 pcv->c_slweight = cv->c_slweight;
669 CanvasInitBlank(pcv);
670 cv->c_slweight = 1;
671 cv->c_slnext = 0;
672 cv->c_slprev = 0;
673 cv->c_slperp = 0;
674 cv->c_slback = pcv;
675 cv->c_slorient = SLICE_UNKN;
676 return pcv;
680 AddCanvas(orient)
681 int orient;
683 struct canvas *cv;
684 int xs, xe, ys, ye;
685 int h, num;
687 cv = D_forecv;
688 debug2("AddCanvas orient %d, forecv is %d\n", orient, cv->c_slorient);
690 if (cv->c_slorient != SLICE_UNKN && cv->c_slorient != orient)
691 if (!AddPerp(cv))
692 return -1;
694 cv = D_forecv;
695 xs = cv->c_slback->c_xs;
696 xe = cv->c_slback->c_xe;
697 ys = cv->c_slback->c_ys;
698 ye = cv->c_slback->c_ye;
699 if (!captionalways && cv == D_canvas.c_slperp && !cv->c_slnext)
700 ye--; /* need space for caption */
701 debug2("Adding Canvas to slice %d,%d ", xs, ys);
702 debug2("%d,%d\n", xe, ye);
704 num = CountCanvas(cv->c_slback->c_slperp) + 1;
705 debug1("Num = %d\n", num);
706 if (orient == SLICE_VERT)
707 h = ye - ys + 1;
708 else
709 h = xe - xs + 1;
711 h -= 2 * num - 1;
712 if (h < 0)
713 return -1; /* can't fit in */
715 if ((cv = (struct canvas *)calloc(1, sizeof *cv)) == 0)
716 return -1;
718 D_forecv->c_slback->c_ye = ye; /* in case we modified it above */
719 D_forecv->c_slorient = orient; /* in case it was UNKN */
720 cv->c_slnext = D_forecv->c_slnext;
721 cv->c_slprev = D_forecv;
722 D_forecv->c_slnext = cv;
723 if (cv->c_slnext)
724 cv->c_slnext->c_slprev = cv;
725 cv->c_slorient = orient;
726 cv->c_slback = D_forecv->c_slback;
728 cv->c_xs = xs;
729 cv->c_xe = xe;
730 cv->c_ys = ys;
731 cv->c_ye = ye;
732 cv->c_xoff = 0;
733 cv->c_yoff = 0;
734 cv->c_display = display;
735 cv->c_vplist = 0;
736 cv->c_captev.type = EV_TIMEOUT;
737 cv->c_captev.data = (char *)cv;
738 cv->c_captev.handler = cv_winid_fn;
740 CanvasInitBlank(cv);
741 cv->c_lnext = 0;
743 cv->c_next = 0;
745 cv = cv->c_slback;
746 EqualizeCanvas(cv->c_slperp, 0);
747 ResizeCanvas(cv);
748 RecreateCanvasChain();
749 RethinkDisplayViewports();
750 ResizeLayersToCanvases();
751 return 0;
754 void
755 RemCanvas()
757 int xs, xe, ys, ye;
758 struct canvas *cv;
760 debug("RemCanvas\n");
761 cv = D_forecv;
762 if (cv->c_slorient == SLICE_UNKN)
763 return;
764 while (cv->c_slprev)
765 cv = cv->c_slprev;
766 if (!cv->c_slnext)
767 return;
768 if (!cv->c_slnext->c_slnext && cv->c_slback->c_slback)
770 /* two canvases in slice, kill perp node */
771 cv = D_forecv;
772 debug("deleting perp node\n");
773 FreePerp(cv->c_slprev ? cv->c_slprev : cv->c_slnext);
774 FreePerp(cv->c_slback);
776 xs = cv->c_slback->c_xs;
777 xe = cv->c_slback->c_xe;
778 ys = cv->c_slback->c_ys;
779 ye = cv->c_slback->c_ye;
780 /* free canvas */
781 cv = D_forecv;
782 D_forecv = cv->c_slprev;
783 if (!D_forecv)
784 D_forecv = cv->c_slnext;
785 FreeCanvas(cv);
787 cv = D_forecv;
788 while (D_forecv->c_slperp)
789 D_forecv = D_forecv->c_slperp;
791 /* if only one canvas left, set orient back to unknown */
792 if (!cv->c_slnext && !cv->c_slprev && !cv->c_slback->c_slback && !cv->c_slperp)
794 cv->c_slorient = SLICE_UNKN;
795 if (!captionalways)
796 cv->c_slback->c_ye = ++ye; /* caption line no longer needed */
798 cv = cv->c_slback;
799 EqualizeCanvas(cv->c_slperp, 0);
800 ResizeCanvas(cv);
802 D_fore = Layer2Window(D_forecv->c_layer);
803 flayer = D_forecv->c_layer;
805 RecreateCanvasChain();
806 RethinkDisplayViewports();
807 ResizeLayersToCanvases();
810 void
811 OneCanvas()
813 struct canvas *cv = D_forecv, *ocv = 0;
815 if (cv->c_slprev)
817 ocv = cv->c_slprev;
818 cv->c_slprev->c_slnext = cv->c_slnext;
820 if (cv->c_slnext)
822 ocv = cv->c_slnext;
823 cv->c_slnext->c_slprev = cv->c_slprev;
825 if (!ocv)
826 return;
827 if (cv->c_slback && cv->c_slback->c_slperp == cv)
828 cv->c_slback->c_slperp = ocv;
829 cv->c_slorient = SLICE_UNKN;
830 while (D_canvas.c_slperp)
831 FreeCanvas(D_canvas.c_slperp);
832 cv = D_forecv;
833 D_canvas.c_slperp = cv;
834 cv->c_slback = &D_canvas;
835 cv->c_slnext = 0;
836 cv->c_slprev = 0;
837 ASSERT(!cv->c_slperp);
838 if (!captionalways)
839 D_canvas.c_ye++; /* caption line no longer needed */
840 ResizeCanvas(&D_canvas);
841 RecreateCanvasChain();
842 RethinkDisplayViewports();
843 ResizeLayersToCanvases();
846 void
847 DupLayoutCv(cvf, cvt, save)
848 struct canvas *cvf, *cvt;
849 int save;
851 while(cvf)
853 cvt->c_slorient = cvf->c_slorient;
854 cvt->c_slweight = cvf->c_slweight;
855 if (cvf == D_forecv)
856 D_forecv = cvt;
857 if (!save)
859 cvt->c_display = display;
860 if (!cvf->c_slperp)
862 cvt->c_captev.type = EV_TIMEOUT;
863 cvt->c_captev.data = (char *)cvt;
864 cvt->c_captev.handler = cv_winid_fn;
865 cvt->c_blank.l_cvlist = 0;
866 cvt->c_blank.l_layfn = &BlankLf;
867 cvt->c_blank.l_bottom = &cvt->c_blank;
869 cvt->c_layer = cvf->c_layer;
871 else
873 struct win *p = cvf->c_layer ? Layer2Window(cvf->c_layer) : 0;
874 cvt->c_layer = p ? &p->w_layer : 0;
876 if (cvf->c_slperp)
878 cvt->c_slperp = (struct canvas *)calloc(1, sizeof(struct canvas));
879 cvt->c_slperp->c_slback = cvt;
880 CanvasInitBlank(cvt->c_slperp);
881 DupLayoutCv(cvf->c_slperp, cvt->c_slperp, save);
883 if (cvf->c_slnext)
885 cvt->c_slnext = (struct canvas *)calloc(1, sizeof(struct canvas));
886 cvt->c_slnext->c_slprev = cvt;
887 cvt->c_slnext->c_slback = cvt->c_slback;
888 CanvasInitBlank(cvt->c_slnext);
890 cvf = cvf->c_slnext;
891 cvt = cvt->c_slnext;