billiob pushed a commit to branch master.

http://git.enlightenment.org/apps/terminology.git/commit/?id=2228945f2ce29c12d98890498c61e493171d5c55

commit 2228945f2ce29c12d98890498c61e493171d5c55
Author: Boris Faure <bill...@gmail.com>
Date:   Sun Mar 22 18:17:16 2015 +0100

    refactor win.c to use the Term_Container abstraction
---
 src/bin/controls.c       |    4 +-
 src/bin/main.c           |   19 +-
 src/bin/sel.c            |   84 +-
 src/bin/sel.h            |    5 +-
 src/bin/term_container.h |   61 +
 src/bin/win.c            | 3441 ++++++++++++++++++++++++++++------------------
 src/bin/win.h            |    4 +
 7 files changed, 2250 insertions(+), 1368 deletions(-)

diff --git a/src/bin/controls.c b/src/bin/controls.c
index 365cd3a..1640073 100644
--- a/src/bin/controls.c
+++ b/src/bin/controls.c
@@ -76,13 +76,13 @@ _cb_ct_new(void *data EINA_UNUSED, Evas_Object *obj 
EINA_UNUSED, void *event EIN
 static void
 _cb_ct_split_v(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void 
*event EINA_UNUSED)
 {
-   main_split_v(ct_win, ct_term, NULL);
+   split_vertically(ct_win, ct_term, NULL);
 }
 
 static void
 _cb_ct_split_h(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void 
*event EINA_UNUSED)
 {
-   main_split_h(ct_win, ct_term, NULL);
+   split_horizontally(ct_win, ct_term, NULL);
 }
 
 static void
diff --git a/src/bin/main.c b/src/bin/main.c
index 6eca428..2912d65 100644
--- a/src/bin/main.c
+++ b/src/bin/main.c
@@ -291,12 +291,9 @@ main_ipc_new(Ipc_Instance *inst)
         free(nargv);
         return;
      }
-   else
-     {
-        win_term_swallow(wn, term);
-     }
 
-   win_add_split(wn, term);
+   if (win_term_set(wn, term) < 0)
+     return;
 
    main_trans_update(config);
    main_media_update(config);
@@ -866,13 +863,13 @@ remote:
         retval = EXIT_FAILURE;
         goto end;
      }
-   else
+
+   if (win_term_set(wn, term) < 0)
      {
-        win_term_swallow(wn, term);
+        retval = EXIT_FAILURE;
+        goto end;
      }
 
-   win_add_split(wn, term);
-
    main_trans_update(config);
    main_media_update(config);
    win_sizing_handle(wn);
@@ -890,14 +887,14 @@ remote:
              if (startup_split[i] == 'v')
                {
                   pch = eina_list_nth(cmds_list, 1);
-                  main_split_v(win_evas_object_get(term_win_get(next)),
+                  split_vertically(win_evas_object_get(term_win_get(next)),
                                main_term_evas_object_get(next), pch);
                   cmds_list = eina_list_remove(cmds_list, pch);
                }
              else if (startup_split[i] == 'h')
                {
                   pch = eina_list_nth(cmds_list, 1);
-                  main_split_h(win_evas_object_get(term_win_get(next)),
+                  split_horizontally(win_evas_object_get(term_win_get(next)),
                                main_term_evas_object_get(next), pch);
                   cmds_list = eina_list_remove(cmds_list, pch);
                }
diff --git a/src/bin/sel.c b/src/bin/sel.c
index 9f5244a..0da8e45 100644
--- a/src/bin/sel.c
+++ b/src/bin/sel.c
@@ -6,7 +6,7 @@
 #include "sel.h"
 #include "config.h"
 #include "utils.h"
-#include "termio.h"
+#include "term_container.h"
 
 typedef struct _Sel Sel;
 typedef struct _Entry Entry;
@@ -41,7 +41,8 @@ struct _Sel
 
 struct _Entry
 {
-   Evas_Object *obj, *bg, *termio;
+   Evas_Object *obj, *bg;
+   Term_Container *tc;
    unsigned char selected : 1;
    unsigned char selected_before : 1;
    unsigned char selected_orig : 1;
@@ -476,39 +477,40 @@ _label_redo(Entry *en)
 {
    const char *s;
 
-   if (!en->obj) return;
-   if (!en->termio) return;
-   s = termio_title_get(en->termio);
-   if (!s) s = termio_icon_name_get(en->termio);
-   if (s) edje_object_part_text_set(en->bg, "terminology.label", s);
+   if (!en->obj || !en->tc)
+     return;
+   s = en->tc->title;
+   if (!s)
+     s = "Terminology";
+   edje_object_part_text_set(en->bg, "terminology.label", s);
 }
 
-static void
-_title_cb(void *data, Evas_Object *obj EINA_UNUSED, void *info EINA_UNUSED)
+void
+sel_entry_title_set(void *entry, const char *title)
 {
-   _label_redo(data);
-}
+   Entry *en = entry;
 
-static void
-_icon_cb(void *data, Evas_Object *obj EINA_UNUSED, void *info EINA_UNUSED)
-{
-   _label_redo(data);
+   edje_object_part_text_set(en->bg, "terminology.label", title);
 }
 
-static void
-_bell_cb(void *data, Evas_Object *obj EINA_UNUSED, void *info EINA_UNUSED)
+void
+sel_entry_close(void *data)
 {
    Entry *en = data;
-   edje_object_signal_emit(en->bg, "bell", "terminology");
+
+   en->tc = NULL;
 }
 
-static void
-_entry_termio_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj 
EINA_UNUSED, void *info EINA_UNUSED)
+void
+sel_entry_update(void *data)
 {
    Entry *en = data;
-   if (en->termio) evas_object_event_callback_del_full
-     (en->termio, EVAS_CALLBACK_DEL, _entry_termio_del_cb, en);
-   en->termio = NULL;
+
+   en->tc = evas_object_data_get(en->obj, "tc");
+   if (en->tc)
+     {
+        _label_redo(en);
+     }
 }
 
 static void
@@ -518,10 +520,9 @@ _entry_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object 
*obj EINA_UNUSED, voi
    if (en->obj) evas_object_event_callback_del_full
      (en->obj, EVAS_CALLBACK_DEL, _entry_del_cb, en);
    en->obj = NULL;
+   /*
    if (en->termio)
      {
-        evas_object_event_callback_del_full(en->termio, EVAS_CALLBACK_DEL,
-                                            _entry_termio_del_cb, en);
         evas_object_smart_callback_del_full(en->termio, "title,change",
                                             _title_cb, en);
         evas_object_smart_callback_del_full(en->termio, "icon,change",
@@ -530,6 +531,7 @@ _entry_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object 
*obj EINA_UNUSED, voi
                                             _bell_cb, en);
         en->termio = NULL;
      }
+   */
 }
 
 static void
@@ -562,17 +564,6 @@ _smart_del(Evas_Object *obj)
    if (sd->autozoom_timeout) ecore_timer_del(sd->autozoom_timeout);
    EINA_LIST_FREE(sd->items, en)
      {
-        if (en->termio)
-          {
-             evas_object_event_callback_del_full(en->termio, EVAS_CALLBACK_DEL,
-                                                 _entry_termio_del_cb, en);
-             evas_object_smart_callback_del_full(en->termio, "title,change",
-                                                 _title_cb, en);
-             evas_object_smart_callback_del_full(en->termio, "icon,change",
-                                                 _icon_cb, en);
-             evas_object_smart_callback_del_full(en->termio, "bell",
-                                                 _bell_cb, en);
-          }
         if (en->obj) evas_object_event_callback_del_full
           (en->obj, EVAS_CALLBACK_DEL, _entry_del_cb, en);
         if (en->obj) evas_object_del(en->obj);
@@ -669,12 +660,13 @@ sel_add(Evas_Object *parent)
    return obj;
 }
 
-void
-sel_entry_add(Evas_Object *obj, Evas_Object *entry, Eina_Bool selected, 
Eina_Bool bell, Config *config)
+void *
+sel_entry_add(Evas_Object *obj, Evas_Object *entry,
+              Eina_Bool selected, Eina_Bool bell, Config *config)
 {
    Sel *sd = evas_object_smart_data_get(obj);
    Entry *en = calloc(1, sizeof(Entry));
-   if (!en) return;
+   if (!en) return NULL;
    sd->items = eina_list_append(sd->items, en);
    sd->config = config;
    en->obj = entry;
@@ -703,21 +695,15 @@ sel_entry_add(Evas_Object *obj, Evas_Object *entry, 
Eina_Bool selected, Eina_Boo
         edje_object_message_signal_process(en->bg);
      }
    sd->interp = 1.0;
-   en->termio = evas_object_data_get(en->obj, "termio");
-   if (en->termio)
+   en->tc = evas_object_data_get(en->obj, "tc");
+   if (en->tc)
      {
-        evas_object_smart_callback_add(en->termio, "title,change",
-                                       _title_cb, en);
-        evas_object_smart_callback_add(en->termio, "icon,change",
-                                       _icon_cb, en);
-        evas_object_smart_callback_add(en->termio, "bell",
-                                       _bell_cb, en);
         _label_redo(en);
-        evas_object_event_callback_add(en->termio, EVAS_CALLBACK_DEL,
-                                       _entry_termio_del_cb, en);
      }
    evas_object_event_callback_add(en->obj, EVAS_CALLBACK_DEL,
                                   _entry_del_cb, en);
+
+   return en;
 }
 
 void
diff --git a/src/bin/sel.h b/src/bin/sel.h
index 724674d..f01f545 100644
--- a/src/bin/sel.h
+++ b/src/bin/sel.h
@@ -4,7 +4,10 @@
 #include "config.h"
 
 Evas_Object *sel_add(Evas_Object *parent);
-void sel_entry_add(Evas_Object *obj, Evas_Object *entry, Eina_Bool selected, 
Eina_Bool bell, Config *config);
+void *sel_entry_add(Evas_Object *obj, Evas_Object *entry, Eina_Bool selected, 
Eina_Bool bell, Config *config);
+void sel_entry_title_set(void *entry, const char *title);
+void sel_entry_close(void *entry);
+void sel_entry_update(void *entry);
 void sel_go(Evas_Object *obj);
 void sel_entry_selected_set(Evas_Object *obj, Evas_Object *entry, Eina_Bool 
keep_before);
 void sel_zoom(Evas_Object *obj, double zoom);
diff --git a/src/bin/term_container.h b/src/bin/term_container.h
new file mode 100644
index 0000000..cd4059f
--- /dev/null
+++ b/src/bin/term_container.h
@@ -0,0 +1,61 @@
+#ifndef _TERM_CONTAINER_H__
+#define _TERM_CONTAINER_H__ 1
+
+
+typedef struct _Term_Container Term_Container;
+typedef struct _Term  Term;
+typedef struct _Win Win;
+typedef struct _Sizeinfo Sizeinfo;
+
+struct _Sizeinfo
+{
+   int min_w;
+   int min_h;
+   int step_x;
+   int step_y;
+   int req_w;
+   int req_h;
+   int bg_min_w;
+   int bg_min_h;
+   int req;
+};
+
+typedef enum _Term_Container_Type
+{
+   TERM_CONTAINER_TYPE_UNKNOWN,
+   TERM_CONTAINER_TYPE_SOLO,
+   TERM_CONTAINER_TYPE_SPLIT,
+   TERM_CONTAINER_TYPE_TABS,
+   TERM_CONTAINER_TYPE_WIN
+} Term_Container_Type;
+
+struct _Term_Container {
+     Term_Container_Type type;
+     Term_Container *parent;
+     Win *wn;
+     Evas_Object *selector_img;
+     Eina_Bool is_focused;
+     const char *title;
+
+     Term *(*term_next)(Term_Container *tc, Term_Container *child);
+     Term *(*term_prev)(Term_Container *tc, Term_Container *child);
+     Term *(*term_first)(Term_Container *tc);
+     Term *(*term_last)(Term_Container *tc);
+     Term *(*focused_term_get)(Term_Container *tc);
+     Evas_Object* (*get_evas_object)(Term_Container *container);
+     Term *(*find_term_at_coords)(Term_Container *container,
+                                  Evas_Coord mx, Evas_Coord my);
+     void (*split)(Term_Container *tc, Term_Container *child,
+                   const char *cmd, Eina_Bool is_horizontal);
+     void (*size_eval)(Term_Container *container, Sizeinfo *info);
+     void (*swallow)(Term_Container *container, Term_Container *orig,
+                     Term_Container *new_child);
+     void (*focus)(Term_Container *tc, Term_Container *relative);
+     void (*unfocus)(Term_Container *tc, Term_Container *relative);
+     void (*set_title)(Term_Container *tc, Term_Container *child, const char 
*title);
+     void (*bell)(Term_Container *tc, Term_Container *child);
+     void (*close)(Term_Container *container, Term_Container *child);
+     void (*update)(Term_Container *tc);
+};
+
+#endif
diff --git a/src/bin/win.c b/src/bin/win.c
index 0f1840b..5f4425f 100644
--- a/src/bin/win.c
+++ b/src/bin/win.c
@@ -1,3 +1,4 @@
+#include <assert.h>
 #include <Elementary.h>
 #include "win.h"
 #include "termcmd.h"
@@ -12,6 +13,7 @@
 #include "dbus.h"
 #include "sel.h"
 #include "controls.h"
+#include "term_container.h"
 
 #if (ELM_VERSION_MAJOR == 1) && (ELM_VERSION_MINOR < 8)
   #define PANES_TOP "left"
@@ -39,6 +41,7 @@ struct _Term
    Win         *wn;
    Config      *config;
 
+   Term_Container *container;
    Evas_Object *bg;
    Evas_Object *base;
    Evas_Object *termio;
@@ -58,7 +61,6 @@ struct _Term
       int       x, y;
    } down;
    int refcnt;
-   unsigned char focused : 1;
    unsigned char hold : 1;
    unsigned char unswallowed : 1;
    unsigned char missed_bell : 1;
@@ -66,10 +68,47 @@ struct _Term
    unsigned char popmedia_deleted : 1;
 };
 
+typedef struct _Solo Solo;
+typedef struct _Tabs Tabs;
+
+struct _Solo {
+     Term_Container tc;
+     Term *term;
+};
+
+typedef struct _Tab_Item Tab_Item;
+struct _Tab_Item {
+     Term_Container *tc;
+     Evas_Object *obj;
+     void *selector_entry;
+};
+
+struct _Tabs {
+     Term_Container tc;
+     Evas_Object *selector;
+     Evas_Object *selector_bg;
+     Eina_List *tabs; // Tab_Item
+     Tab_Item *current;
+};
+
+struct _Split
+{
+   Term_Container tc;
+   Term_Container *tc1, *tc2; // left/right or top/bottom child splits, null 
if leaf
+   Evas_Object *panes;
+   Term_Container *last_focus;
+
+   unsigned char is_horizontal : 1;
+};
+
+
 
 
 struct _Win
 {
+   Term_Container tc;
+
+   Term_Container *child;
    Evas_Object *win;
    Evas_Object *conform;
    Evas_Object *backbg;
@@ -85,130 +124,326 @@ struct _Win
    unsigned char cmdbox_up : 1;
 };
 
-struct _Split
-{
-   Win         *wn; // win this split belongs to
-   Split       *parent; // the parent split or null if toplevel
-   Split       *s1, *s2; // left/right or top/bottom child splits, null if leaf
-   Term        *term; // if leaf node this is not null - the CURRENT term from 
terms list
-   Eina_List   *terms; // list of terms in the "tabs"
-   Evas_Object *panes; // null if a leaf node
-   Evas_Object *sel; // multi "tab" selector is active
-   Evas_Object *sel_bg; // multi "tab" selector wrapper edje obj for styling
-   unsigned char horizontal : 1;
-};
-
 /* }}} */
 static Eina_List   *wins = NULL;
 
-
-static void _term_resize_track_start(Split *sp);
-static void _split_tabcount_update(Split *sp, Term *tm);
-static Term * win_focused_term_get(Win *wn);
-static Split * _split_find(Evas_Object *win, Evas_Object *term, Term **ptm);
-static void _term_focus(Term *term);
-static void term_free(Term *term);
-static void _split_free(Split *sp);
-static void _sel_restore(Split *sp);
-static void _sel_go(Split *sp, Term *term);
-static void _term_resize_track_stop(Split *sp);
-static void _split_merge(Split *spp, Split *sp, const char *slot);
-static void _term_focus_show(Split *sp, Term *term);
-static void _main_term_bg_redo(Term *term);
+static Eina_Bool _win_is_focused(Win *wn);
+static Eina_Bool _term_is_focused(Term *term);
+static Term_Container *_solo_new(Term *term, Win *wn);
+static Term_Container *_split_new(Term_Container *tc1, Term_Container *tc2, 
Eina_Bool is_horizontal);
+static Term_Container *_tabs_new(Term_Container *child, Term_Container 
*parent);
+static void _term_focus(Term *term, Eina_Bool force);
+static void _term_free(Term *term);
 static void _term_media_update(Term *term, const Config *config);
 static void _term_miniview_check(Term *term);
 static void _popmedia_queue_process(Term *term);
+static void _cb_size_hint(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, 
void *event EINA_UNUSED);
+static void _tab_new_cb(void *data, Evas_Object *obj EINA_UNUSED, void 
*event_info EINA_UNUSED);
+static Tab_Item* tab_item_new(Tabs *tabs, Term_Container *child);
+static void _tabs_refresh(Tabs *tabs);
 
-void
-win_add_split(Win *wn, Term *term)
+
+/* {{{ Solo */
+
+static Evas_Object *
+_solo_get_evas_object(Term_Container *container)
+{
+   Solo *solo;
+   assert (container->type == TERM_CONTAINER_TYPE_SOLO);
+   solo = (Solo*)container;
+
+   return solo->term->bg;
+}
+
+static Term *
+_solo_focused_term_get(Term_Container *container)
+{
+   Solo *solo;
+   assert (container->type == TERM_CONTAINER_TYPE_SOLO);
+   solo = (Solo*)container;
+
+   return container->is_focused ? solo->term : NULL;
+}
+
+static Term *
+_solo_find_term_at_coords(Term_Container *tc,
+                          Evas_Coord mx EINA_UNUSED,
+                          Evas_Coord my EINA_UNUSED)
+{
+   Solo *solo;
+   assert (tc->type == TERM_CONTAINER_TYPE_SOLO);
+   solo = (Solo*) tc;
+
+   return solo->term;
+}
+
+static void
+_solo_size_eval(Term_Container *container, Sizeinfo *info)
+{
+   Term *term;
+   int mw = 0, mh = 0;
+   Solo *solo;
+   assert (container->type == TERM_CONTAINER_TYPE_SOLO);
+   solo = (Solo*)container;
+
+   term = solo->term;
+
+   info->min_w = term->min_w;
+   info->min_h = term->min_h;
+   info->step_x = term->step_x;
+   info->step_y = term->step_y;
+   info->req_w = term->req_w;
+   info->req_h = term->req_h;
+   if (!evas_object_data_get(term->termio, "sizedone"))
+     {
+        evas_object_data_set(term->termio, "sizedone", term->termio);
+        info->req = 1;
+     }
+   evas_object_size_hint_min_get(term->bg, &mw, &mh);
+   info->bg_min_w = mw;
+   info->bg_min_h = mh;
+}
+
+static void
+_solo_close(Term_Container *tc, Term_Container *child EINA_UNUSED)
+{
+   tc->parent->close(tc->parent, tc);
+
+   eina_stringshare_del(tc->title);
+
+   free(tc);
+}
+
+static void
+_solo_tabs_new(Term_Container *tc)
+{
+   if (tc->parent->type != TERM_CONTAINER_TYPE_TABS)
+     _tabs_new(tc, tc->parent);
+   _tab_new_cb(tc->parent, NULL, NULL);
+}
+
+static void
+_solo_split(Term_Container *tc, Term_Container *child EINA_UNUSED,
+            const char *cmd, Eina_Bool is_horizontal)
+{
+   tc->parent->split(tc->parent, tc, cmd, is_horizontal);
+}
+
+static Term *
+_solo_term_next(Term_Container *tc, Term_Container *child EINA_UNUSED)
+{
+   return tc->parent->term_next(tc->parent, tc);
+}
+
+static Term *
+_solo_term_prev(Term_Container *tc, Term_Container *child EINA_UNUSED)
 {
-   Split *sp;
+   return tc->parent->term_prev(tc->parent, tc);
+}
 
