Changelog the last few changes.
[screen-lua.git] / src / canvas.c
blob4cc4fe2ae84a71f23516d21ac09166ce5e8ad13f
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 LayerCleanupMemory(&pcv->c_blank);
85 free(pcv);
88 void
89 FreeCanvas(cv)
90 struct canvas *cv;
92 struct viewport *vp, *nvp;
93 struct canvas **cvp;
94 struct win *p;
96 if (cv->c_slprev)
97 cv->c_slprev->c_slnext = cv->c_slnext;
98 if (cv->c_slnext)
99 cv->c_slnext->c_slprev = cv->c_slprev;
100 if (cv->c_slback && cv->c_slback->c_slperp == cv)
101 cv->c_slback->c_slperp = cv->c_slnext ? cv->c_slnext : cv->c_slprev;
102 if (cv->c_slperp)
104 while (cv->c_slperp)
105 FreeCanvas(cv->c_slperp);
106 LayerCleanupMemory(&cv->c_blank);
107 free(cv);
108 return;
111 if (display)
113 if (D_forecv == cv)
114 D_forecv = 0;
115 /* remove from canvas chain as SetCanvasWindow might call
116 * some layer function */
117 for (cvp = &D_cvlist; *cvp ; cvp = &(*cvp)->c_next)
118 if (*cvp == cv)
120 *cvp = cv->c_next;
121 break;
124 p = cv->c_layer ? Layer2Window(cv->c_layer) : 0;
125 SetCanvasWindow(cv, 0);
126 if (p)
127 WindowChanged(p, 'u');
128 if (flayer == cv->c_layer)
129 flayer = 0;
130 for (vp = cv->c_vplist; vp; vp = nvp)
132 vp->v_canvas = 0;
133 nvp = vp->v_next;
134 vp->v_next = 0;
135 free(vp);
137 evdeq(&cv->c_captev);
138 LayerCleanupMemory(&cv->c_blank);
139 free(cv);
143 CountCanvas(cv)
144 struct canvas *cv;
146 int num = 0;
147 for (; cv; cv = cv->c_slnext)
149 if (cv->c_slperp)
151 struct canvas *cvp;
152 int nump = 1, n;
153 for (cvp = cv->c_slperp; cvp; cvp = cvp->c_slnext)
154 if (cvp->c_slperp)
156 n = CountCanvas(cvp->c_slperp);
157 if (n > nump)
158 nump = n;
160 num += nump;
162 else
163 num++;
165 return num;
169 CountCanvasPerp(cv)
170 struct canvas *cv;
172 struct canvas *cvp;
173 int num = 1, n;
174 for (cvp = cv->c_slperp; cvp; cvp = cvp->c_slnext)
175 if (cvp->c_slperp)
177 n = CountCanvas(cvp->c_slperp);
178 if (n > num)
179 num = n;
181 return num;
184 struct canvas *
185 FindCanvas(x, y)
186 int x, y;
188 struct canvas *cv, *mcv = 0;
189 int m, mm = 0;
191 for (cv = D_cvlist; cv; cv = cv->c_next)
193 /* ye + 1 because of caption line */
194 if (x >= cv->c_xs && x <= cv->c_xe && y >= cv->c_ys && y <= cv->c_ye + 1)
195 return cv;
196 if (cv == D_forecv)
197 continue;
198 m = 0;
199 if (x >= D_forecv->c_xs && x <= D_forecv->c_xe)
201 if (x < cv->c_xs || x > cv->c_xe)
202 continue;
203 if (y < D_forecv->c_ys && y < cv->c_ys)
204 continue;
205 if (y > D_forecv->c_ye + 1 && y > cv->c_ye + 1)
206 continue;
207 if (y < cv->c_ys)
208 m = cv->c_ys - y;
209 if (y > cv->c_ye + 1)
210 m = y - (cv->c_ye + 1);
212 if (y >= D_forecv->c_ys && y <= D_forecv->c_ye + 1)
214 if (y < cv->c_ys || y > cv->c_ye + 1)
215 continue;
216 if (x < D_forecv->c_xs && x < cv->c_xs)
217 continue;
218 if (x > D_forecv->c_xe && x > cv->c_xe)
219 continue;
220 if (x < cv->c_xs)
221 m = cv->c_xs - x;
222 if (x > cv->c_xe)
223 m = x - cv->c_xe;
225 if (m && (!mm || m < mm))
227 mcv = cv;
228 mm = m;
231 return mcv ? mcv : D_forecv;
234 void
235 SetCanvasWindow(cv, wi)
236 struct canvas *cv;
237 struct win *wi;
239 struct win *p = 0, **pp;
240 struct layer *l;
241 struct canvas *cvp, **cvpp;
243 l = cv->c_layer;
244 display = cv->c_display;
246 if (l)
248 /* remove old layer */
249 for (cvpp = &l->l_cvlist; (cvp = *cvpp); cvpp = &cvp->c_lnext)
250 if (cvp == cv)
251 break;
252 ASSERT(cvp);
253 *cvpp = cvp->c_lnext;
255 p = Layer2Window(l);
256 l = cv->c_layer;
257 cv->c_layer = 0;
259 if (p && cv == D_forecv)
261 #ifdef MULTIUSER
262 ReleaseAutoWritelock(display, p);
263 #endif
264 if (p->w_silence)
266 SetTimeout(&p->w_silenceev, p->w_silencewait * 1000);
267 evenq(&p->w_silenceev);
269 D_other = fore;
270 D_fore = 0;
272 if (l->l_cvlist == 0 && (p == 0 || l != p->w_savelayer))
273 KillLayerChain(l);
276 /* find right layer to display on canvas */
277 if (wi && wi->w_type != W_TYPE_GROUP)
279 l = &wi->w_layer;
280 if (wi->w_savelayer && (wi->w_blocked || wi->w_savelayer->l_cvlist == 0))
281 l = wi->w_savelayer;
283 else
285 l = &cv->c_blank;
286 if (wi)
287 l->l_data = (char *)wi;
288 else
289 l->l_data = 0;
292 /* add our canvas to the layer's canvaslist */
293 ASSERT(l->l_cvlist != cv);
294 cv->c_lnext = l->l_cvlist;
295 l->l_cvlist = cv;
296 cv->c_layer = l;
297 cv->c_xoff = cv->c_xs;
298 cv->c_yoff = cv->c_ys;
299 RethinkViewportOffsets(cv);
301 if (flayer == 0)
302 flayer = l;
304 if (wi && wi->w_type == W_TYPE_GROUP)
306 /* auto-start windowlist on groups */
307 struct display *d = display;
308 struct layer *oldflayer = flayer;
309 flayer = l;
310 display_wlist(0, 0, wi);
311 flayer = oldflayer;
312 display = d;
315 if (wi && D_other == wi)
316 D_other = wi->w_next; /* Might be 0, but that's OK. */
317 if (cv == D_forecv)
319 D_fore = wi;
320 fore = D_fore; /* XXX ? */
321 if (wi)
323 #ifdef MULTIUSER
324 ObtainAutoWritelock(display, wi);
325 #endif
327 * Place the window at the head of the most-recently-used list
329 if (windows != wi)
331 for (pp = &windows; (p = *pp); pp = &p->w_next)
332 if (p == wi)
333 break;
334 ASSERT(p);
335 *pp = p->w_next;
336 p->w_next = windows;
337 windows = p;
338 WListLinkChanged();
344 static void
345 cv_winid_fn(ev, data)
346 struct event *ev;
347 char *data;
349 int ox, oy;
350 struct canvas *cv = (struct canvas *)data;
352 display = cv->c_display;
353 if (D_status == STATUS_ON_WIN)
355 SetTimeout(ev, 1);
356 evenq(ev);
357 return;
359 ox = D_x;
360 oy = D_y;
361 if (cv->c_ye + 1 < D_height)
362 RefreshLine(cv->c_ye + 1, 0, D_width - 1, 0);
363 if (ox != -1 && oy != -1)
364 GotoPos(ox, oy);
368 MakeDefaultCanvas()
370 struct canvas *cv;
372 ASSERT(display);
373 if ((cv = (struct canvas *)calloc(1, sizeof *cv)) == 0)
374 return -1;
375 cv->c_xs = 0;
376 cv->c_xe = D_width - 1;
377 cv->c_ys = 0;
378 cv->c_ye = D_height - 1 - (D_has_hstatus == HSTATUS_LASTLINE) - captionalways;
379 debug2("MakeDefaultCanvas 0,0 %d,%d\n", cv->c_xe, cv->c_ye);
380 cv->c_xoff = 0;
381 cv->c_yoff = 0;
382 cv->c_next = 0;
383 cv->c_display = display;
384 cv->c_vplist = 0;
385 cv->c_slnext = 0;
386 cv->c_slprev = 0;
387 cv->c_slperp = 0;
388 cv->c_slweight = 1;
389 cv->c_slback = &D_canvas;
390 D_canvas.c_slperp = cv;
391 D_canvas.c_xs = cv->c_xs;
392 D_canvas.c_xe = cv->c_xe;
393 D_canvas.c_ys = cv->c_ys;
394 D_canvas.c_ye = cv->c_ye;
395 cv->c_slorient = SLICE_UNKN;
396 cv->c_captev.type = EV_TIMEOUT;
397 cv->c_captev.data = (char *)cv;
398 cv->c_captev.handler = cv_winid_fn;
400 CanvasInitBlank(cv);
401 cv->c_lnext = 0;
403 D_cvlist = cv;
404 RethinkDisplayViewports();
405 D_forecv = cv; /* default input focus */
406 return 0;
409 static struct canvas **
410 CreateCanvasChainRec(cv, cvp)
411 struct canvas *cv;
412 struct canvas **cvp;
414 for (; cv; cv = cv->c_slnext)
416 if (cv->c_slperp)
417 cvp = CreateCanvasChainRec(cv->c_slperp, cvp);
418 else
420 *cvp = cv;
421 cvp = &cv->c_next;
424 return cvp;
427 void
428 RecreateCanvasChain()
430 struct canvas **cvp;
431 cvp = CreateCanvasChainRec(D_canvas.c_slperp, &D_cvlist);
432 *cvp = 0;
435 void
436 EqualizeCanvas(cv, gflag)
437 struct canvas *cv;
438 int gflag;
440 struct canvas *cv2;
441 for (; cv; cv = cv->c_slnext)
443 if (cv->c_slperp && gflag)
445 cv->c_slweight = CountCanvasPerp(cv);
446 for (cv2 = cv->c_slperp; cv2; cv2 = cv2->c_slnext)
447 if (cv2->c_slperp)
448 EqualizeCanvas(cv2->c_slperp, gflag);
450 else
451 cv->c_slweight = 1;
455 void
456 ResizeCanvas(cv)
457 struct canvas *cv;
459 struct canvas *cv2, *cvn, *fcv;
460 int nh, i, maxi, hh, m, w, wsum;
461 int need, got;
462 int xs, ys, xe, ye;
463 int focusmin = 0;
465 xs = cv->c_xs;
466 ys = cv->c_ys;
467 xe = cv->c_xe;
468 ye = cv->c_ye;
469 cv = cv->c_slperp;
470 debug2("ResizeCanvas: %d,%d", xs, ys);
471 debug2(" %d,%d\n", xe, ye);
472 if (cv == 0)
473 return;
474 if (cv->c_slorient == SLICE_UNKN)
476 ASSERT(!cv->c_slnext && !cv->c_slperp);
477 cv->c_xs = xs;
478 cv->c_xe = xe;
479 cv->c_ys = ys;
480 cv->c_ye = ye;
481 cv->c_xoff = cv->c_xs;
482 cv->c_yoff = cv->c_ys;
483 cv->c_blank.l_width = cv->c_xe - cv->c_xs + 1;
484 cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1;
485 return;
488 fcv = 0;
489 if (focusminwidth || focusminheight)
491 debug("searching for focus canvas\n");
492 cv2 = D_forecv;
493 while (cv2->c_slback)
495 if (cv2->c_slback == cv->c_slback)
497 fcv = cv2;
498 focusmin = cv->c_slorient == SLICE_VERT ? focusminheight : focusminwidth;
499 if (focusmin > 0)
500 focusmin--;
501 else if (focusmin < 0)
502 focusmin = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2;
503 debug1("found, focusmin=%d\n", focusmin);
505 cv2 = cv2->c_slback;
508 if (focusmin)
510 m = CountCanvas(cv) * 2;
511 nh = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2;
512 nh -= m;
513 if (nh < 0)
514 nh = 0;
515 if (focusmin > nh)
516 focusmin = nh;
517 debug1("corrected to %d\n", focusmin);
520 /* pass 1: calculate weight sum */
521 for (cv2 = cv, wsum = 0; cv2; cv2 = cv2->c_slnext)
523 debug1(" weight %d\n", cv2->c_slweight);
524 wsum += cv2->c_slweight;
526 debug1("wsum = %d\n", wsum);
527 if (wsum == 0)
528 wsum = 1;
529 w = wsum;
531 /* pass 2: calculate need/excess space */
532 nh = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2;
533 for (cv2 = cv, need = got = 0; cv2; cv2 = cv2->c_slnext)
535 m = cv2->c_slperp ? CountCanvasPerp(cv2) * 2 - 1 : 1;
536 if (cv2 == fcv)
537 m += focusmin;
538 hh = cv2->c_slweight ? nh * cv2->c_slweight / w : 0;
539 w -= cv2->c_slweight;
540 nh -= hh;
541 debug2(" should %d min %d\n", hh, m);
542 if (hh <= m + 1)
543 need += m + 1 - hh;
544 else
545 got += hh - m - 1;
547 debug2("need: %d, got %d\n", need, got);
548 if (need > got)
549 need = got;
551 /* pass 3: distribute space */
552 nh = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2;
553 i = cv->c_slorient == SLICE_VERT ? ys : xs;
554 maxi = cv->c_slorient == SLICE_VERT ? ye : xe;
555 w = wsum;
556 for (; cv; cv = cvn)
558 cvn = cv->c_slnext;
559 if (i > maxi)
561 if (cv->c_slprev && !cv->c_slback->c_slback && !cv->c_slprev->c_slperp && !cv->c_slprev->c_slprev)
563 cv->c_slprev->c_slorient = SLICE_UNKN;
564 if (!captionalways)
566 cv->c_slback->c_ye++;
567 cv->c_slprev->c_ye++;
570 SetCanvasWindow(cv, 0);
571 FreeCanvas(cv);
572 continue;
574 m = cv->c_slperp ? CountCanvasPerp(cv) * 2 - 1 : 1;
575 if (cv == fcv)
576 m += focusmin;
577 hh = cv->c_slweight ? nh * cv->c_slweight / w : 0;
578 w -= cv->c_slweight;
579 nh -= hh;
580 debug2(" should %d min %d\n", hh, m);
581 if (hh <= m + 1)
583 hh = m + 1;
584 debug1(" -> %d\n", hh);
586 else
588 int hx = need * (hh - m - 1) / got;
589 debug3(" -> %d - %d = %d\n", hh, hx, hh - hx);
590 got -= (hh - m - 1);
591 hh -= hx;
592 need -= hx;
593 debug2(" now need=%d got=%d\n", need, got);
595 ASSERT(hh >= m + 1);
596 /* hh is window size plus pation line */
597 if (i + hh > maxi + 2)
599 hh = maxi + 2 - i;
600 debug1(" not enough space, reducing to %d\n", hh);
602 if (i + hh == maxi + 1)
604 hh++;
605 debug(" incrementing as no other canvas will fit\n");
607 if (cv->c_slorient == SLICE_VERT)
609 cv->c_xs = xs;
610 cv->c_xe = xe;
611 cv->c_ys = i;
612 cv->c_ye = i + hh - 2;
613 cv->c_xoff = xs;
614 cv->c_yoff = i;
616 else
618 cv->c_xs = i;
619 cv->c_xe = i + hh - 2;
620 cv->c_ys = ys;
621 cv->c_ye = ye;
622 cv->c_xoff = i;
623 cv->c_yoff = ys;
625 cv->c_xoff = cv->c_xs;
626 cv->c_yoff = cv->c_ys;
627 cv->c_blank.l_width = cv->c_xe - cv->c_xs + 1;
628 cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1;
629 if (cv->c_slperp)
631 ResizeCanvas(cv);
632 if (!cv->c_slperp->c_slnext)
634 debug("deleting perp node\n");
635 FreePerp(cv->c_slperp);
636 FreePerp(cv);
639 i += hh;
643 static struct canvas *
644 AddPerp(cv)
645 struct canvas *cv;
647 struct canvas *pcv;
648 debug("Creating new perp node\n");
650 if ((pcv = (struct canvas *)calloc(1, sizeof *cv)) == 0)
651 return 0;
652 pcv->c_next = 0;
653 pcv->c_display = cv->c_display;
654 pcv->c_slnext = cv->c_slnext;
655 pcv->c_slprev = cv->c_slprev;
656 pcv->c_slperp = cv;
657 pcv->c_slback = cv->c_slback;
658 if (cv->c_slback && cv->c_slback->c_slperp == cv)
659 cv->c_slback->c_slperp = pcv;
660 pcv->c_slorient = cv->c_slorient;
661 pcv->c_xoff = 0;
662 pcv->c_yoff = 0;
663 pcv->c_xs = cv->c_xs;
664 pcv->c_xe = cv->c_xe;
665 pcv->c_ys = cv->c_ys;
666 pcv->c_ye = cv->c_ye;
667 if (pcv->c_slnext)
668 pcv->c_slnext->c_slprev = pcv;
669 if (pcv->c_slprev)
670 pcv->c_slprev->c_slnext = pcv;
671 pcv->c_slweight = cv->c_slweight;
672 CanvasInitBlank(pcv);
673 cv->c_slweight = 1;
674 cv->c_slnext = 0;
675 cv->c_slprev = 0;
676 cv->c_slperp = 0;
677 cv->c_slback = pcv;
678 cv->c_slorient = SLICE_UNKN;
679 return pcv;
683 AddCanvas(orient)
684 int orient;
686 struct canvas *cv;
687 int xs, xe, ys, ye;
688 int h, num;
690 cv = D_forecv;
691 debug2("AddCanvas orient %d, forecv is %d\n", orient, cv->c_slorient);
693 if (cv->c_slorient != SLICE_UNKN && cv->c_slorient != orient)
694 if (!AddPerp(cv))
695 return -1;
697 cv = D_forecv;
698 xs = cv->c_slback->c_xs;
699 xe = cv->c_slback->c_xe;
700 ys = cv->c_slback->c_ys;
701 ye = cv->c_slback->c_ye;
702 if (!captionalways && cv == D_canvas.c_slperp && !cv->c_slnext)
703 ye--; /* need space for caption */
704 debug2("Adding Canvas to slice %d,%d ", xs, ys);
705 debug2("%d,%d\n", xe, ye);
707 num = CountCanvas(cv->c_slback->c_slperp) + 1;
708 debug1("Num = %d\n", num);
709 if (orient == SLICE_VERT)
710 h = ye - ys + 1;
711 else
712 h = xe - xs + 1;
714 h -= 2 * num - 1;
715 if (h < 0)
716 return -1; /* can't fit in */
718 if ((cv = (struct canvas *)calloc(1, sizeof *cv)) == 0)
719 return -1;
721 D_forecv->c_slback->c_ye = ye; /* in case we modified it above */
722 D_forecv->c_slorient = orient; /* in case it was UNKN */
723 cv->c_slnext = D_forecv->c_slnext;
724 cv->c_slprev = D_forecv;
725 D_forecv->c_slnext = cv;
726 if (cv->c_slnext)
727 cv->c_slnext->c_slprev = cv;
728 cv->c_slorient = orient;
729 cv->c_slback = D_forecv->c_slback;
731 cv->c_xs = xs;
732 cv->c_xe = xe;
733 cv->c_ys = ys;
734 cv->c_ye = ye;
735 cv->c_xoff = 0;
736 cv->c_yoff = 0;
737 cv->c_display = display;
738 cv->c_vplist = 0;
739 cv->c_captev.type = EV_TIMEOUT;
740 cv->c_captev.data = (char *)cv;
741 cv->c_captev.handler = cv_winid_fn;
743 CanvasInitBlank(cv);
744 cv->c_lnext = 0;
746 cv->c_next = 0;
748 cv = cv->c_slback;
749 EqualizeCanvas(cv->c_slperp, 0);
750 ResizeCanvas(cv);
751 RecreateCanvasChain();
752 RethinkDisplayViewports();
753 ResizeLayersToCanvases();
754 return 0;
757 void
758 RemCanvas()
760 int xs, xe, ys, ye;
761 struct canvas *cv;
763 debug("RemCanvas\n");
764 cv = D_forecv;
765 if (cv->c_slorient == SLICE_UNKN)
766 return;
767 while (cv->c_slprev)
768 cv = cv->c_slprev;
769 if (!cv->c_slnext)
770 return;
771 if (!cv->c_slnext->c_slnext && cv->c_slback->c_slback)
773 /* two canvases in slice, kill perp node */
774 cv = D_forecv;
775 debug("deleting perp node\n");
776 FreePerp(cv->c_slprev ? cv->c_slprev : cv->c_slnext);
777 FreePerp(cv->c_slback);
779 xs = cv->c_slback->c_xs;
780 xe = cv->c_slback->c_xe;
781 ys = cv->c_slback->c_ys;
782 ye = cv->c_slback->c_ye;
783 /* free canvas */
784 cv = D_forecv;
785 D_forecv = cv->c_slprev;
786 if (!D_forecv)
787 D_forecv = cv->c_slnext;
788 FreeCanvas(cv);
790 cv = D_forecv;
791 while (D_forecv->c_slperp)
792 D_forecv = D_forecv->c_slperp;
794 /* if only one canvas left, set orient back to unknown */
795 if (!cv->c_slnext && !cv->c_slprev && !cv->c_slback->c_slback && !cv->c_slperp)
797 cv->c_slorient = SLICE_UNKN;
798 if (!captionalways)
799 cv->c_slback->c_ye = ++ye; /* caption line no longer needed */
801 cv = cv->c_slback;
802 EqualizeCanvas(cv->c_slperp, 0);
803 ResizeCanvas(cv);
805 D_fore = Layer2Window(D_forecv->c_layer);
806 flayer = D_forecv->c_layer;
808 RecreateCanvasChain();
809 RethinkDisplayViewports();
810 ResizeLayersToCanvases();
813 void
814 OneCanvas()
816 struct canvas *cv = D_forecv, *ocv = 0;
818 if (cv->c_slprev)
820 ocv = cv->c_slprev;
821 cv->c_slprev->c_slnext = cv->c_slnext;
823 if (cv->c_slnext)
825 ocv = cv->c_slnext;
826 cv->c_slnext->c_slprev = cv->c_slprev;
828 if (!ocv)
829 return;
830 if (cv->c_slback && cv->c_slback->c_slperp == cv)
831 cv->c_slback->c_slperp = ocv;
832 cv->c_slorient = SLICE_UNKN;
833 while (D_canvas.c_slperp)
834 FreeCanvas(D_canvas.c_slperp);
835 cv = D_forecv;
836 D_canvas.c_slperp = cv;
837 cv->c_slback = &D_canvas;
838 cv->c_slnext = 0;
839 cv->c_slprev = 0;
840 ASSERT(!cv->c_slperp);
841 if (!captionalways)
842 D_canvas.c_ye++; /* caption line no longer needed */
843 ResizeCanvas(&D_canvas);
844 RecreateCanvasChain();
845 RethinkDisplayViewports();
846 ResizeLayersToCanvases();
849 void
850 DupLayoutCv(cvf, cvt, save)
851 struct canvas *cvf, *cvt;
852 int save;
854 while(cvf)
856 cvt->c_slorient = cvf->c_slorient;
857 cvt->c_slweight = cvf->c_slweight;
858 if (cvf == D_forecv)
859 D_forecv = cvt;
860 if (!save)
862 cvt->c_display = display;
863 if (!cvf->c_slperp)
865 cvt->c_captev.type = EV_TIMEOUT;
866 cvt->c_captev.data = (char *)cvt;
867 cvt->c_captev.handler = cv_winid_fn;
868 cvt->c_blank.l_cvlist = 0;
869 cvt->c_blank.l_layfn = &BlankLf;
870 cvt->c_blank.l_bottom = &cvt->c_blank;
872 cvt->c_layer = cvf->c_layer;
874 else
876 struct win *p = cvf->c_layer ? Layer2Window(cvf->c_layer) : 0;
877 cvt->c_layer = p ? &p->w_layer : 0;
879 if (cvf->c_slperp)
881 cvt->c_slperp = (struct canvas *)calloc(1, sizeof(struct canvas));
882 cvt->c_slperp->c_slback = cvt;
883 CanvasInitBlank(cvt->c_slperp);
884 DupLayoutCv(cvf->c_slperp, cvt->c_slperp, save);
886 if (cvf->c_slnext)
888 cvt->c_slnext = (struct canvas *)calloc(1, sizeof(struct canvas));
889 cvt->c_slnext->c_slprev = cvt;
890 cvt->c_slnext->c_slback = cvt->c_slback;
891 CanvasInitBlank(cvt->c_slnext);
893 cvf = cvf->c_slnext;
894 cvt = cvt->c_slnext;
898 void
899 PutWindowCv(cv)
900 struct canvas *cv;
902 struct win *p;
903 for (; cv; cv = cv->c_slnext)
905 if (cv->c_slperp)
907 PutWindowCv(cv->c_slperp);
908 continue;
910 p = cv->c_layer ? (struct win *)cv->c_layer->l_data : 0;
911 cv->c_layer = 0;
912 SetCanvasWindow(cv, p);