2014-09-30 07:56:16 -07:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <Enventor.h>
|
|
|
|
#include "enventor_private.h"
|
2014-07-18 21:31:08 -07:00
|
|
|
|
|
|
|
#define QUEUE_SIZE 20
|
|
|
|
#define COMPSET_PAIR_MINIMUM 1
|
2015-06-23 22:06:32 -07:00
|
|
|
#define MAX_CONTEXT_STACK 40
|
2015-06-16 00:53:23 -07:00
|
|
|
#define MAX_KEYWORD_LENGHT 40
|
2014-07-18 21:31:08 -07:00
|
|
|
|
2015-06-08 08:35:16 -07:00
|
|
|
typedef struct lexem_s
|
2014-07-18 21:31:08 -07:00
|
|
|
{
|
2015-06-08 08:35:16 -07:00
|
|
|
Eina_List *nodes;
|
2014-07-18 21:31:08 -07:00
|
|
|
char **txt;
|
2015-06-08 08:35:16 -07:00
|
|
|
int txt_count;
|
2014-07-18 21:31:08 -07:00
|
|
|
int cursor_offset;
|
|
|
|
int line_back;
|
2015-07-02 19:49:11 -07:00
|
|
|
char **name;
|
|
|
|
int name_count;
|
2015-06-22 16:16:01 -07:00
|
|
|
int dot;
|
2015-06-08 08:35:16 -07:00
|
|
|
} lexem;
|
2014-07-18 21:31:08 -07:00
|
|
|
|
|
|
|
typedef struct autocomp_s
|
|
|
|
{
|
|
|
|
char queue[QUEUE_SIZE];
|
|
|
|
int queue_pos;
|
2015-06-08 08:35:16 -07:00
|
|
|
const lexem *lexem_root;
|
|
|
|
lexem *lexem_ptr;
|
|
|
|
Eet_File *source_file;
|
2014-07-18 21:31:08 -07:00
|
|
|
edit_data *ed;
|
|
|
|
Evas_Object *anchor;
|
|
|
|
Evas_Object *list;
|
|
|
|
Ecore_Thread *init_thread;
|
|
|
|
Eina_Bool anchor_visible : 1;
|
|
|
|
Eina_Bool initialized : 1;
|
2014-09-30 07:56:16 -07:00
|
|
|
Eina_Bool enabled : 1;
|
2015-06-15 21:28:59 -07:00
|
|
|
Ecore_Thread *cntx_lexem_thread;
|
2015-06-22 16:16:01 -07:00
|
|
|
Eina_Bool dot_candidate : 1;
|
2015-08-26 08:58:01 -07:00
|
|
|
Eina_Bool on_keygrab : 1;
|
2014-07-18 21:31:08 -07:00
|
|
|
} autocomp_data;
|
|
|
|
|
2015-06-15 21:28:59 -07:00
|
|
|
typedef struct ctx_lexem_thread_data_s
|
|
|
|
{
|
|
|
|
char *utf8;
|
|
|
|
int cur_pos;
|
|
|
|
lexem *result;
|
|
|
|
autocomp_data *ad;
|
2015-06-16 00:53:23 -07:00
|
|
|
Eina_Bool list_show;
|
2015-06-15 21:28:59 -07:00
|
|
|
} ctx_lexem_td;
|
|
|
|
|
2014-07-18 21:31:08 -07:00
|
|
|
static autocomp_data *g_ad = NULL;
|
|
|
|
|
2014-09-30 07:56:16 -07:00
|
|
|
/*****************************************************************************/
|
|
|
|
/* Internal method implementation */
|
|
|
|
/*****************************************************************************/
|
2015-06-08 08:35:16 -07:00
|
|
|
static Eet_Data_Descriptor *lex_desc = NULL;
|
2015-06-16 00:53:23 -07:00
|
|
|
static void candidate_list_show(autocomp_data *ad);
|
|
|
|
static void queue_reset(autocomp_data *ad);
|
|
|
|
static void entry_anchor_off(autocomp_data *ad);
|
2015-08-26 08:58:01 -07:00
|
|
|
static void anchor_key_down_cb(void *data, Evas *evas, Evas_Object *obj, void *event_info);
|
|
|
|
|
2015-06-08 08:35:16 -07:00
|
|
|
|
|
|
|
static void
|
|
|
|
eddc_init(void)
|
|
|
|
{
|
|
|
|
Eet_Data_Descriptor_Class eddc;
|
|
|
|
|
|
|
|
EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, lexem);
|
|
|
|
lex_desc = eet_data_descriptor_file_new(&eddc);
|
|
|
|
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_LIST(lex_desc, lexem, "nodes", nodes, lex_desc);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_VAR_ARRAY_STRING(lex_desc, lexem, "txt", txt);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(lex_desc, lexem, "cursor_offset", cursor_offset, EET_T_INT);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(lex_desc, lexem, "line_back", line_back, EET_T_INT);
|
2015-06-22 16:16:01 -07:00
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(lex_desc, lexem, "dot", dot, EET_T_INT);
|
2015-07-02 19:49:11 -07:00
|
|
|
EET_DATA_DESCRIPTOR_ADD_VAR_ARRAY_STRING(lex_desc, lexem, "name", name);
|
2015-06-08 08:35:16 -07:00
|
|
|
}
|
2014-09-30 07:56:16 -07:00
|
|
|
|
2014-07-18 21:31:08 -07:00
|
|
|
static void
|
2015-06-08 08:35:16 -07:00
|
|
|
autocomp_load(autocomp_data *ad)
|
2014-07-18 21:31:08 -07:00
|
|
|
{
|
2015-06-08 08:35:16 -07:00
|
|
|
char buf[PATH_MAX];
|
2015-06-08 23:40:30 -07:00
|
|
|
snprintf(buf, sizeof(buf), "%s/autocomp/autocomp.eet",
|
|
|
|
eina_prefix_data_get(PREFIX));
|
|
|
|
|
2015-06-08 08:35:16 -07:00
|
|
|
if (ad->source_file)
|
|
|
|
{
|
|
|
|
if (lex_desc)
|
|
|
|
eet_data_descriptor_free(lex_desc);
|
|
|
|
eet_close(ad->source_file);
|
|
|
|
|
|
|
|
}
|
|
|
|
ad->source_file = eet_open(buf, EET_FILE_MODE_READ);
|
|
|
|
|
|
|
|
ad->lexem_root = (lexem *)eet_data_read(ad->source_file, lex_desc, "node");
|
|
|
|
ad->lexem_ptr = (lexem *)ad->lexem_root;
|
2014-07-18 21:31:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
init_thread_cb(void *data, Ecore_Thread *thread EINA_UNUSED)
|
|
|
|
{
|
|
|
|
autocomp_data *ad = data;
|
2015-06-08 08:35:16 -07:00
|
|
|
eddc_init();
|
|
|
|
autocomp_load(ad);
|
|
|
|
}
|
|
|
|
|
2015-06-21 22:51:18 -07:00
|
|
|
static void
|
|
|
|
lexem_tree_free(lexem **root)
|
|
|
|
{
|
|
|
|
lexem *data = NULL;
|
|
|
|
Eina_List *l = NULL;
|
|
|
|
|
|
|
|
if (!(*root)) return;
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH((*root)->nodes, l, data)
|
|
|
|
{
|
|
|
|
if (data->nodes)
|
|
|
|
lexem_tree_free(&data);
|
|
|
|
}
|
|
|
|
|
|
|
|
EINA_LIST_FREE((*root)->nodes, data)
|
|
|
|
{
|
|
|
|
free(data->txt);
|
2015-07-02 19:49:11 -07:00
|
|
|
free(data->name);
|
2015-06-21 22:51:18 -07:00
|
|
|
free(data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-15 21:28:59 -07:00
|
|
|
static void
|
|
|
|
context_lexem_thread_cb(void *data, Ecore_Thread *thread EINA_UNUSED)
|
2015-06-08 08:35:16 -07:00
|
|
|
{
|
2015-06-15 21:28:59 -07:00
|
|
|
ctx_lexem_td *td = (ctx_lexem_td *)data;
|
2015-06-08 08:35:16 -07:00
|
|
|
|
|
|
|
Eina_Bool find_flag = EINA_FALSE;
|
2015-06-16 00:53:23 -07:00
|
|
|
Eina_Bool dot_lex = EINA_FALSE;
|
2015-06-08 08:35:16 -07:00
|
|
|
Eina_List *l = NULL;
|
2015-06-15 21:28:59 -07:00
|
|
|
Eina_List *nodes = td->ad->lexem_root->nodes;
|
|
|
|
td->result = (lexem *)td->ad->lexem_root;
|
|
|
|
int cur_pos = td->cur_pos;
|
|
|
|
if (cur_pos <= 1) return;
|
2015-06-08 08:35:16 -07:00
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
|
2015-06-15 21:28:59 -07:00
|
|
|
if (!td->utf8) return;
|
2015-06-08 08:35:16 -07:00
|
|
|
|
2015-06-23 22:06:32 -07:00
|
|
|
char *utf8 = td->utf8;
|
2015-06-08 08:35:16 -07:00
|
|
|
char *cur = utf8;
|
|
|
|
char *end = cur + cur_pos;
|
2015-06-16 00:53:23 -07:00
|
|
|
char stack[MAX_CONTEXT_STACK][MAX_KEYWORD_LENGHT];
|
2015-06-08 08:35:16 -07:00
|
|
|
int depth = 0;
|
|
|
|
char *help_ptr = NULL;
|
|
|
|
char *help_end_ptr = NULL;
|
|
|
|
|
|
|
|
const char *quot = QUOT_UTF8;
|
|
|
|
const int quot_len = QUOT_UTF8_LEN;
|
|
|
|
int quot_cnt = 0;
|
2015-06-16 00:53:23 -07:00
|
|
|
int context_len = 0;
|
2015-06-08 08:35:16 -07:00
|
|
|
|
2015-06-15 21:38:06 -07:00
|
|
|
while (cur && cur <= end)
|
2015-06-08 08:35:16 -07:00
|
|
|
{
|
2015-08-19 19:09:37 -07:00
|
|
|
if ((cur != end) && (!strncmp(cur, quot, quot_len)))
|
|
|
|
{
|
|
|
|
/*TODO: add exception for case '\"'*/
|
|
|
|
quot_cnt++;
|
|
|
|
cur++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (quot_cnt % 2)
|
|
|
|
{
|
|
|
|
cur++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2015-06-08 08:35:16 -07:00
|
|
|
|
2015-06-15 21:38:06 -07:00
|
|
|
//Check inside comment
|
|
|
|
if (*cur == '/')
|
|
|
|
{
|
|
|
|
if (cur[1] == '/')
|
|
|
|
{
|
|
|
|
cur = strchr(cur, '\n');
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (cur[1] == '*')
|
|
|
|
{
|
|
|
|
cur = strstr(cur, "*/");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-08 08:35:16 -07:00
|
|
|
if (*cur == '{')
|
|
|
|
{
|
|
|
|
for (help_end_ptr = cur;
|
|
|
|
!isalnum(*help_end_ptr);
|
|
|
|
help_end_ptr--);
|
|
|
|
for (help_ptr = help_end_ptr;
|
|
|
|
(((isalnum(*help_ptr )) || (*help_ptr == '_')));
|
|
|
|
help_ptr--);
|
|
|
|
if (help_ptr != utf8)
|
|
|
|
help_ptr++;
|
|
|
|
|
2015-06-16 00:53:23 -07:00
|
|
|
context_len = help_end_ptr - help_ptr + 1;
|
|
|
|
if (context_len >= MAX_KEYWORD_LENGHT)
|
|
|
|
{
|
|
|
|
cur++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(stack[depth], 0x0, MAX_KEYWORD_LENGHT);
|
2015-06-17 01:02:58 -07:00
|
|
|
strncpy(stack[depth], help_ptr, context_len);
|
2015-06-08 08:35:16 -07:00
|
|
|
depth++;
|
2015-06-23 22:06:32 -07:00
|
|
|
if (depth == MAX_CONTEXT_STACK) break;
|
2015-06-08 08:35:16 -07:00
|
|
|
}
|
2015-06-16 00:53:23 -07:00
|
|
|
if (*cur == '.')
|
|
|
|
{
|
|
|
|
Eina_Bool alpha_present = EINA_FALSE;
|
|
|
|
help_end_ptr = cur - 1;
|
|
|
|
for (help_ptr = help_end_ptr; help_ptr && isalnum(*help_ptr); help_ptr--)
|
|
|
|
if (isalpha(*help_ptr)) alpha_present = EINA_TRUE;
|
|
|
|
if ((!alpha_present) || (!strncmp(help_ptr, quot, quot_len)))
|
|
|
|
{
|
|
|
|
cur++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (help_ptr != utf8) help_ptr++;
|
|
|
|
context_len = help_end_ptr - help_ptr + 1;
|
|
|
|
if (context_len >= MAX_KEYWORD_LENGHT)
|
|
|
|
{
|
|
|
|
cur++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
memset(stack[depth], 0x0, MAX_KEYWORD_LENGHT);
|
|
|
|
strncpy(stack[depth], help_ptr, context_len);
|
|
|
|
depth++;
|
2015-06-23 22:06:32 -07:00
|
|
|
if (depth == MAX_CONTEXT_STACK) break;
|
2015-06-16 00:53:23 -07:00
|
|
|
dot_lex = EINA_TRUE;
|
|
|
|
}
|
|
|
|
if ((*cur == ';') && dot_lex)
|
|
|
|
{
|
|
|
|
dot_lex = EINA_FALSE;
|
|
|
|
memset(stack[depth], 0x0, MAX_KEYWORD_LENGHT);
|
2015-06-17 01:02:58 -07:00
|
|
|
if (depth > 0) depth--;
|
2015-06-16 00:53:23 -07:00
|
|
|
}
|
2015-06-08 08:35:16 -07:00
|
|
|
if (*cur == '}')
|
|
|
|
{
|
2015-06-16 00:53:23 -07:00
|
|
|
memset(stack[depth], 0x0, MAX_KEYWORD_LENGHT);
|
2015-06-15 21:38:06 -07:00
|
|
|
if (depth > 0) depth--;
|
2015-06-08 08:35:16 -07:00
|
|
|
}
|
|
|
|
cur++;
|
|
|
|
}
|
|
|
|
|
2015-06-15 21:28:59 -07:00
|
|
|
if (quot_cnt % 2)
|
|
|
|
{
|
|
|
|
td->result = NULL;
|
|
|
|
return;
|
|
|
|
}
|
2015-06-08 08:35:16 -07:00
|
|
|
|
2015-07-02 19:49:11 -07:00
|
|
|
int k = 0;
|
2015-06-08 08:35:16 -07:00
|
|
|
for (i = 0; i < depth; i++)
|
|
|
|
{
|
|
|
|
find_flag = EINA_FALSE;
|
2015-06-15 21:28:59 -07:00
|
|
|
EINA_LIST_FOREACH(nodes, l, td->result)
|
2015-06-08 08:35:16 -07:00
|
|
|
{
|
2015-07-02 19:49:11 -07:00
|
|
|
for (k = 0; k < td->result->name_count; k++)
|
2015-06-08 08:35:16 -07:00
|
|
|
{
|
2015-07-02 19:49:11 -07:00
|
|
|
if (!strncmp(stack[i], td->result->name[k], strlen(td->result->name[k])))
|
|
|
|
{
|
|
|
|
nodes = td->result->nodes;
|
|
|
|
find_flag = EINA_TRUE;
|
|
|
|
}
|
|
|
|
if (find_flag) break;
|
2015-06-08 08:35:16 -07:00
|
|
|
}
|
2015-07-02 19:49:11 -07:00
|
|
|
if (find_flag) break;
|
2015-06-08 08:35:16 -07:00
|
|
|
}
|
2015-06-15 21:28:59 -07:00
|
|
|
if (!find_flag)
|
|
|
|
{
|
|
|
|
td->result = NULL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
context_lexem_thread_end_cb(void *data, Ecore_Thread *thread EINA_UNUSED)
|
|
|
|
{
|
|
|
|
ctx_lexem_td *td = (ctx_lexem_td *)data;
|
|
|
|
|
2015-08-31 03:14:37 -07:00
|
|
|
td->ad->lexem_ptr = td->result;
|
2015-06-23 22:06:32 -07:00
|
|
|
td->ad->cntx_lexem_thread = NULL;
|
2015-06-16 00:53:23 -07:00
|
|
|
|
2015-06-22 16:16:01 -07:00
|
|
|
if (td->list_show || (td->result && td->result->dot && td->ad->dot_candidate))
|
2015-06-16 00:53:23 -07:00
|
|
|
candidate_list_show(td->ad);
|
2015-06-22 16:16:01 -07:00
|
|
|
td->ad->dot_candidate = EINA_FALSE;
|
2015-06-21 22:45:54 -07:00
|
|
|
free(td->utf8);
|
2015-06-15 21:28:59 -07:00
|
|
|
free(td);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
context_lexem_thread_cancel_cb(void *data, Ecore_Thread *thread EINA_UNUSED)
|
|
|
|
{
|
|
|
|
ctx_lexem_td *td = (ctx_lexem_td *)data;
|
|
|
|
|
2015-08-31 03:14:37 -07:00
|
|
|
td->ad->lexem_ptr = td->result;
|
2015-06-22 16:16:01 -07:00
|
|
|
if (td->list_show || (td->result && td->result->dot && td->ad->dot_candidate))
|
2015-06-16 00:53:23 -07:00
|
|
|
candidate_list_show(td->ad);
|
2015-06-23 22:06:32 -07:00
|
|
|
td->ad->cntx_lexem_thread = NULL;
|
2015-06-22 16:16:01 -07:00
|
|
|
td->ad->dot_candidate = EINA_FALSE;
|
2015-06-21 22:45:54 -07:00
|
|
|
free(td->utf8);
|
2015-06-15 21:28:59 -07:00
|
|
|
free(td);
|
|
|
|
}
|
|
|
|
|
2015-06-16 00:53:23 -07:00
|
|
|
static void
|
|
|
|
context_lexem_get(autocomp_data *ad, Evas_Object *entry, Eina_Bool list_show)
|
2015-06-15 21:28:59 -07:00
|
|
|
{
|
|
|
|
const char *text = elm_entry_entry_get(entry);
|
|
|
|
if (!text)
|
|
|
|
{
|
|
|
|
ad->lexem_ptr = (lexem *)ad->lexem_root;
|
|
|
|
return;
|
2015-06-08 08:35:16 -07:00
|
|
|
}
|
2015-06-23 22:06:32 -07:00
|
|
|
ecore_thread_cancel(ad->cntx_lexem_thread);
|
2015-06-15 21:28:59 -07:00
|
|
|
|
|
|
|
ctx_lexem_td *td = (ctx_lexem_td *)calloc(1, sizeof(ctx_lexem_td));
|
2015-06-21 22:45:54 -07:00
|
|
|
td->utf8 = elm_entry_markup_to_utf8(text);
|
2015-06-15 21:28:59 -07:00
|
|
|
td->cur_pos = elm_entry_cursor_pos_get(entry);
|
|
|
|
td->ad = ad;
|
|
|
|
td->result = NULL;
|
2015-06-16 00:53:23 -07:00
|
|
|
td->list_show = list_show;
|
2015-06-15 21:28:59 -07:00
|
|
|
|
|
|
|
ad->cntx_lexem_thread = ecore_thread_run(context_lexem_thread_cb,
|
|
|
|
context_lexem_thread_end_cb,
|
2015-06-23 22:06:32 -07:00
|
|
|
context_lexem_thread_cancel_cb,
|
|
|
|
td);
|
2015-06-08 08:35:16 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
context_changed(autocomp_data *ad, Evas_Object *edit)
|
|
|
|
{
|
|
|
|
if ((!ad->enabled) || (!ad->initialized)) return;
|
|
|
|
|
|
|
|
int cursor_position = elm_entry_cursor_pos_get(edit);
|
|
|
|
|
|
|
|
if (!cursor_position)
|
|
|
|
{
|
|
|
|
ad->lexem_ptr = (lexem *)ad->lexem_root;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-06-16 00:53:23 -07:00
|
|
|
context_lexem_get(ad, edit, EINA_FALSE);
|
2014-07-18 21:31:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
init_thread_end_cb(void *data, Ecore_Thread *thread EINA_UNUSED)
|
|
|
|
{
|
|
|
|
autocomp_data *ad = data;
|
|
|
|
ad->initialized = EINA_TRUE;
|
|
|
|
ad->init_thread = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
init_thread_cancel_cb(void *data, Ecore_Thread *thread EINA_UNUSED)
|
|
|
|
{
|
|
|
|
autocomp_data *ad = data;
|
|
|
|
ad->init_thread = NULL;
|
|
|
|
}
|
|
|
|
|
2015-08-26 08:58:01 -07:00
|
|
|
static void
|
|
|
|
anchor_keygrab_set(autocomp_data *ad, Eina_Bool grab)
|
|
|
|
{
|
|
|
|
Evas_Object *anchor = ad->anchor;
|
|
|
|
|
|
|
|
if (grab)
|
|
|
|
{
|
|
|
|
if (ad->on_keygrab) return;
|
|
|
|
if (!evas_object_key_grab(anchor, "BackSpace", 0, 0, EINA_TRUE))
|
|
|
|
EINA_LOG_ERR("Failed to grab key - BackSpace");
|
|
|
|
if (!evas_object_key_grab(anchor, "Return", 0, 0, EINA_TRUE))
|
|
|
|
EINA_LOG_ERR("Failed to grab key - Return");
|
|
|
|
if (!evas_object_key_grab(anchor, "Tab", 0, 0, EINA_TRUE))
|
|
|
|
EINA_LOG_ERR("Failed to grab key - Tab");
|
|
|
|
if (!evas_object_key_grab(anchor, "Up", 0, 0, EINA_TRUE))
|
|
|
|
EINA_LOG_ERR("Failed to grab key - Up");
|
|
|
|
if (!evas_object_key_grab(anchor, "Down", 0, 0, EINA_TRUE))
|
|
|
|
EINA_LOG_ERR("Failed to grab key - Down");
|
|
|
|
ad->on_keygrab = EINA_TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!ad->on_keygrab) return;
|
|
|
|
evas_object_key_ungrab(anchor, "BackSpace", 0, 0);
|
|
|
|
evas_object_key_ungrab(anchor, "Return", 0, 0);
|
|
|
|
evas_object_key_ungrab(anchor, "Tab", 0, 0);
|
|
|
|
evas_object_key_ungrab(anchor, "Up", 0, 0);
|
|
|
|
evas_object_key_ungrab(anchor, "Down", 0, 0);
|
|
|
|
ad->on_keygrab = EINA_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-18 21:31:08 -07:00
|
|
|
static void
|
|
|
|
entry_anchor_off(autocomp_data *ad)
|
|
|
|
{
|
2014-08-14 07:33:20 -07:00
|
|
|
if (ad->anchor_visible)
|
|
|
|
{
|
|
|
|
elm_object_tooltip_hide(ad->anchor);
|
|
|
|
/* Reset content_cb to have guarantee the callback call. If anchor is
|
|
|
|
changed faster than tooltip hide, the callback won't be called
|
|
|
|
since tooltip regards the content callback is same with before. */
|
|
|
|
elm_object_tooltip_content_cb_set(ad->anchor, NULL, NULL, NULL);
|
|
|
|
}
|
2015-08-26 08:58:01 -07:00
|
|
|
anchor_keygrab_set(ad, EINA_FALSE);
|
2014-07-18 21:31:08 -07:00
|
|
|
ad->anchor_visible = EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
2015-08-26 08:58:01 -07:00
|
|
|
|
2014-07-18 21:31:08 -07:00
|
|
|
static void
|
2015-06-22 18:11:03 -07:00
|
|
|
anchor_unfocused_cb(void *data, Evas_Object *obj EINA_UNUSED,
|
2014-07-18 21:31:08 -07:00
|
|
|
void *event_info EINA_UNUSED)
|
|
|
|
{
|
2015-06-22 18:11:03 -07:00
|
|
|
autocomp_data *ad = data;
|
|
|
|
if (!ad) return;
|
2014-07-18 21:31:08 -07:00
|
|
|
entry_anchor_off(ad);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
queue_reset(autocomp_data *ad)
|
|
|
|
{
|
2015-06-22 17:57:08 -07:00
|
|
|
if ((ad->queue_pos == 0) && (!ad->anchor_visible)) return;
|
2015-06-08 08:35:16 -07:00
|
|
|
ad->queue_pos = 0;
|
2014-07-18 21:31:08 -07:00
|
|
|
memset(ad->queue, 0x0, sizeof(ad->queue));
|
|
|
|
entry_anchor_off(ad);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
push_char(autocomp_data *ad, char c)
|
|
|
|
{
|
|
|
|
if (ad->queue_pos == QUEUE_SIZE)
|
|
|
|
{
|
|
|
|
memset(ad->queue, 0x0, sizeof(ad->queue));
|
|
|
|
ad->queue_pos = 0;
|
|
|
|
}
|
|
|
|
ad->queue[ad->queue_pos] = c;
|
|
|
|
|
2015-06-08 08:35:16 -07:00
|
|
|
ad->queue_pos++;
|
2014-07-18 21:31:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
pop_char(autocomp_data *ad, int cnt)
|
|
|
|
{
|
|
|
|
if (ad->queue_pos == -1) return;
|
|
|
|
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < cnt; i++)
|
|
|
|
{
|
|
|
|
ad->queue[ad->queue_pos] = 0x0;
|
2015-06-08 08:35:16 -07:00
|
|
|
if (ad->queue_pos == 0) break;
|
2014-07-18 21:31:08 -07:00
|
|
|
ad->queue_pos--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
insert_completed_text(autocomp_data *ad)
|
|
|
|
{
|
2015-06-08 08:35:16 -07:00
|
|
|
if (!ad->lexem_ptr) return;
|
2014-07-18 21:31:08 -07:00
|
|
|
Elm_Object_Item *it = elm_list_selected_item_get(ad->list);
|
|
|
|
|
2015-06-08 08:35:16 -07:00
|
|
|
lexem *candidate = elm_object_item_data_get(it);
|
|
|
|
char **txt = candidate->txt;
|
2014-07-18 21:31:08 -07:00
|
|
|
Evas_Object *entry = edit_entry_get(ad->ed);
|
|
|
|
|
|
|
|
int space = edit_cur_indent_depth_get(ad->ed);
|
2014-08-02 00:41:24 -07:00
|
|
|
int cursor_pos = elm_entry_cursor_pos_get(entry);
|
2014-07-18 21:31:08 -07:00
|
|
|
|
|
|
|
//Insert the first line.
|
2015-07-02 19:49:11 -07:00
|
|
|
const char *first_line = eina_stringshare_printf(txt[0], elm_object_item_part_text_get(it, NULL));
|
|
|
|
elm_entry_entry_insert(entry, first_line + (ad->queue_pos));
|
|
|
|
eina_stringshare_del(first_line);
|
2014-07-18 21:31:08 -07:00
|
|
|
|
|
|
|
//Insert last lines
|
2015-06-08 08:35:16 -07:00
|
|
|
if (candidate->txt_count > 1)
|
2014-07-18 21:31:08 -07:00
|
|
|
{
|
|
|
|
//Alloc Empty spaces
|
|
|
|
char *p = alloca(space + 1);
|
|
|
|
memset(p, ' ', space);
|
|
|
|
p[space] = '\0';
|
|
|
|
|
|
|
|
int i;
|
2015-06-08 08:35:16 -07:00
|
|
|
for (i = 1; i < (candidate->txt_count - 1); i++)
|
2014-07-18 21:31:08 -07:00
|
|
|
{
|
|
|
|
elm_entry_entry_insert(entry, p);
|
|
|
|
elm_entry_entry_insert(entry, txt[i]);
|
|
|
|
}
|
|
|
|
elm_entry_entry_insert(entry, p);
|
|
|
|
elm_entry_entry_insert(entry, txt[i]);
|
|
|
|
}
|
|
|
|
|
2014-08-02 00:41:24 -07:00
|
|
|
int cursor_pos2 = elm_entry_cursor_pos_get(entry);
|
|
|
|
redoundo_data *rd = evas_object_data_get(entry, "redoundo");
|
|
|
|
redoundo_entry_region_push(rd, cursor_pos, cursor_pos2);
|
2014-08-01 21:45:47 -07:00
|
|
|
|
2015-06-16 00:53:23 -07:00
|
|
|
entry_anchor_off(ad);
|
|
|
|
|
2015-06-08 08:35:16 -07:00
|
|
|
cursor_pos2 -= (candidate->cursor_offset + (candidate->line_back * space));
|
2014-08-02 00:41:24 -07:00
|
|
|
elm_entry_cursor_pos_set(entry, cursor_pos2);
|
2015-06-08 08:35:16 -07:00
|
|
|
edit_line_increase(ad->ed, (candidate->txt_count - 1));
|
2014-07-18 21:31:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
list_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
|
|
|
|
void *event_info EINA_UNUSED)
|
|
|
|
{
|
|
|
|
autocomp_data *ad = data;
|
|
|
|
ad->list = NULL;
|
|
|
|
}
|
|
|
|
|
2015-07-02 19:49:11 -07:00
|
|
|
|
|
|
|
static int
|
|
|
|
list_item_compare(const void *data1, const void *data2)
|
|
|
|
{
|
|
|
|
Elm_Object_Item *it1 = (Elm_Object_Item *) data1;
|
|
|
|
Elm_Object_Item *it2 = (Elm_Object_Item *) data2;
|
|
|
|
const char *name1 = NULL, *name2 = NULL;
|
|
|
|
if (!it1) return -1;
|
|
|
|
if (!it2) return 1;
|
|
|
|
|
|
|
|
name1 = elm_object_item_part_text_get(it1, NULL);
|
|
|
|
if (!name1) return -1;
|
|
|
|
name2 = elm_object_item_part_text_get(it2, NULL);
|
|
|
|
if (!name2) return 1;
|
|
|
|
|
|
|
|
return strcmp(name1, name2);
|
|
|
|
}
|
|
|
|
|
2014-07-18 21:31:08 -07:00
|
|
|
static Evas_Object *
|
|
|
|
entry_tooltip_content_cb(void *data, Evas_Object *obj EINA_UNUSED,
|
|
|
|
Evas_Object *tt EINA_UNUSED)
|
|
|
|
{
|
|
|
|
autocomp_data *ad = data;
|
2015-06-08 08:35:16 -07:00
|
|
|
Eina_Bool found = EINA_FALSE;
|
|
|
|
|
|
|
|
if (!ad->lexem_ptr) return NULL;
|
2014-07-18 21:31:08 -07:00
|
|
|
|
|
|
|
ad->list = elm_list_add(obj);
|
|
|
|
elm_object_focus_allow_set(ad->list, EINA_FALSE);
|
|
|
|
elm_list_mode_set(ad->list, ELM_LIST_EXPAND);
|
|
|
|
|
2015-06-22 17:57:08 -07:00
|
|
|
//compute list size to prevent over-sizing than enventor window.
|
|
|
|
Evas_Coord y, y2, h;
|
|
|
|
evas_object_geometry_get(edit_obj_get(ad->ed), NULL, &y, NULL, &h);
|
|
|
|
evas_object_geometry_get(ad->anchor, NULL, &y2, NULL, NULL);
|
|
|
|
Elm_Tooltip_Orient tooltip_orient =
|
|
|
|
elm_object_tooltip_orient_get(ad->anchor);
|
|
|
|
Evas_Coord mh;
|
|
|
|
if (tooltip_orient == ELM_TOOLTIP_ORIENT_BOTTOM) mh = (h - y2);
|
|
|
|
else mh = (y2 - y);
|
|
|
|
evas_object_size_hint_max_set(ad->list, 999999, mh);
|
|
|
|
|
|
|
|
//add keywords
|
2014-07-18 21:31:08 -07:00
|
|
|
Eina_List *l;
|
2015-06-08 08:35:16 -07:00
|
|
|
lexem *lexem_data;
|
2015-07-02 19:49:11 -07:00
|
|
|
int k = 0;
|
2015-06-08 08:35:16 -07:00
|
|
|
EINA_LIST_FOREACH(ad->lexem_ptr->nodes, l, lexem_data)
|
|
|
|
{
|
2015-07-02 19:49:11 -07:00
|
|
|
for (k = 0; k < lexem_data->name_count; k++)
|
|
|
|
if (!strncmp(lexem_data->name[k], ad->queue, ad->queue_pos))
|
2015-06-08 08:35:16 -07:00
|
|
|
{
|
2015-07-02 19:49:11 -07:00
|
|
|
elm_list_item_sorted_insert(ad->list, lexem_data->name[k],
|
|
|
|
NULL, NULL, NULL, lexem_data,
|
|
|
|
list_item_compare);
|
2015-06-08 08:35:16 -07:00
|
|
|
found = EINA_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-21 22:05:27 -07:00
|
|
|
//select first item in default.
|
|
|
|
Elm_Object_Item *it = elm_list_first_item_get(ad->list);
|
|
|
|
if (it) elm_list_item_selected_set(it, EINA_TRUE);
|
|
|
|
|
2014-07-18 21:31:08 -07:00
|
|
|
evas_object_event_callback_add(ad->list, EVAS_CALLBACK_DEL, list_del_cb, ad);
|
2015-06-08 08:35:16 -07:00
|
|
|
if (!found)
|
|
|
|
{
|
|
|
|
entry_anchor_off(ad);
|
|
|
|
return NULL;
|
|
|
|
}
|
2014-07-18 21:31:08 -07:00
|
|
|
elm_list_go(ad->list);
|
|
|
|
evas_object_show(ad->list);
|
|
|
|
|
|
|
|
return ad->list;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
anchor_list_update(autocomp_data *ad)
|
|
|
|
{
|
2015-06-08 08:35:16 -07:00
|
|
|
lexem *data;
|
|
|
|
Eina_List *l;
|
2014-07-18 21:31:08 -07:00
|
|
|
Elm_Object_Item *it;
|
2015-06-08 08:35:16 -07:00
|
|
|
Eina_Bool found = EINA_FALSE;
|
2014-07-18 21:31:08 -07:00
|
|
|
|
2015-06-08 08:35:16 -07:00
|
|
|
elm_list_clear(ad->list);
|
2014-07-18 21:31:08 -07:00
|
|
|
//Append new candidates
|
2015-07-02 19:49:11 -07:00
|
|
|
int k = 0;
|
2015-06-08 08:35:16 -07:00
|
|
|
EINA_LIST_FOREACH(ad->lexem_ptr->nodes, l, data)
|
|
|
|
{
|
2015-07-02 19:49:11 -07:00
|
|
|
for (k = 0; k < data->name_count; k++)
|
|
|
|
if (!strncmp(data->name[k], ad->queue, ad->queue_pos))
|
|
|
|
{
|
|
|
|
elm_list_item_sorted_insert(ad->list, data->name[k],
|
|
|
|
NULL, NULL, NULL, data, list_item_compare);
|
|
|
|
found = EINA_TRUE;
|
|
|
|
}
|
2015-06-08 08:35:16 -07:00
|
|
|
}
|
|
|
|
if (!found)
|
2014-07-18 21:31:08 -07:00
|
|
|
{
|
2015-06-08 08:35:16 -07:00
|
|
|
entry_anchor_off(ad);
|
|
|
|
return;
|
2014-07-18 21:31:08 -07:00
|
|
|
}
|
|
|
|
it = elm_list_first_item_get(ad->list);
|
|
|
|
elm_list_item_selected_set(it, EINA_TRUE);
|
|
|
|
elm_list_go(ad->list);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
candidate_list_show(autocomp_data *ad)
|
|
|
|
{
|
2015-06-08 08:35:16 -07:00
|
|
|
if (!ad->lexem_ptr)
|
2014-07-18 21:31:08 -07:00
|
|
|
{
|
|
|
|
entry_anchor_off(ad);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Evas_Object *entry = edit_entry_get(ad->ed);
|
|
|
|
|
|
|
|
//Update anchor position
|
|
|
|
Evas_Coord x, y, h;
|
|
|
|
Evas_Coord cx, cy, cw, ch;
|
|
|
|
evas_object_geometry_get(entry, &x, &y, NULL, NULL);
|
|
|
|
elm_entry_cursor_geometry_get(entry, &cx, &cy, &cw, &ch);
|
|
|
|
evas_object_move(ad->anchor, cx + x, cy + y);
|
|
|
|
evas_object_resize(ad->anchor, cw, ch);
|
|
|
|
|
|
|
|
//Show the tooltip
|
|
|
|
if (!ad->anchor_visible)
|
|
|
|
{
|
|
|
|
//Decide the Tooltip direction
|
|
|
|
Elm_Tooltip_Orient tooltip_orient = ELM_TOOLTIP_ORIENT_BOTTOM;
|
2014-09-30 07:56:16 -07:00
|
|
|
evas_object_geometry_get(edit_obj_get(ad->ed), NULL, NULL, NULL, &h);
|
2014-07-18 21:31:08 -07:00
|
|
|
if ((cy + y) > (h / 2)) tooltip_orient = ELM_TOOLTIP_ORIENT_TOP;
|
|
|
|
|
|
|
|
//Tooltip set
|
|
|
|
elm_object_tooltip_content_cb_set(ad->anchor,
|
|
|
|
entry_tooltip_content_cb, ad, NULL);
|
|
|
|
elm_object_tooltip_orient_set(ad->anchor, tooltip_orient);
|
|
|
|
elm_object_tooltip_show(ad->anchor);
|
2015-08-26 08:58:01 -07:00
|
|
|
anchor_keygrab_set(ad, EINA_TRUE);
|
2014-07-18 21:31:08 -07:00
|
|
|
ad->anchor_visible = EINA_TRUE;
|
|
|
|
}
|
|
|
|
//Already tooltip is visible, just update the list item
|
|
|
|
else anchor_list_update(ad);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2015-06-22 18:11:03 -07:00
|
|
|
entry_changed_cb(void *data, Evas_Object *obj EINA_UNUSED,
|
2014-11-01 04:03:39 -07:00
|
|
|
void *event_info)
|
2014-07-18 21:31:08 -07:00
|
|
|
{
|
2015-06-22 18:11:03 -07:00
|
|
|
autocomp_data *ad = data;
|
|
|
|
if ((!ad) || (!ad->enabled)) return;
|
2014-11-01 04:03:39 -07:00
|
|
|
|
2014-07-18 21:31:08 -07:00
|
|
|
Elm_Entry_Change_Info *info = event_info;
|
|
|
|
|
|
|
|
if (info->insert)
|
|
|
|
{
|
|
|
|
if ((strlen(info->change.insert.content) > 1) ||
|
|
|
|
(info->change.insert.content[0] == ' ') ||
|
|
|
|
(info->change.insert.content[0] == '.'))
|
|
|
|
{
|
2015-06-16 00:53:23 -07:00
|
|
|
if (info->change.insert.content[0] == '.' && ad->queue_pos > 2)
|
|
|
|
{
|
2015-06-22 16:16:01 -07:00
|
|
|
ad->dot_candidate = EINA_TRUE;
|
|
|
|
context_lexem_get(ad, obj, EINA_FALSE);
|
2015-06-16 00:53:23 -07:00
|
|
|
}
|
2014-07-18 21:31:08 -07:00
|
|
|
queue_reset(ad);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
push_char(ad, info->change.insert.content[0]);
|
|
|
|
candidate_list_show(ad);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (info->change.del.content[0] != ' ')
|
|
|
|
{
|
|
|
|
entry_anchor_off(ad);
|
|
|
|
int cnt = abs(info->change.del.end - info->change.del.start);
|
|
|
|
pop_char(ad, cnt);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2015-06-22 18:11:03 -07:00
|
|
|
entry_cursor_changed_manual_cb(void *data,
|
2014-11-01 04:03:39 -07:00
|
|
|
Evas_Object *obj EINA_UNUSED,
|
2014-07-18 21:31:08 -07:00
|
|
|
void *event_info EINA_UNUSED)
|
|
|
|
{
|
2015-06-22 18:11:03 -07:00
|
|
|
autocomp_data *ad = data;
|
|
|
|
if (!ad) return;
|
2015-06-22 17:57:08 -07:00
|
|
|
if (ad->anchor_visible) entry_anchor_off(ad);
|
2014-07-18 21:31:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2015-06-22 18:11:03 -07:00
|
|
|
entry_cursor_changed_cb(void *data, Evas_Object *obj,
|
2014-07-18 21:31:08 -07:00
|
|
|
void *event_info EINA_UNUSED)
|
|
|
|
{
|
2015-06-22 18:11:03 -07:00
|
|
|
autocomp_data *ad = data;
|
|
|
|
if (!ad) return;
|
2014-07-18 21:31:08 -07:00
|
|
|
|
|
|
|
//Update anchor position
|
|
|
|
Evas_Coord x, y, cx, cy, cw, ch;
|
|
|
|
evas_object_geometry_get(obj, &x, &y, NULL, NULL);
|
|
|
|
elm_entry_cursor_geometry_get(obj, &cx, &cy, &cw, &ch);
|
|
|
|
evas_object_move(ad->anchor, cx + x, cy + y);
|
|
|
|
evas_object_resize(ad->anchor, cw, ch);
|
2015-06-08 08:35:16 -07:00
|
|
|
context_changed(ad, edit_entry_get(ad->ed));
|
2014-07-18 21:31:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2015-06-22 18:11:03 -07:00
|
|
|
entry_press_cb(void *data, Evas_Object *obj EINA_UNUSED,
|
2014-07-18 21:31:08 -07:00
|
|
|
void *event_info EINA_UNUSED)
|
|
|
|
{
|
2015-06-22 18:11:03 -07:00
|
|
|
autocomp_data *ad = data;
|
|
|
|
if (!ad) return;
|
2015-06-22 17:57:08 -07:00
|
|
|
if (ad->anchor_visible) entry_anchor_off(ad);
|
2014-07-18 21:31:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2015-06-22 18:11:03 -07:00
|
|
|
entry_move_cb(void *data, Evas *e EINA_UNUSED,
|
2014-11-01 04:03:39 -07:00
|
|
|
Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
|
2014-07-18 21:31:08 -07:00
|
|
|
{
|
2015-06-22 18:11:03 -07:00
|
|
|
autocomp_data *ad = data;
|
|
|
|
if (!ad) return;
|
2015-06-22 17:57:08 -07:00
|
|
|
if (ad->anchor_visible) entry_anchor_off(ad);
|
2014-07-18 21:31:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
list_item_move(autocomp_data *ad, Eina_Bool up)
|
|
|
|
{
|
|
|
|
Evas_Object *entry = edit_entry_get(ad->ed);
|
|
|
|
evas_object_smart_callback_del(entry, "unfocused", anchor_unfocused_cb);
|
|
|
|
|
|
|
|
Elm_Object_Item *it = elm_list_selected_item_get(ad->list);
|
|
|
|
if (up) it = elm_list_item_prev(it);
|
|
|
|
else it = elm_list_item_next(it);
|
|
|
|
if (it) elm_list_item_selected_set(it, EINA_TRUE);
|
|
|
|
|
2014-11-01 04:03:39 -07:00
|
|
|
evas_object_smart_callback_add(entry, "unfocused", anchor_unfocused_cb,
|
2015-06-22 18:11:03 -07:00
|
|
|
ad);
|
2014-07-18 21:31:08 -07:00
|
|
|
}
|
|
|
|
|
2015-08-26 08:58:01 -07:00
|
|
|
static void
|
|
|
|
anchor_key_down_cb(void *data, Evas *evas EINA_UNUSED,
|
|
|
|
Evas_Object *obj EINA_UNUSED, void *event_info)
|
|
|
|
{
|
|
|
|
autocomp_data *ad = data;
|
|
|
|
if (!ad->anchor_visible) return;
|
|
|
|
|
|
|
|
Evas_Event_Key_Down *ev = event_info;
|
|
|
|
|
|
|
|
//Cancel the auto complete.
|
2015-08-26 11:49:33 -07:00
|
|
|
if (!strcmp(ev->key, "BackSpace"))
|
2015-08-26 08:58:01 -07:00
|
|
|
{
|
|
|
|
queue_reset(ad);
|
|
|
|
ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
|
|
|
|
return;
|
|
|
|
}
|
2015-08-26 11:49:33 -07:00
|
|
|
if (!strcmp(ev->key, "Return") || !strcmp(ev->key, "Tab"))
|
2015-08-26 08:58:01 -07:00
|
|
|
{
|
|
|
|
insert_completed_text(ad);
|
|
|
|
queue_reset(ad);
|
|
|
|
edit_syntax_color_partial_apply(ad->ed, -1);
|
|
|
|
ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
|
|
|
|
return;
|
|
|
|
}
|
2015-08-26 11:49:33 -07:00
|
|
|
if (!strcmp(ev->key, "Up"))
|
2015-08-26 08:58:01 -07:00
|
|
|
{
|
|
|
|
list_item_move(ad, EINA_TRUE);
|
|
|
|
ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
|
|
|
|
return;
|
|
|
|
}
|
2015-08-26 11:49:33 -07:00
|
|
|
if (!strcmp(ev->key, "Down"))
|
2015-08-26 08:58:01 -07:00
|
|
|
{
|
|
|
|
list_item_move(ad, EINA_FALSE);
|
|
|
|
ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-30 07:56:16 -07:00
|
|
|
/*****************************************************************************/
|
|
|
|
/* Externally accessible calls */
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
2015-06-21 22:34:52 -07:00
|
|
|
void
|
|
|
|
autocomp_list_show(void)
|
|
|
|
{
|
|
|
|
Evas_Object *entry;
|
|
|
|
autocomp_data *ad = g_ad;
|
|
|
|
if (!g_ad || !g_ad->enabled) return;
|
|
|
|
|
|
|
|
entry = edit_entry_get(ad->ed);
|
|
|
|
context_lexem_get(ad, entry, EINA_TRUE);
|
|
|
|
}
|
|
|
|
|
2015-06-22 18:21:22 -07:00
|
|
|
void
|
|
|
|
autocomp_reset(void)
|
|
|
|
{
|
|
|
|
autocomp_data *ad = g_ad;
|
|
|
|
if (!ad) return;
|
|
|
|
queue_reset(ad);
|
|
|
|
}
|
|
|
|
|
2014-07-18 21:31:08 -07:00
|
|
|
void
|
|
|
|
autocomp_target_set(edit_data *ed)
|
|
|
|
{
|
|
|
|
autocomp_data *ad = g_ad;
|
|
|
|
Evas_Object *entry;
|
|
|
|
|
|
|
|
queue_reset(ad);
|
|
|
|
|
|
|
|
//Unset previous target
|
|
|
|
if (ad->ed)
|
|
|
|
{
|
|
|
|
entry = edit_entry_get(ad->ed);
|
|
|
|
evas_object_smart_callback_del(entry, "changed,user", entry_changed_cb);
|
|
|
|
evas_object_smart_callback_del(entry, "cursor,changed",
|
|
|
|
entry_cursor_changed_cb);
|
|
|
|
evas_object_smart_callback_del(entry, "cursor,changed,manual",
|
|
|
|
entry_cursor_changed_manual_cb);
|
|
|
|
evas_object_smart_callback_del(entry, "unfocused", anchor_unfocused_cb);
|
|
|
|
evas_object_smart_callback_del(entry, "press", entry_press_cb);
|
|
|
|
evas_object_event_callback_del(entry, EVAS_CALLBACK_MOVE,
|
|
|
|
entry_move_cb);
|
2014-09-30 07:56:16 -07:00
|
|
|
evas_object_del(ad->anchor);
|
|
|
|
ad->anchor = NULL;
|
2014-07-18 21:31:08 -07:00
|
|
|
ad->ed = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ed) return;
|
|
|
|
|
|
|
|
entry = edit_entry_get(ed);
|
2015-06-22 18:11:03 -07:00
|
|
|
evas_object_smart_callback_add(entry, "changed,user", entry_changed_cb, ad);
|
2014-07-18 21:31:08 -07:00
|
|
|
evas_object_smart_callback_add(entry, "cursor,changed,manual",
|
2015-06-22 18:11:03 -07:00
|
|
|
entry_cursor_changed_manual_cb, ad);
|
2014-07-18 21:31:08 -07:00
|
|
|
evas_object_smart_callback_add(entry, "cursor,changed",
|
2015-06-22 18:11:03 -07:00
|
|
|
entry_cursor_changed_cb, ad);
|
|
|
|
evas_object_smart_callback_add(entry, "unfocused", anchor_unfocused_cb, ad);
|
|
|
|
evas_object_smart_callback_add(entry, "press", entry_press_cb, ad);
|
|
|
|
evas_object_event_callback_add(entry, EVAS_CALLBACK_MOVE, entry_move_cb, ad);
|
2014-09-30 07:56:16 -07:00
|
|
|
|
|
|
|
ad->anchor = elm_button_add(edit_obj_get(ed));
|
2015-08-26 08:58:01 -07:00
|
|
|
evas_object_event_callback_add(ad->anchor, EVAS_CALLBACK_KEY_DOWN,
|
|
|
|
anchor_key_down_cb, ad);
|
2014-07-18 21:31:08 -07:00
|
|
|
ad->ed = ed;
|
|
|
|
}
|
|
|
|
|
2014-09-30 07:56:16 -07:00
|
|
|
Eina_Bool
|
|
|
|
autocomp_event_dispatch(const char *key)
|
|
|
|
{
|
|
|
|
autocomp_data *ad = g_ad;
|
2014-10-31 06:02:08 -07:00
|
|
|
if (!ad) return EINA_FALSE;
|
2015-08-26 08:58:01 -07:00
|
|
|
if (ad->anchor_visible) return EINA_FALSE;
|
2014-10-31 06:02:08 -07:00
|
|
|
|
|
|
|
//Reset queue.
|
2015-08-26 08:58:01 -07:00
|
|
|
if (!strcmp(key, "Up") || !strcmp(key, "Down") ||
|
|
|
|
!strcmp(key, "Left") || !strcmp(key, "Right"))
|
|
|
|
queue_reset(ad);
|
2014-09-30 07:56:16 -07:00
|
|
|
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
2014-07-18 21:31:08 -07:00
|
|
|
|
|
|
|
void
|
2014-09-30 07:56:16 -07:00
|
|
|
autocomp_init(void)
|
2014-07-18 21:31:08 -07:00
|
|
|
{
|
|
|
|
autocomp_data *ad = calloc(1, sizeof(autocomp_data));
|
2014-07-27 21:40:58 -07:00
|
|
|
if (!ad)
|
|
|
|
{
|
|
|
|
EINA_LOG_ERR("Failed to allocate Memory!");
|
|
|
|
return;
|
|
|
|
}
|
2014-09-30 07:56:16 -07:00
|
|
|
|
2014-07-18 21:31:08 -07:00
|
|
|
ad->init_thread = ecore_thread_run(init_thread_cb, init_thread_end_cb,
|
|
|
|
init_thread_cancel_cb, ad);
|
2015-06-08 08:35:16 -07:00
|
|
|
ad->queue_pos = 0;
|
2014-07-18 21:31:08 -07:00
|
|
|
g_ad = ad;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-08-04 23:32:12 -07:00
|
|
|
autocomp_term(void)
|
2014-07-18 21:31:08 -07:00
|
|
|
{
|
|
|
|
autocomp_data *ad = g_ad;
|
|
|
|
evas_object_del(ad->anchor);
|
|
|
|
ecore_thread_cancel(ad->init_thread);
|
|
|
|
|
2015-06-21 22:51:18 -07:00
|
|
|
lexem_tree_free((lexem **)&ad->lexem_root);
|
|
|
|
|
2015-06-08 08:35:16 -07:00
|
|
|
eet_data_descriptor_free(lex_desc);
|
|
|
|
eet_close(ad->source_file);
|
2014-07-18 21:31:08 -07:00
|
|
|
|
|
|
|
free(ad);
|
|
|
|
g_ad = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-09-30 07:56:16 -07:00
|
|
|
autocomp_enabled_set(Eina_Bool enabled)
|
2014-07-18 21:31:08 -07:00
|
|
|
{
|
2014-09-30 07:56:16 -07:00
|
|
|
autocomp_data *ad = g_ad;
|
|
|
|
enabled = !!enabled;
|
|
|
|
ad->enabled = enabled;
|
2014-07-18 21:31:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
Eina_Bool
|
2014-09-30 07:56:16 -07:00
|
|
|
autocomp_enabled_get(void)
|
2014-07-18 21:31:08 -07:00
|
|
|
{
|
|
|
|
autocomp_data *ad = g_ad;
|
2014-09-30 07:56:16 -07:00
|
|
|
return ad->enabled;
|
2014-07-18 21:31:08 -07:00
|
|
|
}
|