Fix state losses for recursive outliner trees (e.g. datablocks editor)
[blender-staging.git] / source / blender / editors / space_outliner / outliner_tree.c
index 097823135f34ae6a6c96a6d99379bd59d12da13a..0a9478ed52c9446706acfaaee6d0dcb3cf3b1618 100644 (file)
 #include "BLI_blenlib.h"
 #include "BLI_utildefines.h"
 #include "BLI_math.h"
+#include "BLI_ghash.h"
+#include "BLI_mempool.h"
+
+#include "BLF_translation.h"
 
 #include "BKE_fcurve.h"
 #include "BKE_main.h"
+#include "BKE_library.h"
 #include "BKE_modifier.h"
 #include "BKE_sequencer.h"
+#include "BKE_idcode.h"
+#include "BKE_treehash.h"
 
 #include "ED_armature.h"
 #include "ED_screen.h"
 
 #include "outliner_intern.h"
 
-/* ********************************************************* */
-/* Defines */
-
-#define TS_CHUNK  128
-
 /* ********************************************************* */
 /* Persistent Data */
 
 static void outliner_storage_cleanup(SpaceOops *soops)
 {
-       TreeStore *ts = soops->treestore;
+       BLI_mempool *ts = soops->treestore;
        
        if (ts) {
                TreeStoreElem *tselem;
-               int a, unused = 0;
+               int unused = 0;
                
                /* each element used once, for ID blocks with more users to have each a treestore */
-               for (a = 0, tselem = ts->data; a < ts->usedelem; a++, tselem++) tselem->used = 0;
+               BLI_mempool_iter iter;
+
+               BLI_mempool_iternew(ts, &iter);
+               while ((tselem = BLI_mempool_iterstep(&iter))) {
+                       tselem->used = 0;
+               }
                
                /* cleanup only after reading file or undo step, and always for
                 * RNA datablocks view in order to save memory */
                if (soops->storeflag & SO_TREESTORE_CLEANUP) {
-                       
-                       for (a = 0, tselem = ts->data; a < ts->usedelem; a++, tselem++) {
+                       BLI_mempool_iternew(ts, &iter);
+                       while ((tselem = BLI_mempool_iterstep(&iter))) {
                                if (tselem->id == NULL) unused++;
                        }
                        
                        if (unused) {
-                               if (ts->usedelem == unused) {
-                                       MEM_freeN(ts->data);
-                                       ts->data = NULL;
-                                       ts->usedelem = ts->totelem = 0;
+                               if (BLI_mempool_count(ts) == unused) {
+                                       BLI_mempool_destroy(ts);
+                                       soops->treestore = NULL;
+                                       if (soops->treehash) {
+                                               BKE_treehash_free(soops->treehash);
+                                               soops->treehash = NULL;
+                                       }
                                }
                                else {
-                                       TreeStoreElem *tsnewar, *tsnew;
-                                       
-                                       tsnew = tsnewar = MEM_mallocN((ts->usedelem - unused) * sizeof(TreeStoreElem), "new tselem");
-                                       for (a = 0, tselem = ts->data; a < ts->usedelem; a++, tselem++) {
+                                       TreeStoreElem *tsenew;
+                                       BLI_mempool *new_ts = BLI_mempool_create(sizeof(TreeStoreElem), BLI_mempool_count(ts) - unused,
+                                                                                512, BLI_MEMPOOL_ALLOW_ITER);
+                                       BLI_mempool_iternew(ts, &iter);
+                                       while ((tselem = BLI_mempool_iterstep(&iter))) {
                                                if (tselem->id) {
-                                                       *tsnew = *tselem;
-                                                       tsnew++;
+                                                       tsenew = BLI_mempool_alloc(new_ts);
+                                                       *tsenew = *tselem;
                                                }
                                        }
-                                       MEM_freeN(ts->data);
-                                       ts->data = tsnewar;
-                                       ts->usedelem -= unused;
-                                       ts->totelem = ts->usedelem;
+                                       BLI_mempool_destroy(ts);
+                                       soops->treestore = new_ts;
+                                       if (soops->treehash) {
+                                               /* update hash table to fix broken pointers */
+                                               BKE_treehash_rebuild_from_treestore(soops->treehash, soops->treestore);
+                                       }
                                }
                        }
                }
        }
 }
 
-/* XXX - THIS FUNCTION IS INCREDIBLY SLOW
- * ... it can bring blenders tools and viewport to a grinding halt becuase of searching
- * for duplicate items every times they are added.
- *
- * TODO (possible speedups)
- * - use a hash for duplicate (could even store a hash per type)
- * - use mempool for TreeElements
- * */
 static void check_persistent(SpaceOops *soops, TreeElement *te, ID *id, short type, short nr)
 {
-       TreeStore *ts;
        TreeStoreElem *tselem;
-       int a;
        
-       /* case 1; no TreeStore */
        if (soops->treestore == NULL) {
-               soops->treestore = MEM_callocN(sizeof(TreeStore), "treestore");
+               /* if treestore was not created in readfile.c, create it here */
+               soops->treestore = BLI_mempool_create(sizeof(TreeStoreElem), 1, 512, BLI_MEMPOOL_ALLOW_ITER);
+               
        }
-       ts = soops->treestore;
-       
-       /* check if 'te' is in treestore */
-       tselem = ts->data;
-       for (a = 0; a < ts->usedelem; a++, tselem++) {
-               if ((tselem->used == 0) && (tselem->type == type) && (tselem->id == id)) {
-                       if ((type == 0) || (tselem->nr == nr)) {
-                               te->store_index = a;
-                               tselem->used = 1;
-                               return;
-                       }
-               }
+       if (soops->treehash == NULL) {
+               soops->treehash = BKE_treehash_create_from_treestore(soops->treestore);
        }
-       
-       /* add 1 element to treestore */
-       if (ts->usedelem == ts->totelem) {
-               TreeStoreElem *tsnew;
-               
-               tsnew = MEM_mallocN((ts->totelem + TS_CHUNK) * sizeof(TreeStoreElem), "treestore data");
-               if (ts->data) {
-                       memcpy(tsnew, ts->data, ts->totelem * sizeof(TreeStoreElem));
-                       MEM_freeN(ts->data);
-               }
-               ts->data = tsnew;
-               ts->totelem += TS_CHUNK;
+
+       /* find any unused tree element in treestore and mark it as used
+        * (note that there may be multiple unused elements in case of linked objects) */
+       tselem = BKE_treehash_lookup_unused(soops->treehash, type, nr, id);
+       if (tselem) {
+               te->store_elem = tselem;
+               tselem->used = 1;
+               return;
        }
-       
-       tselem = ts->data + ts->usedelem;
-       
+
+       /* add 1 element to treestore */
+       tselem = BLI_mempool_alloc(soops->treestore);
        tselem->type = type;
-       if (type) tselem->nr = nr;  // we're picky! :)
-       else tselem->nr = 0;
+       tselem->nr = type ? nr : 0;
        tselem->id = id;
        tselem->used = 0;
        tselem->flag = TSE_CLOSED;
-       te->store_index = ts->usedelem;
-       
-       ts->usedelem++;
+       te->store_elem = tselem;
+       BKE_treehash_add_element(soops->treehash, tselem);
 }
 
 /* ********************************************************* */
@@ -212,15 +200,14 @@ void outliner_cleanup_tree(SpaceOops *soops)
        outliner_storage_cleanup(soops);
 }
 
-/* Find ith item from the treestore */
-static TreeElement *outliner_find_tree_element(ListBase *lb, int store_index)
+/* Find specific item from the treestore */
+static TreeElement *outliner_find_tree_element(ListBase *lb, TreeStoreElem *store_elem)
 {
-       TreeElement *te = lb->first, *tes;
-       while (te) {
-               if (te->store_index == store_index) return te;
-               tes = outliner_find_tree_element(&te->subtree, store_index);
+       TreeElement *te, *tes;
+       for (te = lb->first; te; te = te->next) {
+               if (te->store_elem == store_elem) return te;
+               tes = outliner_find_tree_element(&te->subtree, store_elem);
                if (tes) return tes;
-               te = te->next;
        }
        return NULL;
 }
@@ -228,23 +215,14 @@ static TreeElement *outliner_find_tree_element(ListBase *lb, int store_index)
 /* tse is not in the treestore, we use its contents to find a match */
 TreeElement *outliner_find_tse(SpaceOops *soops, TreeStoreElem *tse)
 {
-       TreeStore *ts = soops->treestore;
        TreeStoreElem *tselem;
-       int a;
-       
+
        if (tse->id == NULL) return NULL;
        
        /* check if 'tse' is in treestore */
-       tselem = ts->data;
-       for (a = 0; a < ts->usedelem; a++, tselem++) {
-               if ((tse->type == 0 && tselem->type == 0) || (tselem->type == tse->type && tselem->nr == tse->nr)) {
-                       if (tselem->id == tse->id) {
-                               break;
-                       }
-               }
-       }
+       tselem = BKE_treehash_lookup_any(soops->treehash, tse->type, tse->nr, tse->id);
        if (tselem) 
-               return outliner_find_tree_element(&soops->tree, a);
+               return outliner_find_tree_element(&soops->tree, tselem);
        
        return NULL;
 }
@@ -270,7 +248,7 @@ TreeElement *outliner_find_id(SpaceOops *soops, ListBase *lb, ID *id)
 }
 
 
-ID *outliner_search_back(SpaceOops *soops, TreeElement *te, short idcode)
+ID *outliner_search_back(SpaceOops *UNUSED(soops), TreeElement *te, short idcode)
 {
        TreeStoreElem *tselem;
        te = te->parent;
@@ -320,7 +298,7 @@ static void outliner_add_passes(SpaceOops *soops, TreeElement *tenla, ID *id, Sc
         * in order to not overflow short tselem->nr */
        
        te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_COMBINED));
-       te->name = "Combined";
+       te->name = IFACE_("Combined");
        te->directdata = &srl->passflag;
        
        /* save cpu cycles, but we add the first to invoke an open/close triangle */
@@ -329,87 +307,94 @@ static void outliner_add_passes(SpaceOops *soops, TreeElement *tenla, ID *id, Sc
                return;
        
        te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_Z));
-       te->name = "Z";
+       te->name = IFACE_("Z");
        te->directdata = &srl->passflag;
 
        te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_VECTOR));
-       te->name = "Vector";
+       te->name = IFACE_("Vector");
        te->directdata = &srl->passflag;
 
        te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_NORMAL));