-   sp = wn->split = calloc(1, sizeof(Split));
-   sp->wn = wn;
-   sp->term = term;
-   sp->terms = eina_list_append(sp->terms, sp->term);
-   _term_resize_track_start(sp);
-   _split_tabcount_update(sp, sp->term);
+static Term *
+_solo_term_first(Term_Container *tc)
+{
+   Solo *solo;
+   assert (tc->type == TERM_CONTAINER_TYPE_SOLO);
+   solo = (Solo*) tc;
+   return solo->term;
 }
 
 static Term *
-_find_term_under_mouse(Win *wn)
+_solo_term_last(Term_Container *tc)
+{
+   Solo *solo;
+   assert (tc->type == TERM_CONTAINER_TYPE_SOLO);
+   solo = (Solo*) tc;
+   return solo->term;
+}
+
+static void
+_solo_set_title(Term_Container *tc, Term_Container *child EINA_UNUSED,
+                const char *title)
+{
+   eina_stringshare_del(tc->title);
+   tc->title = eina_stringshare_add(title);
+   tc->parent->set_title(tc->parent, tc, title);
+}
+
+static void
+_solo_bell(Term_Container *tc, Term_Container *child EINA_UNUSED)
 {
-   Evas_Coord mx, my;
-   Split *sp;
+   Solo *solo;
+   Term *term;
+
+   assert (tc->type == TERM_CONTAINER_TYPE_SOLO);
+   solo = (Solo*) tc;
+   term = solo->term;
 
-   evas_pointer_canvas_xy_get(evas_object_evas_get(wn->win), &mx, &my);
+   if (tc->is_focused)
+     return;
+   term->missed_bell = EINA_TRUE;
 
-   sp = wn->split;
-   while (sp)
+   if (!tc->wn->config->disable_visual_bell)
      {
-        if (sp->term)
+        edje_object_signal_emit(term->bg, "bell", "terminology");
+        edje_object_signal_emit(term->base, "bell", "terminology");
+        if (tc->wn->config->bell_rings)
           {
-            return sp->term;
+             edje_object_signal_emit(term->bg, "bell,ring", "terminology");
+             edje_object_signal_emit(term->base, "bell,ring", "terminology");
           }
-        else
-          {
-             Evas_Coord ox, oy, ow, oh;
-             Evas_Object *o1 = sp->s1->panes ? sp->s1->panes : 
sp->s1->term->base;
+     }
+   tc->parent->bell(tc->parent, tc);
+}
 
-             evas_object_geometry_get(o1, &ox, &oy, &ow, &oh);
-             if (ELM_RECTS_INTERSECT(ox, oy, ow, oh, mx, my, 1, 1))
-               {
-                  sp = sp->s1;
-               }
-             else
-               {
-                  sp = sp->s2;
-               }
-          }
+static void
+_solo_unfocus(Term_Container *tc, Term_Container *relative)
+{
+   Solo *solo;
+   Term *term;
+
+   assert (tc->type == TERM_CONTAINER_TYPE_SOLO);
+   solo = (Solo*) tc;
+   term = solo->term;
+
+   if (!tc->is_focused)
+     return;
+
+   if (tc->parent != relative)
+     tc->parent->unfocus(tc->parent, tc);
+
+   edje_object_signal_emit(term->bg, "focus,out", "terminology");
+   edje_object_signal_emit(term->base, "focus,out", "terminology");
+
+   if (!tc->wn->cmdbox_up)
+     elm_object_focus_set(term->termio, EINA_FALSE);
+
+   tc->is_focused = EINA_FALSE;
+}
+
+static void
+_solo_focus(Term_Container *tc, Term_Container *relative)
+{
+   Solo *solo;
+   Term *term;
+   const char *title;
+
+   assert (tc->type == TERM_CONTAINER_TYPE_SOLO);
+   solo = (Solo*) tc;
+   term = solo->term;
+
+   if (tc->is_focused)
+     return;
+
+   term->missed_bell = EINA_FALSE;
+
+   if (tc->parent != relative)
+     tc->parent->focus(tc->parent, tc);
+
+   tc->is_focused = EINA_TRUE;
+   edje_object_signal_emit(term->bg, "focus,in", "terminology");
+   edje_object_signal_emit(term->base, "focus,in", "terminology");
+   if (term->wn->cmdbox)
+     elm_object_focus_set(term->wn->cmdbox, EINA_FALSE);
+   elm_object_focus_set(term->termio, EINA_TRUE);
+
+   title = termio_title_get(term->termio);
+   if (title)
+      tc->set_title(tc, tc, title);
+
+   if (term->missed_bell)
+     term->missed_bell = EINA_FALSE;
+}
+
+static void
+_solo_update(Term_Container *tc)
+{
+   assert (tc->type == TERM_CONTAINER_TYPE_SOLO);
+}
+
+static Term_Container *
+_solo_new(Term *term, Win *wn)
+{
+   Term_Container *tc = NULL;
+   Solo *solo = NULL;
+   solo = calloc(1, sizeof(Solo));
+   if (!solo)
+     {
+        free(solo);
+        return NULL;
      }
-   return NULL;
+
+   tc = (Term_Container*)solo;
+   tc->term_next = _solo_term_next;
+   tc->term_prev = _solo_term_prev;
+   tc->term_first = _solo_term_first;
+   tc->term_last = _solo_term_last;
+   tc->focused_term_get = _solo_focused_term_get;
+   tc->get_evas_object = _solo_get_evas_object;
+   tc->split = _solo_split;
+   tc->find_term_at_coords = _solo_find_term_at_coords;
+   tc->size_eval = _solo_size_eval;
+   tc->swallow = NULL;
+   tc->focus = _solo_focus;
+   tc->unfocus = _solo_unfocus;
+   tc->set_title = _solo_set_title;
+   tc->bell = _solo_bell;
+   tc->close = _solo_close;
+   tc->update = _solo_update;
+   tc->title = eina_stringshare_add("Terminology");
+   tc->type = TERM_CONTAINER_TYPE_SOLO;
+
+   tc->parent = NULL;
+   tc->wn = wn;
+
+   solo->term = term;
+
+   term->container = tc;
+
+   return tc;
 }
 
+/* }}} */
+/* {{{ Win */
+
 static void
-_cb_win_focus_in(void *data, Evas_Object *obj EINA_UNUSED, void *event 
EINA_UNUSED)
+_cb_win_focus_in(void *data,
+                 Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
 {
    Win *wn = data;
+   Term_Container *tc = (Term_Container*) wn;
    Term *term;
-   Split *sp;
 
-   if (!wn->focused) elm_win_urgent_set(wn->win, EINA_FALSE);
-   wn->focused = EINA_TRUE;
+   if (!tc->is_focused) elm_win_urgent_set(wn->win, EINA_FALSE);
+   tc->is_focused = EINA_TRUE;
    if ((wn->cmdbox_up) && (wn->cmdbox))
      elm_object_focus_set(wn->cmdbox, EINA_TRUE);
 
-   term = win_focused_term_get(wn);
+   term = tc->focused_term_get(tc);
 
    if ( wn->config->mouse_over_focus )
      {
         Term *term_mouse;
+        Evas_Coord mx, my;
 
-        term_mouse = _find_term_under_mouse(wn);
+        evas_pointer_canvas_xy_get(evas_object_evas_get(wn->win), &mx, &my);
+        term_mouse = tc->find_term_at_coords(tc, mx, my);
         if ((term_mouse) && (term_mouse != term))
           {
              if (term)
                {
                   edje_object_signal_emit(term->bg, "focus,out", 
"terminology");
                   edje_object_signal_emit(term->base, "focus,out", 
"terminology");
-                  if (!wn->cmdbox_up) elm_object_focus_set(term->termio, 
EINA_FALSE);
+                  if (!wn->cmdbox_up)
+                    elm_object_focus_set(term->termio, EINA_FALSE);
                }
              term = term_mouse;
           }
      }
 
-   if (!term) return;
-   sp = _split_find(wn->win, term->termio, NULL);
-   if (sp->sel)
-     {
-        if (!wn->cmdbox_up) elm_object_focus_set(sp->sel, EINA_TRUE);
-     }
+   if (term)
+     _term_focus(term, EINA_TRUE);
    else
-     {
-        edje_object_signal_emit(term->bg, "focus,in", "terminology");
-        edje_object_signal_emit(term->base, "focus,in", "terminology");
-        if (!wn->cmdbox_up) elm_object_focus_set(term->termio, EINA_TRUE);
-     }
+     tc->focus(tc, tc);
 }
 
 static void
@@ -216,54 +451,47 @@ _cb_win_focus_out(void *data, Evas_Object *obj 
EINA_UNUSED,
                   void *event EINA_UNUSED)
 {
    Win *wn = data;
-   Term *term;
+   Term_Container *tc = (Term_Container*) wn;
 
-   wn->focused = EINA_FALSE;
-   if ((wn->cmdbox_up) && (wn->cmdbox))
-     elm_object_focus_set(wn->cmdbox, EINA_FALSE);
-   term = win_focused_term_get(wn);
-   if (!term) return;
-   edje_object_signal_emit(term->bg, "focus,out", "terminology");
-   edje_object_signal_emit(term->base, "focus,out", "terminology");
-   if (!wn->cmdbox_up) elm_object_focus_set(term->termio, EINA_FALSE);
+   tc->unfocus(tc, NULL);
 }
 
-static void
-_cb_term_mouse_in(void *data, Evas *e EINA_UNUSED,
-                  Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
+static Eina_Bool
+_win_is_focused(Win *wn)
 {
-   Term *term = data;
-   Config *config;
+   Term_Container *tc;
+   if (!wn)
+     return EINA_FALSE;
 
-   if ((!term) || (!term->termio)) return;
+   tc = (Term_Container*) wn;
 
-   config = termio_config_get(term->termio);
+   return tc->is_focused;
+}
 
-   if ((!config) || (!config->mouse_over_focus)) return;
-   if ((!term->wn) || (!term->wn->focused)) return;
 
-   term->focused = EINA_TRUE;
+int win_term_set(Win *wn, Term *term)
+{
+   Term_Container *tc_win = NULL, *tc_child = NULL;
+   Evas_Object *base = win_base_get(wn);
+   Evas *evas = evas_object_evas_get(base);
 
-   _term_focus(term);
-}
+   tc_child = _solo_new(term, wn);
+   if (!tc_child)
+     goto bad;
 
-static void
-_cb_term_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj 
EINA_UNUSED, void *event )
-{
-   Evas_Event_Mouse_Down *ev = event;
-   Term *term = data;
-   Term *term2;
+   tc_win = (Term_Container*) wn;
 
-   term2 = win_focused_term_get(term->wn);
-   if (term == term2) return;
-   term->down.x = ev->canvas.x;
-   term->down.y = ev->canvas.y;
-   _term_focus(term);
-}
+   tc_win->swallow(tc_win, NULL, tc_child);
 
+   _cb_size_hint(term, evas, term->termio, NULL);
 
+   return 0;
+
+bad:
+   free(tc_child);
+   return -1;
+}
 
-/* {{{ Win */
 
 Evas_Object *
 win_base_get(Win *wn)
@@ -348,7 +576,8 @@ main_trans_update(const Config *config)
 
 
 static void
