2014-03-18 14:53:02 -07:00
|
|
|
#include <Elementary.h>
|
|
|
|
#include <stdio.h>
|
2014-04-20 09:45:21 -07:00
|
|
|
#include <assert.h>
|
|
|
|
|
2014-05-01 15:08:58 -07:00
|
|
|
#include "miniview.h"
|
2014-03-18 14:53:02 -07:00
|
|
|
#include "col.h"
|
|
|
|
#include "termpty.h"
|
|
|
|
#include "termio.h"
|
2014-03-26 12:37:35 -07:00
|
|
|
#include "main.h"
|
|
|
|
|
|
|
|
/* specific log domain to help debug only miniview */
|
|
|
|
int _miniview_log_dom = -1;
|
|
|
|
|
|
|
|
#undef CRITICAL
|
|
|
|
#undef ERR
|
|
|
|
#undef WRN
|
|
|
|
#undef INF
|
|
|
|
#undef DBG
|
|
|
|
|
|
|
|
#define CRIT(...) EINA_LOG_DOM_CRIT(_miniview_log_dom, __VA_ARGS__)
|
|
|
|
#define ERR(...) EINA_LOG_DOM_ERR(_miniview_log_dom, __VA_ARGS__)
|
|
|
|
#define WRN(...) EINA_LOG_DOM_WARN(_miniview_log_dom, __VA_ARGS__)
|
|
|
|
#define INF(...) EINA_LOG_DOM_INFO(_miniview_log_dom, __VA_ARGS__)
|
|
|
|
#define DBG(...) EINA_LOG_DOM_DBG(_miniview_log_dom, __VA_ARGS__)
|
|
|
|
|
2014-04-26 14:42:17 -07:00
|
|
|
/*TODO: work with splits */
|
|
|
|
|
2014-03-26 12:37:35 -07:00
|
|
|
void
|
|
|
|
miniview_init(void)
|
|
|
|
{
|
|
|
|
if (_miniview_log_dom >= 0) return;
|
|
|
|
|
|
|
|
_miniview_log_dom = eina_log_domain_register("miniview", NULL);
|
|
|
|
if (_miniview_log_dom < 0)
|
|
|
|
EINA_LOG_CRIT("could not create log domain 'miniview'.");
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
miniview_shutdown(void)
|
|
|
|
{
|
|
|
|
if (_miniview_log_dom < 0) return;
|
|
|
|
eina_log_domain_unregister(_miniview_log_dom);
|
|
|
|
_miniview_log_dom = -1;
|
|
|
|
}
|
2014-03-18 14:53:02 -07:00
|
|
|
|
|
|
|
typedef struct _Miniview Miniview;
|
|
|
|
|
|
|
|
struct _Miniview
|
|
|
|
{
|
2014-03-30 11:38:49 -07:00
|
|
|
Evas_Object *self;
|
2014-04-27 12:34:27 -07:00
|
|
|
Evas_Object *img;
|
2014-03-18 14:53:02 -07:00
|
|
|
Evas_Object *termio;
|
|
|
|
Termpty *pty;
|
2014-04-26 14:42:17 -07:00
|
|
|
|
2014-05-03 13:16:27 -07:00
|
|
|
int img_hist; /* history rendered is between img_hist (<0) and
|
|
|
|
img_hist + img_h */
|
|
|
|
unsigned img_h;
|
|
|
|
unsigned rows;
|
|
|
|
unsigned cols;
|
2014-05-01 15:08:58 -07:00
|
|
|
|
2014-05-04 08:03:05 -07:00
|
|
|
Ecore_Timer *deferred_renderer;
|
|
|
|
|
|
|
|
int is_shown : 1;
|
|
|
|
int to_render : 1;
|
2014-03-18 14:53:02 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
static Evas_Smart *_smart = NULL;
|
|
|
|
|
2014-04-27 14:48:54 -07:00
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
_draw_line(unsigned int *pixels, Termcell *cells, int length)
|
|
|
|
{
|
|
|
|
int x;
|
|
|
|
|
|
|
|
for (x = 0 ; x < length; x++)
|
|
|
|
{
|
|
|
|
int r, g, b;
|
|
|
|
|
|
|
|
if (cells[x].codepoint > 0 && !isspace(cells[x].codepoint) &&
|
|
|
|
!cells[x].att.newline && !cells[x].att.tab &&
|
|
|
|
!cells[x].att.invisible && cells[x].att.bg != COL_INVIS)
|
|
|
|
{
|
|
|
|
switch (cells[x].att.fg)
|
|
|
|
{
|
2014-05-03 13:16:27 -07:00
|
|
|
// TODO: get pixel colors from current theme...
|
2014-04-27 14:48:54 -07:00
|
|
|
case 0:
|
|
|
|
r = 180; g = 180; b = 180;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
r = 204; g = 51; b = 51;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
r = 51; g = 204; b = 51;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
r = 204; g = 136; b = 51;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
r = 51; g = 51; b = 204;
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
r = 204; g = 51; b = 204;
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
r = 51; g = 204; b = 204;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
r = 180; g = 180; b = 180;
|
|
|
|
}
|
|
|
|
pixels[x] = (0xff << 24) | (r << 16) | (g << 8) | b;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-26 14:42:17 -07:00
|
|
|
static void
|
|
|
|
_smart_cb_mouse_wheel(void *data, Evas *e EINA_UNUSED,
|
|
|
|
Evas_Object *obj EINA_UNUSED, void *event)
|
|
|
|
{
|
|
|
|
Evas_Event_Mouse_Wheel *ev = event;
|
|
|
|
Miniview *mv = evas_object_smart_data_get(data);
|
|
|
|
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(mv);
|
|
|
|
|
|
|
|
/* do not handle horizontal scrolling */
|
|
|
|
if (ev->direction) return;
|
|
|
|
|
|
|
|
DBG("ev->z:%d", ev->z);
|
|
|
|
|
2014-05-03 13:16:27 -07:00
|
|
|
mv->img_hist += ev->z * 10;
|
2014-05-04 08:03:05 -07:00
|
|
|
mv->to_render = 1;
|
2014-04-27 14:48:54 -07:00
|
|
|
}
|
|
|
|
|
2014-05-04 08:15:39 -07:00
|
|
|
static void
|
|
|
|
_smart_cb_mouse_down(void *data, Evas *e EINA_UNUSED,
|
|
|
|
Evas_Object *obj EINA_UNUSED, void *event)
|
|
|
|
{
|
|
|
|
Evas_Event_Mouse_Down *ev = event;
|
|
|
|
Miniview *mv= evas_object_smart_data_get(data);
|
|
|
|
int pos;
|
|
|
|
Evas_Coord oy;
|
|
|
|
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(mv);
|
|
|
|
|
|
|
|
evas_object_geometry_get(mv->img, NULL, &oy, NULL, NULL);
|
|
|
|
pos = oy - ev->canvas.y;
|
|
|
|
pos -= mv->img_hist;
|
|
|
|
if (pos < 0)
|
|
|
|
pos = 0;
|
|
|
|
else
|
|
|
|
pos += mv->rows / 2;
|
|
|
|
termio_scroll_set(mv->termio, pos);
|
|
|
|
}
|
|
|
|
|
2014-03-18 14:53:02 -07:00
|
|
|
static void
|
|
|
|
_smart_add(Evas_Object *obj)
|
|
|
|
{
|
|
|
|
Miniview *mv;
|
|
|
|
Evas_Object *o;
|
2014-03-30 11:38:49 -07:00
|
|
|
Evas *canvas = evas_object_evas_get(obj);
|
|
|
|
|
|
|
|
DBG("%p", obj);
|
2014-03-18 14:53:02 -07:00
|
|
|
|
|
|
|
mv = calloc(1, sizeof(Miniview));
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(mv);
|
|
|
|
evas_object_smart_data_set(obj, mv);
|
|
|
|
|
2014-03-30 11:38:49 -07:00
|
|
|
mv->self = obj;
|
2014-03-18 14:53:02 -07:00
|
|
|
|
|
|
|
/* miniview output widget */
|
2014-03-30 11:38:49 -07:00
|
|
|
o = evas_object_image_add(canvas);
|
2014-03-18 14:53:02 -07:00
|
|
|
evas_object_image_alpha_set(o, EINA_TRUE);
|
2014-03-30 11:38:49 -07:00
|
|
|
|
2014-03-18 14:53:02 -07:00
|
|
|
evas_object_smart_member_add(o, obj);
|
2014-04-27 12:34:27 -07:00
|
|
|
mv->img = o;
|
2014-04-26 14:42:17 -07:00
|
|
|
|
|
|
|
evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_WHEEL,
|
|
|
|
_smart_cb_mouse_wheel, obj);
|
2014-05-04 08:15:39 -07:00
|
|
|
evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN,
|
|
|
|
_smart_cb_mouse_down, obj);
|
2014-03-18 14:53:02 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-03-30 11:38:49 -07:00
|
|
|
_smart_del(Evas_Object *obj)
|
2014-03-18 14:53:02 -07:00
|
|
|
{
|
|
|
|
Miniview *mv = evas_object_smart_data_get(obj);
|
|
|
|
|
2014-03-30 11:38:49 -07:00
|
|
|
DBG("%p", obj);
|
|
|
|
if (!mv) return;
|
2014-05-04 08:03:05 -07:00
|
|
|
|
|
|
|
ecore_timer_del(mv->deferred_renderer);
|
|
|
|
|
|
|
|
evas_object_del(mv->img);
|
|
|
|
free(mv);
|
2014-03-30 11:38:49 -07:00
|
|
|
DBG("%p", obj);
|
2014-03-18 14:53:02 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-03-30 11:38:49 -07:00
|
|
|
_smart_move(Evas_Object *obj, Evas_Coord x EINA_UNUSED, Evas_Coord y EINA_UNUSED)
|
2014-03-18 14:53:02 -07:00
|
|
|
{
|
|
|
|
Miniview *mv = evas_object_smart_data_get(obj);
|
|
|
|
|
2014-03-30 11:38:49 -07:00
|
|
|
if (!mv) return;
|
|
|
|
/* TODO */
|
|
|
|
DBG("%p x:%d y:%d", obj, x, y);
|
2014-04-27 12:34:27 -07:00
|
|
|
evas_object_move(mv->img, x, y);
|
2014-03-18 14:53:02 -07:00
|
|
|
}
|
|
|
|
|
2014-04-20 09:45:21 -07:00
|
|
|
static void
|
|
|
|
_smart_show(Evas_Object *obj)
|
|
|
|
{
|
|
|
|
Miniview *mv = evas_object_smart_data_get(obj);
|
|
|
|
|
|
|
|
if (!mv) return;
|
|
|
|
|
2014-05-01 15:08:58 -07:00
|
|
|
if (!mv->is_shown)
|
|
|
|
{
|
2014-05-03 13:16:27 -07:00
|
|
|
Evas_Coord ox, oy, ow, oh, font_w, font_h;
|
|
|
|
|
2014-05-01 15:08:58 -07:00
|
|
|
mv->is_shown = 1;
|
2014-05-03 13:16:27 -07:00
|
|
|
mv->img_hist = 0;
|
|
|
|
|
|
|
|
evas_object_geometry_get(mv->termio, &ox, &oy, &ow, &oh);
|
|
|
|
if (ow == 0 || oh == 0) return;
|
|
|
|
evas_object_size_hint_min_get(mv->termio, &font_w, &font_h);
|
|
|
|
|
|
|
|
if (font_w <= 0 || font_h <= 0) return;
|
|
|
|
|
|
|
|
mv->img_h = oh;
|
|
|
|
mv->rows = oh / font_h;
|
|
|
|
mv->cols = ow / font_w;
|
|
|
|
|
|
|
|
if (mv->rows == 0 || mv->cols == 0) return;
|
|
|
|
|
|
|
|
evas_object_resize(mv->img, mv->cols, mv->img_h);
|
|
|
|
evas_object_image_size_set(mv->img, mv->cols, mv->img_h);
|
|
|
|
|
|
|
|
evas_object_image_fill_set(mv->img, 0, 0, mv->cols, mv->img_h);
|
|
|
|
evas_object_move(mv->img, ox + ow - mv->cols, oy);
|
|
|
|
|
2014-05-04 08:03:05 -07:00
|
|
|
mv->to_render = 1;
|
2014-05-01 15:08:58 -07:00
|
|
|
evas_object_show(mv->img);
|
|
|
|
}
|
2014-04-20 09:45:21 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_smart_hide(Evas_Object *obj)
|
|
|
|
{
|
|
|
|
Miniview *mv = evas_object_smart_data_get(obj);
|
|
|
|
|
|
|
|
if (!mv) return;
|
|
|
|
|
2014-05-01 15:08:58 -07:00
|
|
|
if (mv->is_shown)
|
|
|
|
{
|
|
|
|
mv->is_shown = 0;
|
|
|
|
evas_object_hide(mv->img);
|
|
|
|
}
|
2014-04-20 09:45:21 -07:00
|
|
|
}
|
|
|
|
|
2014-05-01 15:08:58 -07:00
|
|
|
void
|
2014-05-03 13:16:27 -07:00
|
|
|
miniview_redraw(Evas_Object *obj)
|
2014-03-18 14:53:02 -07:00
|
|
|
{
|
2014-05-01 15:08:58 -07:00
|
|
|
Miniview *mv;
|
2014-05-04 08:03:05 -07:00
|
|
|
if (!obj) return;
|
|
|
|
mv = evas_object_smart_data_get(obj);
|
|
|
|
if (!mv || !mv->is_shown) return;
|
|
|
|
|
|
|
|
mv->to_render = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_deferred_renderer(void *data)
|
|
|
|
{
|
|
|
|
Miniview *mv = data;
|
2014-05-01 15:08:58 -07:00
|
|
|
Evas_Coord ox, oy, ow, oh;
|
2014-05-03 13:16:27 -07:00
|
|
|
int history_len, wret;
|
|
|
|
unsigned int *pixels, y;
|
2014-04-26 14:42:17 -07:00
|
|
|
Termcell *cells;
|
|
|
|
|
2014-05-04 08:03:05 -07:00
|
|
|
if (!mv || !mv->is_shown || !mv->to_render) return EINA_TRUE;
|
2014-03-18 14:53:02 -07:00
|
|
|
|
2014-03-30 11:38:49 -07:00
|
|
|
evas_object_geometry_get(mv->termio, &ox, &oy, &ow, &oh);
|
2014-05-04 08:03:05 -07:00
|
|
|
if (ow == 0 || oh == 0) return EINA_TRUE;
|
2014-03-18 14:53:02 -07:00
|
|
|
|
2014-04-26 14:42:17 -07:00
|
|
|
history_len = mv->pty->backscroll_num;
|
2014-03-18 14:53:02 -07:00
|
|
|
|
2014-04-27 12:34:27 -07:00
|
|
|
pixels = evas_object_image_data_get(mv->img, EINA_TRUE);
|
2014-05-03 13:16:27 -07:00
|
|
|
memset(pixels, 0, sizeof(*pixels) * mv->cols * mv->img_h);
|
2014-04-26 14:42:17 -07:00
|
|
|
|
2014-05-03 13:16:27 -07:00
|
|
|
DBG("history_len:%d hist:%d img_h:%d rows:%d cols:%d",
|
|
|
|
history_len, mv->img_hist, mv->img_h, mv->rows, mv->cols);
|
|
|
|
/* "current"? */
|
|
|
|
if (mv->img_hist >= - ((int)mv->img_h - (int)mv->rows))
|
|
|
|
mv->img_hist = -((int)mv->img_h - (int)mv->rows);
|
|
|
|
if (mv->img_hist < -history_len)
|
|
|
|
mv->img_hist = -history_len;
|
2014-04-26 14:42:17 -07:00
|
|
|
|
2014-04-27 12:34:27 -07:00
|
|
|
for (y = 0; y < mv->img_h; y++)
|
2014-04-26 14:42:17 -07:00
|
|
|
{
|
2014-04-27 12:34:27 -07:00
|
|
|
cells = termpty_cellrow_get(mv->pty, mv->img_hist + y, &wret);
|
2014-04-26 14:42:17 -07:00
|
|
|
if (cells == NULL)
|
|
|
|
{
|
2014-04-27 12:34:27 -07:00
|
|
|
DBG("y:%d get:%d", y, mv->img_hist + y);
|
2014-04-26 14:42:17 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-05-03 13:16:27 -07:00
|
|
|
_draw_line(&pixels[y * mv->cols], cells, wret);
|
2014-04-26 14:42:17 -07:00
|
|
|
}
|
2014-05-03 13:16:27 -07:00
|
|
|
DBG("history_len:%d hist:%d img_h:%d rows:%d cols:%d",
|
|
|
|
history_len, mv->img_hist, mv->img_h, mv->rows, mv->cols);
|
|
|
|
evas_object_image_data_set(mv->img, pixels);
|
|
|
|
evas_object_image_data_update_add(mv->img, 0, 0, mv->cols, mv->img_h);
|
2014-05-04 08:03:05 -07:00
|
|
|
|
|
|
|
mv->to_render = 0;
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
2014-03-18 14:53:02 -07:00
|
|
|
}
|
|
|
|
|
2014-04-15 14:25:12 -07:00
|
|
|
|
2014-03-30 11:38:49 -07:00
|
|
|
static void
|
|
|
|
_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
|
2014-03-18 14:53:02 -07:00
|
|
|
{
|
|
|
|
Miniview *mv = evas_object_smart_data_get(obj);
|
|
|
|
if (!mv) return;
|
|
|
|
|
2014-03-30 11:38:49 -07:00
|
|
|
DBG("smart resize %p w:%d h:%d", obj, w, h);
|
2014-04-27 12:34:27 -07:00
|
|
|
evas_object_resize(mv->img, w, h);
|
2014-03-18 14:53:02 -07:00
|
|
|
}
|
|
|
|
|
2014-03-30 11:38:49 -07:00
|
|
|
|
|
|
|
static void
|
|
|
|
_smart_init(void)
|
2014-03-18 14:53:02 -07:00
|
|
|
{
|
2014-03-30 11:38:49 -07:00
|
|
|
static Evas_Smart_Class sc = EVAS_SMART_CLASS_INIT_NULL;
|
2014-03-18 14:53:02 -07:00
|
|
|
|
2014-03-30 11:38:49 -07:00
|
|
|
DBG("smart init");
|
|
|
|
|
|
|
|
sc.name = "miniview";
|
|
|
|
sc.version = EVAS_SMART_CLASS_VERSION;
|
|
|
|
sc.add = _smart_add;
|
|
|
|
sc.del = _smart_del;
|
|
|
|
sc.resize = _smart_resize;
|
|
|
|
sc.move = _smart_move;
|
|
|
|
sc.show = _smart_show;
|
|
|
|
sc.hide = _smart_hide;
|
|
|
|
_smart = evas_smart_class_new(&sc);
|
2014-03-18 14:53:02 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
Evas_Object *
|
2014-03-30 11:38:49 -07:00
|
|
|
miniview_add(Evas_Object *parent, Evas_Object *termio)
|
2014-03-18 14:53:02 -07:00
|
|
|
{
|
|
|
|
Evas *e;
|
2014-03-30 11:38:49 -07:00
|
|
|
Evas_Object *obj;
|
2014-03-18 14:53:02 -07:00
|
|
|
Miniview *mv;
|
|
|
|
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
|
|
|
|
e = evas_object_evas_get(parent);
|
|
|
|
if (!e) return NULL;
|
|
|
|
|
2014-03-30 11:38:49 -07:00
|
|
|
DBG("ADD parent:%p", parent);
|
|
|
|
|
2014-03-18 14:53:02 -07:00
|
|
|
if (!_smart) _smart_init();
|
2014-03-30 11:38:49 -07:00
|
|
|
|
2014-03-18 14:53:02 -07:00
|
|
|
obj = evas_object_smart_add(e, _smart);
|
|
|
|
mv = evas_object_smart_data_get(obj);
|
|
|
|
if (!mv) return obj;
|
|
|
|
|
2014-03-30 11:38:49 -07:00
|
|
|
mv->termio = termio;
|
|
|
|
mv->pty = termio_pty_get(termio);
|
2014-05-04 08:03:05 -07:00
|
|
|
mv->deferred_renderer = ecore_timer_add(0.1, _deferred_renderer, mv);
|
2014-03-18 14:53:02 -07:00
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|