-       te->name = "Normal";
+       te->name = IFACE_("Normal");
        te->directdata = &srl->passflag;
 
        te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_UV));
-       te->name = "UV";
+       te->name = IFACE_("UV");
        te->directdata = &srl->passflag;
 
        te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_MIST));
-       te->name = "Mist";
+       te->name = IFACE_("Mist");
        te->directdata = &srl->passflag;
 
        te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_INDEXOB));
-       te->name = "Index Object";
+       te->name = IFACE_("Index Object");
        te->directdata = &srl->passflag;
 
        te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_INDEXMA));
-       te->name = "Index Material";
+       te->name = IFACE_("Index Material");
        te->directdata = &srl->passflag;
 
        te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_RGBA));
-       te->name = "Color";
+       te->name = IFACE_("Color");
        te->directdata = &srl->passflag;
 
        te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_DIFFUSE));
-       te->name = "Diffuse";
+       te->name = IFACE_("Diffuse");
        te->directdata = &srl->passflag;
 
        te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_SPEC));
-       te->name = "Specular";
+       te->name = IFACE_("Specular");
        te->directdata = &srl->passflag;
 
        te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_SHADOW));
-       te->name = "Shadow";
+       te->name = IFACE_("Shadow");
        te->directdata = &srl->passflag;
 
        te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_AO));
