2015-03-17 15:42:03 -07:00
|
|
|
#ifdef HAVE_CONFIG
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "Elm_Code.h"
|
|
|
|
|
|
|
|
#include "elm_code_private.h"
|
|
|
|
|
|
|
|
static Elm_Code_Widget_Selection_Data *
|
|
|
|
_elm_code_widget_selection_new()
|
|
|
|
{
|
|
|
|
Elm_Code_Widget_Selection_Data *data;
|
|
|
|
|
|
|
|
data = calloc(1, sizeof(Elm_Code_Widget_Selection_Data));
|
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
2015-03-18 15:24:56 -07:00
|
|
|
static void
|
|
|
|
_elm_code_widget_selection_limit(Evas_Object *widget EINA_UNUSED, Elm_Code_Widget_Data *pd,
|
|
|
|
unsigned int *row, unsigned int *col)
|
|
|
|
{
|
|
|
|
Elm_Code_Line *line;
|
|
|
|
Elm_Code_File *file;
|
2015-03-29 12:12:28 -07:00
|
|
|
unsigned int width;
|
2015-03-18 15:24:56 -07:00
|
|
|
|
|
|
|
file = pd->code->file;
|
|
|
|
|
|
|
|
if (*row > elm_code_file_lines_get(file))
|
|
|
|
*row = elm_code_file_lines_get(file);
|
|
|
|
|
|
|
|
line = elm_code_file_line_get(file, *row);
|
2015-03-29 12:12:28 -07:00
|
|
|
width = elm_code_line_text_column_width(line, pd->tabstop);
|
2015-03-18 15:24:56 -07:00
|
|
|
|
2015-03-29 12:12:28 -07:00
|
|
|
if (*col > width + 1)
|
|
|
|
*col = width + 1;
|
2015-03-18 15:24:56 -07:00
|
|
|
if (*col < 1)
|
|
|
|
*col = 1;
|
|
|
|
}
|
|
|
|
|
2015-03-17 15:42:03 -07:00
|
|
|
EAPI void
|
|
|
|
elm_code_widget_selection_start(Evas_Object *widget,
|
|
|
|
unsigned int line, unsigned int col)
|
|
|
|
{
|
|
|
|
Elm_Code_Widget_Data *pd;
|
|
|
|
Elm_Code_Widget_Selection_Data *selection;
|
|
|
|
|
|
|
|
pd = eo_data_scope_get(widget, ELM_CODE_WIDGET_CLASS);
|
|
|
|
|
2015-03-18 15:24:56 -07:00
|
|
|
_elm_code_widget_selection_limit(widget, pd, &line, &col);
|
2015-03-17 15:42:03 -07:00
|
|
|
if (!pd->selection)
|
|
|
|
{
|
|
|
|
selection = _elm_code_widget_selection_new();
|
|
|
|
|
|
|
|
selection->end_line = line;
|
|
|
|
selection->end_col = col;
|
|
|
|
|
|
|
|
pd->selection = selection;
|
|
|
|
}
|
|
|
|
|
|
|
|
pd->selection->start_line = line;
|
|
|
|
pd->selection->start_col = col;
|
2015-03-22 15:28:07 -07:00
|
|
|
eo_do(widget,
|
|
|
|
eo_event_callback_call(ELM_CODE_WIDGET_EVENT_SELECTION_CHANGED, widget),
|
|
|
|
elm_code_widget_cursor_position_set(col, line));
|
2015-03-17 15:42:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
elm_code_widget_selection_end(Evas_Object *widget,
|
|
|
|
unsigned int line, unsigned int col)
|
|
|
|
{
|
|
|
|
Elm_Code_Widget_Data *pd;
|
|
|
|
Elm_Code_Widget_Selection_Data *selection;
|
|
|
|
|
|
|
|
pd = eo_data_scope_get(widget, ELM_CODE_WIDGET_CLASS);
|
|
|
|
|
2015-03-18 15:24:56 -07:00
|
|
|
_elm_code_widget_selection_limit(widget, pd, &line, &col);
|
2015-03-17 15:42:03 -07:00
|
|
|
if (!pd->selection)
|
|
|
|
{
|
|
|
|
selection = _elm_code_widget_selection_new();
|
|
|
|
|
|
|
|
selection->start_line = line;
|
|
|
|
selection->start_col = col;
|
|
|
|
|
|
|
|
pd->selection = selection;
|
|
|
|
}
|
|
|
|
|
|
|
|
pd->selection->end_line = line;
|
|
|
|
pd->selection->end_col = col;
|
2015-03-18 15:24:56 -07:00
|
|
|
eo_do(widget, eo_event_callback_call(ELM_CODE_WIDGET_EVENT_SELECTION_CHANGED, widget));
|
2015-03-17 15:42:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
elm_code_widget_selection_clear(Evas_Object *widget)
|
|
|
|
{
|
|
|
|
Elm_Code_Widget_Data *pd;
|
|
|
|
|
|
|
|
pd = eo_data_scope_get(widget, ELM_CODE_WIDGET_CLASS);
|
|
|
|
|
|
|
|
if (pd->selection)
|
|
|
|
free(pd->selection);
|
|
|
|
|
|
|
|
pd->selection = NULL;
|
2015-03-18 15:24:56 -07:00
|
|
|
eo_do(widget, eo_event_callback_call(ELM_CODE_WIDGET_EVENT_SELECTION_CLEARED, widget));
|
2015-03-17 15:42:03 -07:00
|
|
|
}
|
|
|
|
|
2015-03-28 08:17:08 -07:00
|
|
|
static void
|
|
|
|
_elm_code_widget_selection_delete_single(Elm_Code_Widget_Data *pd)
|
|
|
|
{
|
|
|
|
Elm_Code_Line *line;
|
|
|
|
const char *old;
|
|
|
|
unsigned int old_length, length;
|
|
|
|
char *content;
|
|
|
|
|
2015-03-28 09:05:36 -07:00
|
|
|
if (pd->selection->end_col < pd->selection->start_col)
|
2015-03-28 08:17:08 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
line = elm_code_file_line_get(pd->code->file, pd->selection->start_line);
|
|
|
|
old = elm_code_line_text_get(line, &old_length);
|
|
|
|
length = line->length - (pd->selection->end_col - pd->selection->start_col);
|
|
|
|
content = malloc(sizeof(char) * (length + 1));
|
|
|
|
snprintf(content, pd->selection->start_col, old);
|
|
|
|
snprintf(content + pd->selection->start_col - 1, old_length - pd->selection->end_col + 1,
|
|
|
|
old + pd->selection->end_col);
|
|
|
|
elm_code_line_text_set(line, content, length);
|
|
|
|
free(content);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_elm_code_widget_selection_delete_multi(Elm_Code_Widget_Data *pd)
|
|
|
|
{
|
|
|
|
Elm_Code_Line *line;
|
|
|
|
const char *first, *last;
|
|
|
|
unsigned int last_length, length, i;
|
|
|
|
char *content;
|
|
|
|
|
|
|
|
if (pd->selection->end_line <= pd->selection->start_line)
|
|
|
|
return;
|
|
|
|
|
|
|
|
line = elm_code_file_line_get(pd->code->file, pd->selection->start_line);
|
|
|
|
first = elm_code_line_text_get(line, NULL);
|
|
|
|
line = elm_code_file_line_get(pd->code->file, pd->selection->end_line);
|
|
|
|
last = elm_code_line_text_get(line, &last_length);
|
|
|
|
length = pd->selection->start_col + last_length - pd->selection->end_col + 1;
|
|
|
|
content = malloc(sizeof(char) * (length + 1));
|
|
|
|
snprintf(content, pd->selection->start_col, first);
|
|
|
|
snprintf(content + pd->selection->start_col - 1, last_length - pd->selection->end_col + 1,
|
|
|
|
last + pd->selection->end_col);
|
|
|
|
|
|
|
|
for (i = line->number; i > pd->selection->start_line; i--)
|
|
|
|
elm_code_file_line_remove(pd->code->file, i);
|
|
|
|
|
|
|
|
line = elm_code_file_line_get(pd->code->file, pd->selection->start_line);
|
|
|
|
elm_code_line_text_set(line, content, length);
|
|
|
|
free(content);
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
elm_code_widget_selection_delete(Evas_Object *widget)
|
|
|
|
{
|
|
|
|
Elm_Code_Widget_Data *pd;
|
|
|
|
|
|
|
|
pd = eo_data_scope_get(widget, ELM_CODE_WIDGET_CLASS);
|
|
|
|
|
|
|
|
if (!pd->selection)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (pd->selection->start_line == pd->selection->end_line)
|
|
|
|
_elm_code_widget_selection_delete_single(pd);
|
|
|
|
else
|
|
|
|
_elm_code_widget_selection_delete_multi(pd);
|
|
|
|
|
|
|
|
free(pd->selection);
|
|
|
|
pd->selection = NULL;
|
|
|
|
eo_do(widget, eo_event_callback_call(ELM_CODE_WIDGET_EVENT_SELECTION_CLEARED, widget));
|
|
|
|
}
|
|
|
|
|
2015-03-25 15:17:41 -07:00
|
|
|
static char *
|
|
|
|
_elm_code_widget_selection_text_single_get(Elm_Code_Widget_Data *pd)
|
|
|
|
{
|
|
|
|
Elm_Code_Line *line;
|
|
|
|
|
|
|
|
line = elm_code_file_line_get(pd->code->file, pd->selection->start_line);
|
|
|
|
|
|
|
|
return elm_code_line_text_substr(line, pd->selection->start_col - 1,
|
|
|
|
pd->selection->end_col - pd->selection->start_col + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
|
|
|
_elm_code_widget_selection_text_multi_get(Elm_Code_Widget_Data *pd)
|
|
|
|
{
|
|
|
|
Elm_Code_Line *line;
|
2015-03-25 15:55:32 -07:00
|
|
|
char *first, *last, *ret, *ptr;
|
2015-03-25 15:17:41 -07:00
|
|
|
const char *newline;
|
|
|
|
short newline_len;
|
|
|
|
int ret_len;
|
2015-03-25 15:55:32 -07:00
|
|
|
unsigned int row;
|
2015-03-25 15:17:41 -07:00
|
|
|
|
|
|
|
newline = elm_code_file_line_ending_chars_get(pd->code->file, &newline_len);
|
|
|
|
|
|
|
|
line = elm_code_file_line_get(pd->code->file, pd->selection->start_line);
|
|
|
|
first = elm_code_line_text_substr(line, pd->selection->start_col - 1,
|
|
|
|
line->length - pd->selection->start_col + 1);
|
|
|
|
|
|
|
|
line = elm_code_file_line_get(pd->code->file, pd->selection->end_line);
|
2015-03-25 15:55:32 -07:00
|
|
|
last = elm_code_line_text_substr(line, 0, pd->selection->end_col);
|
2015-03-25 15:17:41 -07:00
|
|
|
|
|
|
|
ret_len = strlen(first) + strlen(last) + newline_len;
|
2015-03-25 15:55:32 -07:00
|
|
|
|
|
|
|
for (row = pd->selection->start_line + 1; row < pd->selection->end_line; row++)
|
|
|
|
{
|
|
|
|
line = elm_code_file_line_get(pd->code->file, row);
|
|
|
|
ret_len += line->length + newline_len;
|
|
|
|
}
|
|
|
|
|
2015-03-25 15:17:41 -07:00
|
|
|
ret = malloc(sizeof(char) * (ret_len + 1));
|
2015-03-25 15:55:32 -07:00
|
|
|
snprintf(ret, strlen(first) + newline_len + 1, "%s%s", first, newline);
|
|
|
|
|
|
|
|
ptr = ret;
|
|
|
|
ptr += strlen(first) + newline_len;
|
|
|
|
|
|
|
|
for (row = pd->selection->start_line + 1; row < pd->selection->end_line; row++)
|
|
|
|
{
|
|
|
|
line = elm_code_file_line_get(pd->code->file, row);
|
|
|
|
if (line->modified)
|
|
|
|
snprintf(ptr, line->length + 1, "%s", line->modified);
|
|
|
|
else
|
|
|
|
snprintf(ptr, line->length + 1, "%s", line->content);
|
|
|
|
|
|
|
|
snprintf(ptr + line->length, newline_len + 1, "%s", newline);
|
|
|
|
ptr += line->length + newline_len;
|
|
|
|
}
|
|
|
|
snprintf(ptr, strlen(last) + 1, "%s", last);
|
2015-03-25 15:17:41 -07:00
|
|
|
|
|
|
|
free(first);
|
|
|
|
free(last);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-03-25 14:55:00 -07:00
|
|
|
EAPI char *
|
2015-03-17 15:42:03 -07:00
|
|
|
elm_code_widget_selection_text_get(Evas_Object *widget)
|
|
|
|
{
|
|
|
|
Elm_Code_Widget_Data *pd;
|
|
|
|
|
|
|
|
pd = eo_data_scope_get(widget, ELM_CODE_WIDGET_CLASS);
|
|
|
|
|
2015-03-25 15:17:41 -07:00
|
|
|
if (!pd->selection || pd->selection->end_line < pd->selection->start_line)
|
2015-03-25 14:55:00 -07:00
|
|
|
return strdup("");
|
|
|
|
|
|
|
|
if (pd->selection->start_line == pd->selection->end_line)
|
2015-03-25 15:17:41 -07:00
|
|
|
return _elm_code_widget_selection_text_single_get(pd);
|
|
|
|
else
|
|
|
|
return _elm_code_widget_selection_text_multi_get(pd);
|
2015-03-17 15:42:03 -07:00
|
|
|
}
|
2015-03-28 10:57:47 -07:00
|
|
|
|
|
|
|
static void
|
|
|
|
_selection_loss_cb(void *data, Elm_Sel_Type selection EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Elm_Code_Widget *widget;
|
|
|
|
|
|
|
|
widget = (Elm_Code_Widget *)data;
|
|
|
|
// TODO we need to know whih selection we are clearing!
|
|
|
|
// elm_code_widget_selection_clear(widget);
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
elm_code_widget_selection_cut(Evas_Object *widget)
|
|
|
|
{
|
|
|
|
char *text;
|
|
|
|
|
|
|
|
text = elm_code_widget_selection_text_get(widget);
|
|
|
|
elm_cnp_selection_set(widget, ELM_SEL_TYPE_CLIPBOARD, ELM_SEL_FORMAT_TEXT, text, strlen(text));
|
|
|
|
elm_cnp_selection_loss_callback_set(widget, ELM_SEL_TYPE_CLIPBOARD, _selection_loss_cb, widget);
|
|
|
|
free(text);
|
|
|
|
|
|
|
|
elm_code_widget_selection_delete(widget);
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
elm_code_widget_selection_copy(Evas_Object *widget)
|
|
|
|
{
|
|
|
|
char *text;
|
|
|
|
|
|
|
|
text = elm_code_widget_selection_text_get(widget);
|
|
|
|
elm_cnp_selection_set(widget, ELM_SEL_TYPE_CLIPBOARD, ELM_SEL_FORMAT_TEXT, text, strlen(text));
|
|
|
|
elm_cnp_selection_loss_callback_set(widget, ELM_SEL_TYPE_CLIPBOARD, _selection_loss_cb, widget);
|
|
|
|
free(text);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_selection_paste_cb(void *data, Evas_Object *obj EINA_UNUSED, Elm_Selection_Data *ev)
|
|
|
|
{
|
|
|
|
Elm_Code *code;
|
|
|
|
Elm_Code_Widget *widget;
|
|
|
|
Elm_Code_Line *line;
|
2015-03-30 12:07:45 -07:00
|
|
|
Elm_Code_Widget_Data *pd;
|
|
|
|
unsigned int row, col, col_width, position;
|
2015-03-28 10:57:47 -07:00
|
|
|
|
|
|
|
widget = (Elm_Code_Widget *)data;
|
2015-03-30 12:07:45 -07:00
|
|
|
pd = eo_data_scope_get(widget, ELM_CODE_WIDGET_CLASS);
|
|
|
|
|
2015-03-28 10:57:47 -07:00
|
|
|
if (ev->format != ELM_SEL_FORMAT_TEXT)
|
|
|
|
return EINA_TRUE;
|
|
|
|
|
|
|
|
if (ev->len <= 0)
|
|
|
|
return EINA_TRUE;
|
|
|
|
|
|
|
|
eo_do(widget,
|
|
|
|
code = elm_code_widget_code_get(),
|
|
|
|
elm_code_widget_cursor_position_get(&col, &row));
|
|
|
|
line = elm_code_file_line_get(code->file, row);
|
|
|
|
|
2015-03-30 12:07:45 -07:00
|
|
|
position = elm_code_line_text_position_for_column_get(line, col - 1, pd->tabstop);
|
|
|
|
elm_code_line_text_insert(line, position + 1, ev->data, ev->len - 1);
|
2015-03-28 10:57:47 -07:00
|
|
|
|
2015-03-30 12:07:45 -07:00
|
|
|
col_width = elm_code_line_text_column_width_to_position(line, position + ev->len - 1, pd->tabstop) -
|
|
|
|
elm_code_line_text_column_width_to_position(line, position, pd->tabstop);
|
2015-03-28 10:57:47 -07:00
|
|
|
eo_do(widget,
|
2015-03-30 12:07:45 -07:00
|
|
|
elm_code_widget_cursor_position_set(col + col_width, row));
|
2015-03-28 10:57:47 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
elm_code_widget_selection_paste(Evas_Object *widget)
|
|
|
|
{
|
|
|
|
elm_code_widget_selection_delete(widget);
|
|
|
|
|
|
|
|
elm_cnp_selection_get(widget, ELM_SEL_TYPE_CLIPBOARD, ELM_SEL_FORMAT_TEXT, _selection_paste_cb, widget);
|
|
|
|
}
|