-_cb_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void 
*event EINA_UNUSED)
+_cb_del(void *data, Evas *e EINA_UNUSED,
+        Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
 {
    Win *wn = data;
 
@@ -382,11 +611,6 @@ win_free(Win *wn)
         evas_object_del(wn->cmdbox);
         wn->cmdbox = NULL;
      }
-   if (wn->split)
-     {
-        _split_free(wn->split);
-        wn->split = NULL;
-     }
    if (wn->win)
      {
         evas_object_event_callback_del_full(wn->win, EVAS_CALLBACK_DEL, 
_cb_del, wn);
@@ -449,311 +673,763 @@ tg_win_add(const char *name, const char *role, const 
char *title, const char *ic
    return win;
 }
 
-Win *
-win_new(const char *name, const char *role, const char *title,
-        const char *icon_name, Config *config,
-        Eina_Bool fullscreen, Eina_Bool iconic,
-        Eina_Bool borderless, Eina_Bool override,
-        Eina_Bool maximized)
+static Evas_Object *
+_win_get_evas_object(Term_Container *tc)
 {
    Win *wn;
-   Evas_Object *o;
+   assert (tc->type == TERM_CONTAINER_TYPE_WIN);
 
-   wn = calloc(1, sizeof(Win));
-   if (!wn) return NULL;
+   wn = (Win*) tc;
 
-   wn->win = tg_win_add(name, role, title, icon_name);
-   if (!wn->win)
-     {
-        free(wn);
-        return NULL;
-     }
+   return wn->win;
+}
 
-   config_default_font_set(config, evas_object_evas_get(wn->win));
+static Term *
+_win_term_next(Term_Container *tc EINA_UNUSED, Term_Container *child)
+{
+   return child->term_first(child);
+}
 
-   wn->config = config_fork(config);
+static Term *
+_win_term_prev(Term_Container *tc EINA_UNUSED, Term_Container *child)
+{
+   return child->term_last(child);
+}
 
-   evas_object_event_callback_add(wn->win, EVAS_CALLBACK_DEL, _cb_del, wn);
+static Term *
+_win_term_first(Term_Container *tc)
+{
+   Win *wn;
+   assert (tc->type == TERM_CONTAINER_TYPE_WIN);
 
-   if (fullscreen) elm_win_fullscreen_set(wn->win, EINA_TRUE);
-   if (iconic) elm_win_iconified_set(wn->win, EINA_TRUE);
-   if (borderless) elm_win_borderless_set(wn->win, EINA_TRUE);
-   if (override) elm_win_override_set(wn->win, EINA_TRUE);
-   if (maximized) elm_win_maximized_set(wn->win, EINA_TRUE);
+   wn = (Win*) tc;
+   return wn->child->term_first(wn->child);
+}
 
-   wn->backbg = o = evas_object_rectangle_add(evas_object_evas_get(wn->win));
-   evas_object_color_set(o, 0, 0, 0, 255);
-   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
-   evas_object_size_hint_fill_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
-   elm_win_resize_object_add(wn->win, o);
-   evas_object_show(o);
+static Term *
+_win_term_last(Term_Container *tc)
+{
+   Win *wn;
+   assert (tc->type == TERM_CONTAINER_TYPE_WIN);
 
-   wn->conform = o = elm_conformant_add(wn->win);
-   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
-   evas_object_size_hint_fill_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
-   elm_win_resize_object_add(wn->win, o);
-   evas_object_show(o);
+   wn = (Win*) tc;
+   return wn->child->term_last(wn->child);
+}
 
-   wn->base = o = edje_object_add(evas_object_evas_get(wn->win));
-   theme_apply(o, config, "terminology/base");
-   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
-   evas_object_size_hint_fill_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
-   elm_object_content_set(wn->conform, o);
-   evas_object_show(o);
+static Term *
+_win_focused_term_get(Term_Container *tc)
+{
+   Win *wn;
+   assert (tc->type == TERM_CONTAINER_TYPE_WIN);
 
-   evas_object_smart_callback_add(wn->win, "focus,in", _cb_win_focus_in, wn);
-   evas_object_smart_callback_add(wn->win, "focus,out", _cb_win_focus_out, wn);
+   wn = (Win*) tc;
 
-   wins = eina_list_append(wins, wn);
-   return wn;
+   return tc->is_focused ? wn->child->focused_term_get(wn->child) : NULL;
 }
 
-void
-main_close(Evas_Object *win, Evas_Object *term)
+static Term *
+_win_find_term_at_coords(Term_Container *tc,
+                         Evas_Coord mx, Evas_Coord my)
 {
-   Term *tm = NULL;
-   Split *sp = _split_find(win, term, &tm);
-   Split *spp, *spkeep = NULL;
-   Eina_List *l;
-   const char *slot = PANES_TOP;
-   Eina_Bool term_was_focused;
+   Win *wn;
+   assert (tc->type == TERM_CONTAINER_TYPE_WIN);
 
-   if (!sp) return;
-   if (!sp->term) return;
-   if (!tm) return;
-   if (sp->sel) _sel_restore(sp);
-   spp = sp->parent;
-   sp->wn->terms = eina_list_remove(sp->wn->terms, tm);
+   wn = (Win*) tc;
 
-   term_was_focused = tm->focused;
+   return wn->child->find_term_at_coords(wn->child, mx, my);
+}
 
-   if (spp)
-     {
-        if (eina_list_count(sp->terms) <= 1)
-          {
-             if (sp == spp->s2)
-               {
-                  spkeep = spp->s1;
-                  spp->s2 = NULL;
-               }
-             else
-               {
-                  spkeep = spp->s2;
-                  spp->s1 = NULL;
-               }
-          }
-        l = eina_list_data_find_list(sp->terms, tm);
-        _term_resize_track_stop(sp);
-        term_unref(tm);
-        if (l)
-          {
-             if (tm == sp->term)
-               {
-                  if (l->next) sp->term = l->next->data;
-                  else if (l->prev) sp->term = l->prev->data;
-                  else sp->term = NULL;
-               }
-             sp->terms = eina_list_remove_list(sp->terms, l);
-          }
-        else
+static void
+_win_size_eval(Term_Container *tc, Sizeinfo *info)
+{
+   Win *wn;
+   assert (tc->type == TERM_CONTAINER_TYPE_WIN);
+
+   wn = (Win*) tc;
+
+   wn->child->size_eval(wn->child, info);
+}
+
+static void
+_win_swallow(Term_Container *tc, Term_Container *orig,
+             Term_Container *new_child)
+{
+   Win *wn;
+   Evas_Object *base;
+   Evas_Object *o;
+   Evas_Coord x, y, w, h;
+
+   assert (tc->type == TERM_CONTAINER_TYPE_WIN);
+
+   wn = (Win*) tc;
+   base = win_base_get(wn);
+
+   if (orig)
+     {
+        o = edje_object_part_swallow_get(base, "terminology.content");
+        edje_object_part_unswallow(base, o);
+        evas_object_hide(o);
+        o = orig->get_evas_object(orig);
+        evas_object_geometry_get(o, &x, &y, &w, &h);
+     }
+   o = new_child->get_evas_object(new_child);
+   edje_object_part_swallow(base, "terminology.content", o);
+   if (orig)
+     evas_object_geometry_set(o, x, y, w, h);
+   evas_object_show(o);
+   new_child->parent = tc;
+   wn->child = new_child;
+   if (tc->is_focused)
+     new_child->focus(new_child, tc);
+}
+
+static void
+_win_close(Term_Container *tc, Term_Container *child EINA_UNUSED)
+{
+   Win *wn;
+   assert (tc->type == TERM_CONTAINER_TYPE_WIN);
+
+   wn = (Win*) tc;
+   eina_stringshare_del(tc->title);
+   win_free(wn);
+}
+
+static void
+_win_focus(Term_Container *tc, Term_Container *child)
+{
+   Win *wn;
+   assert (tc->type == TERM_CONTAINER_TYPE_WIN);
+
+   wn = (Win*) tc;
+   if (child != wn->child)
+     wn->child->focus(wn->child, tc);
+
+   if (!tc->is_focused) elm_win_urgent_set(wn->win, EINA_FALSE);
+   tc->is_focused = EINA_TRUE;
+}
+
+static void
+_win_unfocus(Term_Container *tc, Term_Container *relative)
+{
+   Win *wn;
+   assert (tc->type == TERM_CONTAINER_TYPE_WIN);
+
+   wn = (Win*) tc;
+
+   tc->is_focused = EINA_FALSE;
+   if (relative != wn->child)
+     wn->child->unfocus(wn->child, tc);
+
+   if ((wn->cmdbox_up) && (wn->cmdbox))
+     elm_object_focus_set(wn->cmdbox, EINA_FALSE);
+}
+
+static void
+_win_bell(Term_Container *tc, Term_Container *child EINA_UNUSED)
+{
+   Win *wn;
+   assert (tc->type == TERM_CONTAINER_TYPE_WIN);
+
+   wn = (Win*) tc;
+
+   if (tc->is_focused) return;
+
+   if (wn->config->urg_bell)
+     {
+        elm_win_urgent_set(wn->win, EINA_TRUE);
+     }
+}
+
+static void
+_win_set_title(Term_Container *tc, Term_Container *child EINA_UNUSED,
+               const char *title)
+{
+   Win *wn;
+   assert (tc->type == TERM_CONTAINER_TYPE_WIN);
+
+   wn = (Win*) tc;
+
+   eina_stringshare_del(tc->title);
+   tc->title =  eina_stringshare_ref(title);
+
+   elm_win_title_set(wn->win, title);
+}
+
+static void
+_win_split(Term_Container *tc, Term_Container *child, const char *cmd,
+           Eina_Bool is_horizontal)
+{
+   Term *tm_new, *tm;
+   Term_Container *tc_split, *tc_solo_new;
+   Win *wn;
+   Evas_Object *obj_split;
+   char buf[PATH_MAX], *wdir = NULL;
+
+   assert (tc->type == TERM_CONTAINER_TYPE_WIN);
+   wn = (Win*) tc;
+
+   tm = tc->focused_term_get(tc);
+   if (tm && termio_cwd_get(tm->termio, buf, sizeof(buf)))
+     wdir = buf;
+   tm_new = term_new(wn, wn->config,
+                     cmd, wn->config->login_shell, wdir,
+                     80, 24, EINA_FALSE);
+   tc_solo_new = _solo_new(tm_new, wn);
+   evas_object_data_set(tm_new->termio, "sizedone", tm_new->termio);
+
+   tc_split = _split_new(child, tc_solo_new, is_horizontal);
+
+   obj_split = tc_split->get_evas_object(tc_split);
+
+   tc_split->is_focused = tc->is_focused;
+   tc->swallow(tc, child, tc_split);
+
+   evas_object_show(obj_split);
+}
+
+static void
+_win_update(Term_Container *tc)
+{
+   Win *wn;
+
+   assert (tc->type == TERM_CONTAINER_TYPE_WIN);
+   wn = (Win*) tc;
+
+   wn->child->update(wn->child);
+}
+
+Win *
+win_new(const char *name, const char *role, const char *title,
+        const char *icon_name, Config *config,
+        Eina_Bool fullscreen, Eina_Bool iconic,
+        Eina_Bool borderless, Eina_Bool override,
+        Eina_Bool maximized)
+{
+   Win *wn;
+   Evas_Object *o;
+   Term_Container *tc;
+
+   wn = calloc(1, sizeof(Win));
+   if (!wn) return NULL;
+
+   wn->win = tg_win_add(name, role, title, icon_name);
+   if (!wn->win)
+     {
+        free(wn);
+        return NULL;
+     }
+
+   tc = (Term_Container*) wn;
+   tc->term_next = _win_term_next;
+   tc->term_prev = _win_term_prev;
+   tc->term_first = _win_term_first;
+   tc->term_last = _win_term_last;
+   tc->focused_term_get = _win_focused_term_get;
+   tc->get_evas_object = _win_get_evas_object;
+   tc->split = _win_split;
+   tc->find_term_at_coords = _win_find_term_at_coords;
+   tc->size_eval = _win_size_eval;
+   tc->swallow = _win_swallow;
+   tc->focus = _win_focus;
+   tc->unfocus = _win_unfocus;
+   tc->set_title = _win_set_title;
+   tc->bell = _win_bell;
+   tc->close = _win_close;
+   tc->update = _win_update;
+   tc->title = eina_stringshare_add("Terminology");
+   tc->type = TERM_CONTAINER_TYPE_WIN;
+   tc->wn = wn;
+
+   config_default_font_set(config, evas_object_evas_get(wn->win));
+
+   wn->config = config_fork(config);
+
+   evas_object_event_callback_add(wn->win, EVAS_CALLBACK_DEL, _cb_del, wn);
+
+   if (fullscreen) elm_win_fullscreen_set(wn->win, EINA_TRUE);
+   if (iconic) elm_win_iconified_set(wn->win, EINA_TRUE);
+   if (borderless) elm_win_borderless_set(wn->win, EINA_TRUE);
+   if (override) elm_win_override_set(wn->win, EINA_TRUE);
+   if (maximized) elm_win_maximized_set(wn->win, EINA_TRUE);
+
+   wn->backbg = o = evas_object_rectangle_add(evas_object_evas_get(wn->win));
+   evas_object_color_set(o, 0, 0, 0, 255);
+   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_fill_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_win_resize_object_add(wn->win, o);
+   evas_object_show(o);
+
+   wn->conform = o = elm_conformant_add(wn->win);
+   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_fill_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_win_resize_object_add(wn->win, o);
+   evas_object_show(o);
+
+   wn->base = o = edje_object_add(evas_object_evas_get(wn->win));
+   theme_apply(o, config, "terminology/base");
+   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_fill_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_object_content_set(wn->conform, o);
+   evas_object_show(o);
+
+   evas_object_smart_callback_add(wn->win, "focus,in", _cb_win_focus_in, wn);
+   evas_object_smart_callback_add(wn->win, "focus,out", _cb_win_focus_out, wn);
+
+   wins = eina_list_append(wins, wn);
+   return wn;
+}
+
+void
+main_close(Evas_Object *win, Evas_Object *term)
+{
+   Term *tm;
+   Term_Container *tc;
+   Win *wn = _win_find(win);
+
+   if (!wn) return;
+
+   tm = evas_object_data_get(term, "term");
+   if (!tm) return;
+
+   wn->terms = eina_list_remove(wn->terms, tm);
+   tc = tm->container;
+
+   tc->close(tc, tc);
+
+   term_unref(tm);
+}
+
+/* }}} */
+/* {{{ Splits */
+
+static Term *
+_split_term_next(Term_Container *tc, Term_Container *child)
+{
+   Split *split;
+
+   assert (tc->type == TERM_CONTAINER_TYPE_SPLIT);
+   split = (Split*) tc;
+
+   if (child == split->tc1)
+     return split->tc2->term_first(split->tc2);
+   else
+     return tc->parent->term_next(tc->parent, tc);
+}
+
+static Term *
+_split_term_prev(Term_Container *tc, Term_Container *child)
+{
+   Split *split;
+
+   assert (tc->type == TERM_CONTAINER_TYPE_SPLIT);
+   split = (Split*) tc;
+
+   if (child == split->tc2)
+     return split->tc1->term_last(split->tc1);
+   else
+     return tc->parent->term_prev(tc->parent, tc);
+}
+
+static Term *
+_split_term_first(Term_Container *tc)
+{
+   Split *split;
+
+   assert (tc->type == TERM_CONTAINER_TYPE_SPLIT);
+   split = (Split*) tc;
+
+   return split->tc1->term_first(split->tc1);
+}
+
+static Term *
+_split_term_last(Term_Container *tc)
+{
+   Split *split;
+
+   assert (tc->type == TERM_CONTAINER_TYPE_SPLIT);
+   split = (Split*) tc;
+
+   return split->tc2->term_last(split->tc2);
+}
+
+static Evas_Object *
+_split_get_evas_object(Term_Container *tc)
+{
+   Split *split;
+
+   assert (tc->type == TERM_CONTAINER_TYPE_SPLIT);
+   split = (Split*) tc;
+
+   return split->panes;
+}
+
+static void
+_split_size_eval(Term_Container *tc, Sizeinfo *info)
+{
+   Evas_Coord mw = 0, mh = 0;
+   Term_Container *tc1, *tc2;
+   Sizeinfo inforet = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+   Split *split;
+
+   assert (tc->type == TERM_CONTAINER_TYPE_SPLIT);
+   split = (Split*) tc;
+
+   tc1 = split->tc1;
+   tc2 = split->tc2;
+
+   info->min_w = 0;
+   info->min_h = 0;
+   info->req_w = 0;
+   info->req_h = 0;
+
+   evas_object_size_hint_min_get(split->panes, &mw, &mh);
+   info->bg_min_w = mw;
+   info->bg_min_h = mh;
+
+   if (split->is_horizontal)
+     {
+        tc1->size_eval(tc1, &inforet);
+        info->req |= inforet.req;
+        mh -= inforet.min_h;
+        if (info->req)
           {
-             sp->term = NULL;
+             info->req_h += inforet.req_h;
+             info->req_w = inforet.req_w;
           }
-        if (!sp->term)
-          {
-             _split_free(sp);
-             sp = NULL;
-             if ((spp->parent) && (spp->parent->s2 == spp))
-               slot = PANES_BOTTOM;
-             _split_merge(spp, spkeep, slot);
 
-             if (term_was_focused)
-               {
-                  tm = spp->term;
-                  sp = spp;
-                  while (tm == NULL)
-                    {
-                       tm = spp->term;
-                       sp = spp;
-                       spp = spp->s1;
-                    }
-                  _term_focus(tm);
-                  _term_focus_show(sp, tm);
-                  _split_tabcount_update(sp, tm);
-               }
-          }
-        else
+        tc2->size_eval(tc2, &inforet);
+        info->req |= inforet.req;
+        mh -= inforet.min_h;
+        if (info->req)
           {
-             _term_resize_track_start(sp);
-             if ((sp->parent) && (sp->parent->s2 == sp)) slot = PANES_BOTTOM;
-             elm_object_part_content_set(sp->parent->panes, slot,
-                                         sp->term->bg);
-             evas_object_show(sp->term->bg);
-             if (term_was_focused)
-               {
-                  _term_focus(sp->term);
-                  _term_focus_show(sp, sp->term);
-                  _split_tabcount_update(sp, sp->term);
-               }
+             info->req_h += inforet.req_h;
+             info->req_w = inforet.req_w;
           }
-        if (sp) _split_tabcount_update(sp, sp->term);
+        info->req_h += mh;
+        if (info->req)
+          info->req_w += mw - inforet.min_w - inforet.step_x;
      }
    else
      {
-        _term_resize_track_stop(sp);
-        edje_object_part_unswallow(sp->wn->base, sp->term->bg);
-        l = eina_list_data_find_list(sp->terms, tm);
-        term_unref(tm);
-        if (l)
-          {
-             if (tm == sp->term)
-               {
-                  if (l->next) sp->term = l->next->data;
-                  else if (l->prev) sp->term = l->prev->data;
-                  else sp->term = NULL;
-               }
-             sp->terms = eina_list_remove_list(sp->terms, l);
-          }
-        else
+        tc1->size_eval(tc1, &inforet);
+        info->req |= inforet.req;
+        mw -= inforet.min_w;
+        if (info->req)
           {
-             sp->term = NULL;
+             info->req_w += inforet.req_w;
+             info->req_h = inforet.req_h;
           }
-        if (sp->term)
+
+        tc2->size_eval(tc2, &inforet);
+        info->req |= inforet.req;
+        mw -= inforet.min_w;
+        if (info->req)
           {
-             _term_resize_track_start(sp);
-             edje_object_part_swallow(sp->wn->base, "terminology.content",
-                                      sp->term->bg);
-             evas_object_show(sp->term->bg);
-             _term_focus(sp->term);
-             _term_focus_show(sp, sp->term);
-             _split_tabcount_update(sp, sp->term);
+             info->req_w += inforet.req_w;
+             info->req_h = inforet.req_h;
           }
-        if (!sp->wn->terms) evas_object_del(sp->wn->win);
-        else _split_tabcount_update(sp, sp->term);
+        info->req_w += mw;
+        if (info->req)
+          info->req_h += mh - inforet.min_h - inforet.step_y;
+     }
+   info->step_x = inforet.step_x;
+   info->step_y = inforet.step_y;
+}
+
+static void
+_split_swallow(Term_Container *tc, Term_Container *orig,
+               Term_Container *new_child)
+{
+   Split *split;
+   Evas_Object *o;
+   Evas_Coord x, y, w, h;
+
+   assert (tc->type == TERM_CONTAINER_TYPE_SPLIT);
+   split = (Split*) tc;
+
+   assert (orig && (orig == split->tc1 || orig == split->tc2));
+
+   o = orig->get_evas_object(orig);
+   evas_object_geometry_get(o, &x, &y, &w, &h);
+   evas_object_hide(o);
+
+   if (orig == split->last_focus)
+     split->last_focus = new_child;
+
+   o = new_child->get_evas_object(new_child);
+   if (split->tc1 == orig)
+     {
+        elm_object_part_content_unset(split->panes, PANES_TOP);
+        elm_object_part_content_set(split->panes, PANES_TOP, o);
+        split->tc1 = new_child;
      }
+   else
+     {
+        elm_object_part_content_unset(split->panes, PANES_BOTTOM);
+        elm_object_part_content_set(split->panes, PANES_BOTTOM, o);
+        split->tc2 = new_child;
+     }
+   new_child->parent = tc;
+   evas_object_geometry_set(o, x, y, w, h);
+   evas_object_show(o);
+   evas_object_show(split->panes);
+
+   if (tc->is_focused)
+     new_child->focus(new_child, tc);
 }
 
 static Term *
-win_focused_term_get(Win *wn)
+_split_focused_term_get(Term_Container *tc)
 {
-   Term *term;
-   Eina_List *l;
+   Split *split;
 
-   EINA_LIST_FOREACH(wn->terms, l, term)
+   assert (tc->type == TERM_CONTAINER_TYPE_SPLIT);
+   split = (Split*) tc;
+
+   return tc->is_focused ?
+      split->last_focus->focused_term_get(split->last_focus)
+      : NULL;
+}
+
+static Term *
+_split_find_term_at_coords(Term_Container *tc,
+                           Evas_Coord mx, Evas_Coord my)
+{
+   Split *split;
+   Evas_Coord ox, oy, ow, oh;
+   Evas_Object *o;
+
+   assert (tc->type == TERM_CONTAINER_TYPE_SPLIT);
+   split = (Split*) tc;
+
+   o = split->tc1->get_evas_object(split->tc1);
+
+   evas_object_geometry_get(o, &ox, &oy, &ow, &oh);
+   if (ELM_RECTS_INTERSECT(ox, oy, ow, oh, mx, my, 1, 1))
      {
-        if (term->focused) return term;
+        tc = split->tc1;
      }
-   return NULL;
+   else
+     {
+        tc = split->tc2;
+     }
+
+   return tc->find_term_at_coords(tc, mx, my);
 }
 
+static void
+_split_close(Term_Container *tc, Term_Container *child)
+{
+   Split *split;
+   Term_Container *parent, *other_child;
 
-/* }}} */
-/* {{{ Splits */
+   assert (tc->type == TERM_CONTAINER_TYPE_SPLIT);
+   split = (Split*) tc;
+
+   elm_object_part_content_unset(split->panes, PANES_TOP);
+   elm_object_part_content_unset(split->panes, PANES_BOTTOM);
+
+   parent = tc->parent;
+   other_child = (child == split->tc1) ? split->tc2 : split->tc1;
+   parent->swallow(parent, tc, other_child);
 
-typedef struct _Sizeinfo Sizeinfo;
+   evas_object_del(split->panes);
+
+   eina_stringshare_del(tc->title);
+   free(tc);
+}
 
-struct _Sizeinfo
+static void
+_split_update(Term_Container *tc)
 {
-   int min_w, min_h;
-   int step_x, step_y;
-   int req_w, req_h;
-   int req;
-};
+   Split *split;
+
+   assert (tc->type == TERM_CONTAINER_TYPE_SPLIT);
+   split = (Split*) tc;
+
+   split->tc1->update(split->tc1);
+   split->tc2->update(split->tc2);
+}
 
 static void
-_split_size_walk(Split *sp, Sizeinfo *info)
+_split_focus(Term_Container *tc, Term_Container *relative)
 {
-   Sizeinfo inforet = { 0, 0, 0, 0, 0, 0, 0 };
+   Split *split;
+   assert (tc->type == TERM_CONTAINER_TYPE_SPLIT);
+   split = (Split*) tc;
 
-   if (sp->term)
+   if (tc->parent == relative)
      {
-        info->min_w = sp->term->min_w;
-        info->min_h = sp->term->min_h;
-        info->step_x = sp->term->step_x;
-        info->step_y = sp->term->step_y;
-        info->req_w = sp->term->req_w;
-        info->req_h = sp->term->req_h;
-        // XXXX sp->terms sizedone too?
-        if (!evas_object_data_get(sp->term->termio, "sizedone"))
-          {
-             evas_object_data_set(sp->term->termio, "sizedone", 
sp->term->termio);
-             info->req = 1;
-          }
+        tc->is_focused = EINA_TRUE;
+        split->last_focus->focus(split->last_focus, tc);
      }
    else
      {
-        Evas_Coord mw = 0, mh = 0;
+        if (split->last_focus != relative)
+          split->last_focus->unfocus(split->last_focus, tc);
+        split->last_focus = relative;
+        if (!tc->is_focused)
+          tc->parent->focus(tc->parent, tc);
+        tc->is_focused = EINA_TRUE;
+     }
+}
 
-        info->min_w = 0;
-        info->min_h = 0;
-        info->req_w = 0;
-        info->req_h = 0;
-        evas_object_size_hint_min_get(sp->panes, &mw, &mh);
-        if (!sp->horizontal)
-          {
-             _split_size_walk(sp->s1, &inforet);
-             info->req |= inforet.req;
-             mw -= inforet.min_w;
-             if (info->req)
-               {
-                  info->req_w += inforet.req_w;
-                  info->req_h = inforet.req_h;
-               }
+static void
+_split_unfocus(Term_Container *tc, Term_Container *relative)
+{
+   Split *split;
+   assert (tc->type == TERM_CONTAINER_TYPE_SPLIT);
+   split = (Split*) tc;
 
-             _split_size_walk(sp->s2, &inforet);
-             info->req |= inforet.req;
-             mw -= inforet.min_w;
-             if (info->req)
-               {
-                  info->req_w += inforet.req_w;
-                  info->req_h = inforet.req_h;
-               }
-             info->req_w += mw;
-             if (info->req) info->req_h += mh - inforet.min_h - inforet.step_y;
-          }
-        else
-          {
-             _split_size_walk(sp->s1, &inforet);
-             info->req |= inforet.req;
-             mh -= inforet.min_h;
-             if (info->req)
-               {
-                  info->req_h += inforet.req_h;
-                  info->req_w = inforet.req_w;
-               }
+   if (!tc->is_focused)
+     return;
+
+   tc->is_focused = EINA_FALSE;
+   if (tc->parent == relative)
+     split->last_focus->unfocus(split->last_focus, tc);
+   else
+     tc->parent->unfocus(tc->parent, tc);
+}
+
+static void
+_split_set_title(Term_Container *tc, Term_Container *child,
+                 const char *title)
+{
+   Split *split;
+
+   assert (tc->type == TERM_CONTAINER_TYPE_SPLIT);
+   split = (Split*) tc;
+
+   if (child == split->last_focus)
+     {
+        eina_stringshare_del(tc->title);
+        tc->title =  eina_stringshare_ref(title);
+        tc->parent->set_title(tc->parent, tc, title);
+     }
+}
+
+static void
+_split_bell(Term_Container *tc, Term_Container *child EINA_UNUSED)
+{
+   assert (tc->type == TERM_CONTAINER_TYPE_SPLIT);
+
+   if (tc->is_focused)
+     return;
+
+   tc->parent->bell(tc->parent, tc);
+}
+
+static void
+_split_split(Term_Container *tc, Term_Container *child,
+             const char *cmd, Eina_Bool is_horizontal)
+{
+   Term *tm_new, *tm;
+   Term_Container *tc_split, *tc_solo_new;
+   Win *wn;
+   Evas_Object *obj_split;
+   char buf[PATH_MAX], *wdir = NULL;
+
+   assert (tc->type == TERM_CONTAINER_TYPE_SPLIT);
+   wn = tc->wn;
+
+   tm = child->focused_term_get(child);
+   if (tm && termio_cwd_get(tm->termio, buf, sizeof(buf)))
+     wdir = buf;
+   tm_new = term_new(wn, wn->config,
+                     cmd, wn->config->login_shell, wdir,
+                     80, 24, EINA_FALSE);
+   tc_solo_new = _solo_new(tm_new, wn);
+   evas_object_data_set(tm_new->termio, "sizedone", tm_new->termio);
+
+   tc_split = _split_new(child, tc_solo_new, is_horizontal);
+
+   obj_split = tc_split->get_evas_object(tc_split);
+
+   tc_split->is_focused = tc->is_focused;
+   tc->swallow(tc, child, tc_split);
+
+   evas_object_show(obj_split);
+}
+
+static Term_Container *
+_split_new(Term_Container *tc1, Term_Container *tc2, Eina_Bool is_horizontal)
+{
+   Evas_Object *o;
+   Term_Container *tc = NULL;
+   Split *split = NULL;
+   split = calloc(1, sizeof(Split));
+   if (!split)
+     {
+        free(split);
+        return NULL;
+     }
+
+   tc = (Term_Container*)split;
+   tc->term_next = _split_term_next;
+   tc->term_prev = _split_term_prev;
+   tc->term_first = _split_term_first;
+   tc->term_last = _split_term_last;
+   tc->focused_term_get = _split_focused_term_get;
+   tc->get_evas_object = _split_get_evas_object;
+   tc->split = _split_split;
+   tc->find_term_at_coords = _split_find_term_at_coords;
+   tc->size_eval = _split_size_eval;
+   tc->swallow = _split_swallow;
+   tc->focus = _split_focus;
+   tc->unfocus = _split_unfocus;
+   tc->set_title = _split_set_title;
+   tc->bell = _split_bell;
+   tc->close = _split_close;
+   tc->update = _split_update;
+   tc->title = eina_stringshare_add("Terminology");
+   tc->type = TERM_CONTAINER_TYPE_SPLIT;
+
+
+   tc->parent = NULL;
+   tc->wn = tc1->wn;
+
+   tc1->parent = tc2->parent = tc;
+
+   split->tc1 = tc1;
+   split->tc2 = tc2;
+   if (tc1->is_focused)
+     tc1->unfocus(tc1, tc);
+   tc2->focus(tc2, tc);
+   split->last_focus = tc2;
+
+   o = split->panes = elm_panes_add(tc1->wn->win);
+   elm_object_style_set(o, "flush");
+   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
 
-             _split_size_walk(sp->s2, &inforet);
-             info->req |= inforet.req;
-             mh -= inforet.min_h;
-             if (info->req)
-               {
-                  info->req_h += inforet.req_h;
-                  info->req_w = inforet.req_w;
-               }
-             info->req_h += mh;
-             if (info->req) info->req_w += mw - inforet.min_w - inforet.step_x;
-         }
-        info->step_x = inforet.step_x;
-        info->step_y = inforet.step_y;
-     }
+   split->is_horizontal = is_horizontal;
+   elm_panes_horizontal_set(o, split->is_horizontal);
+
+   elm_object_part_content_set(o, PANES_TOP,
+                               tc1->get_evas_object(tc1));
+   elm_object_part_content_set(o, PANES_BOTTOM,
+                               tc2->get_evas_object(tc2));
+
+   return tc;
 }
 
 static void
 _size_job(void *data)
 {
    Win *wn = data;
-   Sizeinfo info = { 0, 0, 0, 0, 0, 0, 0 };
-   Evas_Coord mw = 0, mh = 0;
+   Sizeinfo info = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+   Term_Container *tc = (Term_Container*) wn;
 
    wn->size_job = NULL;
-   _split_size_walk(wn->split, &info);
-   if (wn->split->panes)
-     evas_object_size_hint_min_get(wn->split->panes, &mw, &mh);
-   else
-     evas_object_size_hint_min_get(wn->split->term->bg, &mw, &mh);
-   elm_win_size_base_set(wn->win, mw - info.step_x, mh - info.step_y);
+   tc->size_eval(tc, &info);
+
+   elm_win_size_base_set(wn->win,
+                         info.bg_min_w - info.step_x,
+                         info.bg_min_h - info.step_y);
    elm_win_size_step_set(wn->win, info.step_x, info.step_y);
-   evas_object_size_hint_min_set(wn->backbg, mw, mh);
+   evas_object_size_hint_min_set(wn->backbg,
+                                 info.bg_min_w,
+                                 info.bg_min_h);
    if (info.req) evas_object_resize(wn->win, info.req_w, info.req_h);
 }
 
@@ -765,7 +1441,8 @@ win_sizing_handle(Win *wn)
 }
 
 static void
