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
10 *
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.
15 *
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.
20 *
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 * https://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
25 *
26 ****************************************************************
27 */
28
29 #include "config.h"
30 #include "screen.h"
31 #include "extern.h"
32 #include "canvas.h"
33 #include "list_generic.h"
34
35 extern struct display *display;
36 extern struct win *fore, *windows;
37 extern struct layer *flayer;
38 extern int captionalways;
39 extern struct LayFuncs BlankLf;
40 extern int focusminwidth, focusminheight;
41
42 static void
CanvasInitBlank(cv)43 CanvasInitBlank(cv)
44 struct canvas *cv;
45 {
46 cv->c_blank.l_cvlist = cv;
47 cv->c_blank.l_width = cv->c_xe - cv->c_xs + 1;
48 cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1;
49 cv->c_blank.l_x = cv->c_blank.l_y = 0;
50 cv->c_blank.l_layfn = &BlankLf;
51 cv->c_blank.l_data = 0;
52 cv->c_blank.l_next = 0;
53 cv->c_blank.l_bottom = &cv->c_blank;
54 cv->c_blank.l_blocking = 0;
55 cv->c_layer = &cv->c_blank;
56 }
57
58 static void
FreePerp(pcv)59 FreePerp(pcv)
60 struct canvas *pcv;
61 {
62 struct canvas *cv;
63
64 if (!pcv->c_slperp)
65 return;
66 cv = pcv->c_slperp;
67 cv->c_slprev = pcv->c_slprev;
68 if (cv->c_slprev)
69 cv->c_slprev->c_slnext = cv;
70 cv->c_slback = pcv->c_slback;
71 if (cv->c_slback && cv->c_slback->c_slperp == pcv)
72 cv->c_slback->c_slperp = cv;
73 cv->c_slorient = pcv->c_slorient;
74 cv->c_slweight = pcv->c_slweight;
75 while (cv->c_slnext)
76 {
77 cv = cv->c_slnext;
78 cv->c_slorient = pcv->c_slorient;
79 cv->c_slback = pcv->c_slback;
80 cv->c_slweight = pcv->c_slweight;
81 }
82 cv->c_slnext = pcv->c_slnext;
83 if (cv->c_slnext)
84 cv->c_slnext->c_slprev = cv;
85 LayerCleanupMemory(&pcv->c_blank);
86 free(pcv);
87 }
88
89 void
FreeCanvas(cv)90 FreeCanvas(cv)
91 struct canvas *cv;
92 {
93 struct viewport *vp, *nvp;
94 struct canvas **cvp;
95 struct win *p;
96
97 if (cv->c_slprev)
98 cv->c_slprev->c_slnext = cv->c_slnext;
99 if (cv->c_slnext)
100 cv->c_slnext->c_slprev = cv->c_slprev;
101 if (cv->c_slback && cv->c_slback->c_slperp == cv)
102 cv->c_slback->c_slperp = cv->c_slnext ? cv->c_slnext : cv->c_slprev;
103 if (cv->c_slperp)
104 {
105 while (cv->c_slperp)
106 FreeCanvas(cv->c_slperp);
107 LayerCleanupMemory(&cv->c_blank);
108 free(cv);
109 return;
110 }
111
112 if (display)
113 {
114 if (D_forecv == cv)
115 D_forecv = 0;
116 /* remove from canvas chain as SetCanvasWindow might call
117 * some layer function */
118 for (cvp = &D_cvlist; *cvp ; cvp = &(*cvp)->c_next)
119 if (*cvp == cv)
120 {
121 *cvp = cv->c_next;
122 break;
123 }
124 }
125 p = cv->c_layer ? Layer2Window(cv->c_layer) : 0;
126 SetCanvasWindow(cv, 0);
127 if (p)
128 WindowChanged(p, 'u');
129 if (flayer == cv->c_layer)
130 flayer = 0;
131 for (vp = cv->c_vplist; vp; vp = nvp)
132 {
133 vp->v_canvas = 0;
134 nvp = vp->v_next;
135 vp->v_next = 0;
136 free(vp);
137 }
138 evdeq(&cv->c_captev);
139 LayerCleanupMemory(&cv->c_blank);
140 free(cv);
141 }
142
143 int
CountCanvas(cv)144 CountCanvas(cv)
145 struct canvas *cv;
146 {
147 int num = 0;
148 for (; cv; cv = cv->c_slnext)
149 {
150 if (cv->c_slperp)
151 {
152 struct canvas *cvp;
153 int nump = 1, n;
154 for (cvp = cv->c_slperp; cvp; cvp = cvp->c_slnext)
155 if (cvp->c_slperp)
156 {
157 n = CountCanvas(cvp->c_slperp);
158 if (n > nump)
159 nump = n;
160 }
161 num += nump;
162 }
163 else
164 num++;
165 }
166 return num;
167 }
168
169 int
CountCanvasPerp(cv)170 CountCanvasPerp(cv)
171 struct canvas *cv;
172 {
173 struct canvas *cvp;
174 int num = 1, n;
175 for (cvp = cv->c_slperp; cvp; cvp = cvp->c_slnext)
176 if (cvp->c_slperp)
177 {
178 n = CountCanvas(cvp->c_slperp);
179 if (n > num)
180 num = n;
181 }
182 return num;
183 }
184
185 struct canvas *
FindCanvas(x,y)186 FindCanvas(x, y)
187 int x, y;
188 {
189 struct canvas *cv, *mcv = 0;
190 int m, mm = 0;
191
192 for (cv = D_cvlist; cv; cv = cv->c_next)
193 {
194 /* ye + 1 because of caption line */
195 if (x >= cv->c_xs && x <= cv->c_xe && y >= cv->c_ys && y <= cv->c_ye + 1)
196 return cv;
197 if (cv == D_forecv)
198 continue;
199 m = 0;
200 if (x >= D_forecv->c_xs && x <= D_forecv->c_xe)
201 {
202 if (x < cv->c_xs || x > cv->c_xe)
203 continue;
204 if (y < D_forecv->c_ys && y < cv->c_ys)
205 continue;
206 if (y > D_forecv->c_ye + 1 && y > cv->c_ye + 1)
207 continue;
208 if (y < cv->c_ys)
209 m = cv->c_ys - y;
210 if (y > cv->c_ye + 1)
211 m = y - (cv->c_ye + 1);
212 }
213 if (y >= D_forecv->c_ys && y <= D_forecv->c_ye + 1)
214 {
215 if (y < cv->c_ys || y > cv->c_ye + 1)
216 continue;
217 if (x < D_forecv->c_xs && x < cv->c_xs)
218 continue;
219 if (x > D_forecv->c_xe && x > cv->c_xe)
220 continue;
221 if (x < cv->c_xs)
222 m = cv->c_xs - x;
223 if (x > cv->c_xe)
224 m = x - cv->c_xe;
225 }
226 if (m && (!mm || m < mm))
227 {
228 mcv = cv;
229 mm = m;
230 }
231 }
232 return mcv ? mcv : D_forecv;
233 }
234
235 void
SetCanvasWindow(cv,wi)236 SetCanvasWindow(cv, wi)
237 struct canvas *cv;
238 struct win *wi;
239 {
240 struct win *p = 0, **pp;
241 struct layer *l;
242 struct canvas *cvp, **cvpp;
243
244 l = cv->c_layer;
245 display = cv->c_display;
246
247 if (l)
248 {
249 /* remove old layer */
250 for (cvpp = &l->l_cvlist; (cvp = *cvpp); cvpp = &cvp->c_lnext)
251 if (cvp == cv)
252 break;
253 ASSERT(cvp);
254 *cvpp = cvp->c_lnext;
255
256 p = Layer2Window(l);
257 l = cv->c_layer;
258 cv->c_layer = 0;
259
260 if (p && cv == D_forecv)
261 {
262 #ifdef MULTIUSER
263 ReleaseAutoWritelock(display, p);
264 #endif
265 if (p->w_silence)
266 {
267 SetTimeout(&p->w_silenceev, p->w_silencewait * 1000);
268 evenq(&p->w_silenceev);
269 }
270 D_other = fore;
271 D_fore = 0;
272 }
273 if (l->l_cvlist == 0 && (p == 0 || l != p->w_savelayer))
274 KillLayerChain(l);
275 }
276
277 /* find right layer to display on canvas */
278 if (wi && wi->w_type != W_TYPE_GROUP)
279 {
280 l = &wi->w_layer;
281 if (wi->w_savelayer && (wi->w_blocked || wi->w_savelayer->l_cvlist == 0))
282 l = wi->w_savelayer;
283 }
284 else
285 {
286 l = &cv->c_blank;
287 if (wi)
288 l->l_data = (char *)wi;
289 else
290 l->l_data = 0;
291 }
292
293 /* add our canvas to the layer's canvaslist */
294 ASSERT(l->l_cvlist != cv);
295 cv->c_lnext = l->l_cvlist;
296 l->l_cvlist = cv;
297 cv->c_layer = l;
298 cv->c_xoff = cv->c_xs;
299 cv->c_yoff = cv->c_ys;
300 RethinkViewportOffsets(cv);
301
302 if (flayer == 0)
303 flayer = l;
304
305 if (wi && wi->w_type == W_TYPE_GROUP)
306 {
307 /* auto-start windowlist on groups */
308 struct display *d = display;
309 struct layer *oldflayer = flayer;
310 flayer = l;
311 display_windows(0, 0, wi);
312 flayer = oldflayer;
313 display = d;
314 }
315
316 if (wi && D_other == wi)
317 D_other = wi->w_next; /* Might be 0, but that's OK. */
318 if (cv == D_forecv)
319 {
320 D_fore = wi;
321 fore = D_fore; /* XXX ? */
322 if (wi)
323 {
324 #ifdef MULTIUSER
325 ObtainAutoWritelock(display, wi);
326 #endif
327 /*
328 * Place the window at the head of the most-recently-used list
329 */
330 if (windows != wi)
331 {
332 for (pp = &windows; (p = *pp); pp = &p->w_next)
333 if (p == wi)
334 break;
335 ASSERT(p);
336 *pp = p->w_next;
337 p->w_next = windows;
338 windows = p;
339 WListLinkChanged();
340 }
341 }
342 }
343 }
344
345 static void
cv_winid_fn(ev,data)346 cv_winid_fn(ev, data)
347 struct event *ev;
348 char *data;
349 {
350 int ox, oy;
351 struct canvas *cv = (struct canvas *)data;
352
353 display = cv->c_display;
354 if (D_status == STATUS_ON_WIN)
355 {
356 SetTimeout(ev, 1);
357 evenq(ev);
358 return;
359 }
360 ox = D_x;
361 oy = D_y;
362 if (cv->c_ye + 1 < D_height)
363 RefreshLine(cv->c_ye + 1, 0, D_width - 1, 0);
364 if (ox != -1 && oy != -1)
365 GotoPos(ox, oy);
366 }
367
368 int
MakeDefaultCanvas()369 MakeDefaultCanvas()
370 {
371 struct canvas *cv;
372
373 ASSERT(display);
374 if ((cv = (struct canvas *)calloc(1, sizeof *cv)) == 0)
375 return -1;
376 cv->c_xs = 0;
377 cv->c_xe = D_width - 1;
378 cv->c_ys = (D_has_hstatus == HSTATUS_FIRSTLINE);
379 cv->c_ye = D_height - 1 - (D_has_hstatus == HSTATUS_LASTLINE) - captionalways;
380 debug2("MakeDefaultCanvas 0,0 %d,%d\n", cv->c_xe, cv->c_ye);
381 cv->c_xoff = 0;
382 cv->c_yoff = 0;
383 cv->c_next = 0;
384 cv->c_display = display;
385 cv->c_vplist = 0;
386 cv->c_slnext = 0;
387 cv->c_slprev = 0;
388 cv->c_slperp = 0;
389 cv->c_slweight = 1;
390 cv->c_slback = &D_canvas;
391 D_canvas.c_slperp = cv;
392 D_canvas.c_xs = cv->c_xs;
393 D_canvas.c_xe = cv->c_xe;
394 D_canvas.c_ys = cv->c_ys;
395 D_canvas.c_ye = cv->c_ye;
396 cv->c_slorient = SLICE_UNKN;
397 cv->c_captev.type = EV_TIMEOUT;
398 cv->c_captev.data = (char *)cv;
399 cv->c_captev.handler = cv_winid_fn;
400
401 CanvasInitBlank(cv);
402 cv->c_lnext = 0;
403
404 D_cvlist = cv;
405 RethinkDisplayViewports();
406 D_forecv = cv; /* default input focus */
407 return 0;
408 }
409
410 static struct canvas **
CreateCanvasChainRec(cv,cvp)411 CreateCanvasChainRec(cv, cvp)
412 struct canvas *cv;
413 struct canvas **cvp;
414 {
415 for (; cv; cv = cv->c_slnext)
416 {
417 if (cv->c_slperp)
418 cvp = CreateCanvasChainRec(cv->c_slperp, cvp);
419 else
420 {
421 *cvp = cv;
422 cvp = &cv->c_next;
423 }
424 }
425 return cvp;
426 }
427
428 void
RecreateCanvasChain()429 RecreateCanvasChain()
430 {
431 struct canvas **cvp;
432 cvp = CreateCanvasChainRec(D_canvas.c_slperp, &D_cvlist);
433 *cvp = 0;
434 }
435
436 void
EqualizeCanvas(cv,gflag)437 EqualizeCanvas(cv, gflag)
438 struct canvas *cv;
439 int gflag;
440 {
441 struct canvas *cv2;
442 for (; cv; cv = cv->c_slnext)
443 {
444 if (cv->c_slperp && gflag)
445 {
446 cv->c_slweight = CountCanvasPerp(cv);
447 for (cv2 = cv->c_slperp; cv2; cv2 = cv2->c_slnext)
448 if (cv2->c_slperp)
449 EqualizeCanvas(cv2->c_slperp, gflag);
450 }
451 else
452 cv->c_slweight = 1;
453 }
454 }
455
456 void
ResizeCanvas(cv)457 ResizeCanvas(cv)
458 struct canvas *cv;
459 {
460 struct canvas *cv2, *cvn, *fcv;
461 int nh, i, maxi, hh, m, w, wsum;
462 int need, got;
463 int xs, ys, xe, ye;
464 int focusmin = 0;
465
466 xs = cv->c_xs;
467 ys = cv->c_ys;
468 xe = cv->c_xe;
469 ye = cv->c_ye;
470 cv = cv->c_slperp;
471 debug2("ResizeCanvas: %d,%d", xs, ys);
472 debug2(" %d,%d\n", xe, ye);
473 if (cv == 0)
474 return;
475 if (cv->c_slorient == SLICE_UNKN)
476 {
477 ASSERT(!cv->c_slnext && !cv->c_slperp);
478 cv->c_xs = xs;
479 cv->c_xe = xe;
480 cv->c_ys = ys;
481 cv->c_ye = ye;
482 cv->c_xoff = cv->c_xs;
483 cv->c_yoff = cv->c_ys;
484 cv->c_blank.l_width = cv->c_xe - cv->c_xs + 1;
485 cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1;
486 return;
487 }
488
489 fcv = 0;
490 if (focusminwidth || focusminheight)
491 {
492 debug("searching for focus canvas\n");
493 cv2 = D_forecv;
494 while (cv2->c_slback)
495 {
496 if (cv2->c_slback == cv->c_slback)
497 {
498 fcv = cv2;
499 focusmin = cv->c_slorient == SLICE_VERT ? focusminheight : focusminwidth;
500 if (focusmin > 0)
501 focusmin--;
502 else if (focusmin < 0)
503 focusmin = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2;
504 debug1("found, focusmin=%d\n", focusmin);
505 }
506 cv2 = cv2->c_slback;
507 }
508 }
509 if (focusmin)
510 {
511 m = CountCanvas(cv) * 2;
512 nh = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2;
513 nh -= m;
514 if (nh < 0)
515 nh = 0;
516 if (focusmin > nh)
517 focusmin = nh;
518 debug1("corrected to %d\n", focusmin);
519 }
520
521 /* pass 1: calculate weight sum */
522 for (cv2 = cv, wsum = 0; cv2; cv2 = cv2->c_slnext)
523 {
524 debug1(" weight %d\n", cv2->c_slweight);
525 wsum += cv2->c_slweight;
526 }
527 debug1("wsum = %d\n", wsum);
528 if (wsum == 0)
529 wsum = 1;
530 w = wsum;
531
532 /* pass 2: calculate need/excess space */
533 nh = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2;
534 for (cv2 = cv, need = got = 0; cv2; cv2 = cv2->c_slnext)
535 {
536 m = cv2->c_slperp ? CountCanvasPerp(cv2) * 2 - 1 : 1;
537 if (cv2 == fcv)
538 m += focusmin;
539 hh = cv2->c_slweight ? nh * cv2->c_slweight / w : 0;
540 w -= cv2->c_slweight;
541 nh -= hh;
542 debug2(" should %d min %d\n", hh, m);
543 if (hh <= m + 1)
544 need += m + 1 - hh;
545 else
546 got += hh - m - 1;
547 }
548 debug2("need: %d, got %d\n", need, got);
549 if (need > got)
550 need = got;
551
552 /* pass 3: distribute space */
553 nh = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2;
554 i = cv->c_slorient == SLICE_VERT ? ys : xs;
555 maxi = cv->c_slorient == SLICE_VERT ? ye : xe;
556 w = wsum;
557 for (; cv; cv = cvn)
558 {
559 cvn = cv->c_slnext;
560 if (i > maxi)
561 {
562 if (cv->c_slprev && !cv->c_slback->c_slback && !cv->c_slprev->c_slperp && !cv->c_slprev->c_slprev)
563 {
564 cv->c_slprev->c_slorient = SLICE_UNKN;
565 if (!captionalways)
566 {
567 cv->c_slback->c_ye++;
568 cv->c_slprev->c_ye++;
569 }
570 }
571 SetCanvasWindow(cv, 0);
572 FreeCanvas(cv);
573 continue;
574 }
575 m = cv->c_slperp ? CountCanvasPerp(cv) * 2 - 1 : 1;
576 if (cv == fcv)
577 m += focusmin;
578 hh = cv->c_slweight ? nh * cv->c_slweight / w : 0;
579 w -= cv->c_slweight;
580 nh -= hh;
581 debug2(" should %d min %d\n", hh, m);
582 if (hh <= m + 1)
583 {
584 hh = m + 1;
585 debug1(" -> %d\n", hh);
586 }
587 else
588 {
589 int hx = 1; //FIXME Division by zero (got) is posible. "hx = 1" is random number here!!!
590 if (got != 0)
591 hx = need * (hh - m - 1) / got;
592 else
593 debug(" got = 0\n");
594
595 debug3(" -> %d - %d = %d\n", hh, hx, hh - hx);
596 got -= (hh - m - 1);
597 hh -= hx;
598 need -= hx;
599 debug2(" now need=%d got=%d\n", need, got);
600 }
601 ASSERT(hh >= m + 1);
602 /* hh is window size plus pation line */
603 if (i + hh > maxi + 2)
604 {
605 hh = maxi + 2 - i;
606 debug1(" not enough space, reducing to %d\n", hh);
607 }
608 if (i + hh == maxi + 1)
609 {
610 hh++;
611 debug(" incrementing as no other canvas will fit\n");
612 }
613 if (cv->c_slorient == SLICE_VERT)
614 {
615 cv->c_xs = xs;
616 cv->c_xe = xe;
617 cv->c_ys = i;
618 cv->c_ye = i + hh - 2;
619 cv->c_xoff = xs;
620 cv->c_yoff = i;
621 }
622 else
623 {
624 cv->c_xs = i;
625 cv->c_xe = i + hh - 2;
626 cv->c_ys = ys;
627 cv->c_ye = ye;
628 cv->c_xoff = i;
629 cv->c_yoff = ys;
630 }
631 cv->c_xoff = cv->c_xs;
632 cv->c_yoff = cv->c_ys;
633 cv->c_blank.l_width = cv->c_xe - cv->c_xs + 1;
634 cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1;
635 if (cv->c_slperp)
636 {
637 ResizeCanvas(cv);
638 if (!cv->c_slperp->c_slnext)
639 {
640 debug("deleting perp node\n");
641 FreePerp(cv->c_slperp);
642 FreePerp(cv);
643 }
644 }
645 i += hh;
646 }
647 }
648
649 static struct canvas *
AddPerp(cv)650 AddPerp(cv)
651 struct canvas *cv;
652 {
653 struct canvas *pcv;
654 debug("Creating new perp node\n");
655
656 if ((pcv = (struct canvas *)calloc(1, sizeof *cv)) == 0)
657 return 0;
658 pcv->c_next = 0;
659 pcv->c_display = cv->c_display;
660 pcv->c_slnext = cv->c_slnext;
661 pcv->c_slprev = cv->c_slprev;
662 pcv->c_slperp = cv;
663 pcv->c_slback = cv->c_slback;
664 if (cv->c_slback && cv->c_slback->c_slperp == cv)
665 cv->c_slback->c_slperp = pcv;
666 pcv->c_slorient = cv->c_slorient;
667 pcv->c_xoff = 0;
668 pcv->c_yoff = 0;
669 pcv->c_xs = cv->c_xs;
670 pcv->c_xe = cv->c_xe;
671 pcv->c_ys = cv->c_ys;
672 pcv->c_ye = cv->c_ye;
673 if (pcv->c_slnext)
674 pcv->c_slnext->c_slprev = pcv;
675 if (pcv->c_slprev)
676 pcv->c_slprev->c_slnext = pcv;
677 pcv->c_slweight = cv->c_slweight;
678 CanvasInitBlank(pcv);
679 cv->c_slweight = 1;
680 cv->c_slnext = 0;
681 cv->c_slprev = 0;
682 cv->c_slperp = 0;
683 cv->c_slback = pcv;
684 cv->c_slorient = SLICE_UNKN;
685 return pcv;
686 }
687
688 int
AddCanvas(orient)689 AddCanvas(orient)
690 int orient;
691 {
692 struct canvas *cv;
693 int xs, xe, ys, ye;
694 int h, num;
695
696 cv = D_forecv;
697 debug2("AddCanvas orient %d, forecv is %d\n", orient, cv->c_slorient);
698
699 if (cv->c_slorient != SLICE_UNKN && cv->c_slorient != orient)
700 if (!AddPerp(cv))
701 return -1;
702
703 cv = D_forecv;
704 xs = cv->c_slback->c_xs;
705 xe = cv->c_slback->c_xe;
706 ys = cv->c_slback->c_ys;
707 ye = cv->c_slback->c_ye;
708 if (!captionalways && cv == D_canvas.c_slperp && !cv->c_slnext)
709 ye--; /* need space for caption */
710 debug2("Adding Canvas to slice %d,%d ", xs, ys);
711 debug2("%d,%d\n", xe, ye);
712
713 num = CountCanvas(cv->c_slback->c_slperp) + 1;
714 debug1("Num = %d\n", num);
715 if (orient == SLICE_VERT)
716 h = ye - ys + 1;
717 else
718 h = xe - xs + 1;
719
720 h -= 2 * num - 1;
721 if (h < 0)
722 return -1; /* can't fit in */
723
724 if ((cv = (struct canvas *)calloc(1, sizeof *cv)) == 0)
725 return -1;
726
727 D_forecv->c_slback->c_ye = ye; /* in case we modified it above */
728 D_forecv->c_slorient = orient; /* in case it was UNKN */
729 cv->c_slnext = D_forecv->c_slnext;
730 cv->c_slprev = D_forecv;
731 D_forecv->c_slnext = cv;
732 if (cv->c_slnext)
733 cv->c_slnext->c_slprev = cv;
734 cv->c_slorient = orient;
735 cv->c_slback = D_forecv->c_slback;
736
737 cv->c_xs = xs;
738 cv->c_xe = xe;
739 cv->c_ys = ys;
740 cv->c_ye = ye;
741 cv->c_xoff = 0;
742 cv->c_yoff = 0;
743 cv->c_display = display;
744 cv->c_vplist = 0;
745 cv->c_captev.type = EV_TIMEOUT;
746 cv->c_captev.data = (char *)cv;
747 cv->c_captev.handler = cv_winid_fn;
748
749 CanvasInitBlank(cv);
750 cv->c_lnext = 0;
751
752 cv->c_next = 0;
753
754 cv = cv->c_slback;
755 EqualizeCanvas(cv->c_slperp, 0);
756 ResizeCanvas(cv);
757 RecreateCanvasChain();
758 RethinkDisplayViewports();
759 ResizeLayersToCanvases();
760 return 0;
761 }
762
763 void
RemCanvas()764 RemCanvas()
765 {
766 int ye;
767 struct canvas *cv;
768
769 debug("RemCanvas\n");
770 cv = D_forecv;
771 ye = cv->c_slback->c_ye;
772 if (cv->c_slorient == SLICE_UNKN)
773 return;
774 while (cv->c_slprev)
775 cv = cv->c_slprev;
776 if (!cv->c_slnext)
777 return;
778 if (!cv->c_slnext->c_slnext && cv->c_slback->c_slback)
779 {
780 /* two canvases in slice, kill perp node */
781 cv = D_forecv;
782 debug("deleting perp node\n");
783 FreePerp(cv->c_slprev ? cv->c_slprev : cv->c_slnext);
784 FreePerp(cv->c_slback);
785 }
786 /* free canvas */
787 cv = D_forecv;
788 D_forecv = cv->c_slprev;
789 if (!D_forecv)
790 D_forecv = cv->c_slnext;
791 FreeCanvas(cv);
792
793 cv = D_forecv;
794 while (D_forecv->c_slperp)
795 D_forecv = D_forecv->c_slperp;
796
797 /* if only one canvas left, set orient back to unknown */
798 if (!cv->c_slnext && !cv->c_slprev && !cv->c_slback->c_slback && !cv->c_slperp)
799 {
800 cv->c_slorient = SLICE_UNKN;
801 if (!captionalways)
802 cv->c_slback->c_ye = ++ye; /* caption line no longer needed */
803 }
804 cv = cv->c_slback;
805 EqualizeCanvas(cv->c_slperp, 0);
806 ResizeCanvas(cv);
807
808 D_fore = Layer2Window(D_forecv->c_layer);
809 flayer = D_forecv->c_layer;
810
811 RecreateCanvasChain();
812 RethinkDisplayViewports();
813 ResizeLayersToCanvases();
814 }
815
816 void
OneCanvas()817 OneCanvas()
818 {
819 struct canvas *cv = D_forecv, *ocv = 0;
820
821 if (cv->c_slprev)
822 {
823 ocv = cv->c_slprev;
824 cv->c_slprev->c_slnext = cv->c_slnext;
825 }
826 if (cv->c_slnext)
827 {
828 ocv = cv->c_slnext;
829 cv->c_slnext->c_slprev = cv->c_slprev;
830 }
831 if (!ocv)
832 return;
833 if (cv->c_slback && cv->c_slback->c_slperp == cv)
834 cv->c_slback->c_slperp = ocv;
835 cv->c_slorient = SLICE_UNKN;
836 while (D_canvas.c_slperp)
837 FreeCanvas(D_canvas.c_slperp);
838 cv = D_forecv;
839 D_canvas.c_slperp = cv;
840 cv->c_slback = &D_canvas;
841 cv->c_slnext = 0;
842 cv->c_slprev = 0;
843 ASSERT(!cv->c_slperp);
844 if (!captionalways)
845 D_canvas.c_ye++; /* caption line no longer needed */
846 ResizeCanvas(&D_canvas);
847 RecreateCanvasChain();
848 RethinkDisplayViewports();
849 ResizeLayersToCanvases();
850 }
851
852 void
DupLayoutCv(cvf,cvt,save)853 DupLayoutCv(cvf, cvt, save)
854 struct canvas *cvf, *cvt;
855 int save;
856 {
857 while(cvf)
858 {
859 cvt->c_slorient = cvf->c_slorient;
860 cvt->c_slweight = cvf->c_slweight;
861 if (cvf == D_forecv)
862 D_forecv = cvt;
863 if (!save)
864 {
865 cvt->c_display = display;
866 if (!cvf->c_slperp)
867 {
868 cvt->c_captev.type = EV_TIMEOUT;
869 cvt->c_captev.data = (char *)cvt;
870 cvt->c_captev.handler = cv_winid_fn;
871 cvt->c_blank.l_cvlist = 0;
872 cvt->c_blank.l_layfn = &BlankLf;
873 cvt->c_blank.l_bottom = &cvt->c_blank;
874 }
875 cvt->c_layer = cvf->c_layer;
876 }
877 else
878 {
879 struct win *p = cvf->c_layer ? Layer2Window(cvf->c_layer) : 0;
880 cvt->c_layer = p ? &p->w_layer : 0;
881 }
882 if (cvf->c_slperp)
883 {
884 cvt->c_slperp = (struct canvas *)calloc(1, sizeof(struct canvas));
885 cvt->c_slperp->c_slback = cvt;
886 CanvasInitBlank(cvt->c_slperp);
887 DupLayoutCv(cvf->c_slperp, cvt->c_slperp, save);
888 }
889 if (cvf->c_slnext)
890 {
891 cvt->c_slnext = (struct canvas *)calloc(1, sizeof(struct canvas));
892 cvt->c_slnext->c_slprev = cvt;
893 cvt->c_slnext->c_slback = cvt->c_slback;
894 CanvasInitBlank(cvt->c_slnext);
895 }
896 cvf = cvf->c_slnext;
897 cvt = cvt->c_slnext;
898 }
899 }
900
901 void
PutWindowCv(cv)902 PutWindowCv(cv)
903 struct canvas *cv;
904 {
905 struct win *p;
906 for (; cv; cv = cv->c_slnext)
907 {
908 if (cv->c_slperp)
909 {
910 PutWindowCv(cv->c_slperp);
911 continue;
912 }
913 p = cv->c_layer ? (struct win *)cv->c_layer->l_data : 0;
914 cv->c_layer = 0;
915 SetCanvasWindow(cv, p);
916 }
917 }
918
919