-       te->name = "AO";
+       te->name = IFACE_("AO");
        te->directdata = &srl->passflag;
 
        te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_REFLECT));
-       te->name = "Reflection";
+       te->name = IFACE_("Reflection");
        te->directdata = &srl->passflag;
 
        te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_REFRACT));
-       te->name = "Refraction";
+       te->name = IFACE_("Refraction");
        te->directdata = &srl->passflag;
 
        te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_INDIRECT));
-       te->name = "Indirect";
+       te->name = IFACE_("Indirect");
        te->directdata = &srl->passflag;
 
        te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_ENVIRONMENT));
-       te->name = "Environment";
+       te->name = IFACE_("Environment");
        te->directdata = &srl->passflag;
 
        te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_EMIT));
-       te->name = "Emit";
+       te->name = IFACE_("Emit");
        te->directdata = &srl->passflag;
 }
 
 #undef LOG2I
 
+static bool outliner_animdata_test(AnimData *adt)
+{
+       if (adt)
+               return (adt->action || adt->drivers.first || adt->nla_tracks.first);
+       return false;
+}
+
 static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *sce, TreeElement *te)
 {
        SceneRenderLayer *srl;
        TreeElement *tenla = outliner_add_element(soops, lb, sce, te, TSE_R_LAYER_BASE, 0);
        int a;
        
-       tenla->name = "RenderLayers";
+       tenla->name = IFACE_("RenderLayers");
        for (a = 0, srl = sce->r.layers.first; srl; srl = srl->next, a++) {
                TreeElement *tenlay = outliner_add_element(soops, &tenla->subtree, sce, te, TSE_R_LAYER, a);
                tenlay->name = srl->name;
-               tenlay->directdata = &srl->passflag;
+               tenlay->directdata = &srl->layflag;
                
                if (srl->light_override)
                        outliner_add_element(soops, &tenlay->subtree, srl->light_override, tenlay, TSE_LINKED_LAMP, 0);
@@ -420,7 +405,7 @@ static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *s
        }
        
        // TODO: move this to the front?
-       if (sce->adt)
+       if (outliner_animdata_test(sce->adt))
                outliner_add_element(soops, lb, sce, te, TSE_ANIM_DATA, 0);
        
        outliner_add_element(soops,  lb, sce->world, te, 0, 0);
@@ -431,7 +416,7 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree
 {
        int a = 0;
        
-       if (ob->adt)
+       if (outliner_animdata_test(ob->adt))
                outliner_add_element(soops, &te->subtree, ob, te, TSE_ANIM_DATA, 0);
        
        outliner_add_element(soops, &te->subtree, ob->poselib, te, 0, 0); // XXX FIXME.. add a special type for this
@@ -447,7 +432,7 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree
                TreeElement *ten;
                TreeElement *tenla = outliner_add_element(soops, &te->subtree, ob, te, TSE_POSE_BASE, 0);
                
-               tenla->name = "Pose";
+               tenla->name = IFACE_("Pose");
                
                /* channels undefined in editmode, but we want the 'tenla' pose icon itself */
                if ((arm->edbo == NULL) && (ob->mode & OB_MODE_POSE)) {
@@ -466,7 +451,7 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree
                                        TreeElement *tenla1 = outliner_add_element(soops, &ten->subtree, ob, ten, TSE_CONSTRAINT_BASE, 0);
                                        //char *str;
                                        
-                                       tenla1->name = "Constraints";
+                                       tenla1->name = IFACE_("Constraints");
                                        for (con = pchan->constraints.first; con; con = con->next, const_index++) {
                                                ten1 = outliner_add_element(soops, &tenla1->subtree, ob, tenla1, TSE_CONSTRAINT, const_index);
 #if 0 /* disabled as it needs to be reworked for recoded constraints system */
@@ -506,7 +491,7 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree
                        TreeElement *tenla = outliner_add_element(soops, &te->subtree, ob, te, TSE_POSEGRP_BASE, 0);
                        int a = 0;
                        
-                       tenla->name = "Bone Groups";
+                       tenla->name = IFACE_("Bone Groups");
                        for (agrp = ob->pose->agroups.first; agrp; agrp = agrp->next, a++) {
                                ten = outliner_add_element(soops, &tenla->subtree, ob, tenla, TSE_POSEGRP, a);
                                ten->name = agrp->name;
@@ -525,7 +510,7 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree
                TreeElement *tenla = outliner_add_element(soops, &te->subtree, ob, te, TSE_CONSTRAINT_BASE, 0);
                //char *str;
                
-               tenla->name = "Constraints";
+               tenla->name = IFACE_("Constraints");
                for (con = ob->constraints.first, a = 0; con; con = con->next, a++) {
                        ten = outliner_add_element(soops, &tenla->subtree, ob, tenla, TSE_CONSTRAINT, a);
 #if 0 /* disabled due to constraints system targets recode... code here needs review */
@@ -545,7 +530,7 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree
                TreeElement *temod = outliner_add_element(soops, &te->subtree, ob, te, TSE_MODIFIER_BASE, 0);
                int index;
                
-               temod->name = "Modifiers";
+               temod->name = IFACE_("Modifiers");
                for (index = 0, md = ob->modifiers.first; md; index++, md = md->next) {
                        TreeElement *te = outliner_add_element(soops, &temod->subtree, ob, temod, TSE_MODIFIER, index);
                        te->name = md->name;
@@ -553,16 +538,16 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree
                        
                        if (md->type == eModifierType_Lattice) {
                                outliner_add_element(soops, &te->subtree, ((LatticeModifierData *) md)->object, te, TSE_LINKED_OB, 0);
-                       } 
+                       }
                        else if (md->type == eModifierType_Curve) {
                                outliner_add_element(soops, &te->subtree, ((CurveModifierData *) md)->object, te, TSE_LINKED_OB, 0);
-                       } 
+                       }
                        else if (md->type == eModifierType_Armature) {
                                outliner_add_element(soops, &te->subtree, ((ArmatureModifierData *) md)->object, te, TSE_LINKED_OB, 0);
-                       } 
+                       }
                        else if (md->type == eModifierType_Hook) {
                                outliner_add_element(soops, &te->subtree, ((HookModifierData *) md)->object, te, TSE_LINKED_OB, 0);
-                       } 
+                       }
                        else if (md->type == eModifierType_ParticleSystem) {
                                TreeElement *ten;
                                ParticleSystem *psys = ((ParticleSystemModifierData *) md)->psys;
@@ -580,7 +565,7 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree
                TreeElement *ten;
                TreeElement *tenla = outliner_add_element(soops, &te->subtree, ob, te, TSE_DEFGROUP_BASE, 0);
                
-               tenla->name = "Vertex Groups";
+               tenla->name = IFACE_("Vertex Groups");
                for (defgroup = ob->defbase.first, a = 0; defgroup; defgroup = defgroup->next, a++) {
                        ten = outliner_add_element(soops, &tenla->subtree, ob, tenla, TSE_DEFGROUP, a);
                        ten->name = defgroup->name;
@@ -590,9 +575,10 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree
        
        /* duplicated group */
        if (ob->dup_group)
-               outliner_add_element(soops, &te->subtree, ob->dup_group, te, 0, 0);     
+               outliner_add_element(soops, &te->subtree, ob->dup_group, te, 0, 0);
 }
 
+
 // can be inlined if necessary
 static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStoreElem *tselem, ID *id)
 {
@@ -604,24 +590,24 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
                case ID_LI:
                {
                        te->name = ((Library *)id)->name;
+                       break;
                }
-               break;
                case ID_SCE:
                {
                        outliner_add_scene_contents(soops, &te->subtree, (Scene *)id, te);
+                       break;
                }
-               break;
                case ID_OB:
                {
                        outliner_add_object_contents(soops, te, tselem, (Object *)id);
+                       break;
                }
-               break;
                case ID_ME:
                {
                        Mesh *me = (Mesh *)id;
                        int a;
                        
-                       if (me->adt)
+                       if (outliner_animdata_test(me->adt))
                                outliner_add_element(soops, &te->subtree, me, te, TSE_ANIM_DATA, 0);
                        
                        outliner_add_element(soops, &te->subtree, me->key, te, 0, 0);
@@ -629,117 +615,117 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
                                outliner_add_element(soops, &te->subtree, me->mat[a], te, 0, a);
                        /* could do tfaces with image links, but the images are not grouped nicely.
                         * would require going over all tfaces, sort images in use. etc... */
+                       break;
                }
-               break;
                case ID_CU:
                {
                        Curve *cu = (Curve *)id;
                        int a;
                        
-                       if (cu->adt)
+                       if (outliner_animdata_test(cu->adt))
                                outliner_add_element(soops, &te->subtree, cu, te, TSE_ANIM_DATA, 0);
                        
                        for (a = 0; a < cu->totcol; a++)
                                outliner_add_element(soops, &te->subtree, cu->mat[a], te, 0, a);
+                       break;
                }
-               break;
                case ID_MB:
                {
                        MetaBall *mb = (MetaBall *)id;
                        int a;
                        
-                       if (mb->adt)
+                       if (outliner_animdata_test(mb->adt))
                                outliner_add_element(soops, &te->subtree, mb, te, TSE_ANIM_DATA, 0);
                        
                        for (a = 0; a < mb->totcol; a++)
                                outliner_add_element(soops, &te->subtree, mb->mat[a], te, 0, a);
+                       break;
                }
-               break;
                case ID_MA:
                {
                        Material *ma = (Material *)id;
                        int a;
                        
-                       if (ma->adt)
+                       if (outliner_animdata_test(ma->adt))
                                outliner_add_element(soops, &te->subtree, ma, te, TSE_ANIM_DATA, 0);
                        
                        for (a = 0; a < MAX_MTEX; a++) {
                                if (ma->mtex[a]) outliner_add_element(soops, &te->subtree, ma->mtex[a]->tex, te, 0, a);
                        }
+                       break;
                }
-               break;
                case ID_TE:
                {
                        Tex *tex = (Tex *)id;
                        
-                       if (tex->adt)
+                       if (outliner_animdata_test(tex->adt))
                                outliner_add_element(soops, &te->subtree, tex, te, TSE_ANIM_DATA, 0);
                        
                        outliner_add_element(soops, &te->subtree, tex->ima, te, 0, 0);
+                       break;
                }
-               break;
                case ID_CA:
                {
                        Camera *ca = (Camera *)id;
                        
-                       if (ca->adt)
+                       if (outliner_animdata_test(ca->adt))
                                outliner_add_element(soops, &te->subtree, ca, te, TSE_ANIM_DATA, 0);
+                       break;
                }
-               break;
                case ID_LA:
                {
                        Lamp *la = (Lamp *)id;
                        int a;
                        
-                       if (la->adt)
+                       if (outliner_animdata_test(la->adt))
                                outliner_add_element(soops, &te->subtree, la, te, TSE_ANIM_DATA, 0);
                        
                        for (a = 0; a < MAX_MTEX; a++) {
                                if (la->mtex[a]) outliner_add_element(soops, &te->subtree, la->mtex[a]->tex, te, 0, a);
                        }
+                       break;
                }
-               break;
                case ID_SPK:
                {
                        Speaker *spk = (Speaker *)id;
 
-                       if (spk->adt)
+                       if (outliner_animdata_test(spk->adt))
                                outliner_add_element(soops, &te->subtree, spk, te, TSE_ANIM_DATA, 0);
+                       break;
                }
-               break;
                case ID_WO:
                {
                        World *wrld = (World *)id;
                        int a;
                        
-                       if (wrld->adt)
+                       if (outliner_animdata_test(wrld->adt))
                                outliner_add_element(soops, &te->subtree, wrld, te, TSE_ANIM_DATA, 0);
                        
                        for (a = 0; a < MAX_MTEX; a++) {
                                if (wrld->mtex[a]) outliner_add_element(soops, &te->subtree, wrld->mtex[a]->tex, te, 0, a);
                        }
+                       break;
                }
-               break;
                case ID_KE:
                {
                        Key *key = (Key *)id;
                        
-                       if (key->adt)
+                       if (outliner_animdata_test(key->adt))
                                outliner_add_element(soops, &te->subtree, key, te, TSE_ANIM_DATA, 0);
+                       break;
                }
-               break;
                case ID_AC:
                {
                        // XXX do we want to be exposing the F-Curves here?
-                       //bAction *act= (bAction *)id;
+                       //bAction *act = (bAction *)id;
+                       break;
                }
-               break;
                case ID_AR:
                {
                        bArmature *arm = (bArmature *)id;
                        int a = 0;
                        
-                       if (arm->adt)
+                       if (outliner_animdata_test(arm->adt))
                                outliner_add_element(soops, &te->subtree, arm, te, TSE_ANIM_DATA, 0);
                        
                        if (arm->edbo) {
@@ -769,7 +755,9 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
                        else {
                                /* do not extend Armature when we have posemode */
                                tselem = TREESTORE(te->parent);
-                               if (GS(tselem->id->name) == ID_OB && ((Object *)tselem->id)->mode & OB_MODE_POSE) ;
+                               if (GS(tselem->id->name) == ID_OB && ((Object *)tselem->id)->mode & OB_MODE_POSE) {
+                                       /* pass */
+                               }
                                else {
                                        Bone *curBone;
                                        for (curBone = arm->bonebase.first; curBone; curBone = curBone->next) {
@@ -777,26 +765,32 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
                                        }
                                }
                        }
+                       break;
                }
-               break;
        }
 }
 
 // TODO: this function needs to be split up! It's getting a bit too large...
+// Note: "ID" is not always a real ID
 static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *idv, 
                                          TreeElement *parent, short type, short index)
 {
        TreeElement *te;
        TreeStoreElem *tselem;
        ID *id = idv;
-       int a = 0;
        
        if (ELEM3(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
                id = ((PointerRNA *)idv)->id.data;
                if (!id) id = ((PointerRNA *)idv)->data;
        }
 
-       if (id == NULL) return NULL;
+       /* One exception */
+       if (type == TSE_ID_BASE) {
+               /* pass */
+       }
+       else if (id == NULL) {
+               return NULL;
+       }
 
        te = MEM_callocN(sizeof(TreeElement), "tree elem");
        /* add to the visual tree */
@@ -811,24 +805,40 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
        
        te->parent = parent;
        te->index = index;   // for data arays
-       if (ELEM3(type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) ;
-       else if (ELEM3(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) ;
-       else if (type == TSE_ANIM_DATA) ;
+       if (ELEM3(type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) {
+               /* pass */
+       }
+       else if (ELEM3(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
+               /* pass */
+       }
+       else if (type == TSE_ANIM_DATA) {
+               /* pass */
+       }
+       else if (type == TSE_ID_BASE) {
+               /* pass */
+       }
        else {
-               te->name = id->name + 2; // default, can be overridden by Library or non-ID data
+               /* do here too, for blend file viewer, own ID_LI then shows file name */
+               if (GS(id->name) == ID_LI)
+                       te->name = ((Library *)id)->name;
+               else
+                       te->name = id->name + 2; // default, can be overridden by Library or non-ID data
                te->idcode = GS(id->name);
        }
        
        if (type == 0) {
+               TreeStoreElem *tsepar = parent ? TREESTORE(parent) : NULL;
+               
                /* ID datablock */
-               outliner_add_id_contents(soops, te, tselem, id);
+               if (tsepar == NULL || tsepar->type != TSE_ID_BASE)
+                       outliner_add_id_contents(soops, te, tselem, id);
        }
        else if (type == TSE_ANIM_DATA) {
                IdAdtTemplate *iat = (IdAdtTemplate *)idv;
                AnimData *adt = (AnimData *)iat->adt;
                
                /* this element's info */
-               te->name = "Animation";
+               te->name = IFACE_("Animation");
                te->directdata = adt;
                
                /* Action */
@@ -840,7 +850,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
                        ID *lastadded = NULL;
                        FCurve *fcu;
                        
-                       ted->name = "Drivers";
+                       ted->name = IFACE_("Drivers");
                
                        for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
                                if (fcu->driver && fcu->driver->variables.first) {
@@ -869,7 +879,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
                        NlaTrack *nlt;
                        int a = 0;
                        
-                       tenla->name = "NLA Tracks";
+                       tenla->name = IFACE_("NLA Tracks");
                        
                        for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
                                TreeElement *tenlt = outliner_add_element(soops, &tenla->subtree, nlt, tenla, TSE_NLA_TRACK, a);
@@ -897,24 +907,16 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
                 */
                te->idcode = seq->type;
                te->directdata = seq;
+               te->name = seq->name + 2;
 
-               if (seq->type < 7) {
+               if (seq->type < SEQ_TYPE_EFFECT) {
                        /*
                         * This work like the sequence.
                         * If the sequence have a name (not default name)
                         * show it, in other case put the filename.
                         */
-                       if (strcmp(seq->name, "SQ"))
-                               te->name = seq->name;
-                       else {
-                               if ((seq->strip) && (seq->strip->stripdata))
-                                       te->name = seq->strip->stripdata->name;
-                               else
-                                       te->name = "SQ None";
-                       }
 
-                       if (seq->type == SEQ_META) {
-                               te->name = "Meta Strip";
+                       if (seq->type == SEQ_TYPE_META) {
                                p = seq->seqbase.first;
                                while (p) {
                                        outliner_add_element(soops, &te->subtree, (void *)p, te, TSE_SEQUENCE, index);
@@ -924,16 +926,14 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
                        else
                                outliner_add_element(soops, &te->subtree, (void *)seq->strip, te, TSE_SEQ_STRIP, index);
                }
-               else
-                       te->name = "Effect";
        }
        else if (type == TSE_SEQ_STRIP) {
                Strip *strip = (Strip *)idv;
 
-               if (strip->dir)
+               if (strip->dir[0] != '\0')
                        te->name = strip->dir;
                else
-                       te->name = "Strip None";
+                       te->name = IFACE_("Strip None");
                te->directdata = strip;
        }
        else if (type == TSE_SEQUENCE_DUP) {
@@ -952,7 +952,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
                /* we do lazy build, for speed and to avoid infinite recusion */
 
                if (ptr->data == NULL) {
-                       te->name = "(empty)";
+                       te->name = IFACE_("(empty)");
                }
                else if (type == TSE_RNA_STRUCT) {
                        /* struct */
@@ -1057,7 +1057,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
                te->name = km->idname;
                
                if (TSELEM_OPEN(tselem, soops)) {
-                       a = 0;
+                       int a = 0;
                        
                        for (kmi = km->items.first; kmi; kmi = kmi->next, a++) {
                                const char *key = WM_key_event_string(kmi->type);
@@ -1065,8 +1065,12 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
                                if (key[0]) {
                                        wmOperatorType *ot = NULL;
                                        
-                                       if (kmi->propvalue) ;
-                                       else ot = WM_operatortype_find(kmi->idname, 0);
+                                       if (kmi->propvalue) {
+                                               /* pass */
+                                       }
+                                       else {
+                                               ot = WM_operatortype_find(kmi->idname, 0);
+                                       }
                                        
                                        if (ot || kmi->propvalue) {
                                                TreeElement *ten = outliner_add_element(soops, &te->subtree, kmi, te, TSE_KEYMAP_ITEM, a);
@@ -1074,7 +1078,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
                                                ten->directdata = kmi;
                                                
                                                if (kmi->propvalue) {
-                                                       ten->name = "Modal map, not yet";
+                                                       ten->name = IFACE_("Modal map, not yet");
                                                }
                                                else {
                                                        WM_operator_py_idname(opname, ot->idname);
@@ -1100,7 +1104,7 @@ static int need_add_seq_dup(Sequence *seq)
 {
        Sequence *p;
 
-       if ((!seq->strip) || (!seq->strip->stripdata) || (!seq->strip->stripdata->name))
+       if ((!seq->strip) || (!seq->strip->stripdata))
                return(1);
 
        /*
@@ -1109,7 +1113,7 @@ static int need_add_seq_dup(Sequence *seq)
         */
        p = seq->prev;
        while (p) {
-               if ((!p->strip) || (!p->strip->stripdata) || (!p->strip->stripdata->name)) {
+               if ((!p->strip) || (!p->strip->stripdata)) {
                        p = p->prev;
                        continue;
                }
@@ -1121,7 +1125,7 @@ static int need_add_seq_dup(Sequence *seq)
 
        p = seq->next;
        while (p) {
-               if ((!p->strip) || (!p->strip->stripdata) || (!p->strip->stripdata->name)) {
+               if ((!p->strip) || (!p->strip->stripdata)) {
                        p = p->next;
                        continue;
                }
@@ -1140,13 +1144,13 @@ static void outliner_add_seq_dup(SpaceOops *soops, Sequence *seq, TreeElement *t
 
        p = seq;
        while (p) {
-               if ((!p->strip) || (!p->strip->stripdata) || (!p->strip->stripdata->name)) {
+               if ((!p->strip) || (!p->strip->stripdata) || (p->strip->stripdata->name[0] == '\0')) {
                        p = p->next;
                        continue;
                }
 
                if (!strcmp(p->strip->stripdata->name, seq->strip->stripdata->name))
-                       /* ch= */ /* UNUSED */ outliner_add_element(soops, &te->subtree, (void *)p, te, TSE_SEQUENCE, index);
+                       /* ch = */ /* UNUSED */ outliner_add_element(soops, &te->subtree, (void *)p, te, TSE_SEQUENCE, index);
                p = p->next;
        }
 }
@@ -1157,7 +1161,7 @@ static void outliner_add_seq_dup(SpaceOops *soops, Sequence *seq, TreeElement *t
 /* Hierarchy --------------------------------------------- */
 
 /* make sure elements are correctly nested */
-static void outliner_make_hierarchy(SpaceOops *soops, ListBase *lb)
+static void outliner_make_hierarchy(ListBase *lb)
 {
        TreeElement *te, *ten, *tep;
        TreeStoreElem *tselem;
@@ -1192,8 +1196,8 @@ typedef struct tTreeSort {
        short idcode;
 } tTreeSort;
 
-/* alphabetical comparator */
-static int treesort_alpha(const void *v1, const void *v2)
+/* alphabetical comparator, tryping to put objects first */
+static int treesort_alpha_ob(const void *v1, const void *v2)
 {
        const tTreeSort *x1 = v1, *x2 = v2;
        int comp;
@@ -1214,6 +1218,20 @@ static int treesort_alpha(const void *v1, const void *v2)
        return 0;
 }
 
+/* alphabetical comparator */
+static int treesort_alpha(const void *v1, const void *v2)
+{
+       const tTreeSort *x1 = v1, *x2 = v2;
+       int comp;
+       
+       comp = strcmp(x1->name, x2->name);
+       
+       if (comp > 0) return 1;
+       else if (comp < 0) return -1;
+       return 0;
+}
+
+
 /* this is nice option for later? doesnt look too useful... */
 #if 0
 static int treesort_obtype_alpha(const void *v1, const void *v2)
@@ -1221,19 +1239,23 @@ static int treesort_obtype_alpha(const void *v1, const void *v2)
        const tTreeSort *x1 = v1, *x2 = v2;
        
        /* first put objects last (hierarchy) */
-       if (x1->idcode == ID_OB && x2->idcode != ID_OB) return 1;
-       else if (x2->idcode == ID_OB && x1->idcode != ID_OB) return -1;
+       if (x1->idcode == ID_OB && x2->idcode != ID_OB) {
+               return 1;
+       }
+       else if (x2->idcode == ID_OB && x1->idcode != ID_OB) {
+               return -1;
+       }
        else {
                /* 2nd we check ob type */
                if (x1->idcode == ID_OB && x2->idcode == ID_OB) {
-                       if ( ((Object *)x1->id)->type > ((Object *)x2->id)->type) return 1;
-                       else if ( ((Object *)x1->id)->type > ((Object *)x2->id)->type) return -1;
+                       if      (((Object *)x1->id)->type > ((Object *)x2->id)->type) return  1;
+                       else if (((Object *)x1->id)->type > ((Object *)x2->id)->type) return -1;
                        else return 0;
                }
                else {
                        int comp = strcmp(x1->name, x2->name);
                        
-                       if (comp > 0) return 1;
+                       if      (comp > 0) return  1;
                        else if (comp < 0) return -1;
                        return 0;
                }
@@ -1252,8 +1274,8 @@ static void outliner_sort(SpaceOops *soops, ListBase *lb)
        if (te == NULL) return;
        tselem = TREESTORE(te);
        
-       /* sorting rules; only object lists or deformgroups */
-       if ( (tselem->type == TSE_DEFGROUP) || (tselem->type == 0 && te->idcode == ID_OB)) {
+       /* sorting rules; only object lists, ID lists, or deformgroups */
+       if ( ELEM(tselem->type, TSE_DEFGROUP, TSE_ID_BASE) || (tselem->type == 0 && te->idcode == ID_OB)) {
                
                /* count first */
                for (te = lb->first; te; te = te->next) totelem++;
@@ -1268,15 +1290,27 @@ static void outliner_sort(SpaceOops *soops, ListBase *lb)
                                tp->te = te;
                                tp->name = te->name;
                                tp->idcode = te->idcode;
-                               if (tselem->type && tselem->type != TSE_DEFGROUP) tp->idcode = 0;  // don't sort this
+                               
+                               if (tselem->type && tselem->type != TSE_DEFGROUP)
+                                       tp->idcode = 0;  // don't sort this
+                               if (tselem->type == TSE_ID_BASE)
+                                       tp->idcode = 1; // do sort this
+                               
                                tp->id = tselem->id;
                        }
-                       /* keep beginning of list */
-                       for (tp = tear, skip = 0; skip < totelem; skip++, tp++)
-                               if (tp->idcode) break;
                        
-                       if (skip < totelem)
-                               qsort(tear + skip, totelem - skip, sizeof(tTreeSort), treesort_alpha);
+                       /* just sort alphabetically */
+                       if (tear->idcode == 1) {
+                               qsort(tear, totelem, sizeof(tTreeSort), treesort_alpha);
+                       }
+                       else {
+                               /* keep beginning of list */
+                               for (tp = tear, skip = 0; skip < totelem; skip++, tp++)
+                                       if (tp->idcode) break;
+                               
+                               if (skip < totelem)
+                                       qsort(tear + skip, totelem - skip, sizeof(tTreeSort), treesort_alpha_ob);
+                       }
                        
                        lb->first = lb->last = NULL;
                        tp = tear;
@@ -1382,6 +1416,42 @@ static int outliner_filter_tree(SpaceOops *soops, ListBase *lb)
        return (lb->first != NULL);
 }
 
+static void outliner_add_library_contents(Main *mainvar, SpaceOops *soops, TreeElement *te, Library *lib)
+{
+       TreeElement *ten;
+       ListBase *lbarray[MAX_LIBARRAY];
+       int a, tot;
+       
+       tot = set_listbasepointers(mainvar, lbarray);
+       for (a = 0; a < tot; a++) {
+               if (lbarray[a]->first) {
+                       ID *id = lbarray[a]->first;
+                       
+                       /* check if there's data in current lib */
+                       for (; id; id = id->next)
+                               if (id->lib == lib)
+                                       break;
+                       
+                       if (id) {
+                               
+                               ten = outliner_add_element(soops, &te->subtree, (void *)lbarray[a], NULL, TSE_ID_BASE, 0);
+                               ten->directdata = lbarray[a];
+                               
+                               ten->name = (char *)BKE_idcode_to_name_plural(GS(id->name));
+                               if (ten->name == NULL)
+                                       ten->name = "UNKNOWN";
+                               
+                               for (id = lbarray[a]->first; id; id = id->next) {
+                                       if (id->lib == lib)
+                                               outliner_add_element(soops, &ten->subtree, id, ten, 0, 0);
+                               }
+                       }
+               }
+       }
+       
+}
+
+
 /* ======================================================= */
 /* Main Tree Building API */
 
@@ -1393,7 +1463,7 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
        Object *ob;
        TreeElement *te = NULL, *ten;
        TreeStoreElem *tselem;
-       int show_opened = (soops->treestore == NULL); /* on first view, we open scenes */
+       int show_opened = !soops->treestore || !BLI_mempool_count(soops->treestore); /* on first view, we open scenes */
 
        /* Are we looking for something - we want to tag parents to filter child matches
         * - NOT in datablocks view - searching all datablocks takes way too long to be useful
@@ -1416,17 +1486,31 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
        if (soops->outlinevis == SO_LIBRARIES) {
                Library *lib;
                
+               /* current file first - mainvar provides tselem with unique pointer - not used */
+               ten = outliner_add_element(soops, &soops->tree, mainvar, NULL, TSE_ID_BASE, 0);
+               ten->name = IFACE_("Current File");
+
+               tselem = TREESTORE(ten);
+               if (!tselem->used)
+                       tselem->flag &= ~TSE_CLOSED;
+               
+               outliner_add_library_contents(mainvar, soops, ten, NULL);
+               
                for (lib = mainvar->library.first; lib; lib = lib->id.next) {
                        ten = outliner_add_element(soops, &soops->tree, lib, NULL, 0, 0);
                        lib->id.newid = (ID *)ten;
+                       
+                       outliner_add_library_contents(mainvar, soops, ten, lib);
+
                }
                /* make hierarchy */
                ten = soops->tree.first;
+               ten = ten->next;  /* first one is main */
                while (ten) {
                        TreeElement *nten = ten->next, *par;
                        tselem = TREESTORE(ten);
                        lib = (Library *)tselem->id;
-                       if (lib->parent) {
+                       if (lib && lib->parent) {
                                BLI_remlink(&soops->tree, ten);
                                par = (TreeElement *)lib->parent->id.newid;
                                BLI_addtail(&par->subtree, ten);
@@ -1451,7 +1535,7 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
                                ten = outliner_add_element(soops, &te->subtree, base->object, te, 0, 0);
                                ten->directdata = base;
                        }
-                       outliner_make_hierarchy(soops, &te->subtree);
+                       outliner_make_hierarchy(&te->subtree);
                        /* clear id.newid, to prevent objects be inserted in wrong scenes (parent in other scene) */
                        for (base = sce->base.first; base; base = base->next) base->object->id.newid = NULL;
                }
@@ -1464,14 +1548,14 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
                        ten = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
                        ten->directdata = base;
                }
-               outliner_make_hierarchy(soops, &soops->tree);
+               outliner_make_hierarchy(&soops->tree);
        }
        else if (soops->outlinevis == SO_VISIBLE) {
                for (base = scene->base.first; base; base = base->next) {
                        if (base->lay & scene->lay)
                                outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
                }
-               outliner_make_hierarchy(soops, &soops->tree);
+               outliner_make_hierarchy(&soops->tree);
        }
        else if (soops->outlinevis == SO_GROUPS) {
                Group *group;
@@ -1485,7 +1569,7 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
                                        ten = outliner_add_element(soops, &te->subtree, go->ob, te, 0, 0);
                                        ten->directdata = NULL; /* eh, why? */
                                }
-                               outliner_make_hierarchy(soops, &te->subtree);
+                               outliner_make_hierarchy(&te->subtree);
                                /* clear id.newid, to prevent objects be inserted in wrong scenes (parent in other scene) */
                                for (go = group->gobject.first; go; go = go->next) go->ob->id.newid = NULL;
                        }
@@ -1500,7 +1584,7 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
                                        ten->directdata = base;
                                }
                        }
-                       outliner_make_hierarchy(soops, &soops->tree);
+                       outliner_make_hierarchy(&soops->tree);
                }
        }
        else if (soops->outlinevis == SO_SELECTED) {
@@ -1512,7 +1596,7 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
                                }
                        }
                }
-               outliner_make_hierarchy(soops, &soops->tree);
+               outliner_make_hierarchy(&soops->tree);
        }
        else if (soops->outlinevis == SO_SEQUENCE) {
                Sequence *seq;
@@ -1529,7 +1613,7 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
                while (seq) {
                        op = need_add_seq_dup(seq);
                        if (op == 1) {
-                               /* ten= */ outliner_add_element(soops, &soops->tree, (void *)seq, NULL, TSE_SEQUENCE, 0);
+                               /* ten = */ outliner_add_element(soops, &soops->tree, (void *)seq, NULL, TSE_SEQUENCE, 0);
                        }
                        else if (op == 0) {
                                ten = outliner_add_element(soops, &soops->tree, (void *)seq, NULL, TSE_SEQUENCE_DUP, 0);
@@ -1567,7 +1651,7 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
                wmKeyMap *km;
                
                for (km = wm->defaultconf->keymaps.first; km; km = km->next) {
-                       /* ten= */ outliner_add_element(soops, &soops->tree, (void *)km, NULL, TSE_KEYMAP, 0);
+                       /* ten = */ outliner_add_element(soops, &soops->tree, (void *)km, NULL, TSE_KEYMAP, 0);
                }
        }
        else {