-_cb_size_hint(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event 
EINA_UNUSED)
+_cb_size_hint(void *data,
+              Evas *e EINA_UNUSED, Evas_Object *obj, void *event EINA_UNUSED)
 {
    Term *term = data;
    Evas_Coord mw, mh, rw, rh, w = 0, h = 0;
@@ -787,64 +1464,37 @@ _cb_size_hint(void *data, Evas *e EINA_UNUSED, 
Evas_Object *obj, void *event EIN
    term->wn->size_job = ecore_job_add(_size_job, term->wn);
 }
 
-static Split *
-_split_split_find(Split *sp, Evas_Object *termio, Term **ptm)
+void
+split_horizontally(Evas_Object *win EINA_UNUSED, Evas_Object *term,
+                   const char *cmd)
 {
-   Split *sp2;
-   Eina_List *l;
    Term *tm;
+   Term_Container *tc;
 
-   if (sp->term)
-     {
-        if (sp->term->termio == termio)
-          {
-             if (ptm) *ptm = sp->term;
-             return sp;
-          }
-        EINA_LIST_FOREACH(sp->terms, l, tm)
-          {
-             if (tm->termio == termio)
-               {
-                  if (ptm) *ptm = tm;
-                  return sp;
-               }
-          }
-     }
-   if (sp->s1)
-     {
-        sp2 = _split_split_find(sp->s1, termio, ptm);
-        if (sp2) return sp2;
-     }
-   if (sp->s2)
-     {
-        sp2 = _split_split_find(sp->s2, termio, ptm);
-        if (sp2) return sp2;
-     }
-   return NULL;
+   tm = evas_object_data_get(term, "term");
+   if (!tm) return;
+
+   tc = tm->container;
+   tc->split(tc, tc, cmd, EINA_TRUE);
 }
 
-static Split *
-_split_find(Evas_Object *win, Evas_Object *term, Term **ptm)
+void
+split_vertically(Evas_Object *win EINA_UNUSED, Evas_Object *term,
+                 const char *cmd)
 {
-   Win *wn;
-   Eina_List *l;
+   Term *tm;
+   Term_Container *tc;
 
-   EINA_LIST_FOREACH(wins, l, wn)
-     {
-        if (wn->win == win) return _split_split_find(wn->split, term, ptm);
-     }
-   return NULL;
-}
+   tm = evas_object_data_get(term, "term");
+   if (!tm) return;
 
-static void
-_split_free(Split *sp)
-{
-   if (sp->s1) _split_free(sp->s1);
-   if (sp->s2) _split_free(sp->s2);
-   if (sp->panes) evas_object_del(sp->panes);
-   free(sp);
+   tc = tm->container;
+   tc->split(tc, tc, cmd, EINA_FALSE);
 }
 
+/* }}} */
+/* {{{ Tabs */
+
 static void
 _tabbar_clear(Term *tm)
 {
@@ -865,38 +1515,44 @@ _tabbar_clear(Term *tm)
 }
 
 static void
-_cb_tab_activate(void *data, Evas_Object *obj, const char *sig EINA_UNUSED, 
const char *src EINA_UNUSED)
+_cb_tab_activate(void *data, Evas_Object *obj EINA_UNUSED,
+                 const char *sig EINA_UNUSED, const char *src EINA_UNUSED)
 {
-   Split *sp = data;
-   Term *term = evas_object_data_get(obj, "term");
-   if (term)
-     {
-        _term_focus(term);
-        if (sp)
-          {
-             _term_focus_show(sp, term);
-             _split_tabcount_update(sp, term);
-          }
-     }
+   Tab_Item *tab_item = data;
+   Solo *solo;
+   Term *term;
+
+   assert (tab_item->tc->type == TERM_CONTAINER_TYPE_SOLO);
+   solo = (Solo*)tab_item->tc;
+   term = solo->term;
+   _term_focus(term, EINA_TRUE);
 }
 
 static void
-_split_tabbar_fill(Split *sp, Term *tm)
+_tabbar_fill(Tabs *tabs)
 {
    Eina_List *l;
    Term *term;
+   Solo *solo;
    Evas_Object *o;
-   int n = eina_list_count(sp->terms);
+   int n = eina_list_count(tabs->tabs);
    int i = 0, j = 0;
+   Tab_Item *tab_item;
 
-   EINA_LIST_FOREACH(sp->terms, l, term)
+   EINA_LIST_FOREACH(tabs->tabs, l, tab_item)
      {
-        if (term == tm) break;
+        if (tab_item == tabs->current) break;
         i++;
      }
+
+   tab_item = tabs->current;
+   assert (tab_item->tc->type == TERM_CONTAINER_TYPE_SOLO);
+   solo = (Solo*)tab_item->tc;
+   term = solo->term;
+
    if (i > 0)
      {
-        tm->tabbar.l.box = o = elm_box_add(sp->wn->win);
+        term->tabbar.l.box = o = elm_box_add(tabs->tc.wn->win);
         elm_box_horizontal_set(o, EINA_TRUE);
         elm_box_homogeneous_set(o, EINA_TRUE);
         evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 
EVAS_HINT_EXPAND);
@@ -906,7 +1562,7 @@ _split_tabbar_fill(Split *sp, Term *tm)
      }
    if (i < (n - 1))
      {
-        tm->tabbar.r.box = o = elm_box_add(sp->wn->win);
+        term->tabbar.r.box = o = elm_box_add(tabs->tc.wn->win);
         elm_box_horizontal_set(o, EINA_TRUE);
         elm_box_homogeneous_set(o, EINA_TRUE);
         evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 
EVAS_HINT_EXPAND);
@@ -914,476 +1570,1027 @@ _split_tabbar_fill(Split *sp, Term *tm)
         edje_object_part_swallow(term->bg, "terminology.tabr.content", o);
         evas_object_show(o);
      }
-   EINA_LIST_FOREACH(sp->terms, l, term)
+   EINA_LIST_FOREACH(tabs->tabs, l, tab_item)
      {
-        if (term != tm)
+        if (tab_item != tabs->current)
           {
              Evas_Coord w, h;
 
-             o = edje_object_add(evas_object_evas_get(sp->wn->win));
+             o = edje_object_add(evas_object_evas_get(tabs->tc.wn->win));
              theme_apply(o, term->config, "terminology/tabbar_back");
              evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 
EVAS_HINT_EXPAND);
              evas_object_size_hint_fill_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
-             edje_object_part_text_set(o, "terminology.title", 
termio_title_get(term->termio));
+             edje_object_part_text_set(o, "terminology.title",
+                                       tab_item->tc->title);
              edje_object_size_min_calc(o, &w, &h);
              evas_object_size_hint_min_set(o, w, h);
              if (j < i)
                {
-                  tm->tabbar.l.tabs = eina_list_append(tm->tabbar.l.tabs, o);
-                  elm_box_pack_end(tm->tabbar.l.box, o);
+                  term->tabbar.l.tabs = eina_list_append(term->tabbar.l.tabs, 
o);
+                  elm_box_pack_end(term->tabbar.l.box, o);
                }
              else if (j > i)
                {
-                  tm->tabbar.r.tabs = eina_list_append(tm->tabbar.r.tabs, o);
-                  elm_box_pack_end(tm->tabbar.r.box, o);
+                  term->tabbar.r.tabs = eina_list_append(term->tabbar.r.tabs, 
o);
+                  elm_box_pack_end(term->tabbar.r.box, o);
                }
              evas_object_data_set(o, "term", term);
              evas_object_show(o);
              edje_object_signal_callback_add(o, "tab,activate", "terminology",
-                                             _cb_tab_activate, sp);
+                                             _cb_tab_activate, tab_item);
           }
         j++;
      }
 }
 
 static void
