*
* Copyright (c) Tuomo Valkonen 1999-2007.
*
- * Ion is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
+ * See the included file LICENSE for details.
*/
#include <limits.h>
}
-static WSplitSplit *splittree_scan_stdisp_parent(WSplit *node_, bool set_saw)
+static WSplitST *splittree_scan_stdisp(WSplit *node_, bool set_saw)
{
- WSplitSplit *r, *node=OBJ_CAST(node_, WSplitSplit);
+ WSplitST *r=NULL;
+ WSplitSplit *node=OBJ_CAST(node_, WSplitSplit);
if(node==NULL)
return NULL;
- if(OBJ_IS(node->tl, WSplitST)){
- if(set_saw)
- saw_stdisp=(WSplitST*)node->tl;
- return node;
- }
-
- if(OBJ_IS(node->br, WSplitST)){
+ r=OBJ_CAST(node->tl, WSplitST);
+ if(r==NULL)
+ r=OBJ_CAST(node->br, WSplitST);
+
+ if(r!=NULL){
if(set_saw)
- saw_stdisp=(WSplitST*)node->br;
- return node;
+ saw_stdisp=r;
+ return r;
}
-
- r=splittree_scan_stdisp_parent(node->tl, set_saw);
+
+ r=splittree_scan_stdisp(node->tl, set_saw);
if(r==NULL)
- r=splittree_scan_stdisp_parent(node->br, set_saw);
+ r=splittree_scan_stdisp(node->br, set_saw);
+
return r;
}
}
-static WSplit *move_stdisp_out_of_way(WSplit *node)
+static WSplit *dodge_stdisp(WSplit *node, bool keep_within)
{
+ WSplitST *stdisp;
WSplitSplit *stdispp;
- if(!OBJ_IS(node, WSplitSplit))
+ stdisp=splittree_scan_stdisp(node, TRUE);
+
+ if(stdisp==NULL)
return node;
- stdispp=splittree_scan_stdisp_parent(node, TRUE);
-
+ stdispp=OBJ_CAST(((WSplit*)stdisp)->parent, WSplitSplit);
+
if(stdispp==NULL)
return node;
-
- while(stdispp->tl!=node && stdispp->br!=node){
+
+ if((WSplit*)stdispp==node){
+ /* Node itself immediately contains stdisp. Due to the way
+ * try_unsink works, stdisp this will not change, so another
+ * node must be used, if we want to fully dodge stdisp.
+ */
+ return (keep_within
+ ? node
+ : (stdispp->tl==(WSplit*)stdisp
+ ? stdispp->br
+ : stdispp->tl));
+ }
+
+ do{
if(!split_try_unsink_stdisp(stdispp, FALSE, TRUE)){
warn(TR("Unable to move the status display out of way."));
return NULL;
}
- }
+ }while(stdispp->tl!=node && stdispp->br!=node);
- return (WSplit*)stdispp;
+ return node;
}
assert(node!=NULL && parent!=NULL);
+ splittree_begin_resize();
+
+ node=dodge_stdisp(node, FALSE);
+
+ if(node==NULL)
+ return NULL;
+
if(OBJ_IS(node, WSplitST)){
warn(TR("Splitting the status display is not allowed."));
return NULL;
}
- splittree_begin_resize();
-
- if(!move_stdisp_out_of_way(node))
- return NULL;
-
if(primn!=PRIMN_TL && primn!=PRIMN_BR)
primn=PRIMN_BR;
if(dir!=SPLIT_HORIZONTAL && dir!=SPLIT_VERTICAL)
static int nstdisp=0;
WSplitInner *parent;
WSplit *other;
+ int hprimn=PRIMN_ANY, vprimn=PRIMN_ANY;
assert(node->tl==child || node->br==child);
- if(node->tl==child)
+ if(node->tl==child){
other=node->br;
- else
+ if(node->dir==SPLIT_VERTICAL)
+ vprimn=PRIMN_TL;
+ else
+ hprimn=PRIMN_TL;
+ }else{
other=node->tl;
+ if(node->dir==SPLIT_VERTICAL)
+ vprimn=PRIMN_BR;
+ else
+ hprimn=PRIMN_BR;
+ }
assert(other!=NULL);
splittree_changeroot((WSplit*)node, other);
if(reclaim_space)
- split_resize(other, &(((WSplit*)node)->geom), PRIMN_ANY, PRIMN_ANY);
+ split_resize(other, &(((WSplit*)node)->geom), hprimn, vprimn);
child->parent=NULL;
}
+/* Note: both hprimn and vprimn are inverted when descending. Therefore
+ * one should be either PRIMN_NONE or PRIMN_ANY for sensible geometric
+ * navigation. (Both are PRIMN_TL or PRIMN_BR for pseudo-linear
+ * next/previous navigation.)
+ */
WSplit *splitsplit_nextto(WSplitSplit *node, WSplit *child,
WPrimn hprimn, WPrimn vprimn,
WSplitFilter *filter)
WPrimn primn=(node->dir==SPLIT_HORIZONTAL ? hprimn : vprimn);
WSplit *split=NULL, *nnode=NULL;
- if(node->tl==child && (primn==PRIMN_BR || primn==PRIMN_ANY)){
+ if(node->tl==child && (primn==PRIMN_BR || primn==PRIMN_ANY))
split=node->br;
- primn=PRIMN_TL;
- }else if(node->br==child && (primn==PRIMN_TL || primn==PRIMN_ANY)){
+ else if(node->br==child && (primn==PRIMN_TL || primn==PRIMN_ANY))
split=node->tl;
- primn=PRIMN_BR;
- }
if(split!=NULL){
- if(node->dir==SPLIT_HORIZONTAL){
- hprimn=primn;
- vprimn=primn_none2any(vprimn);
- }else{
- vprimn=primn;
- hprimn=primn_none2any(vprimn);
- }
-
- nnode=split_current_todir(split, hprimn, vprimn, filter);
+ nnode=split_current_todir(split,
+ primn_none2any(primn_invert(hprimn)),
+ primn_none2any(primn_invert(vprimn)),
+ filter);
}
-
+
+ if(nnode==NULL)
+ nnode=split_nextto((WSplit*)node, hprimn, vprimn, filter);
+
return nnode;
}
/*EXTL_DOC
- * Flip contents of \var{node}.
+ * Flip contents of \var{split}.
*/
EXTL_EXPORT_MEMBER
void splitsplit_flip(WSplitSplit *split)
{
splittree_begin_resize();
- if(!move_stdisp_out_of_way((WSplit*)split))
+ split=OBJ_CAST(dodge_stdisp((WSplit*)split, FALSE), WSplitSplit);
+
+ if(split==NULL)
return;
splitsplit_flip_(split);
* geometry calculation we move it immediately below node, and
* resize stdisp's fixed parent node instead.
*/
- node2=move_stdisp_out_of_way(node);
+ node2=dodge_stdisp(node, TRUE);
- if(node2==NULL)
+ if(node==NULL || node2!=node)
return FALSE;
- split_update_bounds(node2, TRUE);
+ split_update_bounds(node, TRUE);
- split_do_rqgeom_(node2, geom, PRIMN_ANY, PRIMN_ANY, &rg, FALSE);
+ split_do_rqgeom_(node, geom, PRIMN_ANY, PRIMN_ANY, &rg, FALSE);
- split_do_resize(node2, &rg, PRIMN_ANY, PRIMN_ANY, trans);
+ split_do_resize(node, &rg, PRIMN_ANY, PRIMN_ANY, trans);
if(flip!=FLIP_NONE)
- splittree_flip_dir(node2, flip);
+ splittree_flip_dir(node, flip);
splittree_end_resize();
}
/*EXTL_DOC
- * Returns the direction of \var{split}; either ''vertical'' or
- * ''horizontal''.
+ * Returns the direction of \var{split}; either \codestr{vertical} or
+ * \codestr{horizontal}.
*/
EXTL_SAFE
EXTL_EXPORT_MEMBER