2012-06-17 10:04:17 -07:00
|
|
|
#include "private.h"
|
|
|
|
|
2012-06-12 03:10:01 -07:00
|
|
|
#include <Elementary.h>
|
|
|
|
#include "termio.h"
|
|
|
|
#include "termpty.h"
|
|
|
|
#include "utf8.h"
|
|
|
|
#include "col.h"
|
|
|
|
#include "keyin.h"
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
typedef struct _Termio Termio;
|
|
|
|
|
|
|
|
struct _Termio
|
|
|
|
{
|
|
|
|
Evas_Object_Smart_Clipped_Data __clipped_data;
|
|
|
|
struct {
|
|
|
|
int size;
|
|
|
|
const char *name;
|
|
|
|
int chw, chh;
|
|
|
|
} font;
|
|
|
|
struct {
|
|
|
|
int w, h;
|
2012-06-15 22:07:33 -07:00
|
|
|
Evas_Object *obj;
|
2012-06-12 03:10:01 -07:00
|
|
|
} grid;
|
|
|
|
struct {
|
|
|
|
Evas_Object *obj, *selo1, *selo2, *selo3;
|
|
|
|
int x, y;
|
|
|
|
struct {
|
|
|
|
int x, y;
|
|
|
|
} sel1, sel2;
|
|
|
|
Eina_Bool sel : 1;
|
|
|
|
Eina_Bool makesel : 1;
|
|
|
|
} cur;
|
2012-06-18 01:56:27 -07:00
|
|
|
struct {
|
|
|
|
struct {
|
|
|
|
int x, y;
|
|
|
|
} sel1, sel2;
|
|
|
|
Eina_Bool sel : 1;
|
|
|
|
} backup;
|
2012-06-12 03:10:01 -07:00
|
|
|
int scroll;
|
|
|
|
Evas_Object *event;
|
|
|
|
Termpty *pty;
|
|
|
|
Ecore_Job *job;
|
|
|
|
Ecore_Timer *delayed_size_timer;
|
|
|
|
Evas_Object *win;
|
2012-06-17 13:24:23 -07:00
|
|
|
Config *config;
|
2012-06-12 03:10:01 -07:00
|
|
|
Eina_Bool jump_on_change : 1;
|
|
|
|
};
|
|
|
|
|
|
|
|
static Evas_Smart *_smart = NULL;
|
2012-06-17 13:24:23 -07:00
|
|
|
static Evas_Smart_Class _parent_sc = EVAS_SMART_CLASS_INIT_NULL;
|
2012-06-12 03:10:01 -07:00
|
|
|
|
|
|
|
static void _smart_calculate(Evas_Object *obj);
|
|
|
|
|
2012-06-17 19:56:58 -07:00
|
|
|
static void
|
|
|
|
_reload_theme(void *data __UNUSED__, Evas_Object *obj,
|
|
|
|
const char *emission __UNUSED__, const char *source __UNUSED__)
|
|
|
|
{
|
|
|
|
const char *file;
|
|
|
|
const char *group;
|
|
|
|
|
|
|
|
edje_object_file_get(obj, &file, &group);
|
|
|
|
edje_object_file_set(obj, file, group);
|
|
|
|
fprintf(stderr, "RELOADING THEME termio\n");
|
|
|
|
}
|
|
|
|
|
2012-06-12 03:10:01 -07:00
|
|
|
static void
|
|
|
|
_smart_apply(Evas_Object *obj)
|
|
|
|
{
|
|
|
|
Termio *sd = evas_object_smart_data_get(obj);
|
|
|
|
Evas_Coord ox, oy, ow, oh;
|
2012-06-17 10:04:17 -07:00
|
|
|
int j, x, y, w, ch1, ch2;
|
2012-06-15 22:07:33 -07:00
|
|
|
|
2012-06-12 03:10:01 -07:00
|
|
|
if (!sd) return;
|
|
|
|
evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
|
2012-06-12 17:26:00 -07:00
|
|
|
|
2012-06-15 22:07:33 -07:00
|
|
|
for (y = 0; y < sd->grid.h; y++)
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
2012-06-15 22:07:33 -07:00
|
|
|
Termcell *cells;
|
|
|
|
Evas_Textgrid_Cell *tc;
|
|
|
|
|
|
|
|
w = 0; j = 0;
|
|
|
|
cells = termpty_cellrow_get(sd->pty, y - sd->scroll, &w);
|
|
|
|
tc = evas_object_textgrid_cellrow_get(sd->grid.obj, y);
|
2012-06-15 22:27:03 -07:00
|
|
|
if (!tc) continue;
|
2012-06-15 22:07:33 -07:00
|
|
|
ch1 = -1;
|
|
|
|
for (x = 0; x < sd->grid.w; x++)
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
2012-06-15 22:07:33 -07:00
|
|
|
if ((!cells) || (x >= w))
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
2012-06-15 22:07:33 -07:00
|
|
|
if ((tc[x].codepoint != 0) ||
|
|
|
|
(tc[x].bg != COL_INVIS) ||
|
|
|
|
(tc[x].bg_extended))
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
2012-06-15 22:07:33 -07:00
|
|
|
if (ch1 < 0) ch1 = x;
|
|
|
|
ch2 = x;
|
2012-06-12 03:10:01 -07:00
|
|
|
}
|
2012-06-15 22:07:33 -07:00
|
|
|
tc[x].codepoint = 0;
|
|
|
|
tc[x].bg = COL_INVIS;
|
|
|
|
tc[x].bg_extended = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (cells[j].att.invisible)
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
2012-06-15 22:07:33 -07:00
|
|
|
if ((tc[x].codepoint != 0) ||
|
|
|
|
(tc[x].bg != COL_INVIS) ||
|
|
|
|
(tc[x].bg_extended))
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
2012-06-15 22:07:33 -07:00
|
|
|
if (ch1 < 0) ch1 = x;
|
|
|
|
ch2 = x;
|
2012-06-12 03:10:01 -07:00
|
|
|
}
|
2012-06-15 22:07:33 -07:00
|
|
|
tc[x].codepoint = 0;
|
|
|
|
tc[x].bg = COL_INVIS;
|
|
|
|
tc[x].bg_extended = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int bold, fg, bg, fgext, bgext, glyph;
|
|
|
|
|
|
|
|
// colors
|
|
|
|
bold = cells[j].att.bold;
|
|
|
|
fgext = cells[j].att.fg256;
|
|
|
|
bgext = cells[j].att.bg256;
|
|
|
|
glyph = cells[j].glyph;
|
|
|
|
|
|
|
|
if (cells[j].att.inverse)
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
2012-06-15 22:07:33 -07:00
|
|
|
fgext = 0;
|
|
|
|
bgext = 0;
|
|
|
|
fg = COL_INVERSE;
|
|
|
|
bg = COL_INVERSEBG;
|
|
|
|
if (bold)
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
2012-06-15 22:07:33 -07:00
|
|
|
fg += 12;
|
|
|
|
bg += 12;
|
2012-06-12 03:10:01 -07:00
|
|
|
}
|
2012-06-15 22:07:33 -07:00
|
|
|
if (cells[j].att.faint)
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
2012-06-15 22:07:33 -07:00
|
|
|
fg += 24;
|
|
|
|
bg += 24;
|
2012-06-12 03:10:01 -07:00
|
|
|
}
|
2012-06-15 22:07:33 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fg = cells[j].att.fg;
|
|
|
|
bg = cells[j].att.bg;
|
|
|
|
|
|
|
|
if (!fgext)
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
2012-06-15 22:07:33 -07:00
|
|
|
if (bold) fg += 12;
|
2012-06-12 03:10:01 -07:00
|
|
|
}
|
2012-06-15 22:07:33 -07:00
|
|
|
if (!bgext)
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
2012-06-15 22:07:33 -07:00
|
|
|
if (bg == COL_DEF) bg = COL_INVIS;
|
2012-06-12 03:10:01 -07:00
|
|
|
}
|
2012-06-15 22:07:33 -07:00
|
|
|
if (cells[j].att.faint)
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
2012-06-15 22:07:33 -07:00
|
|
|
if (!fgext) fg += 24;
|
|
|
|
if (!bgext) bg += 24;
|
2012-06-12 03:10:01 -07:00
|
|
|
}
|
2012-06-15 22:07:33 -07:00
|
|
|
if ((glyph == ' ') || (glyph == 0))
|
|
|
|
fg = COL_INVIS;
|
2012-06-12 03:10:01 -07:00
|
|
|
}
|
2012-06-15 22:07:33 -07:00
|
|
|
if ((tc[x].codepoint != glyph) ||
|
|
|
|
(tc[x].fg != fg) ||
|
|
|
|
(tc[x].bg != bg) ||
|
|
|
|
(tc[x].fg_extended != fgext) ||
|
|
|
|
(tc[x].bg_extended != bgext) ||
|
|
|
|
(tc[x].underline != cells[j].att.underline) ||
|
|
|
|
(tc[x].strikethrough != cells[j].att.strike))
|
|
|
|
{
|
|
|
|
if (ch1 < 0) ch1 = x;
|
|
|
|
ch2 = x;
|
|
|
|
}
|
|
|
|
tc[x].fg_extended = fgext;
|
|
|
|
tc[x].bg_extended = bgext;
|
|
|
|
tc[x].underline = cells[j].att.underline;
|
|
|
|
tc[x].strikethrough = cells[j].att.strike;
|
|
|
|
tc[x].fg = fg;
|
|
|
|
tc[x].bg = bg;
|
|
|
|
tc[x].codepoint = glyph;
|
|
|
|
// cells[j].att.italic // never going 2 support
|
|
|
|
// cells[j].att.blink
|
|
|
|
// cells[j].att.blink2
|
2012-06-12 03:10:01 -07:00
|
|
|
}
|
|
|
|
}
|
2012-06-15 22:07:33 -07:00
|
|
|
j++;
|
2012-06-12 03:10:01 -07:00
|
|
|
}
|
2012-06-15 22:07:33 -07:00
|
|
|
evas_object_textgrid_cellrow_set(sd->grid.obj, y, tc);
|
|
|
|
/* only bothering to keep 1 change span per row - not worth doing
|
|
|
|
* more really */
|
|
|
|
if (ch1 >= 0)
|
|
|
|
evas_object_textgrid_update_add(sd->grid.obj, ch1, y,
|
|
|
|
ch2 - ch1 + 1, 1);
|
2012-06-12 03:10:01 -07:00
|
|
|
}
|
2012-06-15 22:07:33 -07:00
|
|
|
|
2012-06-12 03:10:01 -07:00
|
|
|
if ((sd->scroll != 0) || (sd->pty->state.hidecursor))
|
|
|
|
evas_object_hide(sd->cur.obj);
|
|
|
|
else
|
|
|
|
evas_object_show(sd->cur.obj);
|
|
|
|
sd->cur.x = sd->pty->state.cx;
|
|
|
|
sd->cur.y = sd->pty->state.cy;
|
2012-06-12 17:26:00 -07:00
|
|
|
evas_object_move(sd->cur.obj,
|
2012-06-12 03:10:01 -07:00
|
|
|
ox + (sd->cur.x * sd->font.chw),
|
|
|
|
oy + (sd->cur.y * sd->font.chh));
|
|
|
|
if (sd->cur.sel)
|
|
|
|
{
|
2012-06-17 10:13:50 -07:00
|
|
|
int start_x, start_y, end_x, end_y;
|
2012-06-12 17:26:00 -07:00
|
|
|
|
2012-06-17 10:13:50 -07:00
|
|
|
start_x = sd->cur.sel1.x;
|
|
|
|
start_y = sd->cur.sel1.y;
|
|
|
|
end_x = sd->cur.sel2.x;
|
|
|
|
end_y = sd->cur.sel2.y;
|
|
|
|
if ((start_y > end_y) || ((start_y == end_y) && (end_x < start_x)))
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
|
|
|
int t;
|
2012-06-12 17:26:00 -07:00
|
|
|
|
2012-06-17 10:13:50 -07:00
|
|
|
t = start_x; start_x = end_x; end_x = t;
|
|
|
|
t = start_y; start_y = end_y; end_y = t;
|
2012-06-12 03:10:01 -07:00
|
|
|
}
|
2012-06-12 17:26:00 -07:00
|
|
|
|
2012-06-17 10:13:50 -07:00
|
|
|
if (end_y > start_y)
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
|
|
|
evas_object_move(sd->cur.selo1,
|
2012-06-17 10:13:50 -07:00
|
|
|
ox + (start_x * sd->font.chw),
|
|
|
|
oy + ((start_y + sd->scroll) * sd->font.chh));
|
2012-06-12 03:10:01 -07:00
|
|
|
evas_object_resize(sd->cur.selo1,
|
2012-06-17 10:13:50 -07:00
|
|
|
(sd->grid.w - start_x) * sd->font.chw,
|
2012-06-12 03:10:01 -07:00
|
|
|
sd->font.chh);
|
|
|
|
evas_object_show(sd->cur.selo1);
|
2012-06-12 17:26:00 -07:00
|
|
|
|
2012-06-12 03:10:01 -07:00
|
|
|
evas_object_move(sd->cur.selo3,
|
2012-06-17 10:13:50 -07:00
|
|
|
ox, oy + ((end_y + sd->scroll) * sd->font.chh));
|
2012-06-12 03:10:01 -07:00
|
|
|
evas_object_resize(sd->cur.selo3,
|
2012-06-17 10:13:50 -07:00
|
|
|
(end_x + 1) * sd->font.chw,
|
2012-06-12 03:10:01 -07:00
|
|
|
sd->font.chh);
|
|
|
|
evas_object_show(sd->cur.selo3);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
evas_object_move(sd->cur.selo1,
|
2012-06-17 10:13:50 -07:00
|
|
|
ox + (start_x * sd->font.chw),
|
|
|
|
oy + ((start_y + sd->scroll) * sd->font.chh));
|
2012-06-12 03:10:01 -07:00
|
|
|
evas_object_resize(sd->cur.selo1,
|
2012-06-17 10:13:50 -07:00
|
|
|
(end_x - start_x + 1) * sd->font.chw,
|
2012-06-12 03:10:01 -07:00
|
|
|
sd->font.chh);
|
|
|
|
evas_object_show(sd->cur.selo1);
|
|
|
|
evas_object_hide(sd->cur.selo3);
|
|
|
|
}
|
2012-06-17 10:13:50 -07:00
|
|
|
if (end_y > (start_y + 1))
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
|
|
|
evas_object_move(sd->cur.selo2,
|
2012-06-17 10:13:50 -07:00
|
|
|
ox, oy + ((start_y + 1 + sd->scroll) * sd->font.chh));
|
2012-06-12 03:10:01 -07:00
|
|
|
evas_object_resize(sd->cur.selo2,
|
|
|
|
sd->grid.w * sd->font.chw,
|
2012-06-17 10:13:50 -07:00
|
|
|
(end_y - start_y - 1) * sd->font.chh);
|
2012-06-12 03:10:01 -07:00
|
|
|
evas_object_show(sd->cur.selo2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
evas_object_hide(sd->cur.selo2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
evas_object_hide(sd->cur.selo1);
|
|
|
|
evas_object_hide(sd->cur.selo2);
|
|
|
|
evas_object_hide(sd->cur.selo3);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-06-12 06:08:09 -07:00
|
|
|
_smart_size(Evas_Object *obj, int w, int h, Eina_Bool force)
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
|
|
|
Termio *sd = evas_object_smart_data_get(obj);
|
|
|
|
if (!sd) return;
|
|
|
|
|
|
|
|
if (w < 1) w = 1;
|
|
|
|
if (h < 1) h = 1;
|
2012-06-12 06:08:09 -07:00
|
|
|
if (!force)
|
|
|
|
{
|
|
|
|
if ((w == sd->grid.w) && (h == sd->grid.h)) return;
|
|
|
|
}
|
2012-06-12 03:10:01 -07:00
|
|
|
|
|
|
|
evas_event_freeze(evas_object_evas_get(obj));
|
2012-06-15 22:07:33 -07:00
|
|
|
evas_object_textgrid_size_set(sd->grid.obj, w, h);
|
2012-06-12 03:10:01 -07:00
|
|
|
sd->grid.w = w;
|
|
|
|
sd->grid.h = h;
|
|
|
|
evas_object_resize(sd->cur.obj, sd->font.chw, sd->font.chh);
|
|
|
|
evas_object_size_hint_min_set(obj, sd->font.chw, sd->font.chh);
|
2012-06-12 17:26:00 -07:00
|
|
|
evas_object_size_hint_request_set(obj,
|
2012-06-12 03:10:01 -07:00
|
|
|
sd->font.chw * sd->grid.w,
|
|
|
|
sd->font.chh * sd->grid.h);
|
|
|
|
termpty_resize(sd->pty, w, h);
|
|
|
|
_smart_calculate(obj);
|
|
|
|
_smart_apply(obj);
|
|
|
|
evas_event_thaw(evas_object_evas_get(obj));
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_smart_cb_delayed_size(void *data)
|
|
|
|
{
|
|
|
|
Evas_Object *obj = data;
|
|
|
|
Termio *sd = evas_object_smart_data_get(obj);
|
|
|
|
Evas_Coord ow = 0, oh = 0;
|
|
|
|
int w, h;
|
2012-06-12 17:26:00 -07:00
|
|
|
|
2012-06-12 03:10:01 -07:00
|
|
|
if (!sd) return EINA_FALSE;
|
|
|
|
sd->delayed_size_timer = NULL;
|
|
|
|
|
|
|
|
evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
|
2012-06-12 17:26:00 -07:00
|
|
|
|
2012-06-12 03:10:01 -07:00
|
|
|
w = ow / sd->font.chw;
|
|
|
|
h = oh / sd->font.chh;
|
2012-06-12 06:08:09 -07:00
|
|
|
_smart_size(obj, w, h, EINA_FALSE);
|
2012-06-12 03:10:01 -07:00
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_smart_cb_change(void *data)
|
|
|
|
{
|
|
|
|
Evas_Object *obj = data;
|
|
|
|
Termio *sd;
|
|
|
|
sd = evas_object_smart_data_get(obj);
|
|
|
|
if (!sd) return;
|
|
|
|
sd->job = NULL;
|
|
|
|
_smart_apply(obj);
|
2012-06-16 19:35:07 -07:00
|
|
|
evas_object_smart_callback_call(obj, "changed", NULL);
|
2012-06-12 03:10:01 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_take_selection(Evas_Object *obj)
|
|
|
|
{
|
|
|
|
Termio *sd = evas_object_smart_data_get(obj);
|
2012-06-17 10:13:50 -07:00
|
|
|
int start_x, start_y, end_x, end_y;
|
2012-06-12 03:10:01 -07:00
|
|
|
char *s;
|
2012-06-12 17:26:00 -07:00
|
|
|
|
2012-06-12 03:10:01 -07:00
|
|
|
if (!sd) return;
|
2012-06-17 10:13:50 -07:00
|
|
|
start_x = sd->cur.sel1.x;
|
|
|
|
start_y = sd->cur.sel1.y;
|
|
|
|
end_x = sd->cur.sel2.x;
|
|
|
|
end_y = sd->cur.sel2.y;
|
|
|
|
if ((start_y > end_y) || ((start_y == end_y) && (end_x < start_x)))
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
|
|
|
int t;
|
2012-06-12 17:26:00 -07:00
|
|
|
|
2012-06-17 10:13:50 -07:00
|
|
|
t = start_x; start_x = end_x; end_x = t;
|
|
|
|
t = start_y; start_y = end_y; end_y = t;
|
2012-06-12 03:10:01 -07:00
|
|
|
}
|
2012-06-17 10:13:50 -07:00
|
|
|
s = termio_selection_get(obj, start_x, start_y, end_x, end_y);
|
2012-06-12 03:10:01 -07:00
|
|
|
if (s)
|
|
|
|
{
|
|
|
|
if (sd->win)
|
|
|
|
elm_cnp_selection_set(sd->win, ELM_SEL_TYPE_PRIMARY,
|
|
|
|
ELM_SEL_FORMAT_TEXT, s, strlen(s));
|
|
|
|
free(s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
2012-06-17 10:04:17 -07:00
|
|
|
_getsel_cb(void *data, Evas_Object *obj __UNUSED__, Elm_Selection_Data *ev)
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
|
|
|
Termio *sd = evas_object_smart_data_get(data);
|
|
|
|
if (!sd) return EINA_FALSE;
|
2012-06-12 17:26:00 -07:00
|
|
|
|
2012-06-12 03:10:01 -07:00
|
|
|
if (ev->format == ELM_SEL_FORMAT_TEXT)
|
|
|
|
{
|
|
|
|
if (ev->len > 0)
|
|
|
|
termpty_write(sd->pty, ev->data, ev->len - 1);
|
|
|
|
}
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_paste_selection(Evas_Object *obj)
|
|
|
|
{
|
|
|
|
Termio *sd = evas_object_smart_data_get(obj);
|
|
|
|
if (!sd) return;
|
|
|
|
if (!sd->win) return;
|
|
|
|
elm_cnp_selection_get(sd->win, ELM_SEL_TYPE_PRIMARY, ELM_SEL_FORMAT_TEXT,
|
|
|
|
_getsel_cb, obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-06-17 10:04:17 -07:00
|
|
|
_smart_cb_key_down(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event)
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
|
|
|
Evas_Event_Key_Down *ev = event;
|
|
|
|
Termio *sd;
|
|
|
|
|
|
|
|
sd = evas_object_smart_data_get(data);
|
|
|
|
if (!sd) return;
|
|
|
|
if (evas_key_modifier_is_set(ev->modifiers, "Shift"))
|
|
|
|
{
|
|
|
|
if (ev->keyname)
|
|
|
|
{
|
|
|
|
int by = sd->grid.h - 2;
|
2012-06-12 17:26:00 -07:00
|
|
|
|
2012-06-12 03:10:01 -07:00
|
|
|
if (by < 1) by = 1;
|
|
|
|
if (!strcmp(ev->keyname, "Prior"))
|
|
|
|
{
|
|
|
|
sd->scroll += by;
|
|
|
|
if (sd->scroll > sd->pty->backscroll_num)
|
|
|
|
sd->scroll = sd->pty->backscroll_num;
|
|
|
|
if (sd->job) ecore_job_del(sd->job);
|
|
|
|
sd->job = ecore_job_add(_smart_cb_change, obj);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (!strcmp(ev->keyname, "Next"))
|
|
|
|
{
|
|
|
|
sd->scroll -= by;
|
|
|
|
if (sd->scroll < 0) sd->scroll = 0;
|
|
|
|
if (sd->job) ecore_job_del(sd->job);
|
|
|
|
sd->job = ecore_job_add(_smart_cb_change, obj);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (!strcmp(ev->keyname, "Insert"))
|
|
|
|
{
|
|
|
|
_paste_selection(data);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
keyin_handle(sd->pty, ev);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-06-17 10:04:17 -07:00
|
|
|
_smart_cb_focus_in(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
|
|
|
Termio *sd;
|
|
|
|
|
|
|
|
sd = evas_object_smart_data_get(data);
|
|
|
|
if (!sd) return;
|
|
|
|
edje_object_signal_emit(sd->cur.obj, "focus,in", "terminology");
|
|
|
|
if (!sd->win) return;
|
|
|
|
elm_win_keyboard_mode_set(sd->win, ELM_WIN_KEYBOARD_TERMINAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-06-17 10:04:17 -07:00
|
|
|
_smart_cb_focus_out(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
|
|
|
Termio *sd;
|
|
|
|
|
|
|
|
sd = evas_object_smart_data_get(data);
|
|
|
|
if (!sd) return;
|
|
|
|
edje_object_signal_emit(sd->cur.obj, "focus,out", "terminology");
|
|
|
|
if (!sd->win) return;
|
|
|
|
elm_win_keyboard_mode_set(sd->win, ELM_WIN_KEYBOARD_OFF);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_smart_xy_to_cursor(Evas_Object *obj, Evas_Coord x, Evas_Coord y, int *cx, int *cy)
|
|
|
|
{
|
|
|
|
Termio *sd;
|
|
|
|
Evas_Coord ox, oy;
|
2012-06-12 17:26:00 -07:00
|
|
|
|
2012-06-12 03:10:01 -07:00
|
|
|
sd = evas_object_smart_data_get(obj);
|
|
|
|
if (!sd)
|
|
|
|
{
|
|
|
|
*cx = 0;
|
|
|
|
*cy = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
evas_object_geometry_get(obj, &ox, &oy, NULL, NULL);
|
|
|
|
*cx = (x - ox) / sd->font.chw;
|
|
|
|
*cy = (y - oy) / sd->font.chh;
|
|
|
|
if (*cx < 0) *cx = 0;
|
|
|
|
else if (*cx >= sd->grid.w) *cx = sd->grid.w - 1;
|
|
|
|
if (*cy < 0) *cy = 0;
|
|
|
|
else if (*cy >= sd->grid.h) *cy = sd->grid.h - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_sel_line(Evas_Object *obj, int cx, int cy)
|
|
|
|
{
|
|
|
|
Termio *sd = evas_object_smart_data_get(obj);
|
|
|
|
if (!sd) return;
|
|
|
|
|
|
|
|
sd->cur.sel = 1;
|
|
|
|
sd->cur.makesel = 0;
|
|
|
|
sd->cur.sel1.x = 0;
|
|
|
|
sd->cur.sel1.y = cy;
|
|
|
|
sd->cur.sel2.x = sd->grid.w - 1;
|
|
|
|
sd->cur.sel2.y = cy;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
2012-06-17 13:24:23 -07:00
|
|
|
_glyph_is_wordsep(const Config *config, int g)
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (g == 0) return EINA_TRUE;
|
|
|
|
if (!config->wordsep) return EINA_FALSE;
|
|
|
|
for (i = 0;;)
|
|
|
|
{
|
|
|
|
int g2 = 0;
|
|
|
|
|
|
|
|
if (!config->wordsep[i]) break;
|
|
|
|
i = evas_string_char_next_get(config->wordsep, i, &g2);
|
|
|
|
if (i < 0) break;
|
|
|
|
if (g == g2) return EINA_TRUE;
|
|
|
|
}
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_sel_word(Evas_Object *obj, int cx, int cy)
|
|
|
|
{
|
|
|
|
Termio *sd = evas_object_smart_data_get(obj);
|
|
|
|
Termcell *cells;
|
|
|
|
int x, w = 0;
|
|
|
|
if (!sd) return;
|
|
|
|
|
|
|
|
cells = termpty_cellrow_get(sd->pty, cy - sd->scroll, &w);
|
|
|
|
if (!cells) return;
|
|
|
|
sd->cur.sel = 1;
|
|
|
|
sd->cur.makesel = 0;
|
|
|
|
sd->cur.sel1.x = cx;
|
|
|
|
sd->cur.sel1.y = cy;
|
|
|
|
for (x = sd->cur.sel1.x; x >= 0; x--)
|
|
|
|
{
|
|
|
|
if (x >= w) break;
|
2012-06-17 13:24:23 -07:00
|
|
|
if (_glyph_is_wordsep(sd->config, cells[x].glyph)) break;
|
2012-06-12 03:10:01 -07:00
|
|
|
sd->cur.sel1.x = x;
|
|
|
|
}
|
|
|
|
sd->cur.sel2.x = cx;
|
|
|
|
sd->cur.sel2.y = cy;
|
|
|
|
for (x = sd->cur.sel2.x; x < sd->grid.w; x++)
|
|
|
|
{
|
|
|
|
if (x >= w) break;
|
2012-06-17 13:24:23 -07:00
|
|
|
if (_glyph_is_wordsep(sd->config, cells[x].glyph)) break;
|
2012-06-12 03:10:01 -07:00
|
|
|
sd->cur.sel2.x = x;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-18 01:56:27 -07:00
|
|
|
static void
|
|
|
|
_sel_word_to(Evas_Object *obj, int cx, int cy)
|
|
|
|
{
|
|
|
|
Termio *sd = evas_object_smart_data_get(obj);
|
|
|
|
Termcell *cells;
|
|
|
|
int x, w = 0;
|
|
|
|
if (!sd) return;
|
|
|
|
|
|
|
|
cells = termpty_cellrow_get(sd->pty, cy - sd->scroll, &w);
|
|
|
|
if (!cells) return;
|
|
|
|
if (sd->cur.sel1.x > cx || sd->cur.sel1.y > cy)
|
|
|
|
{
|
|
|
|
sd->cur.sel1.x = cx;
|
|
|
|
sd->cur.sel1.y = cy;
|
|
|
|
for (x = sd->cur.sel1.x; x >= 0; x--)
|
|
|
|
{
|
|
|
|
if (x >= w) break;
|
|
|
|
if (_glyph_is_wordsep(sd->config, cells[x].glyph)) break;
|
|
|
|
sd->cur.sel1.x = x;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (sd->cur.sel2.x < cx || sd->cur.sel2.y < cy)
|
|
|
|
{
|
|
|
|
sd->cur.sel2.x = cx;
|
|
|
|
sd->cur.sel2.y = cy;
|
|
|
|
for (x = sd->cur.sel2.x; x < sd->grid.w; x++)
|
|
|
|
{
|
|
|
|
if (x >= w) break;
|
|
|
|
if (_glyph_is_wordsep(sd->config, cells[x].glyph)) break;
|
|
|
|
sd->cur.sel2.x = x;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-12 03:10:01 -07:00
|
|
|
static void
|
2012-06-17 10:04:17 -07:00
|
|
|
_smart_cb_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event)
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
|
|
|
Evas_Event_Mouse_Down *ev = event;
|
|
|
|
Termio *sd;
|
|
|
|
int cx, cy;
|
|
|
|
|
|
|
|
sd = evas_object_smart_data_get(data);
|
|
|
|
if (!sd) return;
|
|
|
|
_smart_xy_to_cursor(data, ev->canvas.x, ev->canvas.y, &cx, &cy);
|
|
|
|
if (ev->button == 1)
|
|
|
|
{
|
|
|
|
if (ev->flags & EVAS_BUTTON_TRIPLE_CLICK)
|
|
|
|
{
|
|
|
|
_sel_line(data, cx, cy - sd->scroll);
|
|
|
|
if (sd->cur.sel) _take_selection(data);
|
|
|
|
}
|
|
|
|
else if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
|
|
|
|
{
|
2012-06-18 01:56:27 -07:00
|
|
|
if (evas_key_modifier_is_set(ev->modifiers, "Shift") && sd->backup.sel)
|
|
|
|
{
|
|
|
|
sd->cur.sel = 1;
|
|
|
|
sd->cur.sel1.x = sd->backup.sel1.x;
|
|
|
|
sd->cur.sel1.y = sd->backup.sel1.y;
|
|
|
|
sd->cur.sel2.x = sd->backup.sel2.x;
|
|
|
|
sd->cur.sel2.y = sd->backup.sel2.y;
|
|
|
|
|
|
|
|
_sel_word_to(data, cx, cy - sd->scroll);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_sel_word(data, cx, cy - sd->scroll);
|
|
|
|
}
|
2012-06-12 03:10:01 -07:00
|
|
|
if (sd->cur.sel) _take_selection(data);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-06-18 01:56:27 -07:00
|
|
|
sd->backup.sel = sd->cur.sel;
|
|
|
|
sd->backup.sel1.x = sd->cur.sel1.x;
|
|
|
|
sd->backup.sel1.y = sd->cur.sel1.y;
|
|
|
|
sd->backup.sel2.x = sd->cur.sel2.x;
|
|
|
|
sd->backup.sel2.y = sd->cur.sel2.y;
|
2012-06-13 01:23:18 -07:00
|
|
|
if (sd->cur.sel) sd->cur.sel = 0;
|
2012-06-12 03:10:01 -07:00
|
|
|
sd->cur.makesel = 1;
|
|
|
|
sd->cur.sel1.x = cx;
|
|
|
|
sd->cur.sel1.y = cy - sd->scroll;
|
|
|
|
sd->cur.sel2.x = cx;
|
|
|
|
sd->cur.sel2.y = cy - sd->scroll;
|
|
|
|
}
|
|
|
|
if (sd->job) ecore_job_del(sd->job);
|
|
|
|
sd->job = ecore_job_add(_smart_cb_change, data);
|
|
|
|
}
|
|
|
|
else if (ev->button == 2)
|
|
|
|
_paste_selection(data);
|
|
|
|
else if (ev->button == 3)
|
2012-06-12 06:08:09 -07:00
|
|
|
evas_object_smart_callback_call(data, "options", NULL);
|
2012-06-12 03:10:01 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-06-17 10:04:17 -07:00
|
|
|
_smart_cb_mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event)
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
|
|
|
Evas_Event_Mouse_Up *ev = event;
|
|
|
|
Termio *sd;
|
|
|
|
int cx, cy;
|
|
|
|
|
|
|
|
sd = evas_object_smart_data_get(data);
|
|
|
|
if (!sd) return;
|
|
|
|
_smart_xy_to_cursor(data, ev->canvas.x, ev->canvas.y, &cx, &cy);
|
|
|
|
if (sd->cur.makesel)
|
|
|
|
{
|
|
|
|
sd->cur.makesel = 0;
|
|
|
|
if (sd->cur.sel)
|
|
|
|
{
|
|
|
|
sd->cur.sel2.x = cx;
|
|
|
|
sd->cur.sel2.y = cy - sd->scroll;
|
|
|
|
if (sd->job) ecore_job_del(sd->job);
|
|
|
|
sd->job = ecore_job_add(_smart_cb_change, data);
|
|
|
|
_take_selection(data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-06-17 10:04:17 -07:00
|
|
|
_smart_cb_mouse_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event)
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
|
|
|
Evas_Event_Mouse_Move *ev = event;
|
|
|
|
Termio *sd;
|
|
|
|
int cx, cy;
|
|
|
|
|
|
|
|
sd = evas_object_smart_data_get(data);
|
|
|
|
if (!sd) return;
|
|
|
|
_smart_xy_to_cursor(data, ev->cur.canvas.x, ev->cur.canvas.y, &cx, &cy);
|
|
|
|
if (sd->cur.makesel)
|
|
|
|
{
|
|
|
|
if (!sd->cur.sel)
|
|
|
|
{
|
|
|
|
if ((cx != sd->cur.sel1.x) ||
|
|
|
|
((cy - sd->scroll) != sd->cur.sel1.y))
|
|
|
|
sd->cur.sel = 1;
|
|
|
|
}
|
|
|
|
sd->cur.sel2.x = cx;
|
|
|
|
sd->cur.sel2.y = cy - sd->scroll;
|
|
|
|
if (sd->job) ecore_job_del(sd->job);
|
|
|
|
sd->job = ecore_job_add(_smart_cb_change, data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-06-17 10:04:17 -07:00
|
|
|
_smart_cb_mouse_wheel(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event)
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
|
|
|
Evas_Event_Mouse_Wheel *ev = event;
|
|
|
|
Termio *sd;
|
|
|
|
|
|
|
|
sd = evas_object_smart_data_get(data);
|
|
|
|
if (!sd) return;
|
|
|
|
if (sd->pty->altbuf) return;
|
|
|
|
sd->scroll -= (ev->z * 4);
|
|
|
|
if (sd->scroll > sd->pty->backscroll_num)
|
|
|
|
sd->scroll = sd->pty->backscroll_num;
|
|
|
|
else if (sd->scroll < 0) sd->scroll = 0;
|
|
|
|
if (sd->job) ecore_job_del(sd->job);
|
|
|
|
sd->job = ecore_job_add(_smart_cb_change, data);
|
|
|
|
}
|
|
|
|
|
2012-06-15 22:07:33 -07:00
|
|
|
static void
|
2012-06-17 10:04:17 -07:00
|
|
|
_win_obj_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event __UNUSED__)
|
2012-06-15 22:07:33 -07:00
|
|
|
{
|
|
|
|
Termio *sd;
|
|
|
|
|
|
|
|
sd = evas_object_smart_data_get(data);
|
|
|
|
if (!sd) return;
|
|
|
|
if (obj == sd->win)
|
|
|
|
{
|
|
|
|
evas_object_event_callback_del_full(sd->win, EVAS_CALLBACK_DEL,
|
|
|
|
_win_obj_del, data);
|
|
|
|
sd->win = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-12 03:10:01 -07:00
|
|
|
static void
|
2012-06-17 13:24:23 -07:00
|
|
|
_termio_config_set(Evas_Object *obj, Config *config)
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
2012-06-17 13:24:23 -07:00
|
|
|
Termio *sd = evas_object_smart_data_get(obj);
|
2012-06-15 22:07:33 -07:00
|
|
|
Evas_Coord w = 2, h = 2;
|
2012-06-17 13:24:23 -07:00
|
|
|
|
|
|
|
sd->config = config;
|
2012-06-12 03:10:01 -07:00
|
|
|
|
|
|
|
sd->jump_on_change = config->jump_on_change;
|
2012-06-12 17:26:00 -07:00
|
|
|
|
2012-06-15 22:07:33 -07:00
|
|
|
if (config->font.bitmap)
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
2012-06-17 13:24:23 -07:00
|
|
|
char buf[PATH_MAX];
|
2012-06-15 22:07:33 -07:00
|
|
|
snprintf(buf, sizeof(buf), "%s/fonts/%s",
|
|
|
|
elm_app_data_dir_get(), config->font.name);
|
|
|
|
sd->font.name = eina_stringshare_add(buf);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
sd->font.name = eina_stringshare_add(config->font.name);
|
|
|
|
sd->font.size = config->font.size;
|
2012-06-17 13:24:23 -07:00
|
|
|
|
2012-06-18 00:54:40 -07:00
|
|
|
evas_object_scale_set(sd->grid.obj, elm_config_scale_get());
|
2012-06-17 13:24:23 -07:00
|
|
|
evas_object_textgrid_font_set(sd->grid.obj, sd->font.name, sd->font.size);
|
|
|
|
evas_object_textgrid_size_set(sd->grid.obj, 1, 1);
|
|
|
|
evas_object_textgrid_cell_size_get(sd->grid.obj, &w, &h);
|
|
|
|
if (w < 1) w = 1;
|
|
|
|
if (h < 1) h = 1;
|
|
|
|
sd->font.chw = w;
|
|
|
|
sd->font.chh = h;
|
|
|
|
|
|
|
|
edje_object_file_set(sd->cur.obj,
|
|
|
|
config_theme_path_get(config), "terminology/cursor");
|
2012-06-17 19:56:58 -07:00
|
|
|
edje_object_signal_callback_add(sd->cur.obj, "edje,change,file", "edje", _reload_theme, NULL);
|
2012-06-17 13:24:23 -07:00
|
|
|
evas_object_resize(sd->cur.obj, sd->font.chw, sd->font.chh);
|
|
|
|
evas_object_show(sd->cur.obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_smart_add(Evas_Object *obj)
|
|
|
|
{
|
|
|
|
Termio *sd;
|
|
|
|
Evas_Object_Smart_Clipped_Data *cd;
|
|
|
|
Evas_Object *o;
|
|
|
|
int i, j, k, n;
|
|
|
|
|
|
|
|
_parent_sc.add(obj);
|
|
|
|
cd = evas_object_smart_data_get(obj);
|
|
|
|
if (!cd) return;
|
|
|
|
sd = calloc(1, sizeof(Termio));
|
|
|
|
if (!sd) return;
|
|
|
|
sd->__clipped_data = *cd;
|
|
|
|
free(cd);
|
|
|
|
evas_object_smart_data_set(obj, sd);
|
|
|
|
|
2012-06-15 22:07:33 -07:00
|
|
|
o = evas_object_textgrid_add(evas_object_evas_get(obj));
|
|
|
|
evas_object_pass_events_set(o, EINA_TRUE);
|
|
|
|
evas_object_propagate_events_set(o, EINA_FALSE);
|
|
|
|
evas_object_smart_member_add(o, obj);
|
|
|
|
evas_object_show(o);
|
|
|
|
sd->grid.obj = o;
|
2012-06-17 13:24:23 -07:00
|
|
|
|
2012-06-15 22:07:33 -07:00
|
|
|
for (n = 0, k = 0; k < 2; k++)
|
|
|
|
{
|
|
|
|
for (j = 0; j < 2; j++)
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
2012-06-15 22:07:33 -07:00
|
|
|
for (i = 0; i < 12; i++, n++)
|
|
|
|
evas_object_textgrid_palette_set
|
|
|
|
(o, EVAS_TEXTGRID_PALETTE_STANDARD, n,
|
|
|
|
colors[j][i].r / (k + 1), colors[j][i].g / (k + 1),
|
|
|
|
colors[j][i].b / (k + 1), colors[j][i].a / (k + 1));
|
2012-06-12 03:10:01 -07:00
|
|
|
}
|
|
|
|
}
|
2012-06-15 22:07:33 -07:00
|
|
|
for (n = 0; n < 256; n++)
|
|
|
|
{
|
|
|
|
evas_object_textgrid_palette_set
|
|
|
|
(o, EVAS_TEXTGRID_PALETTE_EXTENDED, n,
|
|
|
|
colors256[n].r, colors256[n].g,
|
|
|
|
colors256[n].b, colors256[n].a);
|
|
|
|
}
|
|
|
|
o = evas_object_rectangle_add(evas_object_evas_get(obj));
|
|
|
|
evas_object_pass_events_set(o, EINA_TRUE);
|
|
|
|
evas_object_propagate_events_set(o, EINA_FALSE);
|
|
|
|
evas_object_smart_member_add(o, obj);
|
|
|
|
sd->cur.selo1 = o;
|
|
|
|
evas_object_color_set(o, 64, 64, 64, 64);
|
|
|
|
o = evas_object_rectangle_add(evas_object_evas_get(obj));
|
|
|
|
evas_object_pass_events_set(o, EINA_TRUE);
|
|
|
|
evas_object_propagate_events_set(o, EINA_FALSE);
|
|
|
|
evas_object_smart_member_add(o, obj);
|
|
|
|
sd->cur.selo2 = o;
|
|
|
|
evas_object_color_set(o, 64, 64, 64, 64);
|
|
|
|
o = evas_object_rectangle_add(evas_object_evas_get(obj));
|
|
|
|
evas_object_pass_events_set(o, EINA_TRUE);
|
|
|
|
evas_object_propagate_events_set(o, EINA_FALSE);
|
|
|
|
evas_object_smart_member_add(o, obj);
|
|
|
|
sd->cur.selo3 = o;
|
|
|
|
evas_object_color_set(o, 64, 64, 64, 64);
|
|
|
|
|
|
|
|
o = edje_object_add(evas_object_evas_get(obj));
|
|
|
|
evas_object_pass_events_set(o, EINA_TRUE);
|
|
|
|
evas_object_propagate_events_set(o, EINA_FALSE);
|
|
|
|
evas_object_smart_member_add(o, obj);
|
|
|
|
sd->cur.obj = o;
|
|
|
|
|
|
|
|
o = evas_object_rectangle_add(evas_object_evas_get(obj));
|
|
|
|
evas_object_smart_member_add(o, obj);
|
|
|
|
sd->event = o;
|
|
|
|
evas_object_color_set(o, 0, 0, 0, 0);
|
|
|
|
evas_object_show(o);
|
|
|
|
|
|
|
|
evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN,
|
|
|
|
_smart_cb_mouse_down, obj);
|
|
|
|
evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_UP,
|
|
|
|
_smart_cb_mouse_up, obj);
|
|
|
|
evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_MOVE,
|
|
|
|
_smart_cb_mouse_move, obj);
|
|
|
|
evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_WHEEL,
|
|
|
|
_smart_cb_mouse_wheel, obj);
|
2012-06-12 03:10:01 -07:00
|
|
|
|
|
|
|
evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_DOWN,
|
|
|
|
_smart_cb_key_down, obj);
|
|
|
|
evas_object_event_callback_add(obj, EVAS_CALLBACK_FOCUS_IN,
|
|
|
|
_smart_cb_focus_in, obj);
|
|
|
|
evas_object_event_callback_add(obj, EVAS_CALLBACK_FOCUS_OUT,
|
|
|
|
_smart_cb_focus_out, obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_smart_del(Evas_Object *obj)
|
|
|
|
{
|
|
|
|
Termio *sd = evas_object_smart_data_get(obj);
|
|
|
|
if (!sd) return;
|
|
|
|
if (sd->cur.obj) evas_object_del(sd->cur.obj);
|
|
|
|
if (sd->event) evas_object_del(sd->event);
|
|
|
|
if (sd->cur.selo1) evas_object_del(sd->cur.selo1);
|
|
|
|
if (sd->cur.selo2) evas_object_del(sd->cur.selo2);
|
|
|
|
if (sd->cur.selo3) evas_object_del(sd->cur.selo3);
|
|
|
|
if (sd->job) ecore_job_del(sd->job);
|
|
|
|
if (sd->delayed_size_timer) ecore_timer_del(sd->delayed_size_timer);
|
|
|
|
if (sd->font.name) eina_stringshare_del(sd->font.name);
|
|
|
|
if (sd->pty) termpty_free(sd->pty);
|
|
|
|
sd->cur.obj = NULL;
|
|
|
|
sd->event = NULL;
|
|
|
|
sd->cur.selo1 = NULL;
|
|
|
|
sd->cur.selo2 = NULL;
|
|
|
|
sd->cur.selo3 = NULL;
|
|
|
|
sd->job = NULL;
|
|
|
|
sd->delayed_size_timer = NULL;
|
|
|
|
sd->font.name = NULL;
|
|
|
|
sd->pty = NULL;
|
2012-06-17 13:24:23 -07:00
|
|
|
_parent_sc.del(obj);
|
2012-06-12 03:10:01 -07:00
|
|
|
evas_object_smart_data_set(obj, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
|
|
|
|
{
|
|
|
|
Termio *sd = evas_object_smart_data_get(obj);
|
|
|
|
Evas_Coord ow, oh;
|
|
|
|
if (!sd) return;
|
|
|
|
evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
|
|
|
|
if ((ow == w) && (oh == h)) return;
|
|
|
|
evas_object_smart_changed(obj);
|
2012-06-16 19:35:07 -07:00
|
|
|
if (!sd->delayed_size_timer) sd->delayed_size_timer =
|
|
|
|
ecore_timer_add(0.0, _smart_cb_delayed_size, obj);
|
|
|
|
else ecore_timer_delay(sd->delayed_size_timer, 0.0);
|
2012-06-12 03:10:01 -07:00
|
|
|
evas_object_resize(sd->event, ow, oh);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_smart_calculate(Evas_Object *obj)
|
|
|
|
{
|
|
|
|
Termio *sd = evas_object_smart_data_get(obj);
|
|
|
|
Evas_Coord ox, oy, ow, oh;
|
2012-06-12 17:26:00 -07:00
|
|
|
|
2012-06-12 03:10:01 -07:00
|
|
|
if (!sd) return;
|
|
|
|
|
|
|
|
evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
|
2012-06-15 22:07:33 -07:00
|
|
|
evas_object_move(sd->grid.obj, ox, oy);
|
|
|
|
evas_object_resize(sd->grid.obj,
|
|
|
|
sd->grid.w * sd->font.chw,
|
|
|
|
sd->grid.h * sd->font.chh);
|
2012-06-12 17:26:00 -07:00
|
|
|
evas_object_move(sd->cur.obj,
|
2012-06-12 03:10:01 -07:00
|
|
|
ox + (sd->cur.x * sd->font.chw),
|
|
|
|
oy + (sd->cur.y * sd->font.chh));
|
|
|
|
evas_object_move(sd->event, ox, oy);
|
|
|
|
evas_object_resize(sd->event, ow, oh);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-06-17 10:04:17 -07:00
|
|
|
_smart_move(Evas_Object *obj, Evas_Coord x __UNUSED__, Evas_Coord y __UNUSED__)
|
2012-06-12 17:26:00 -07:00
|
|
|
{
|
2012-06-12 03:10:01 -07:00
|
|
|
Termio *sd = evas_object_smart_data_get(obj);
|
|
|
|
if (!sd) return;
|
|
|
|
evas_object_smart_changed(obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_smart_init(void)
|
|
|
|
{
|
|
|
|
static Evas_Smart_Class sc;
|
2012-06-12 17:26:00 -07:00
|
|
|
|
2012-06-17 13:24:23 -07:00
|
|
|
evas_object_smart_clipped_smart_set(&_parent_sc);
|
|
|
|
sc = _parent_sc;
|
2012-06-12 03:10:01 -07:00
|
|
|
sc.name = "termio";
|
|
|
|
sc.version = EVAS_SMART_CLASS_VERSION;
|
|
|
|
sc.add = _smart_add;
|
|
|
|
sc.del = _smart_del;
|
|
|
|
sc.resize = _smart_resize;
|
|
|
|
sc.move = _smart_move;
|
|
|
|
sc.calculate = _smart_calculate;
|
|
|
|
_smart = evas_smart_class_new(&sc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_smart_pty_change(void *data)
|
|
|
|
{
|
|
|
|
Evas_Object *obj = data;
|
|
|
|
Termio *sd;
|
|
|
|
sd = evas_object_smart_data_get(obj);
|
|
|
|
if (!sd) return;
|
|
|
|
|
|
|
|
if (sd->jump_on_change) // if scroll to bottom on updates
|
|
|
|
{
|
|
|
|
// if term changed = croll back to bottom
|
|
|
|
sd->scroll = 0;
|
|
|
|
}
|
|
|
|
if (sd->job) ecore_job_del(sd->job);
|
|
|
|
sd->job = ecore_job_add(_smart_cb_change, obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_smart_pty_scroll(void *data)
|
|
|
|
{
|
|
|
|
Evas_Object *obj = data;
|
|
|
|
Termio *sd;
|
|
|
|
int changed = 0;
|
|
|
|
sd = evas_object_smart_data_get(obj);
|
|
|
|
if (!sd) return;
|
|
|
|
|
|
|
|
if ((!sd->jump_on_change) && // if NOT scroll to bottom on updates
|
2012-06-12 17:26:00 -07:00
|
|
|
(sd->scroll > 0))
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
|
|
|
// adjust scroll position for added scrollback
|
|
|
|
sd->scroll++;
|
|
|
|
if (sd->scroll > sd->pty->backscroll_num)
|
|
|
|
sd->scroll = sd->pty->backscroll_num;
|
|
|
|
changed = 1;
|
|
|
|
}
|
|
|
|
if (sd->cur.sel)
|
|
|
|
{
|
|
|
|
sd->cur.sel1.y--;
|
|
|
|
sd->cur.sel2.y--;
|
|
|
|
changed = 1;
|
|
|
|
}
|
|
|
|
if (changed)
|
|
|
|
{
|
|
|
|
if (sd->job) ecore_job_del(sd->job);
|
|
|
|
sd->job = ecore_job_add(_smart_cb_change, obj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_smart_pty_title(void *data)
|
|
|
|
{
|
|
|
|
Evas_Object *obj = data;
|
|
|
|
Termio *sd;
|
|
|
|
sd = evas_object_smart_data_get(obj);
|
|
|
|
if (!sd) return;
|
|
|
|
if (!sd->win) return;
|
|
|
|
elm_win_title_set(sd->win, sd->pty->prop.title);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_smart_pty_icon(void *data)
|
|
|
|
{
|
|
|
|
Evas_Object *obj = data;
|
|
|
|
Termio *sd;
|
|
|
|
sd = evas_object_smart_data_get(obj);
|
|
|
|
if (!sd) return;
|
|
|
|
if (!sd->win) return;
|
|
|
|
elm_win_icon_name_set(sd->win, sd->pty->prop.icon);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_smart_pty_cancel_sel(void *data)
|
|
|
|
{
|
|
|
|
Evas_Object *obj = data;
|
|
|
|
Termio *sd;
|
|
|
|
sd = evas_object_smart_data_get(obj);
|
|
|
|
if (!sd) return;
|
|
|
|
if (sd->cur.sel)
|
|
|
|
{
|
|
|
|
sd->cur.sel = 0;
|
|
|
|
sd->cur.makesel = 0;
|
|
|
|
if (sd->job) ecore_job_del(sd->job);
|
|
|
|
sd->job = ecore_job_add(_smart_cb_change, data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Evas_Object *
|
2012-06-17 13:24:23 -07:00
|
|
|
termio_add(Evas_Object *parent, Config *config, const char *cmd, int w, int h)
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
|
|
|
Evas *e;
|
|
|
|
Evas_Object *obj;
|
|
|
|
Termio *sd;
|
|
|
|
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
|
|
|
|
e = evas_object_evas_get(parent);
|
|
|
|
if (!e) return NULL;
|
2012-06-12 17:26:00 -07:00
|
|
|
|
2012-06-12 03:10:01 -07:00
|
|
|
if (!_smart) _smart_init();
|
|
|
|
obj = evas_object_smart_add(e, _smart);
|
|
|
|
sd = evas_object_smart_data_get(obj);
|
|
|
|
if (!sd) return obj;
|
2012-06-17 13:24:23 -07:00
|
|
|
|
|
|
|
_termio_config_set(obj, config);
|
|
|
|
|
2012-06-12 03:10:01 -07:00
|
|
|
sd->pty = termpty_new(cmd, w, h, config->scrollback);
|
|
|
|
sd->pty->cb.change.func = _smart_pty_change;
|
|
|
|
sd->pty->cb.change.data = obj;
|
|
|
|
sd->pty->cb.scroll.func = _smart_pty_scroll;
|
|
|
|
sd->pty->cb.scroll.data = obj;
|
|
|
|
sd->pty->cb.set_title.func = _smart_pty_title;
|
|
|
|
sd->pty->cb.set_title.data = obj;
|
|
|
|
sd->pty->cb.set_icon.func = _smart_pty_icon;
|
|
|
|
sd->pty->cb.set_icon.data = obj;
|
|
|
|
sd->pty->cb.cancel_sel.func = _smart_pty_cancel_sel;
|
|
|
|
sd->pty->cb.cancel_sel.data = obj;
|
2012-06-12 06:08:09 -07:00
|
|
|
_smart_size(obj, w, h, EINA_FALSE);
|
2012-06-12 03:10:01 -07:00
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
termio_win_set(Evas_Object *obj, Evas_Object *win)
|
|
|
|
{
|
2012-06-12 06:08:09 -07:00
|
|
|
Termio *sd = evas_object_smart_data_get(obj);
|
2012-06-12 03:10:01 -07:00
|
|
|
if (!sd) return;
|
2012-06-15 22:07:33 -07:00
|
|
|
if (sd->win)
|
|
|
|
{
|
|
|
|
evas_object_event_callback_del_full(sd->win, EVAS_CALLBACK_DEL,
|
|
|
|
_win_obj_del, obj);
|
|
|
|
sd->win = NULL;
|
|
|
|
}
|
2012-06-17 03:56:21 -07:00
|
|
|
if (win)
|
2012-06-15 22:07:33 -07:00
|
|
|
{
|
|
|
|
sd->win = win;
|
|
|
|
evas_object_event_callback_add(sd->win, EVAS_CALLBACK_DEL,
|
|
|
|
_win_obj_del, obj);
|
|
|
|
}
|
2012-06-12 03:10:01 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
termio_selection_get(Evas_Object *obj, int c1x, int c1y, int c2x, int c2y)
|
|
|
|
{
|
2012-06-12 06:08:09 -07:00
|
|
|
Termio *sd = evas_object_smart_data_get(obj);
|
2012-06-12 03:10:01 -07:00
|
|
|
Eina_Strbuf *sb;
|
|
|
|
char *s, txt[8];
|
|
|
|
int x, y;
|
2012-06-12 17:26:00 -07:00
|
|
|
|
2012-06-12 03:10:01 -07:00
|
|
|
if (!sd) return NULL;
|
|
|
|
sb = eina_strbuf_new();
|
|
|
|
for (y = c1y; y <= c2y; y++)
|
|
|
|
{
|
|
|
|
Termcell *cells;
|
2012-06-17 10:13:50 -07:00
|
|
|
int w, last0, v, start_x, end_x;
|
2012-06-12 17:26:00 -07:00
|
|
|
|
2012-06-12 03:10:01 -07:00
|
|
|
w = 0;
|
|
|
|
last0 = -1;
|
2012-06-13 01:23:18 -07:00
|
|
|
cells = termpty_cellrow_get(sd->pty, y, &w);
|
2012-06-12 03:10:01 -07:00
|
|
|
if (w > sd->grid.w) w = sd->grid.w;
|
2012-06-17 10:13:50 -07:00
|
|
|
start_x = c1x;
|
|
|
|
end_x = c2x;
|
2012-06-12 03:10:01 -07:00
|
|
|
if (c1y != c2y)
|
|
|
|
{
|
2012-06-17 10:13:50 -07:00
|
|
|
if (y == c1y) end_x = w - 1;
|
|
|
|
else if (y == c2y) start_x = 0;
|
2012-06-12 03:10:01 -07:00
|
|
|
else
|
|
|
|
{
|
2012-06-17 10:13:50 -07:00
|
|
|
start_x = 0;
|
|
|
|
end_x = w - 1;
|
2012-06-12 03:10:01 -07:00
|
|
|
}
|
|
|
|
}
|
2012-06-17 10:13:50 -07:00
|
|
|
for (x = start_x; x <= end_x; x++)
|
2012-06-12 03:10:01 -07:00
|
|
|
{
|
|
|
|
if (x >= w) break;
|
|
|
|
if (cells[x].glyph == 0)
|
|
|
|
{
|
|
|
|
if (last0 < 0) last0 = x;
|
|
|
|
}
|
|
|
|
else if (cells[x].att.newline)
|
|
|
|
{
|
|
|
|
last0 = -1;
|
|
|
|
eina_strbuf_append(sb, "\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (cells[x].att.tab)
|
|
|
|
{
|
|
|
|
eina_strbuf_append(sb, "\t");
|
|
|
|
x = ((x + 8) / 8) * 8;
|
|
|
|
x--;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (last0 >= 0)
|
|
|
|
{
|
|
|
|
v = x - last0 - 1;
|
|
|
|
last0 = -1;
|
|
|
|
while (v >= 0)
|
|
|
|
{
|
|
|
|
eina_strbuf_append(sb, " ");
|
|
|
|
v--;
|
|
|
|
}
|
|
|
|
if (x == (w - 1))
|
|
|
|
{
|
|
|
|
if (!cells[x].att.autowrapped)
|
|
|
|
eina_strbuf_append(sb, "\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
glyph_to_utf8(cells[x].glyph, txt);
|
|
|
|
eina_strbuf_append(sb, txt);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (last0 >= 0)
|
|
|
|
{
|
|
|
|
eina_strbuf_append(sb, "\n");
|
|
|
|
}
|
|
|
|
}
|
2012-06-12 17:26:00 -07:00
|
|
|
|
2012-06-12 03:10:01 -07:00
|
|
|
s = eina_strbuf_string_steal(sb);
|
|
|
|
eina_strbuf_free(sb);
|
|
|
|
return s;
|
|
|
|
}
|
2012-06-12 06:08:09 -07:00
|
|
|
|
|
|
|
void
|
|
|
|
termio_config_update(Evas_Object *obj)
|
|
|
|
{
|
|
|
|
Termio *sd = evas_object_smart_data_get(obj);
|
|
|
|
Evas_Coord w, h;
|
|
|
|
char buf[4096];
|
2012-06-12 17:26:00 -07:00
|
|
|
|
2012-06-12 06:08:09 -07:00
|
|
|
if (!sd) return;
|
2012-06-12 17:26:00 -07:00
|
|
|
|
2012-06-12 06:08:09 -07:00
|
|
|
if (sd->font.name) eina_stringshare_del(sd->font.name);
|
|
|
|
sd->font.name = NULL;
|
2012-06-12 17:26:00 -07:00
|
|
|
|
2012-06-17 13:24:23 -07:00
|
|
|
if (sd->config->font.bitmap)
|
2012-06-12 06:08:09 -07:00
|
|
|
{
|
|
|
|
snprintf(buf, sizeof(buf), "%s/fonts/%s",
|
2012-06-17 13:24:23 -07:00
|
|
|
elm_app_data_dir_get(), sd->config->font.name);
|
2012-06-12 06:08:09 -07:00
|
|
|
sd->font.name = eina_stringshare_add(buf);
|
|
|
|
}
|
|
|
|
else
|
2012-06-17 13:24:23 -07:00
|
|
|
sd->font.name = eina_stringshare_add(sd->config->font.name);
|
|
|
|
sd->font.size = sd->config->font.size;
|
2012-06-12 17:26:00 -07:00
|
|
|
|
2012-06-17 13:24:23 -07:00
|
|
|
sd->jump_on_change = sd->config->jump_on_change;
|
2012-06-16 10:31:54 -07:00
|
|
|
|
2012-06-17 13:24:23 -07:00
|
|
|
termpty_backscroll_set(sd->pty, sd->config->scrollback);
|
2012-06-16 10:31:54 -07:00
|
|
|
sd->scroll = 0;
|
|
|
|
|
2012-06-18 00:54:40 -07:00
|
|
|
evas_object_scale_set(sd->grid.obj, elm_config_scale_get());
|
2012-06-15 23:28:39 -07:00
|
|
|
evas_object_textgrid_font_set(sd->grid.obj, sd->font.name, sd->font.size);
|
|
|
|
evas_object_textgrid_cell_size_get(sd->grid.obj, &w, &h);
|
2012-06-12 06:08:09 -07:00
|
|
|
if (w < 1) w = 1;
|
|
|
|
if (h < 1) h = 1;
|
|
|
|
sd->font.chw = w;
|
|
|
|
sd->font.chh = h;
|
|
|
|
_smart_size(obj, sd->grid.w, sd->grid.h, EINA_TRUE);
|
|
|
|
}
|
2012-06-17 13:24:23 -07:00
|
|
|
|
|
|
|
Config *
|
|
|
|
termio_config_get(const Evas_Object *obj)
|
|
|
|
{
|
|
|
|
Termio *sd = evas_object_smart_data_get(obj);
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(sd, NULL);
|
|
|
|
return sd->config;
|
|
|
|
}
|