-_split_tabcount_update(Split *sp, Term *tm)
+_tab_go(Term *term, int tnum)
+{
+   Term_Container *tc = term->container,
+                  *child = tc;
+
+   while (tc)
+     {
+        Tabs *tabs;
+        Tab_Item *tab_item;
+
+        if (tc->type != TERM_CONTAINER_TYPE_TABS)
+          {
+             child = tc;
+             tc = tc->parent;
+             continue;
+          }
+        tabs = (Tabs*) tc;
+        tab_item = eina_list_nth(tabs->tabs, tnum);
+        if (!tab_item)
+          {
+             child = tc;
+             tc = tc->parent;
+             continue;
+          }
+        if (tab_item == tabs->current)
+          return;
+        tab_item->tc->focus(tab_item->tc, child);
+        return;
+     }
+}
+
+#define CB_TAB(TAB) \
+static void                                             \
+_cb_tab_##TAB(void *data, Evas_Object *obj EINA_UNUSED, \
+             void *event EINA_UNUSED)                   \
+{                                                       \
+   _tab_go(data, TAB - 1);                              \
+}
+
+CB_TAB(1)
+CB_TAB(2)
+CB_TAB(3)
+CB_TAB(4)
+CB_TAB(5)
+CB_TAB(6)
+CB_TAB(7)
+CB_TAB(8)
+CB_TAB(9)
+CB_TAB(10)
+#undef CB_TAB
+
+static void
+_tabs_selector_cb_selected(void *data,
+                           Evas_Object *obj EINA_UNUSED,
+                           void *info);
+static void
+_tabs_selector_cb_exit(void *data,
+                       Evas_Object *obj EINA_UNUSED,
+                       void *info EINA_UNUSED);
+
+static void
+_tabs_restore(Tabs *tabs)
 {
-   char buf[32], bufm[32];
-   int n = eina_list_count(sp->terms);
-   int missed = 0;
-   int cnt = 0, term_cnt = 0;
-   int i = 0;
    Eina_List *l;
+   Tab_Item *tab_item;
+   Term_Container *tc = (Term_Container*)tabs;
    Term *term;
+   Solo *solo;
+
+   if (!tabs->selector)
+     return;
+
+   EINA_LIST_FOREACH(tc->wn->terms, l, term)
+     {
+        if (term->unswallowed)
+          {
+#if (EVAS_VERSION_MAJOR > 1) || (EVAS_VERSION_MINOR >= 8)
+             evas_object_image_source_visible_set(term->sel, EINA_TRUE);
+#endif
+             edje_object_part_swallow(term->bg, "terminology.content", 
term->base);
+             term->unswallowed = EINA_FALSE;
+             evas_object_show(term->base);
+          }
+     }
+
+   EINA_LIST_FOREACH(tabs->tabs, l, tab_item)
+     {
+        tab_item->selector_entry = NULL;
+     }
+
+   evas_object_smart_callback_del_full(tabs->selector, "selected",
+                                  _tabs_selector_cb_selected, tabs);
+   evas_object_smart_callback_del_full(tabs->selector, "exit",
+                                  _tabs_selector_cb_exit, tabs);
+   evas_object_del(tabs->selector);
+   evas_object_del(tabs->selector_bg);
+   tabs->selector = NULL;
+   tabs->selector_bg = NULL;
+
+   /* XXX: reswallow in parent */
+   tc->parent->swallow(tc->parent, tc, tc);
+   solo = (Solo*)tabs->current->tc;
+   term = solo->term;
+   _tabbar_clear(term);
+   if (!term->config->notabs)
+     {
+        _tabbar_fill(tabs);
+     }
+
+   _tabs_refresh(tabs);
+   tabs->current->tc->focus(tabs->current->tc, tabs->current->tc);
+}
+
+static void
+_tabs_selector_cb_selected(void *data,
+                           Evas_Object *obj EINA_UNUSED,
+                           void *info)
+{
+   Tabs *tabs = data;
+   Eina_List *l;
+   Tab_Item *tab_item;
+
+   EINA_LIST_FOREACH(tabs->tabs, l, tab_item)
+     {
+        if (tab_item->tc->selector_img == info)
+          {
+             tabs->current = tab_item;
+             _tabs_restore(tabs);
+             return;
+          }
+     }
+
+   ERR("Can't find selected tab item");
+}
+
+static void
+_tabs_selector_cb_exit(void *data,
+                       Evas_Object *obj EINA_UNUSED,
+                       void *info EINA_UNUSED)
+{
+   Tabs *tabs = data;
+
+   _tabs_restore(tabs);
+}
+
+static void
+_cb_tab_selector_show(Tabs *tabs)
+{
+   Term_Container *tc = (Term_Container *)tabs;
+   Eina_List *l;
+   int count;
+   double z;
+   Edje_Message_Int msg;
+   Win *wn = tc->wn;
+   Tab_Item *tab_item;
+   Evas_Object *o;
+   Evas_Coord x, y, w, h;
 
-   EINA_LIST_FOREACH(sp->terms, l, term)
+   if (tabs->selector_bg)
+     return;
+
+   o = tc->get_evas_object(tc);
+   evas_object_geometry_get(o, &x, &y, &w, &h);
+
+   tabs->selector_bg = edje_object_add(evas_object_evas_get(tc->wn->win));
+   theme_apply(tabs->selector_bg, wn->config, "terminology/sel/base");
+
+   evas_object_geometry_set(tabs->selector_bg, x, y, w, h);
+   evas_object_hide(o);
+
+   if (wn->config->translucent)
+     msg.val = wn->config->opacity;
+   else
+     msg.val = 100;
+
+   edje_object_message_send(tabs->selector_bg, EDJE_MESSAGE_INT, 1, &msg);
+   edje_object_signal_emit(tabs->selector_bg, "begin", "terminology");
+
+   tab_item = tabs->current;
+
+   tabs->selector = sel_add(wn->win);
+   EINA_LIST_FOREACH(tabs->tabs, l, tab_item)
      {
-        if (term->missed_bell) missed++;
+        Evas_Object *img;
+        Eina_Bool is_selected, missed_bell;
+        Solo *solo;
+        Term *term;
+
+        solo = (Solo*)tab_item->tc;
+        term = solo->term;
+        _tabbar_clear(term);
+
+        edje_object_part_unswallow(term->bg, term->base);
+        term->unswallowed = EINA_TRUE;
+        img = evas_object_image_filled_add(evas_object_evas_get(wn->win));
+        o = term->base;
+        evas_object_lower(o);
+        evas_object_move(o, -9999, -9999);
+        evas_object_show(o);
+        evas_object_clip_unset(o);
+        evas_object_image_source_set(img, o);
+        evas_object_geometry_get(o, NULL, NULL, &w, &h);
+        evas_object_resize(img, w, h);
+        evas_object_data_set(img, "tc", tab_item->tc);
+        tab_item->tc->selector_img = img;
 
-        cnt++;
-        if (tm == term) term_cnt = cnt;
+        is_selected = (tab_item == tabs->current);
+        missed_bell = term->missed_bell;
+        tab_item->selector_entry = sel_entry_add(tabs->selector, img,
+                                                 is_selected,
+                                                 missed_bell, wn->config);
      }
-   snprintf(buf, sizeof(buf), "%i/%i", term_cnt, n);
-   if (missed > 0) snprintf(bufm, sizeof(bufm), "%i", missed);
-   else bufm[0] = 0;
-   EINA_LIST_FOREACH(sp->terms, l, term)
+   edje_object_part_swallow(tabs->selector_bg, "terminology.content",
+                            tabs->selector);
+
+   evas_object_show(tabs->selector);
+
+   /* XXX: refresh */
+   tc->parent->swallow(tc->parent, tc, tc);
+
+   evas_object_smart_callback_add(tabs->selector, "selected",
+                                  _tabs_selector_cb_selected, tabs);
+   evas_object_smart_callback_add(tabs->selector, "exit",
+                                  _tabs_selector_cb_exit, tabs);
+   z = 1.0;
+   sel_go(tabs->selector);
+   count = eina_list_count(tabs->tabs);
+   if (count >= 1)
+     z = 1.0 / (sqrt(count) * 0.8);
+   if (z > 1.0) z = 1.0;
+   sel_orig_zoom_set(tabs->selector, z);
+   sel_zoom(tabs->selector, z);
+   elm_object_focus_set(tabs->selector, EINA_TRUE);
+}
+
+static void
+_cb_select(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
+{
+   Term *term = data;
+   Term_Container *tc = term->container;
+
+   while (tc)
      {
-        Evas_Coord w = 0, h = 0;
+        Tabs *tabs;
 
-        if (!term->tabcount_spacer)
+        if (tc->type != TERM_CONTAINER_TYPE_TABS)
           {
-             term->tabcount_spacer = 
evas_object_rectangle_add(evas_object_evas_get(term->bg));
-             evas_object_color_set(term->tabcount_spacer, 0, 0, 0, 0);
+             tc = tc->parent;
+             continue;
           }
-        elm_coords_finger_size_adjust(1, &w, 1, &h);
-        evas_object_size_hint_min_set(term->tabcount_spacer, w, h);
-        edje_object_part_swallow(term->bg, "terminology.tabcount.control", 
term->tabcount_spacer);
-        if (n > 1)
+        tabs = (Tabs*) tc;
+        if (eina_list_count(tabs->tabs) < 2)
           {
-             edje_object_part_text_set(term->bg, "terminology.tabcount.label", 
buf);
-             edje_object_part_text_set(term->bg, 
"terminology.tabmissed.label", bufm);
-             edje_object_signal_emit(term->bg, "tabcount,on", "terminology");
-             // this is all below just for tab bar at the top
-             if (!term->config->notabs)
-               {
-                  double v1, v2;
+             tc = tc->parent;
+             continue;
+          }
 
-                  v1 = (double)i / (double)n;
-                  v2 = (double)(i + 1) / (double)n;
-                  if (!term->tab_spacer)
-                    {
-                       term->tab_spacer = 
evas_object_rectangle_add(evas_object_evas_get(term->bg));
-                       evas_object_color_set(term->tab_spacer, 0, 0, 0, 0);
-                       elm_coords_finger_size_adjust(1, &w, 1, &h);
-                       evas_object_size_hint_min_set(term->tab_spacer, w, h);
-                       edje_object_part_swallow(term->bg, "terminology.tab", 
term->tab_spacer);
-                       edje_object_part_drag_value_set(term->bg, 
"terminology.tabl", v1, 0.0);
-                       edje_object_part_drag_value_set(term->bg, 
"terminology.tabr", v2, 0.0);
-                       edje_object_part_text_set(term->bg, 
"terminology.tab.title", termio_title_get(term->termio));
-                       edje_object_signal_emit(term->bg, "tabbar,on", 
"terminology");
-                       edje_object_message_signal_process(term->bg);
-                    }
-                  else
-                    {
-                       edje_object_part_drag_value_set(term->bg, 
"terminology.tabl", v1, 0.0);
-                       edje_object_part_drag_value_set(term->bg, 
"terminology.tabr", v2, 0.0);
-                       edje_object_message_signal_process(term->bg);
-                    }
-                  _tabbar_clear(term);
-                  if (sp->term == term) _split_tabbar_fill(sp, term);
-               }
-             else
-               {
-                  _tabbar_clear(term);
-                  if (term->tab_spacer)
-                    {
-                       edje_object_signal_emit(term->bg, "tabbar,off", 
"terminology");
-                       evas_object_del(term->tab_spacer);
-                       term->tab_spacer = NULL;
-                       edje_object_message_signal_process(term->bg);
-                    }
-               }
+        _cb_tab_selector_show(tabs);
+        return;
+     }
+}
+
+
+
+static Evas_Object *
+_tabs_get_evas_object(Term_Container *container)
+{
+   Tabs *tabs;
+   Term_Container *tc;
+
+   assert (container->type == TERM_CONTAINER_TYPE_TABS);
+   tabs = (Tabs*)container;
+
+   if (tabs->selector_bg)
+     return tabs->selector_bg;
+
+   assert(tabs->current != NULL);
+   tc = tabs->current->tc;
+   return tc->get_evas_object(tc);
+}
+
+static Term *
+_tabs_focused_term_get(Term_Container *tc)
+{
+   Tabs *tabs;
+
+   assert (tc->type == TERM_CONTAINER_TYPE_TABS);
+   tabs = (Tabs*)tc;
+
+
+   return tc->is_focused ?
+      tabs->current->tc->focused_term_get(tabs->current->tc)
+      : NULL;
+}
+
+static Term *
+_tabs_find_term_at_coords(Term_Container *container,
+                          Evas_Coord mx,
+                          Evas_Coord my)
+{
+   Tabs *tabs;
+   Term_Container *tc;
+
+   assert (container->type == TERM_CONTAINER_TYPE_TABS);
+   tabs = (Tabs*)container;
+
+   tc = tabs->current->tc;
+
+   return tc->find_term_at_coords(tc, mx, my);
+}
+
+static void
+_tabs_size_eval(Term_Container *container, Sizeinfo *info)
+{
+   Tabs *tabs;
+   Term_Container *tc;
+
+   assert (container->type == TERM_CONTAINER_TYPE_TABS);
+   tabs = (Tabs*)container;
+
+   tc = tabs->current->tc;
+   tc->size_eval(tc, info);
+}
+
+static Eina_List *
+_tab_item_find(Tabs *tabs, Term_Container *child)
+{
+   Eina_List *l;
+   Tab_Item *tab_item;
+
+   EINA_LIST_FOREACH(tabs->tabs, l, tab_item)
+     {
+        if (tab_item->tc == child)
+          return l;
+     }
+   return NULL;
+}
+
+static void
+_tabs_close(Term_Container *tc, Term_Container *child)
+{
+   int count;
+   Tabs *tabs;
+   Eina_List *l;
+   Tab_Item *item, *next_item;
+   Eina_List *next;
+   Term_Container *next_child, *tc_parent;
+   Term *term;
+   Solo *solo;
+
+   assert (tc->type == TERM_CONTAINER_TYPE_TABS);
+   tabs = (Tabs*)tc;
+
+   tc_parent = tc->parent;
+
+   l = _tab_item_find(tabs, child);
+   item = l->data;
+
+   next = eina_list_next(l);
+   if (!next)
+     next = tabs->tabs;
+   next_item = next->data;
+   next_child = next_item->tc;
+   tabs->tabs = eina_list_remove_list(tabs->tabs, l);
+
+   assert (child->type == TERM_CONTAINER_TYPE_SOLO);
+   solo = (Solo*)child;
+   term = solo->term;
+   _tabbar_clear(term);
+
+   edje_object_signal_emit(term->bg, "tabcount,off", "terminology");
+   if (term->tab_spacer)
+     {
+        edje_object_signal_emit(term->bg, "tabbar,off", "terminology");
+        evas_object_del(term->tab_spacer);
+        term->tab_spacer = NULL;
+        edje_object_message_signal_process(term->bg);
+     }
+
+
+   count = eina_list_count(tabs->tabs);
+   if (count == 1)
+     {
+        assert (next_child->type == TERM_CONTAINER_TYPE_SOLO);
+        solo = (Solo*)next_child;
+        term = solo->term;
+        _tabbar_clear(term);
+
+        edje_object_signal_emit(term->bg, "tabcount,off", "terminology");
+        if (term->tab_spacer)
+          {
+             edje_object_signal_emit(term->bg, "tabbar,off", "terminology");
+             evas_object_del(term->tab_spacer);
+             term->tab_spacer = NULL;
+             edje_object_message_signal_process(term->bg);
           }
-        else
+        if (tabs->selector)
+          _tabs_restore(tabs);
+        eina_stringshare_del(tc->title);
+        tc_parent->swallow(tc_parent, tc, next_child);
+        if (tc->is_focused)
+          next_child->focus(next_child, tc_parent);
+
+        free(next_item);
+        free(tc);
+        free(item);
+     }
+   else
+     {
+        if (item == tabs->current)
           {
-             _tabbar_clear(term);
-             edje_object_signal_emit(term->bg, "tabcount,off", "terminology");
-             if (term->tab_spacer)
-               {
-                  edje_object_signal_emit(term->bg, "tabbar,off", 
"terminology");
-                  evas_object_del(term->tab_spacer);
-                  term->tab_spacer = NULL;
-                  edje_object_message_signal_process(term->bg);
-               }
+             tabs->current = next_item;
+             /* XXX: refresh */
+             tc_parent->swallow(tc_parent, tc, tc);
+             if (tc->is_focused)
+               next_child->focus(next_child, tc);
           }
-        if (missed > 0)
-          edje_object_signal_emit(term->bg, "tabmissed,on", "terminology");
-        else
-          edje_object_signal_emit(term->bg, "tabmissed,off", "terminology");
-        i++;
+
+        if (item->tc->selector_img)
+          {
+             Evas_Object *o;
+             o = item->tc->selector_img;
+             item->tc->selector_img = NULL;
+             evas_object_del(o);
+          }
+
+
+        free(item);
+        count--;
+        _tabs_refresh(tabs);
+     }
+}
+
+static void
+_tabs_update(Term_Container *tc)
+{
+   Tabs *tabs;
+   assert (tc->type == TERM_CONTAINER_TYPE_TABS);
+   tabs = (Tabs*)tc;
+
+   _tabs_refresh(tabs);
+}
+
+static Term *
+_tabs_term_next(Term_Container *tc, Term_Container *child)
+{
+   Tabs *tabs;
+   Tab_Item *tab_item;
+   Eina_List *l;
+
+   assert (tc->type == TERM_CONTAINER_TYPE_TABS);
+   tabs = (Tabs*)tc;
+   l = _tab_item_find(tabs, child);
+   l = eina_list_next(l);
+   if (l)
+     {
+        tab_item = l->data;
+        tc = tab_item->tc;
+        return tc->term_first(tc);
+     }
+   else
+     {
+        return tc->parent->term_next(tc->parent, tc);
      }
 }
 
-static void
-_cb_size_track(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event 
EINA_UNUSED)
+static Term *
+_tabs_term_prev(Term_Container *tc, Term_Container *child)
 {
-   Split *sp = data;
+   Tabs *tabs;
+   Tab_Item *tab_item;
    Eina_List *l;
-   Term *term;
-   Evas_Coord w = 0, h = 0;
 
-   evas_object_geometry_get(obj, NULL, NULL, &w, &h);
-   EINA_LIST_FOREACH(sp->terms, l, term)
+   assert (tc->type == TERM_CONTAINER_TYPE_TABS);
+   tabs = (Tabs*)tc;
+   l = _tab_item_find(tabs, child);
+   l = eina_list_prev(l);
+   if (l)
+     {
+        tab_item = l->data;
+        tc = tab_item->tc;
+        return tc->term_last(tc);
+     }
+   else
      {
-        if (term->bg != obj) evas_object_resize(term->bg, w, h);
+        return tc->parent->term_prev(tc->parent, tc);
      }
 }
 
-static void
-_term_resize_track_start(Split *sp)
+static Term *
+_tabs_term_first(Term_Container *tc)
 {
-   if ((!sp) || (!sp->term) || (!sp->term->bg)) return;
-   evas_object_event_callback_del_full(sp->term->bg, EVAS_CALLBACK_RESIZE,
-                                       _cb_size_track, sp);
-   evas_object_event_callback_add(sp->term->bg, EVAS_CALLBACK_RESIZE,
-                                  _cb_size_track, sp);
+   Tabs *tabs;
+   Tab_Item *tab_item;
+
+   assert (tc->type == TERM_CONTAINER_TYPE_TABS);
+   tabs = (Tabs*)tc;
+
+   tab_item = tabs->tabs->data;
+   tc = tab_item->tc;
+
+   return tc->term_first(tc);
 }
 
-static void
-_term_resize_track_stop(Split *sp)
+static Term *
+_tabs_term_last(Term_Container *tc)
 {
-   if ((!sp) || (!sp->term) || (!sp->term->bg)) return;
-   evas_object_event_callback_del_full(sp->term->bg, EVAS_CALLBACK_RESIZE,
-                                       _cb_size_track, sp);
+   Tabs *tabs;
+   Tab_Item *tab_item;
+   Eina_List *l;
+
+   assert (tc->type == TERM_CONTAINER_TYPE_TABS);
+   tabs = (Tabs*)tc;
+
+   l = eina_list_last(tabs->tabs);
+   tab_item = l->data;
+   tc = tab_item->tc;
+
+   return tc->term_last(tc);
 }
 
 static void
-_split_split(Split *sp, Eina_Bool horizontal, char *cmd)
+_tabs_swallow(Term_Container *tc, Term_Container *orig,
+              Term_Container *new_child)
 {
-   Split *sp2, *sp1;
+   Tabs *tabs;
+   Tab_Item *tab_item;
+   Eina_List *l;
    Evas_Object *o;
-   Config *config;
-   char buf[PATH_MAX], *wdir = NULL;
+   Evas_Coord x, y, w, h;
 
-   if (!sp->term) return;
+   assert (tc->type == TERM_CONTAINER_TYPE_TABS);
+   tabs = (Tabs*) tc;
 
-   o = sp->panes = elm_panes_add(sp->wn->win);
-   elm_object_style_set(o, "flush");
-   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
-   evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
-   sp->horizontal = horizontal;
-   elm_panes_horizontal_set(o, sp->horizontal);
-
-   _term_resize_track_stop(sp);
-   sp1 = sp->s1 = calloc(1, sizeof(Split));
-   sp1->parent = sp;
-   sp1->wn = sp->wn;
-   sp1->term = sp->term;
-   sp1->terms = sp->terms;
-   _term_resize_track_start(sp1);
-
-   sp->terms = NULL;
-
-   if (!sp->parent) edje_object_part_unswallow(sp->wn->base, sp->term->bg);
-   _main_term_bg_redo(sp1->term);
-   _split_tabcount_update(sp1, sp1->term);
-
-   sp2 = sp->s2 = calloc(1, sizeof(Split));
-   sp2->parent = sp;
-   sp2->wn = sp->wn;
-   config = config_fork(sp->term->config);
-   if (termio_cwd_get(sp->term->termio, buf, sizeof(buf))) wdir = buf;
-   sp2->term = term_new(sp->wn, config,
-                        cmd, config->login_shell, wdir,
-                        80, 24, EINA_FALSE);
-   sp2->terms = eina_list_append(sp2->terms, sp2->term);
-   _term_resize_track_start(sp2);
-   _term_focus(sp2->term);
-   _term_media_update(sp2->term, config);
-   _split_tabcount_update(sp2, sp2->term);
-   evas_object_data_set(sp2->term->termio, "sizedone", sp2->term->termio);
-   elm_object_part_content_set(sp->panes, PANES_TOP, sp1->term->bg);
-   elm_object_part_content_set(sp->panes, PANES_BOTTOM, sp2->term->bg);
-
-   if (!sp->parent)
-     edje_object_part_swallow(sp->wn->base, "terminology.content", sp->panes);
-   else
-     {
-        if (sp == sp->parent->s1)
-          {
-             elm_object_part_content_unset(sp->parent->panes, PANES_TOP);
-             elm_object_part_content_set(sp->parent->panes, PANES_TOP, 
sp->panes);
-          }
-        else
-          {
-             elm_object_part_content_unset(sp->parent->panes, PANES_BOTTOM);
-             elm_object_part_content_set(sp->parent->panes, PANES_BOTTOM, 
sp->panes);
-          }
-     }
-   evas_object_show(sp->panes);
-   sp->term = NULL;
-}
+   l = _tab_item_find(tabs, new_child);
+   tab_item = l->data;
 
-static void
-_term_focus_show(Split *sp, Term *term)
-{
-   if (term != sp->term)
+   if (tabs->selector)
      {
-        _term_resize_track_stop(sp);
-        evas_object_hide(sp->term->bg);
-        sp->term = term;
-        _term_resize_track_start(sp);
+        Evas_Object *img = tab_item->tc->selector_img;
+        evas_object_image_source_set(img,
+                                     new_child->get_evas_object(new_child));
+        evas_object_data_set(img, "tc", new_child);
+        sel_entry_update(tab_item->selector_entry);
      }
-   if (!sp->parent)
-     edje_object_part_swallow(sp->wn->base, "terminology.content",
-                              sp->term->bg);
-   else
+   else if (tab_item != tabs->current)
      {
-        if (sp == sp->parent->s1)
-          {
-             elm_object_part_content_unset(sp->parent->panes, PANES_TOP);
-             elm_object_part_content_set(sp->parent->panes, PANES_TOP,
-                                         sp->term->bg);
-          }
-        else
-          {
-             elm_object_part_content_unset(sp->parent->panes, PANES_BOTTOM);
-             elm_object_part_content_set(sp->parent->panes, PANES_BOTTOM,
-                                         sp->term->bg);
-          }
+        Term_Container *tc_parent = tc->parent;
+        if (tc->is_focused)
+          tabs->current->tc->unfocus(tabs->current->tc, tc);
+        tabs->current = tab_item;
+
+        o = orig->get_evas_object(orig);
+        evas_object_geometry_get(o, &x, &y, &w, &h);
+        evas_object_hide(o);
+
+        o = new_child->get_evas_object(new_child);
+        evas_object_geometry_set(o, x, y, w, h);
+        evas_object_show(o);
+
+        /* XXX: need to refresh */
+        tc_parent->swallow(tc_parent, tc, tc);
+        /* TODO: redo title */
      }
-   evas_object_show(sp->term->bg);
-}
 
-void
-main_new_with_dir(Evas_Object *win, Evas_Object *term, const char *wdir)
-{
-   Split *sp = _split_find(win, term, NULL);
-   Config *config;
-   int w, h;
-
-   if (!sp) return;
-   _term_resize_track_stop(sp);
-   evas_object_hide(sp->term->bg);
-   config = config_fork(sp->term->config);
-   termio_size_get(sp->term->termio, &w, &h);
-   sp->term = term_new(sp->wn, config,
-                            NULL, config->login_shell, wdir,
-                            w, h, EINA_FALSE);
-   sp->terms = eina_list_append(sp->terms, sp->term);
-   _term_resize_track_start(sp);
-   _term_focus(sp->term);
-   _term_media_update(sp->term, config);
-   evas_object_data_set(sp->term->termio, "sizedone", sp->term->termio);
-   _term_focus_show(sp, sp->term);
-   _split_tabcount_update(sp, sp->term);
+   _tabs_refresh(tabs);
 }
 
-void
-main_new(Evas_Object *win, Evas_Object *term)
+
+static void
+_tab_new_cb(void *data,
+            Evas_Object *obj EINA_UNUSED,
+            void *event_info EINA_UNUSED)
 {
-   Split *sp = _split_find(win, term, NULL);
-   char buf[PATH_MAX], *wdir = NULL;
+   Tabs *tabs = data;
+   Tab_Item *tab_item;
+   Evas_Object *o;
+   Evas_Coord x, y, w, h;
+   Term_Container *tc = (Term_Container*) tabs,
+                  *tc_new, *tc_parent, *tc_old;
+   Term *tm_new;
+   Win *wn = tc->wn;
+
+   tm_new = term_new(wn, wn->config,
+                     NULL, wn->config->login_shell, NULL,
+                     80, 24, EINA_FALSE);
+   tc_new = _solo_new(tm_new, wn);
+   evas_object_data_set(tm_new->termio, "sizedone", tm_new->termio);
+
+   tc_new->parent = tc;
+
+   tab_item = tab_item_new(tabs, tc_new);
+   tc_parent = tc->parent;
+   tc_old = tabs->current->tc;
+   tc_old->unfocus(tc_old, tc);
+   o = tc_old->get_evas_object(tc_old);
+   evas_object_geometry_get(o, &x, &y, &w, &h);
+   evas_object_hide(o);
+   o = tc_new->get_evas_object(tc_new);
+   evas_object_geometry_set(o, x, y, w, h);
+   evas_object_show(o);
+   tabs->current = tab_item;
+   /* XXX: need to refresh */
+   tc_parent->swallow(tc_parent, tc, tc);
 
-   if (termio_cwd_get(sp->term->termio, buf, sizeof(buf))) wdir = buf;
-   main_new_with_dir(win, term, wdir);
+   if (tc->is_focused)
+     tc_new->focus(tc_new, tc);
+
+   _tabs_refresh(tabs);
 }
 
-void
-main_split_h(Evas_Object *win, Evas_Object *term, char *cmd)
+static void
+_cb_new(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
 {
-   Split *sp = _split_find(win, term, NULL);
+   Term *term = data;
+   Term_Container *tc = term->container;
+
+   assert (tc->type == TERM_CONTAINER_TYPE_SOLO);
 
-   if (!sp) return;
-   _split_split(sp, EINA_TRUE, cmd);
+   _solo_tabs_new(tc);
 }
 
 void
-main_split_v(Evas_Object *win, Evas_Object *term, char *cmd)
+main_new(Evas_Object *win EINA_UNUSED, Evas_Object *term)
 {
-   Split *sp = _split_find(win, term, NULL);
+   Term *tm;
+
+   tm = evas_object_data_get(term, "term");
+   if (!tm) return;
 
-   if (!sp) return;
-   _split_split(sp, EINA_FALSE, cmd);
+   _cb_new(tm, term, NULL);
 }
 
 static void
-_split_append(Split *sp, Eina_List **flat)
+_tabs_focus(Term_Container *tc, Term_Container *relative)
 {
-   if (sp->term)
-     *flat = eina_list_append(*flat, sp);
+   Tabs *tabs;
+
+   assert (tc->type == TERM_CONTAINER_TYPE_TABS);
+   tabs = (Tabs*) tc;
+
+   if (tc->parent == relative)
+     {
+        if (!tc->is_focused)
+          tabs->current->tc->focus(tabs->current->tc, tc);
+     }
    else
      {
-        _split_append(sp->s1, flat);
-        _split_append(sp->s2, flat);
+        Eina_List *l;
+        Tab_Item *tab_item;
+
+        l = _tab_item_find(tabs, relative);
+        assert(l);
+
+        tc->is_focused = EINA_TRUE;
+
+        tab_item = l->data;
+        if (tab_item != tabs->current)
+          {
+             tabs->current->tc->unfocus(tabs->current->tc, tc);
+             tc->swallow(tc, tabs->current->tc, relative);
+          }
+        tc->parent->focus(tc->parent, tc);
      }
+   tc->is_focused = EINA_TRUE;
 }
 
-static Eina_List *
-_split_flatten(Split *sp)
+static void
+_tabs_unfocus(Term_Container *tc, Term_Container *relative)
+{
+   Tabs *tabs;
+
+   if (!tc->is_focused)
+     return;
+
+   assert (tc->type == TERM_CONTAINER_TYPE_TABS);
+   tabs = (Tabs*) tc;
+
+   if (tc->parent == relative)
+     tabs->current->tc->unfocus(tabs->current->tc, tc);
+   else
+     tc->parent->unfocus(tc->parent, tc);
+   tc->is_focused = EINA_FALSE;
+}
+
+static void
+_tabs_bell(Term_Container *tc, Term_Container *child EINA_UNUSED)
 {
-   Eina_List *flat = NULL;
+   Tabs *tabs;
+
+   assert (tc->type == TERM_CONTAINER_TYPE_TABS);
+   tabs = (Tabs*) tc;
+
+   _tabs_refresh(tabs);
 
-   _split_append(sp, &flat);
-   return flat;
+   if (tc->is_focused)
+     return;
+
+   tc->parent->bell(tc->parent, tc);
 }
 
-Term *
-term_next_get(Term *termin)
+static void
+_tabs_set_title(Term_Container *tc, Term_Container *child,
+                const char *title)
 {
-   Split *sp;
-   Eina_List *flat, *l;
+   Tabs *tabs;
+   Tab_Item *tab_item;
+   Eina_List *l;
 
-   sp = _split_find(termin->wn->win, termin->termio, NULL);
-   l = eina_list_data_find_list(sp->terms, termin);
-   if ((l) && (l->next)) return l->next->data;
-   if (!sp->parent) return sp->terms->data;
-   flat = _split_flatten(termin->wn->split);
-   if (!flat) return NULL;
-   l = eina_list_data_find_list(flat, sp);
-   if (!l)
+   assert (tc->type == TERM_CONTAINER_TYPE_TABS);
+   tabs = (Tabs*) tc;
+
+   l = _tab_item_find(tabs, child);
+   assert(l);
+   tab_item = l->data;
+
+   if (tabs->selector)
      {
-        eina_list_free(flat);
-        return NULL;
+        sel_entry_title_set(tab_item->selector_entry, title);
+     }
+
+   if (tab_item == tabs->current)
+     {
+        Solo *solo;
+        Term *term;
+
+        eina_stringshare_del(tc->title);
+        tc->title =  eina_stringshare_ref(title);
+        tc->parent->set_title(tc->parent, tc, title);
+
+        assert (tab_item->tc->type == TERM_CONTAINER_TYPE_SOLO);
+        solo = (Solo*)tab_item->tc;
+        term = solo->term;
+
+        if (!term->config->notabs)
+          {
+             edje_object_part_text_set(term->bg, "terminology.tab.title",
+                                       title);
+          }
      }
-   if (l->next)
+   else
      {
-        sp = l->next->data;
-        eina_list_free(flat);
-        if (sp->terms) return sp->terms->data;
-        return sp->term;
+        _tabs_refresh(tabs);
      }
-   sp = flat->data;
-   eina_list_free(flat);
-   if (sp->terms) return sp->terms->data;
-   return sp->term;
 }
 
-Term *
-term_prev_get(Term *termin)
+static void
+_tabs_refresh(Tabs *tabs)
 {
-   Split *sp;
-   Eina_List *flat, *l;
+   Eina_List *l;
+   Solo *solo;
+   Term *term;
+   char buf[32], bufmissed[32];
+   Tab_Item *tab_item;
+   Evas_Coord w = 0, h = 0;
+   int missed = 0;
+   int i = 1;
+   int n = eina_list_count(tabs->tabs);
 
-   sp = _split_find(termin->wn->win, termin->termio, NULL);
-   l = eina_list_data_find_list(sp->terms, termin);
-   if ((l) && (l->prev)) return l->prev->data;
-   if (!sp->parent) return eina_list_data_get(eina_list_last(sp->terms));
-   flat = _split_flatten(termin->wn->split);
-   if (!flat) return NULL;
-   l = eina_list_data_find_list(flat, sp);
-   if (!l)
+   buf[0] = '\0';
+   EINA_LIST_FOREACH(tabs->tabs, l, tab_item)
      {
-        eina_list_free(flat);
-        return NULL;
+        assert (tab_item->tc->type == TERM_CONTAINER_TYPE_SOLO);
+        solo = (Solo*) tab_item->tc;
+        term = solo->term;
+
+        if (term->missed_bell)
+          missed++;
      }
-   if (l->prev)
+   EINA_LIST_FOREACH(tabs->tabs, l, tab_item)
      {
-        sp = l->prev->data;
-        eina_list_free(flat);
-        l = eina_list_last(sp->terms);
-        if (l) return l->data;
-        return sp->term;
+        if (tabs->current == tab_item)
+          {
+             snprintf(buf, sizeof(buf), "%i/%i", i, n);
+             break;
+          }
+        i++;
      }
-#if (EINA_VERSION_MAJOR > 1) || (EINA_VERSION_MINOR >= 8)
-   sp = eina_list_last_data_get(flat);
-#else
-   sp = eina_list_data_get(eina_list_last(flat));
-#endif
-   eina_list_free(flat);
-   l = eina_list_last(sp->terms);
-   if (l) return l->data;
-   return sp->term;
-}
+   if (missed > 0) snprintf(bufmissed, sizeof(bufmissed), "%i", missed);
+   else bufmissed[0] = '\0';
 
-static void
-_split_merge(Split *spp, Split *sp, const char *slot)
-{
-   Evas_Object *o = NULL;
-   if (!sp) return;
+   tab_item = tabs->current;
+   assert (tab_item->tc->type == TERM_CONTAINER_TYPE_SOLO);
+   solo = (Solo*)tab_item->tc;
+   term = solo->term;
 
-   if (sp->term)
+   if (!term->tabcount_spacer)
+     {
+        term->tabcount_spacer = 
evas_object_rectangle_add(evas_object_evas_get(term->bg));
+        evas_object_color_set(term->tabcount_spacer, 0, 0, 0, 0);
+     }
+   elm_coords_finger_size_adjust(1, &w, 1, &h);
+   evas_object_size_hint_min_set(term->tabcount_spacer, w, h);
+   edje_object_part_swallow(term->bg, "terminology.tabcount.control",
+                            term->tabcount_spacer);
+   edje_object_part_text_set(term->bg, "terminology.tabcount.label", buf);
+   edje_object_part_text_set(term->bg, "terminology.tabmissed.label", 
bufmissed);
+   edje_object_signal_emit(term->bg, "tabcount,on", "terminology");
+   // this is all below just for tab bar at the top
+   if (!term->config->notabs)
      {
-        _main_term_bg_redo(sp->term);
-        _term_resize_track_stop(sp);
-        spp->term = sp->term;
-        spp->terms = sp->terms;
-        sp->term = NULL;
-        sp->terms = NULL;
-        _term_resize_track_start(spp);
-        o = spp->term->bg;
-        spp->s1 = NULL;
-        spp->s2 = NULL;
-        evas_object_del(spp->panes);
-        spp->panes = NULL;
-        if (spp->parent)
+        double v1, v2;
+
+        v1 = (double)(i-1) / (double)n;
+        v2 = (double)i / (double)n;
+        if (!term->tab_spacer)
           {
-             elm_object_part_content_unset(spp->parent->panes, slot);
-             elm_object_part_content_set(spp->parent->panes, slot, o);
+             term->tab_spacer = evas_object_rectangle_add(
+                evas_object_evas_get(term->bg));
+             evas_object_color_set(term->tab_spacer, 0, 0, 0, 0);
+             elm_coords_finger_size_adjust(1, &w, 1, &h);
+             evas_object_size_hint_min_set(term->tab_spacer, w, h);
+             edje_object_part_swallow(term->bg, "terminology.tab", 
term->tab_spacer);
+             edje_object_part_drag_value_set(term->bg, "terminology.tabl", v1, 
0.0);
+             edje_object_part_drag_value_set(term->bg, "terminology.tabr", v2, 
0.0);
+             edje_object_part_text_set(term->bg, "terminology.tab.title",
+                                       solo->tc.title);
+             edje_object_signal_emit(term->bg, "tabbar,on", "terminology");
+             edje_object_message_signal_process(term->bg);
           }
         else
-          edje_object_part_swallow(spp->wn->base, "terminology.content", o);
-        _split_tabcount_update(sp, sp->term);
+          {
+             edje_object_part_drag_value_set(term->bg, "terminology.tabl", v1, 
0.0);
+             edje_object_part_drag_value_set(term->bg, "terminology.tabr", v2, 
0.0);
+             edje_object_message_signal_process(term->bg);
+          }
+        _tabbar_clear(term);
+        _tabbar_fill(tabs);
      }
    else
      {
-        spp->s1 = sp->s1;
-        spp->s2 = sp->s2;
-        spp->s1->parent = spp;
-        spp->s2->parent = spp;
-        spp->horizontal = sp->horizontal;
-        o = sp->panes;
-        elm_object_part_content_unset(sp->parent->panes, slot);
-        elm_object_part_content_unset(sp->parent->panes,
-                                      (!strcmp(slot, PANES_TOP)) ?
-                                      PANES_BOTTOM : PANES_TOP);
-        if (spp->parent)
+        _tabbar_clear(term);
+        if (term->tab_spacer)
           {
-             elm_object_part_content_unset(spp->parent->panes, slot);
-             elm_object_part_content_set(spp->parent->panes, slot, o);
+             edje_object_signal_emit(term->bg, "tabbar,off", "terminology");
+             evas_object_del(term->tab_spacer);
+             term->tab_spacer = NULL;
+             edje_object_message_signal_process(term->bg);
           }
-        else
-          edje_object_part_swallow(spp->wn->base, "terminology.content", o);
-        evas_object_del(spp->panes);
-        spp->panes = o;
-        sp->s1 = NULL;
-        sp->s2 = NULL;
-        sp->panes = NULL;
      }
-   _split_free(sp);
+   if (missed > 0)
+     edje_object_signal_emit(term->bg, "tabmissed,on", "terminology");
+   else
+     edje_object_signal_emit(term->bg, "tabmissed,off", "terminology");
+}
+
+static Tab_Item*
+tab_item_new(Tabs *tabs, Term_Container *child)
+{
+   Tab_Item *tab_item;
+
+   tab_item = calloc(1, sizeof(Tab_Item));
+   tab_item->tc = child;
+   assert(child != NULL);
+   assert(child->type == TERM_CONTAINER_TYPE_SOLO);
+
+   tabs->tabs = eina_list_append(tabs->tabs, tab_item);
+
+   return tab_item;
+}
+
+static void
+_tabs_split(Term_Container *tc, Term_Container *child EINA_UNUSED,
+            const char *cmd, Eina_Bool is_horizontal)
+{
+   tc->parent->split(tc->parent, tc, cmd, is_horizontal);
+}
+
+static Term_Container *
+_tabs_new(Term_Container *child, Term_Container *parent)
+{
+   Win *wn;
+   Term_Container *tc;
+   Tabs *tabs;
+   Tab_Item *tab_item;
+
+   tabs = calloc(1, sizeof(Tabs));
+   if (!tabs)
+     {
+        free(tabs);
+        return NULL;
+     }
+
+   wn = child->wn;
+
+   tc = (Term_Container*)tabs;
+   tc->term_next = _tabs_term_next;
+   tc->term_prev = _tabs_term_prev;
+   tc->term_first = _tabs_term_first;
+   tc->term_last = _tabs_term_last;
+   tc->focused_term_get = _tabs_focused_term_get;
+   tc->get_evas_object = _tabs_get_evas_object;
+   tc->split = _tabs_split;
+   tc->find_term_at_coords = _tabs_find_term_at_coords;
+   tc->size_eval = _tabs_size_eval;
+   tc->swallow = _tabs_swallow;
+   tc->focus = _tabs_focus;
+   tc->unfocus = _tabs_unfocus;
+   tc->set_title = _tabs_set_title;
+   tc->bell = _tabs_bell;
+   tc->close = _tabs_close;
+   tc->update = _tabs_update;
+   tc->title = eina_stringshare_add("Terminology");
+   tc->type = TERM_CONTAINER_TYPE_TABS;
+
+   tc->parent = parent;
+   tc->wn = wn;
+
+   child->parent = tc;
+   tab_item = tab_item_new(tabs, child);
+   tabs->current = tab_item;
+
+   /* XXX: need to refresh */
+   parent->swallow(parent, child, tc);
+
+   tc->is_focused = child->is_focused;
+
+   return tc;
 }
 
+
 /* }}} */
 /* {{{ Term */
 
-void win_term_swallow(Win *wn, Term *term)
+Eina_Bool
+term_has_popmedia(const Term *term)
 {
-   Evas_Object *base = win_base_get(wn);
-   Evas *evas = evas_object_evas_get(base);
+   return !!term->popmedia;
+}
 
-   edje_object_part_swallow(base, "terminology.content", term->bg);
-   _cb_size_hint(term, evas, term->termio, NULL);
+void
+term_popmedia_close(Term *term)
+{
+   if (term->popmedia)
+     edje_object_signal_emit(term->bg, "popmedia,off", "terminology");
+}
+
+
+static void
+_cb_term_mouse_in(void *data, Evas *e EINA_UNUSED,
+                  Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
+{
+   Term *term = data;
+   Config *config;
+
+   if ((!term) || (!term->termio))
+     return;
+
+   config = termio_config_get(term->termio);
+   if ((!config) || (!config->mouse_over_focus))
+     return;
+   if (!_win_is_focused(term->wn))
+     return;
+
+   _term_focus(term, EINA_TRUE);
+}
+
+static void
+_cb_term_mouse_down(void *data, Evas *e EINA_UNUSED,
+                    Evas_Object *obj EINA_UNUSED, void *event)
+{
+   Evas_Event_Mouse_Down *ev = event;
+   Term *term = data;
+   Term *term2;
+   Term_Container *tc;
+
+   tc = (Term_Container*) term->wn;
+   term2 = tc->focused_term_get(tc);
+   if (term == term2) return;
+   term->down.x = ev->canvas.x;
+   term->down.y = ev->canvas.y;
+   _term_focus(term, EINA_TRUE);
+}
+
+static Eina_Bool
+_term_is_focused(Term *term)
+{
+   Term_Container *tc;
+
+   if (!term)
+     return EINA_FALSE;
+
+   tc = term->container;
+   if (!tc)
+     return EINA_FALSE;
+
+   return tc->is_focused;
 }
 
 void change_theme(Evas_Object *win, Config *config)
@@ -1412,120 +2619,87 @@ void change_theme(Evas_Object *win, Config *config)
 }
 
 static void
-_term_focus(Term *term)
+_term_focus(Term *term, Eina_Bool force)
 {
-   Eina_List *l;
-   Term *term2;
-   Split *sp = NULL;
+   Term_Container *tc;
 
-   EINA_LIST_FOREACH(term->wn->terms, l, term2)
-     {
-        if (term2 != term)
-          {
-             if (term2->focused)
-               {
-                  term2->focused = EINA_FALSE;
-                  edje_object_signal_emit(term2->bg, "focus,out", 
"terminology");
-                  edje_object_signal_emit(term2->base, "focus,out", 
"terminology");
-                  elm_object_focus_set(term2->termio, EINA_FALSE);
-               }
-          }
-     }
-   term->focused = EINA_TRUE;
-   edje_object_signal_emit(term->bg, "focus,in", "terminology");
-   edje_object_signal_emit(term->base, "focus,in", "terminology");
-   if (term->wn->cmdbox) elm_object_focus_set(term->wn->cmdbox, EINA_FALSE);
-   elm_object_focus_set(term->termio, EINA_TRUE);
-   elm_win_title_set(term->wn->win, termio_title_get(term->termio));
-   if (term->missed_bell)
-     term->missed_bell = EINA_FALSE;
+   if (!force && (_term_is_focused(term) || !_win_is_focused(term->wn)))
+     return;
 
-   sp = _split_find(term->wn->win, term->termio, NULL);
-   if (sp) _split_tabcount_update(sp, term);
+   tc = term->container;
+   tc->focus(tc, tc);
 }
 
-void
-term_prev(Term *term)
+Term *
+term_prev_get(Term *term)
 {
-   Term *term2 = NULL;
-   Config *config = termio_config_get(term->termio);
+   Term_Container *tc = term->container;
 
-   if (term->focused) term2 = term_prev_get(term);
-   if ((term2 != NULL) && (term2 != term))
-     {
-        Split *sp, *sp0;
+   return tc->term_prev(tc, tc);
+}
 
-        sp0 = _split_find(term->wn->win, term->termio, NULL);
-        sp = _split_find(term2->wn->win, term2->termio, NULL);
-        if ((sp == sp0) && (config->tab_zoom >= 0.01) && (config->notabs))
-          _sel_go(sp, term2);
-        else
-          {
-             _term_focus(term2);
-             if (sp)
-               {
-                  _term_focus_show(sp, term2);
-                  _split_tabcount_update(sp, term2);
-               }
-          }
-     }
+void term_prev(Term *term)
+{
+   Term *new_term, *focused_term;
+   Win *wn = term->wn;
+   Term_Container *tc;
+
+   tc = (Term_Container *) wn;
+
+   focused_term = tc->focused_term_get(tc);
+   if (!focused_term)
+     focused_term = term;
+   tc = focused_term->container;
+   new_term = tc->term_prev(tc, tc);
+   if (new_term && new_term != focused_term)
+     _term_focus(new_term, EINA_FALSE);
+
+   /* TODO: get rid of it? */
    _term_miniview_check(term);
 }
 
-void
-term_next(Term *term)
+Term *
+term_next_get(Term *term)
 {
-   Term *term2 = NULL;
-   Config *config = termio_config_get(term->termio);
+   Term_Container *tc = term->container;
 
-   if (term->focused) term2 = term_next_get(term);
-   if ((term2 != NULL) && (term2 != term))
-     {
-        Split *sp, *sp0;
+   return tc->term_next(tc, tc);
+}
 
-        sp0 = _split_find(term->wn->win, term->termio, NULL);
-        sp = _split_find(term2->wn->win, term2->termio, NULL);
-        if ((sp == sp0) && (config->tab_zoom >= 0.01) && (config->notabs))
-          _sel_go(sp, term2);
-        else
-          {
-             _term_focus(term2);
-             if (sp)
-               {
-                  _term_focus_show(sp, term2);
-                  _split_tabcount_update(sp, term2);
-               }
-          }
-     }
+void term_next(Term *term)
+{
+   Term *new_term, *focused_term;
+   Win *wn = term->wn;
+   Term_Container *tc;
+
+   tc = (Term_Container*) wn;
+
+   focused_term = tc->focused_term_get(tc);
+   if (!focused_term)
+     focused_term = term;
+   tc = focused_term->container;
+   new_term = tc->term_next(tc, tc);
+   if (new_term && new_term != focused_term)
+     _term_focus(new_term, EINA_FALSE);
+
+   /* TODO: get rid of it? */
    _term_miniview_check(term);
 }
 
 static void
-_cb_popmedia_del(void *data, Evas *e EINA_UNUSED, Evas_Object *o EINA_UNUSED, 
void *event_info EINA_UNUSED)
+_cb_popmedia_del(void *data, Evas *e EINA_UNUSED,
+                 Evas_Object *o EINA_UNUSED, void *event_info EINA_UNUSED)
 {
    Term *term = data;
-   
+
    term->popmedia = NULL;
    term->popmedia_deleted = EINA_TRUE;
    edje_object_signal_emit(term->bg, "popmedia,off", "terminology");
 }
 
-Eina_Bool
-term_has_popmedia(const Term *term)
-{
-   return !!term->popmedia;
-}
-
-void
-term_popmedia_close(Term *term)
-{
-   if (term->popmedia)
-     edje_object_signal_emit(term->bg, "popmedia,off", "terminology");
-}
-
-
 static void
-_cb_popmedia_done(void *data, Evas_Object *obj EINA_UNUSED, const char *sig 
EINA_UNUSED, const char *src EINA_UNUSED)
+_cb_popmedia_done(void *data, Evas_Object *obj EINA_UNUSED,
+                  const char *sig EINA_UNUSED, const char *src EINA_UNUSED)
 {
    Term *term = data;
 
@@ -1545,10 +2719,11 @@ _cb_popmedia_done(void *data, Evas_Object *obj 
EINA_UNUSED, const char *sig EINA
 }
 
 static void
-_cb_media_loop(void *data, Evas_Object *obj EINA_UNUSED, void *info 
EINA_UNUSED)
+_cb_media_loop(void *data,
+               Evas_Object *obj EINA_UNUSED, void *info EINA_UNUSED)
 {
    Term *term = data;
-   
+
    if (term->popmedia_queue)
      {
         if (term->popmedia) media_play_set(term->popmedia, EINA_FALSE);
@@ -1749,7 +2924,6 @@ error:
      }
 }
 
-
 static void
 _term_miniview_check(Term *term)
 {
@@ -1762,15 +2936,11 @@ _term_miniview_check(Term *term)
 
    EINA_LIST_FOREACH(wn_list, l, term)
      {
-        Split *sp = _split_find(term->wn->win, term->termio, NULL);
         if (term->miniview_shown)
           {
-             if (term->focused)
+             if (_term_is_focused(term))
                edje_object_signal_emit(term->bg, "miniview,on", "terminology");
-             else if (sp->term != term)
-               edje_object_signal_emit(term->bg, "miniview,off", 
"terminology");
           }
-        sp = NULL;
      }
 }
 
@@ -1809,10 +2979,10 @@ static void
 _popmedia_queue_process(Term *term)
 {
    const char *src;
-   
+
    if (!term->popmedia_queue) return;
    src = term->popmedia_queue->data;
-   term->popmedia_queue = eina_list_remove_list(term->popmedia_queue, 
+   term->popmedia_queue = eina_list_remove_list(term->popmedia_queue,
                                                 term->popmedia_queue);
    if (!src) return;
    _popmedia(term, src);
@@ -1832,6 +3002,7 @@ _cb_popup(void *data, Evas_Object *obj EINA_UNUSED, void 
*event)
 {
    Term *term = data;
    const char *src = event;
+
    if (!src) src = termio_link_get(term->termio);
    if (!src) return;
    _popmedia(term, src);
@@ -1940,13 +3111,10 @@ _cb_command(void *data, Evas_Object *obj EINA_UNUSED, 
void *event)
 }
 
 static void
-_cb_tabcount_go(void *data, Evas_Object *obj EINA_UNUSED, const char *sig 
EINA_UNUSED, const char *src EINA_UNUSED)
+_cb_tabcount_go(void *data, Evas_Object *obj EINA_UNUSED,
+                const char *sig EINA_UNUSED, const char *src EINA_UNUSED)
 {
-   Term *term = data;
-   Split *sp;
-
-   sp = _split_find(term->wn->win, term->termio, NULL);
-   _sel_go(sp, term);
+   _cb_select(data, NULL, NULL);
 }
 
 static void
@@ -1966,133 +3134,54 @@ _cb_next(void *data, Evas_Object *obj EINA_UNUSED, 
void *event EINA_UNUSED)
 }
 
 static void
-_cb_new(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
-{
-   Term *term = data;
-
-   main_new(term->wn->win, term->termio);
-   _term_miniview_check(term);
-}
-
-void
-main_term_focus(Term *term EINA_UNUSED)
-{
-   Split *sp;
-
-   sp = _split_find(term->wn->win, term->termio, NULL);
-   if (sp->terms->next != NULL)
-     _sel_go(sp, term);
-}
-
-static void
-_cb_select(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
-{
-   Term *term = data;
-   main_term_focus(term);
-}
-
-static void
 _cb_split_h(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
 {
    Term *term = data;
+   Term_Container *tc = term->container;
 
-   main_split_h(term->wn->win, term->termio, NULL);
+   assert(tc->type == TERM_CONTAINER_TYPE_SOLO);
+   tc->split(tc, tc, NULL, EINA_TRUE);
 }
 
 static void
 _cb_split_v(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
 {
    Term *term = data;
-   
-   main_split_v(term->wn->win, term->termio, NULL);
+   Term_Container *tc = term->container;
+
+   assert(tc->type == TERM_CONTAINER_TYPE_SOLO);
+   tc->split(tc, tc, NULL, EINA_FALSE);
 }
 
 static void
 _cb_title(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
 {
    Term *term = data;
-   if (term->focused)
-     elm_win_title_set(term->wn->win, termio_title_get(term->termio));
-   edje_object_part_text_set(term->bg, "terminology.tab.title",
-                             termio_title_get(term->termio));
-   if (term->config->notabs)
-     {
-        Split *sp = _split_find(term->wn->win, term->termio, NULL);
-        if (sp)
-          {
-             Eina_List *l, *ll;
-             Evas_Object *o;
-             Term *term2;
+   Term_Container *tc = term->container;
+   const char *title = termio_title_get(term->termio);
 
-             EINA_LIST_FOREACH(sp->terms, l, term)
-               {
-                  EINA_LIST_FOREACH(term->tabbar.l.tabs, ll, o)
-                    {
-                       term2 = evas_object_data_get(o, "term");
-                       if (term2)
-                         edje_object_part_text_set(o, "terminology.title",
-                                                   
termio_title_get(term2->termio));
-                    }
-                  EINA_LIST_FOREACH(term->tabbar.r.tabs, ll, o)
-                    {
-                       term2 = evas_object_data_get(o, "term");
-                       if (term2)
-                         edje_object_part_text_set(o, "terminology.title",
-                                                   
termio_title_get(term2->termio));
-                    }
-               }
-          }
-     }
+   if (title)
+     tc->set_title(tc, tc, title);
 }
 
 static void
 _cb_icon(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
 {
    Term *term = data;
-   if (term->focused)
+   if (_term_is_focused(term))
      elm_win_icon_name_set(term->wn->win, termio_icon_name_get(term->termio));
 }
 
-static void
-_tab_go(Term *term, int tnum)
-{
-   Term *term2;
-   Split *sp = _split_find(term->wn->win, term->termio, NULL);
-   if (!sp) return;
-   
-   term2 = eina_list_nth(sp->terms, tnum);
-   if ((!term2) || (term2 == term)) return;
-   _sel_go(sp, term2);
-}
-
-#define CB_TAB(TAB) \
-static void                                             \
-_cb_tab_##TAB(void *data, Evas_Object *obj EINA_UNUSED, \
-             void *event EINA_UNUSED)                   \
-{                                                       \
-   _tab_go(data, TAB - 1);                              \
-}
-
-CB_TAB(1)
-CB_TAB(2)
-CB_TAB(3)
-CB_TAB(4)
-CB_TAB(5)
-CB_TAB(6)
-CB_TAB(7)
-CB_TAB(8)
-CB_TAB(9)
-CB_TAB(10)
-#undef CB_TAB
-
 static Eina_Bool
 _cb_cmd_focus(void *data)
 {
    Win *wn = data;
    Term *term;
-   
+   Term_Container *tc;
+
    wn->cmdbox_focus_timer = NULL;
-   term = win_focused_term_get(wn);
+   tc = (Term_Container*) wn;
+   term = tc->focused_term_get(tc);
    if (term)
      {
         elm_object_focus_set(term->termio, EINA_FALSE);
@@ -2105,7 +3194,7 @@ static Eina_Bool
 _cb_cmd_del(void *data)
 {
    Win *wn = data;
-   
+
    wn->cmdbox_del_timer = NULL;
    if (wn->cmdbox)
      {
@@ -2121,10 +3210,12 @@ _cb_cmd_activated(void *data, Evas_Object *obj 
EINA_UNUSED, void *event EINA_UNU
    Win *wn = data;
    char *cmd = NULL;
    Term *term;
-   
+   Term_Container *tc;
+
    if (wn->cmdbox) elm_object_focus_set(wn->cmdbox, EINA_FALSE);
    edje_object_signal_emit(wn->base, "cmdbox,hide", "terminology");
-   term = win_focused_term_get(wn);
+   tc = (Term_Container *) wn;
+   term = tc->focused_term_get(tc);
    if (term) elm_object_focus_set(term->termio, EINA_TRUE);
    if (wn->cmdbox) cmd = (char *)elm_entry_entry_get(wn->cmdbox);
    if (cmd)
@@ -2147,14 +3238,17 @@ _cb_cmd_activated(void *data, Evas_Object *obj 
EINA_UNUSED, void *event EINA_UNU
 }
 
 static void
-_cb_cmd_aborted(void *data, Evas_Object *obj EINA_UNUSED, void *event 
EINA_UNUSED)
+_cb_cmd_aborted(void *data,
+                Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
 {
    Win *wn = data;
    Term *term;
-   
+   Term_Container *tc;
+
    if (wn->cmdbox) elm_object_focus_set(wn->cmdbox, EINA_FALSE);
    edje_object_signal_emit(wn->base, "cmdbox,hide", "terminology");
-   term = win_focused_term_get(wn);
+   tc = (Term_Container*) wn;
+   term = tc->focused_term_get(tc);
    if (term) elm_object_focus_set(term->termio, EINA_TRUE);
    if (wn->cmdbox_focus_timer)
      {
@@ -2167,13 +3261,16 @@ _cb_cmd_aborted(void *data, Evas_Object *obj 
EINA_UNUSED, void *event EINA_UNUSE
 }
 
 static void
-_cb_cmd_changed(void *data, Evas_Object *obj EINA_UNUSED, void *event 
EINA_UNUSED)
+_cb_cmd_changed(void *data,
+                Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
 {
    Win *wn = data;
    char *cmd = NULL;
    Term *term;
-   
-   term = win_focused_term_get(wn);
+   Term_Container *tc;
+
+   tc = (Term_Container *) wn;
+   term = tc->focused_term_get(tc);
    if (!term) return;
    if (wn->cmdbox) cmd = (char *)elm_entry_entry_get(wn->cmdbox);
    if (cmd)
@@ -2188,10 +3285,11 @@ _cb_cmd_changed(void *data, Evas_Object *obj 
EINA_UNUSED, void *event EINA_UNUSE
 }
 
 static void
-_cb_cmd_hints_changed(void *data, Evas *e EINA_UNUSED, Evas_Object *obj 
EINA_UNUSED, void *event_info EINA_UNUSED)
+_cb_cmd_hints_changed(void *data, Evas *e EINA_UNUSED,
+                      Evas_Object *obj EINA_UNUSED, void *event_info 
EINA_UNUSED)
 {
    Win *wn = data;
-   
+
    if (wn->cmdbox)
      {
         evas_object_show(wn->cmdbox);
@@ -2200,16 +3298,17 @@ _cb_cmd_hints_changed(void *data, Evas *e EINA_UNUSED, 
Evas_Object *obj EINA_UNU
 }
 
 static void
-_cb_cmdbox(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
+_cb_cmdbox(void *data,
+           Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
 {
    Term *term = data;
-   
+
    term->wn->cmdbox_up = EINA_TRUE;
    if (!term->wn->cmdbox)
      {
         Evas_Object *o;
         Win *wn = term->wn;
-        
+
         wn->cmdbox = o = elm_entry_add(wn->win);
         elm_entry_single_line_set(o, EINA_TRUE);
         elm_entry_scrollable_set(o, EINA_FALSE);
@@ -2245,12 +3344,14 @@ _cb_cmdbox(void *data, Evas_Object *obj EINA_UNUSED, 
void *event EINA_UNUSED)
 
 
 static void
-_cb_media_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, 
void *event_info EINA_UNUSED)
+_cb_media_del(void *data, Evas *e EINA_UNUSED,
+              Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
 {
    Term *term = data;
    Config *config = NULL;
-   
-   if (term->termio) config = termio_config_get(term->termio);
+
+   if (term->termio)
+     config = termio_config_get(term->termio);
    term->media = NULL;
    if (term->bg)
      {
@@ -2413,77 +3514,60 @@ main_config_sync(const Config *config)
 }
 
 static void
-term_free(Term *term)
+_term_free(Term *term)
 {
    const char *s;
-   
+
    EINA_LIST_FREE(term->popmedia_queue, s)
      {
         eina_stringshare_del(s);
      }
-   _tabbar_clear(term);
    if (term->media)
      {
         evas_object_event_callback_del(term->media,
                                        EVAS_CALLBACK_DEL,
                                        _cb_media_del);
         evas_object_del(term->media);
-        term->media = NULL;
      }
-   if (term->popmedia)
-     {
-        evas_object_del(term->popmedia);
-        term->popmedia = NULL;
-     }
-        term->popmedia_deleted = EINA_FALSE;
+   term->media = NULL;
+   if (term->popmedia) evas_object_del(term->popmedia);
    if (term->miniview)
      {
         evas_object_del(term->miniview);
         term->miniview = NULL;
      }
-   if (term->tabcount_spacer)
-     {
-        evas_object_del(term->tabcount_spacer);
-        term->tabcount_spacer = NULL;
-     }
-   if (term->tab_spacer)
-     {
-        evas_object_del(term->tab_spacer);
-        term->tab_spacer = NULL;
-     }
-   if (term->tab_region_bg)
-     {
-        evas_object_del(term->tab_region_bg);
-        term->tab_region_bg = NULL;
-     }
-   if (term->tab_region_base)
-     {
-        evas_object_del(term->tab_region_base);
-        term->tab_region_base = NULL;
-     }
+   term->popmedia = NULL;
+   term->popmedia_deleted = EINA_FALSE;
    evas_object_del(term->termio);
    term->termio = NULL;
    evas_object_del(term->base);
    term->base = NULL;
    evas_object_del(term->bg);
    term->bg = NULL;
+   if (term->tabcount_spacer)
+     {
+        evas_object_del(term->tabcount_spacer);
+        term->tabcount_spacer = NULL;
+     }
    free(term);
 }
 
 static void
-_cb_tabcount_prev(void *data, Evas_Object *obj EINA_UNUSED, const char *sig 
EINA_UNUSED, const char *src EINA_UNUSED)
+_cb_tabcount_prev(void *data, Evas_Object *obj EINA_UNUSED,
+                  const char *sig EINA_UNUSED, const char *src EINA_UNUSED)
 {
    _cb_prev(data, NULL, NULL);
 }
 
 static void
-_cb_tabcount_next(void *data, Evas_Object *obj EINA_UNUSED, const char *sig 
EINA_UNUSED, const char *src EINA_UNUSED)
+_cb_tabcount_next(void *data, Evas_Object *obj EINA_UNUSED,
+                  const char *sig EINA_UNUSED, const char *src EINA_UNUSED)
 {
    _cb_next(data, NULL, NULL);
 }
 
 static void
-main_term_bg_config(Term *term)
+_term_bg_config(Term *term)
 {
    Edje_Message_Int msg;
 
@@ -2497,7 +3581,7 @@ main_term_bg_config(Term *term)
 
    termio_theme_set(term->termio, term->bg);
    edje_object_signal_callback_add(term->bg, "popmedia,done", "terminology",
-                                   _cb_popmedia_done, term); 
+                                   _cb_popmedia_done, term);
    edje_object_signal_callback_add(term->bg, "tabcount,go", "terminology",
                                    _cb_tabcount_go, term);
    edje_object_signal_callback_add(term->bg, "tabcount,prev", "terminology",
@@ -2555,7 +3639,7 @@ main_term_bg_config(Term *term)
           }
      }
 
-   if ((term->focused) && (term->wn->focused))
+   if (_term_is_focused(term) && (_win_is_focused(term->wn)))
      {
         edje_object_signal_emit(term->bg, "focus,in", "terminology");
         edje_object_signal_emit(term->base, "focus,in", "terminology");
@@ -2568,14 +3652,16 @@ main_term_bg_config(Term *term)
 }
 
 static void
-_cb_tabregion_change(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void 
*info EINA_UNUSED)
+_cb_tabregion_change(void *data, Evas *e EINA_UNUSED, Evas_Object *obj,
+                     void *info EINA_UNUSED)
 {
    Term *term = data;
    Evas_Coord w, h;
 
    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
    evas_object_size_hint_min_set(term->tab_region_base, w, h);
-   edje_object_part_swallow(term->base, "terminology.tabregion", 
term->tab_region_base);
+   edje_object_part_swallow(term->base, "terminology.tabregion",
+                            term->tab_region_base);
 }
 
 static void
@@ -2595,71 +3681,6 @@ _term_tabregion_setup(Term *term)
    edje_object_part_swallow(term->base, "terminology.tabregion", o);
 }
 
-static void
-_main_term_bg_redo(Term *term)
-{
-   Evas_Object *o;
-
-   _tabbar_clear(term);
-   if (term->tabcount_spacer)
-     {
-        evas_object_del(term->tabcount_spacer);
-        term->tabcount_spacer = NULL;
-     }
-   if (term->tab_spacer)
-     {
-        evas_object_del(term->tab_spacer);
-        term->tab_spacer = NULL;
-     }
-   if (term->tab_region_bg)
-     {
-        evas_object_del(term->tab_region_bg);
-        term->tab_region_bg = NULL;
-     }
-   if (term->tab_region_base)
-     {
-        evas_object_del(term->tab_region_base);
-        term->tab_region_base = NULL;
-     }
-   if (term->miniview)
-     {
-        edje_object_part_unswallow(term->bg, term->miniview);
-        evas_object_del(term->miniview);
-        term->miniview = NULL;
-     }
-   evas_object_del(term->base);
-   evas_object_del(term->bg);
-
-   term->base = o = edje_object_add(evas_object_evas_get(term->wn->win));
-   theme_apply(o, term->config, "terminology/core");
-
-   theme_auto_reload_enable(o);
-   evas_object_data_set(o, "theme_reload_func", main_term_bg_config);
-   evas_object_data_set(o, "theme_reload_func_data", term);
-   evas_object_show(o);
-
-   term->bg = o = edje_object_add(evas_object_evas_get(term->wn->win));
-   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
-   evas_object_size_hint_fill_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
-   theme_apply(o, term->config, "terminology/background");
-
-   _term_tabregion_setup(term);
-
-   term->miniview = o = miniview_add(term->wn->win, term->termio);
-   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
-   evas_object_size_hint_fill_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
-
-   o = term->bg;
-
-   theme_auto_reload_enable(o);
-   evas_object_data_set(o, "theme_reload_func", main_term_bg_config);
-   evas_object_data_set(o, "theme_reload_func_data", term);
-   evas_object_show(o);
-   main_term_bg_config(term);
-   if (term->miniview_shown)
-     edje_object_signal_emit(term->bg, "miniview,on", "terminology");
-}
-
 Eina_Bool
 main_term_popup_exists(const Term *term)
 {
@@ -2692,48 +3713,25 @@ static void
 _cb_bell(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
 {
    Term *term = data;
-   Config *config = termio_config_get(term->termio);
+   Term_Container *tc;
 
-   if (!config) return;
-   if (!config->disable_visual_bell)
-     {
-        Split *sp;
+   tc = term->container;
 
-        edje_object_signal_emit(term->bg, "bell", "terminology");
-        edje_object_signal_emit(term->base, "bell", "terminology");
-        if (config->bell_rings)
-          {
-             edje_object_signal_emit(term->bg, "bell,ring", "terminology");
-             edje_object_signal_emit(term->base, "bell,ring", "terminology");
-          }
-        sp = _split_find(term->wn->win, term->termio, NULL);
-        if (sp)
-          {
-             if (sp->term != term)
-               {
-                  term->missed_bell = EINA_TRUE;
-                  _split_tabcount_update(sp, sp->term);
-               }
-          }
-     }
-   if (config->urg_bell)
-     {
-        if (!term->wn->focused) elm_win_urgent_set(term->wn->win, EINA_TRUE);
-     }
-   // XXX: update tabbars to have bell status in them
+   tc->bell(tc, tc);
 }
 
 
 static void
-_cb_options_done(void *data EINA_UNUSED)
+_cb_options_done(void *data)
 {
    Win *wn = data;
    Eina_List *l;
    Term *term;
-   if (!wn->focused) return;
+
+   if (!_win_is_focused(wn)) return;
    EINA_LIST_FOREACH(wn->terms, l, term)
      {
-        if (term->focused)
+        if (_term_is_focused(term))
           {
              elm_object_focus_set(term->termio, EINA_TRUE);
              termio_event_feed_mouse_in(term->termio);
@@ -2742,7 +3740,7 @@ _cb_options_done(void *data EINA_UNUSED)
 }
 
 static void
-_cb_options(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
+_cb_options(void *data, Evas_Object *obj EINA_UNUSED,
             void *event EINA_UNUSED)
 {
    Term *term = data;
@@ -2755,9 +3753,11 @@ static void
 _cb_exited(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
 {
    Term *term = data;
+
    if (!term->hold)
      {
-        Evas_Object *win = win_evas_object_get(term->wn);
+        Win *wn = term->wn;
+        Evas_Object *win = win_evas_object_get(wn);
         main_close(win, term->termio);
      }
 }
@@ -2768,17 +3768,19 @@ term_ref(Term *term)
    term->refcnt++;
 }
 
-void term_unref(Term *term)
+void
+term_unref(Term *term)
 {
    EINA_SAFETY_ON_NULL_RETURN(term);
 
    term->refcnt--;
    if (term->refcnt <= 0)
      {
-        term_free(term);
+        _term_free(term);
      }
 }
 
+
 Term *
 term_new(Win *wn, Config *config, const char *cmd,
          Eina_Bool login_shell, const char *cd,
@@ -2803,12 +3805,14 @@ term_new(Win *wn, Config *config, const char *cmd,
    term->wn = wn;
    term->hold = hold;
    term->config = config;
-   
+
    term->base = o = edje_object_add(canvas);
    theme_apply(o, term->config, "terminology/core");
+   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_fill_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
 
    theme_auto_reload_enable(o);
-   evas_object_data_set(o, "theme_reload_func", main_term_bg_config);
+   evas_object_data_set(o, "theme_reload_func", _term_bg_config);
    evas_object_data_set(o, "theme_reload_func_data", term);
    evas_object_show(o);
 
@@ -2824,7 +3828,7 @@ term_new(Win *wn, Config *config, const char *cmd,
      }
 
    theme_auto_reload_enable(o);
-   evas_object_data_set(o, "theme_reload_func", main_term_bg_config);
+   evas_object_data_set(o, "theme_reload_func", _term_bg_config);
    evas_object_data_set(o, "theme_reload_func_data", term);
    evas_object_show(o);
 
@@ -2840,13 +3844,7 @@ term_new(Win *wn, Config *config, const char *cmd,
 
    term->termio = o = termio_add(wn->win, config, cmd, login_shell, cd,
                                  size_w, size_h, term);
-   if (!term->termio)
-     {
-        CRITICAL(_("Could not create termio widget."));
-        evas_object_del(term->bg);
-        free(term);
-        return NULL;
-     }
+   evas_object_data_set(o, "term", term);
    colors_term_init(termio_textgrid_get(term->termio), term->bg, config);
 
    termio_win_set(o, wn->win);
@@ -2860,8 +3858,6 @@ term_new(Win *wn, Config *config, const char *cmd,
 
    edje_object_signal_callback_add(term->bg, "popmedia,done", "terminology",
                                    _cb_popmedia_done, term);
-   edje_object_signal_callback_add(term->bg, "tabcount,go", "terminology",
-                                   _cb_tabcount_go, term);
    edje_object_signal_callback_add(term->bg, "tabcount,prev", "terminology",
                                    _cb_tabcount_prev, term);
    edje_object_signal_callback_add(term->bg, "tabcount,next", "terminology",
@@ -2906,169 +3902,14 @@ term_new(Win *wn, Config *config, const char *cmd,
    evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_IN,
                                   _cb_term_mouse_in, term);
 
-   if (!wn->terms) term->focused = EINA_TRUE;
-
    wn->terms = eina_list_append(wn->terms, term);
 
-   return term;
-}
-
-
-/* }}} */
-/* {{{ Sel */
-
-static void
-_sel_restore(Split *sp)
-{
-   Eina_List *l;
-   Term *tm;
-
-   EINA_LIST_FOREACH(sp->terms, l, tm)
-     {
-        if (tm->unswallowed)
-          {
-#if (EVAS_VERSION_MAJOR > 1) || (EVAS_VERSION_MINOR >= 8)
-             evas_object_image_source_visible_set(tm->sel, EINA_TRUE);
-#endif
-             edje_object_part_swallow(tm->bg, "terminology.content", tm->base);
-             tm->unswallowed = EINA_FALSE;
-             evas_object_show(tm->base);
-             tm->sel = NULL;
-          }
-     }
-   evas_object_del(sp->sel);
-   evas_object_del(sp->sel_bg);
-   sp->sel = NULL;
-   sp->sel_bg = NULL;
-}
-
-static void
-_sel_cb_selected(void *data,
-                 Evas_Object *obj EINA_UNUSED,
-                 void *info EINA_UNUSED)
-{
-   Split *sp = data;
-   Eina_List *l;
-   Term *tm;
-
-   EINA_LIST_FOREACH(sp->terms, l, tm)
-     {
-        if (tm->sel == info)
-          {
-             _term_focus(tm);
-             _term_focus_show(sp, tm);
-             _split_tabcount_update(sp, tm);
-             _sel_restore(sp);
-             _term_miniview_check(tm);
-             return;
-          }
-     }
-   _sel_restore(sp);
-   _term_focus(sp->term);
-   _term_focus_show(sp, sp->term);
-   _split_tabcount_update(sp, sp->term);
-   _term_miniview_check(tm);
-}
-
-static void
-_sel_cb_exit(void *data,
-             Evas_Object *obj EINA_UNUSED,
-             void *info EINA_UNUSED)
-{
-   Split *sp = data;
-   _sel_restore(sp);
-   _term_focus(sp->term);
-   _term_focus_show(sp, sp->term);
-   _split_tabcount_update(sp, sp->term);
-}
+   _term_bg_config(term);
 
-static void
-_sel_cb_ending(void *data, Evas_Object *obj EINA_UNUSED, void *info 
EINA_UNUSED)
-{
-   Split *sp = data;
-   edje_object_signal_emit(sp->sel_bg, "end", "terminology");
+   return term;
 }
 
-static void
-_sel_go(Split *sp, Term *term)
-{
-   Eina_List *l;
-   Term *tm;
-   double z;
-   Edje_Message_Int msg;
-
-   evas_object_hide(sp->term->bg);
-   sp->sel_bg = edje_object_add(evas_object_evas_get(sp->wn->win));
-   theme_apply(sp->sel_bg, term->config, "terminology/sel/base");
-   if (sp->term->config->translucent)
-     msg.val = term->config->opacity;
-   else
-     msg.val = 100;
-   edje_object_message_send(sp->sel_bg, EDJE_MESSAGE_INT, 1, &msg);
-   edje_object_signal_emit(sp->sel_bg, "begin", "terminology");
-   sp->sel = sel_add(sp->wn->win);
-   EINA_LIST_FOREACH(sp->terms, l, tm)
-     {
-        Evas_Object *img;
-        Evas_Coord w, h;
-        
-        edje_object_part_unswallow(tm->bg, tm->base);
-        evas_object_lower(tm->base);
-        evas_object_move(tm->base, -9999, -9999);
-        evas_object_show(tm->base);
-        evas_object_clip_unset(tm->base);
-#if (EVAS_VERSION_MAJOR > 1) || (EVAS_VERSION_MINOR >= 8)
-        evas_object_image_source_visible_set(tm->sel, EINA_FALSE);
-#endif
-        tm->unswallowed = EINA_TRUE;
 
-        img = evas_object_image_filled_add(evas_object_evas_get(sp->wn->win));
-        evas_object_image_source_set(img, tm->base);
-        evas_object_geometry_get(tm->base, NULL, NULL, &w, &h);
-        evas_object_resize(img, w, h);
-        evas_object_data_set(img, "termio", tm->termio);
-        tm->sel = img;
-        
-        sel_entry_add(sp->sel, tm->sel, (tm == sp->term),
-                      tm->missed_bell, tm->config);
-     }
-   edje_object_part_swallow(sp->sel_bg, "terminology.content", sp->sel);
-   evas_object_show(sp->sel);
-   if (!sp->parent)
-     edje_object_part_swallow(sp->wn->base, "terminology.content", sp->sel_bg);
-   else
-     {
-        if (sp == sp->parent->s1)
-          {
-             elm_object_part_content_unset(sp->parent->panes, PANES_TOP);
-             elm_object_part_content_set(sp->parent->panes, PANES_TOP,
-                                         sp->sel_bg);
-          }
-        else
-          {
-             elm_object_part_content_unset(sp->parent->panes, PANES_BOTTOM);
-             elm_object_part_content_set(sp->parent->panes, PANES_BOTTOM,
-                                         sp->sel_bg);
-          }
-     }
-   evas_object_show(sp->sel_bg);
-   evas_object_smart_callback_add(sp->sel, "selected", _sel_cb_selected, sp);
-   evas_object_smart_callback_add(sp->sel, "exit", _sel_cb_exit, sp);
-   evas_object_smart_callback_add(sp->sel, "ending", _sel_cb_ending, sp);
-   z = 1.0;
-   sel_go(sp->sel);
-   if (eina_list_count(sp->terms) >= 1)
-     z = 1.0 / (sqrt(eina_list_count(sp->terms)) * 0.8);
-   if (z > 1.0) z = 1.0;
-   sel_orig_zoom_set(sp->sel, z);
-   sel_zoom(sp->sel, z);
-   if (term != sp->term)
-     {
-        sel_entry_selected_set(sp->sel, term->sel, EINA_TRUE);
-        sel_exit(sp->sel);
-     }
-   elm_object_focus_set(sp->sel, EINA_TRUE);
-}
 /* }}} */
 
 void
@@ -3083,25 +3924,15 @@ windows_free(void)
      }
 }
 
-static void
-_split_update(Split *sp)
-{
-   Eina_List *l;
-   Term *tm;
-
-   EINA_LIST_FOREACH(sp->terms, l, tm)
-     {
-        _split_tabcount_update(sp, tm);
-     }
-   if (sp->s1) _split_update(sp->s1);
-   if (sp->s2) _split_update(sp->s2);
-}
-
 void
 windows_update(void)
 {
    Eina_List *l;
    Win *wn;
 
-   EINA_LIST_FOREACH(wins, l, wn) _split_update(wn->split);
+   EINA_LIST_FOREACH(wins, l, wn)
+     {
+        Term_Container *tc = (Term_Container *) wn;
+        tc->update(tc);
+     }
 }
diff --git a/src/bin/win.h b/src/bin/win.h
index d25f542..91a5b8b 100644
--- a/src/bin/win.h
+++ b/src/bin/win.h
@@ -16,6 +16,9 @@ Evas_Object *term_miniview_get(Term *term);
 void term_miniview_toggle(Term *term);
 void term_miniview_hide(Term *term);
 
+void split_horizontally(Evas_Object *win, Evas_Object *term, const char *cmd);
+void split_vertically(Evas_Object *win, Evas_Object *term, const char *cmd);
+
 
 Win *
 win_new(const char *name, const char *role, const char *title,
@@ -28,6 +31,7 @@ void windows_free(void);
 void windows_update(void);
 
 Term *term_new(Win *wn, Config *config, const char *cmd, Eina_Bool 
login_shell, const char *cd, int size_w, int size_h, Eina_Bool hold);
+int win_term_set(Win *wn, Term *term);
 
 Eina_List *
 terms_from_win_object(Evas_Object *win);

-- 


Reply via email to