Remove commented-out variables
[notion.git] / mod_tiling / split-stdisp.c
blob1b39ec2499bc1d72853f61f2f8d0172c599c81f5
1 /*
2 * ion/mod_tiling/split-stdisp.c
4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
7 */
9 #include <libtu/minmax.h>
10 #include <ioncore/common.h>
11 #include <ioncore/mplex.h>
12 #include <ioncore/resize.h>
13 #include "split.h"
14 #include "split-stdisp.h"
15 #include "tiling.h"
18 /*{{{ Helper routines */
21 #define STDISP_IS_HORIZONTAL(STDISP) \
22 ((STDISP)->orientation==REGION_ORIENTATION_HORIZONTAL)
24 #define STDISP_IS_VERTICAL(STDISP) \
25 ((STDISP)->orientation==REGION_ORIENTATION_VERTICAL)
27 #define STDISP_GROWS_L_TO_R(STDISP) (STDISP_IS_HORIZONTAL(STDISP) && \
28 ((STDISP)->corner==MPLEX_STDISP_TL || \
29 (STDISP)->corner==MPLEX_STDISP_BL))
31 #define STDISP_GROWS_R_TO_L(STDISP) (STDISP_IS_HORIZONTAL(STDISP) && \
32 ((STDISP)->corner==MPLEX_STDISP_TR || \
33 (STDISP)->corner==MPLEX_STDISP_BR))
35 #define STDISP_GROWS_T_TO_B(STDISP) (STDISP_IS_VERTICAL(STDISP) && \
36 ((STDISP)->corner==MPLEX_STDISP_TL || \
37 (STDISP)->corner==MPLEX_STDISP_TR))
39 #define STDISP_GROWS_B_TO_T(STDISP) (STDISP_IS_VERTICAL(STDISP) && \
40 ((STDISP)->corner==MPLEX_STDISP_BL || \
41 (STDISP)->corner==MPLEX_STDISP_BR))
43 #define GEOM(S) (((WSplit*)S)->geom)
45 #define IMPLIES(X, Y) (!(X) || (Y))
48 static int other_dir(int dir)
50 return (dir==SPLIT_VERTICAL ? SPLIT_HORIZONTAL : SPLIT_VERTICAL);
54 static void swap(int *x, int *y)
56 int z=*x;
57 *x=*y;
58 *y=z;
62 static void swapptr(WSplit **x, WSplit **y)
64 void *z=*x;
65 *x=*y;
66 *y=z;
70 static void swapgeom(WRectangle *g, WRectangle *h)
72 WRectangle tmp=*g;
73 *g=*h;
74 *h=tmp;
78 int stdisp_recommended_w(WSplitST *stdisp)
80 if(stdisp->regnode.reg==NULL)
81 return CF_STDISP_MIN_SZ;
83 if(stdisp->fullsize && stdisp->orientation==REGION_ORIENTATION_HORIZONTAL){
84 WTiling *ws=REGION_MANAGER_CHK(stdisp->regnode.reg, WTiling);
85 assert(ws!=NULL);
86 return REGION_GEOM(ws).w;
89 return maxof(CF_STDISP_MIN_SZ, region_min_w(stdisp->regnode.reg));
93 int stdisp_recommended_h(WSplitST *stdisp)
95 if(stdisp->regnode.reg==NULL)
96 return CF_STDISP_MIN_SZ;
98 if(stdisp->fullsize && stdisp->orientation==REGION_ORIENTATION_VERTICAL){
99 WTiling *ws=REGION_MANAGER_CHK(stdisp->regnode.reg, WTiling);
100 assert(ws!=NULL);
101 return REGION_GEOM(ws).h;
104 return maxof(CF_STDISP_MIN_SZ, region_min_h(stdisp->regnode.reg));
108 static bool stdisp_dir_ok(WSplitSplit *p, WSplitST *stdisp)
110 assert(p->tl==(WSplit*)stdisp || p->br==(WSplit*)stdisp);
112 return (IMPLIES(STDISP_IS_HORIZONTAL(stdisp), p->dir==SPLIT_VERTICAL) &&
113 IMPLIES(STDISP_IS_VERTICAL(stdisp), p->dir==SPLIT_HORIZONTAL));
117 /*}}}*/
120 /*{{{ New rotation and flipping primitives */
123 static void replace(WSplitSplit *a, WSplitSplit *p)
125 if(((WSplit*)a)->parent!=NULL)
126 splitinner_replace(((WSplit*)a)->parent, (WSplit*)a, (WSplit*)p);
127 else
128 splittree_changeroot((WSplit*)a, (WSplit*)p);
132 /* Yes, it is overparametrised */
133 static void rotate_right(WSplitSplit *a, WSplitSplit *p, WSplit *y)
135 assert(a->tl==(WSplit*)p && p->tl==y);
137 /* Right rotation:
138 * a p
139 * / \ / \
140 * p x => y a
141 * / \ / \
142 * y ? ? x
145 a->tl=p->br;
146 a->tl->parent=(WSplitInner*)a;
147 replace(a, p);
148 p->br=(WSplit*)a;
149 ((WSplit*)a)->parent=(WSplitInner*)p;
153 static void rot_rs_rotate_right(WSplitSplit *a, WSplitSplit *p, WSplit *y)
155 WRectangle xg, yg, pg, ag, qg;
156 WSplit *x=a->br, *q=p->br;
158 assert(a->dir==other_dir(p->dir));
160 qg=GEOM(q);
161 xg=GEOM(x);
162 yg=GEOM(y);
163 pg=GEOM(p);
164 ag=GEOM(a);
166 if(a->dir==SPLIT_HORIZONTAL){
167 /* yyxx yyyy
168 * ??xx => ??xx
169 * ??xx ??xx
171 yg.w=ag.w;
172 pg.w=ag.w;
173 xg.h=qg.h;
174 ag.h=qg.h;
175 xg.y=qg.y;
176 ag.y=qg.y;
177 }else{
178 /* y?? y??
179 * y?? y??
180 * xxx => yxx
181 * xxx yxx
183 yg.h=ag.h;
184 pg.h=ag.h;
185 xg.w=qg.w;
186 ag.w=qg.w;
187 xg.x=qg.x;
188 ag.x=qg.x;
191 rotate_right(a, p, y);
193 GEOM(p)=pg;
194 GEOM(a)=ag;
196 split_do_resize(x, &xg, PRIMN_TL, PRIMN_TL, FALSE);
197 split_do_resize(y, &yg, PRIMN_BR, PRIMN_BR, FALSE);
202 static void rotate_left(WSplitSplit *a, WSplitSplit *p, WSplit *y)
204 assert(a->br==(WSplit*)p && p->br==y);
206 /* Left rotation:
207 * a p
208 * / \ / \
209 * x p => a y
210 * / \ / \
211 * ? y x ?
214 a->br=p->tl;
215 a->br->parent=(WSplitInner*)a;
216 replace(a, p);
217 p->tl=(WSplit*)a;
218 ((WSplit*)a)->parent=(WSplitInner*)p;
222 static void rot_rs_rotate_left(WSplitSplit *a, WSplitSplit *p, WSplit *y)
224 WRectangle xg, yg, pg, ag, qg;
225 WSplit *x=a->tl, *q=p->tl;
227 assert(a->dir==other_dir(p->dir));
229 qg=GEOM(q);
230 xg=GEOM(x);
231 yg=GEOM(y);
232 pg=GEOM(p);
233 ag=GEOM(a);
235 if(a->dir==SPLIT_HORIZONTAL){
236 /* xx?? xx??
237 * xx?? => xx??
238 * xxyy yyyy
240 yg.w=ag.w;
241 yg.x=ag.x;
242 pg.w=ag.w;
243 pg.x=ag.x;
244 xg.h=qg.h;
245 ag.h=qg.h;
246 }else{
247 /* xxx xxy
248 * xxx xxy
249 * ??y => ??y
250 * ??y ??y
252 yg.h=ag.h;
253 yg.y=ag.y;
254 pg.h=ag.h;
255 pg.y=ag.y;
256 xg.w=qg.w;
257 ag.w=qg.w;
260 rotate_left(a, p, y);
262 GEOM(p)=pg;
263 GEOM(a)=ag;
265 split_do_resize(x, &xg, PRIMN_BR, PRIMN_BR, FALSE);
266 split_do_resize(y, &yg, PRIMN_TL, PRIMN_TL, FALSE);
271 static void flip_right(WSplitSplit *a, WSplitSplit *p)
273 assert(a->tl==(WSplit*)p);
275 /* Right flip:
276 * a p
277 * / \ / \
278 * p x => a y
279 * / \ / \
280 * ? y ? x
283 a->tl=p->tl;
284 a->tl->parent=(WSplitInner*)a;
285 replace(a, p);
286 p->tl=(WSplit*)a;
287 ((WSplit*)a)->parent=(WSplitInner*)p;
291 static void rot_rs_flip_right(WSplitSplit *a, WSplitSplit *p)
293 WRectangle xg, yg, pg, ag, qg;
294 WSplit *x=a->br, *q=p->tl, *y=p->br;
296 assert(a->dir==other_dir(p->dir));
298 qg=GEOM(q);
299 xg=GEOM(x);
300 yg=GEOM(y);
301 pg=GEOM(p);
302 ag=GEOM(a);
304 if(a->dir==SPLIT_HORIZONTAL){
305 /* ??xx ??xx
306 * ??xx => ??xx
307 * yyxx yyyy
309 yg.w=ag.w;
310 pg.w=ag.w;
311 ag.h=qg.h;
312 xg.h=qg.h;
313 }else{
314 /* ??y ??y
315 * ??y ??y
316 * xxx => xxy
317 * xxx xxy
319 yg.h=ag.h;
320 pg.h=ag.h;
321 ag.w=qg.w;
322 xg.w=qg.w;
325 flip_right(a, p);
327 GEOM(p)=pg;
328 GEOM(a)=ag;
330 split_do_resize(x, &xg, PRIMN_BR, PRIMN_BR, FALSE);
331 split_do_resize(y, &yg, PRIMN_BR, PRIMN_BR, FALSE);
335 static void flip_left(WSplitSplit *a, WSplitSplit *p)
337 assert(a->br==(WSplit*)p);
339 /* Left flip:
340 * a p
341 * / \ / \
342 * x p => y a
343 * / \ / \
344 * y ? x ?
347 a->br=p->br;
348 a->br->parent=(WSplitInner*)a;
349 replace(a, p);
350 p->br=(WSplit*)a;
351 ((WSplit*)a)->parent=(WSplitInner*)p;
355 static void rot_rs_flip_left(WSplitSplit *a, WSplitSplit *p)
357 WRectangle xg, yg, pg, ag, qg;
358 WSplit *x=a->tl, *q=p->br, *y=p->tl;
360 assert(a->dir==other_dir(p->dir));
362 qg=GEOM(q);
363 xg=GEOM(x);
364 yg=GEOM(y);
365 pg=GEOM(p);
366 ag=GEOM(a);
368 if(a->dir==SPLIT_HORIZONTAL){
369 /* xxyy yyyy
370 * xx?? => xx??
371 * xx?? xx??
373 yg.x=ag.x;
374 yg.w=ag.w;
375 pg.x=ag.x;
376 pg.w=ag.w;
377 xg.h=qg.h;
378 xg.y=qg.y;
379 ag.h=qg.h;
380 ag.y=qg.y;
381 }else{
382 /* xxx yxx
383 * xxx yxx
384 * y?? => y??
385 * y?? y??
387 yg.y=ag.y;
388 yg.h=ag.h;
389 pg.y=ag.y;
390 pg.h=ag.h;
391 xg.w=qg.w;
392 xg.x=qg.x;
393 ag.w=qg.w;
394 ag.x=qg.x;
397 flip_left(a, p);
399 GEOM(p)=pg;
400 GEOM(a)=ag;
402 split_do_resize(x, &xg, PRIMN_TL, PRIMN_TL, FALSE);
403 split_do_resize(y, &yg, PRIMN_TL, PRIMN_TL, FALSE);
407 static void rot_para_right(WSplitSplit *a, WSplitSplit *p,
408 WSplit *y)
410 rotate_right(a, p, y);
411 if(a->dir==SPLIT_VERTICAL){
412 GEOM(p).y=GEOM(a).y;
413 GEOM(p).h=GEOM(a).h;
414 GEOM(a).y=GEOM(a->tl).y;
415 GEOM(a).h=GEOM(a->br).y+GEOM(a->br).h-GEOM(a).y;
416 }else{
417 GEOM(p).x=GEOM(a).x;
418 GEOM(p).w=GEOM(a).w;
419 GEOM(a).x=GEOM(a->tl).x;
420 GEOM(a).w=GEOM(a->br).x+GEOM(a->br).w-GEOM(a).x;
425 static void rot_para_left(WSplitSplit *a, WSplitSplit *p,
426 WSplit *y)
428 rotate_left(a, p, y);
429 if(a->dir==SPLIT_VERTICAL){
430 GEOM(p).y=GEOM(a).y;
431 GEOM(p).h=GEOM(a).h;
432 GEOM(a).h=GEOM(a->br).y+GEOM(a->br).h-GEOM(a).y;
433 }else{
434 GEOM(p).x=GEOM(a).x;
435 GEOM(p).w=GEOM(a).w;
436 GEOM(a).w=GEOM(a->br).x+GEOM(a->br).w-GEOM(a).x;
441 /*}}}*/
444 /*{{{ Sink */
447 static bool do_try_sink_stdisp_orth(WSplitSplit *p, WSplitST *stdisp,
448 WSplitSplit *other, bool force)
450 bool doit=force;
452 assert(p->dir==other_dir(other->dir));
453 assert(stdisp_dir_ok(p, stdisp));
455 if(STDISP_GROWS_T_TO_B(stdisp) || STDISP_GROWS_L_TO_R(stdisp)){
456 if(STDISP_GROWS_L_TO_R(stdisp)){
457 assert(other->dir==SPLIT_HORIZONTAL);
458 if(other->tl->geom.w>=stdisp_recommended_w(stdisp))
459 doit=TRUE;
460 }else{ /* STDISP_GROWS_T_TO_B */
461 assert(other->dir==SPLIT_VERTICAL);
462 if(other->tl->geom.h>=stdisp_recommended_h(stdisp))
463 doit=TRUE;
466 if(doit){
467 if(p->br==(WSplit*)stdisp)
468 rot_rs_flip_right(p, other);
469 else /* p->tl==stdisp */
470 rot_rs_rotate_left(p, other, other->br);
472 }else{ /* STDISP_GROWS_B_TO_T or STDISP_GROW_R_TO_L */
473 if(STDISP_GROWS_R_TO_L(stdisp)){
474 assert(other->dir==SPLIT_HORIZONTAL);
475 if(other->br->geom.w>=stdisp_recommended_w(stdisp))
476 doit=TRUE;
477 }else{ /* STDISP_GROWS_B_TO_T */
478 assert(other->dir==SPLIT_VERTICAL);
479 if(other->br->geom.h>=stdisp_recommended_h(stdisp))
480 doit=TRUE;
483 if(doit){
484 if(p->tl==(WSplit*)stdisp)
485 rot_rs_flip_left(p, other);
486 else /* p->br==stdisp */
487 rot_rs_rotate_right(p, other, other->tl);
491 return doit;
495 static bool do_try_sink_stdisp_para(WSplitSplit *p, WSplitST *stdisp,
496 WSplitSplit *other, bool force)
498 if(!force){
499 if(STDISP_IS_HORIZONTAL(stdisp)){
500 if(stdisp_recommended_w(stdisp)>=GEOM(p).w)
501 return FALSE;
502 }else{
503 if(stdisp_recommended_h(stdisp)>=GEOM(p).h)
504 return FALSE;
508 if(p->tl==(WSplit*)stdisp)
509 rot_para_left(p, other, other->br);
510 else
511 rot_para_right(p, other, other->tl);
513 return TRUE;
517 bool split_try_sink_stdisp(WSplitSplit *node, bool iterate, bool force)
519 bool didsomething=FALSE;
520 bool more=TRUE;
522 /*assert(OBJ_IS_EXACTLY(node, WSplitSplit));*/
524 while(more){
525 WSplit *tl=node->tl;
526 WSplit *br=node->br;
527 WSplitSplit *other=NULL;
528 WSplitST *st;
530 if(OBJ_IS(tl, WSplitST)){
531 st=(WSplitST*)tl;
532 other=OBJ_CAST(br, WSplitSplit);
533 }else if(OBJ_IS(br, WSplitST)){
534 st=(WSplitST*)br;
535 other=OBJ_CAST(tl, WSplitSplit);
536 }else{
537 break;
540 if(other==NULL)
541 break;
543 if(!stdisp_dir_ok(node, st))
544 break;
546 if(other->dir==other_dir(node->dir)){
547 if(!do_try_sink_stdisp_orth(node, st, other, force))
548 break;
549 }else /*if(br->dir==node->dir)*/{
550 if(!do_try_sink_stdisp_para(node, st, other, force))
551 break;
553 didsomething=TRUE;
554 more=iterate;
557 return didsomething;
561 /*}}}*/
564 /*{{{ Unsink */
567 static bool do_try_unsink_stdisp_orth(WSplitSplit *a, WSplitSplit *p,
568 WSplitST *stdisp, bool force)
570 bool doit=force;
572 assert(p->dir==other_dir(a->dir));
573 assert(stdisp_dir_ok(p, stdisp));
575 if(STDISP_GROWS_T_TO_B(stdisp) || STDISP_GROWS_L_TO_R(stdisp)){
576 if(STDISP_GROWS_L_TO_R(stdisp)){
577 assert(a->dir==SPLIT_HORIZONTAL);
578 if(GEOM(stdisp).w<stdisp_recommended_w(stdisp))
579 doit=TRUE;
580 }else{ /* STDISP_GROWS_T_TO_B */
581 assert(a->dir==SPLIT_VERTICAL);
582 if(GEOM(stdisp).h<stdisp_recommended_h(stdisp))
583 doit=TRUE;
586 if(doit){
587 if((WSplit*)p==a->tl){
588 if((WSplit*)stdisp==p->br)
589 rot_rs_flip_right(a, p);
590 else /*stdisp==p->tl*/
591 rot_rs_rotate_right(a, p, (WSplit*)stdisp);
592 }else{ /*p==a->br*/
593 #if 0
594 /* abnormal cases. */
595 warn(TR("Status display in bad split configuration."));
596 return FALSE;
597 #else
598 if((WSplit*)stdisp==p->br)
599 rot_rs_rotate_left(a, p, (WSplit*)stdisp);
600 else /*stdisp==p->tl*/
601 rot_rs_flip_left(a, p);
602 #endif
605 }else{ /*STDISP_GROWS_B_TO_T || STDISP_GROWS_R_TO_L*/
606 if(STDISP_GROWS_R_TO_L(stdisp)){
607 assert(a->dir==SPLIT_HORIZONTAL);
608 if(GEOM(stdisp).w<stdisp_recommended_w(stdisp))
609 doit=TRUE;
610 }else{ /* STDISP_GROWS_B_TO_T */
611 assert(a->dir==SPLIT_VERTICAL);
612 if(GEOM(stdisp).h<stdisp_recommended_h(stdisp))
613 doit=TRUE;
616 if(doit){
617 if((WSplit*)p==a->tl){
618 #if 0
619 /* abnormal cases. */
620 warn(TR("Status display in bad split configuration."));
621 return FALSE;
622 #else
623 if((WSplit*)stdisp==p->br)
624 rot_rs_flip_right(a, p);
625 else /*stdisp==p->tl*/
626 rot_rs_rotate_right(a, p, (WSplit*)stdisp);
627 #endif
628 }else{ /*p==a->br*/
629 if((WSplit*)stdisp==p->br)
630 rot_rs_rotate_left(a, p, (WSplit*)stdisp);
631 else /*stdisp==p->tl*/
632 rot_rs_flip_left(a, p);
637 return doit;
641 static bool do_try_unsink_stdisp_para(WSplitSplit *a, WSplitSplit *p,
642 WSplitST *stdisp, bool force)
644 if(!force){
645 if(STDISP_IS_HORIZONTAL(stdisp)){
646 if(stdisp_recommended_w(stdisp)<=GEOM(p).w)
647 return FALSE;
648 }else{
649 if(stdisp_recommended_h(stdisp)<=GEOM(p).h)
650 return FALSE;
655 if(a->tl==(WSplit*)p && p->tl==(WSplit*)stdisp){
656 rot_para_right(a, p, (WSplit*)stdisp);
657 }else if(a->br==(WSplit*)p && p->br==(WSplit*)stdisp){
658 rot_para_left(a, p, (WSplit*)stdisp);
659 }else{
660 warn(TR("Status display badly located in split tree."));
661 return FALSE;
664 return TRUE;
668 bool split_try_unsink_stdisp(WSplitSplit *node, bool iterate, bool force)
670 bool didsomething=FALSE;
671 bool more=TRUE;
673 /*assert(OBJ_IS_EXACTLY(node, WSplitSplit));*/
675 while(more){
676 WSplitSplit *p=OBJ_CAST(((WSplit*)node)->parent, WSplitSplit);
677 WSplit *tl=node->tl;
678 WSplit *br=node->br;
679 WSplitST *st;
681 if(p==NULL)
682 break;
684 if(OBJ_IS(tl, WSplitST))
685 st=(WSplitST*)tl;
686 else if(OBJ_IS(br, WSplitST))
687 st=(WSplitST*)br;
688 else
689 break;
691 if(!stdisp_dir_ok(node, st))
692 break;
694 if(p->dir==other_dir(node->dir)){
695 if(!do_try_unsink_stdisp_orth(p, node, st, force))
696 break;
697 }else /*if(p->dir==node->dir)*/{
698 if(!do_try_unsink_stdisp_para(p, node, st, force))
699 break;
702 didsomething=TRUE;
703 more=iterate;
706 return didsomething;
710 /*}}}*/
713 /*{{{ Sink or unsink */
716 bool split_regularise_stdisp(WSplitST *stdisp)
718 WSplitSplit *node=OBJ_CAST(((WSplit*)stdisp)->parent, WSplitSplit);
720 if(node==NULL)
721 return FALSE;
723 if(STDISP_IS_HORIZONTAL(stdisp)){
724 if(GEOM(stdisp).w<stdisp_recommended_w(stdisp))
725 return split_try_unsink_stdisp(node, TRUE, FALSE);
726 else if(GEOM(stdisp).w>stdisp_recommended_w(stdisp))
727 return split_try_sink_stdisp(node, TRUE, FALSE);
728 }else{
729 if(GEOM(stdisp).h<stdisp_recommended_h(stdisp))
730 return split_try_unsink_stdisp(node, TRUE, FALSE);
731 else if(GEOM(stdisp).h>stdisp_recommended_h(stdisp))
732 return split_try_sink_stdisp(node, TRUE, FALSE);
735 return FALSE;
739 /*}}}*/