/* A utility function to delete a range of text from the editable object. * It doesn't update the position of the cursor, nor the selection... */ static int _e_editable_text_delete(Evas_Object *editable, int start, int end) { E_Editable_Smart_Data *sd; int start_id = 0, end_id = 0, i = 0; if ((!editable) || (!(sd = evas_object_smart_data_get(editable)))) return 0; start = E_CLAMP(start, 0, sd->unicode_length); end = E_CLAMP(end, 0, sd->unicode_length); if (end <= start) return 0; for (i = 0; i < end; i++) { end_id = evas_string_char_next_get(sd->text, end_id, NULL); if (i < start) start_id = end_id; } if (end_id <= start_id) return 0; memmove(&sd->text[start_id], &sd->text[end_id], sd->char_length - end_id); sd->char_length -= (end_id - start_id); sd->unicode_length -= (end - start); sd->text[sd->char_length] = '\0'; _e_editable_text_update(editable); return (end - start); }
/** * Gets a range of the text of the editable object, from position @a start to * position @a end * * @param editable an editable object * @param start the start position of the text range to get * @param end the end position of the text range to get * @return Returns the range of text. The returned string will have to be freed */ EAPI char * e_editable_text_range_get(Evas_Object *editable, int start, int end) { E_Editable_Smart_Data *sd; char *range; int start_id = 0, end_id = 0, i; if (evas_object_smart_smart_get(editable) != _e_editable_smart) SMARTERR(NULL); if ((!editable) || (!(sd = evas_object_smart_data_get(editable)))) return NULL; start = E_CLAMP(start, 0, sd->unicode_length); end = E_CLAMP(end, 0, sd->unicode_length); if (end <= start) return NULL; for (i = 0; i < end; i++) { end_id = evas_string_char_next_get(sd->text, end_id, NULL); if (i < start) start_id = end_id; } if (end_id <= start_id) return NULL; range = malloc((end_id - start_id + 1) * sizeof(char)); strncpy(range, &sd->text[start_id], end_id - start_id); range[end_id - start_id] = '\0'; return range; }
/** * Selects the word at the provided character index */ EAPI void e_editable_select_word(Evas_Object *editable, int index) { E_Editable_Smart_Data *sd; int spos = 0, epos = -1, i = 0, pos = 0; if (evas_object_smart_smart_get(editable) != _e_editable_smart) SMARTERRNR(); if ((!editable) || (!(sd = evas_object_smart_data_get(editable)))) return; if ((index < 0) || (index >= sd->unicode_length)) return; while (i < sd->char_length) { if (sd->text[i] == ' ') { if (pos < index) spos = pos + 1; else if (pos > index) { epos = pos; break; } } i = evas_string_char_next_get(sd->text, i, NULL); pos++; } if (epos == -1) epos = pos; e_editable_selection_pos_set(editable, spos); e_editable_cursor_pos_set(editable, epos); }
static void _ekbd_send_x_string_press(const char *str, Ekbd_Mod mod) { char *string = (char*)str; char *key; int glyph = 0; /* First keysym is 'quotedbl' */ string += evas_string_char_next_get(string, 0, &glyph); key = (char*) _glyph_to_keysym(glyph); while(key) { if(strcmp(key,"quotedbl")) _ekbd_send_x_keysym_press(key, mod); glyph = 0; /* utf8 -> glyph id (unicode - ucs4) */ string += evas_string_char_next_get(string, 0, &glyph); key = (char*) _glyph_to_keysym(glyph); } }
/** * Gets the cursor position at the coords ( @a x, @a y ). It's used to know * where to place the cursor or the selection bound on mouse evevents. * * @param editable an editable object * @param x the x coord, relative to the editable object * @param y the y coord, relative to the editable object * @return Returns the position where to place the cursor according to the * given coords */ EAPI int e_editable_pos_get_from_coords(Evas_Object *editable, Evas_Coord x, Evas_Coord y) { E_Editable_Smart_Data *sd; const Evas_Object *text_obj; Evas_Coord ox, oy; Evas_Coord tx, ty, tw, th; Evas_Coord cx, cw; Evas_Coord canvas_x, canvas_y; int index, pos, i, j; const char *text; if (evas_object_smart_smart_get(editable) != _e_editable_smart) SMARTERR(0); if ((!editable) || (!(sd = evas_object_smart_data_get(editable)))) return 0; if (!(text_obj = edje_object_part_object_get(sd->text_object, "e.text.text"))) return 0; evas_object_geometry_get(editable, &ox, &oy, NULL, NULL); evas_object_geometry_get(text_obj, &tx, &ty, &tw, &th); canvas_x = ox + x; canvas_y = oy + y; if ((canvas_y < ty) || (canvas_x < tx)) pos = 0; else if ((canvas_y > (ty + th)) || (canvas_x > (tx + tw))) pos = sd->unicode_length; else { index = evas_object_text_char_coords_get(text_obj, canvas_x - tx, canvas_y - ty, &cx, NULL, &cw, NULL); text = evas_object_text_text_get(text_obj); if ((index >= 0) && (text)) { if ((canvas_x - tx) > (cx + (cw / 2))) index++; i = 0; j = -1; pos = 0; while ((i < index) && (j != i)) { pos++; j = i; i = evas_string_char_next_get(text, i, NULL); } if (pos > sd->unicode_length) pos = sd->unicode_length; } else pos = 0; } return pos; }
/* Gets the geometry of the char according to its utf-8 pos */ static int _e_editable_char_geometry_get_from_pos(Evas_Object *editable, int utf_pos, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch) { E_Editable_Smart_Data *sd; const Evas_Object *text_obj; const char *text; Evas_Coord x, w; int index = 0, i, last_pos, ret; if (cx) *cx = 0; if (cy) *cy = 0; if (cw) *cw = 0; if (ch) *ch = 0; if ((!editable) || (!(sd = evas_object_smart_data_get(editable)))) return 0; if (!(text_obj = edje_object_part_object_get(sd->text_object, "e.text.text"))) return 0; text = evas_object_text_text_get(text_obj); if ((!text) || (sd->unicode_length <= 0) || (utf_pos <= 0)) { e_editable_char_size_get(editable, cw, ch); return 1; } else { if (utf_pos >= sd->unicode_length) { utf_pos = sd->unicode_length - 1; last_pos = 1; } else last_pos = 0; for (i = 0; i < utf_pos; i++) index = evas_string_char_next_get(text, index, NULL); ret = evas_object_text_char_pos_get(text_obj, index, &x, cy, &w, ch); if (cx) *cx = x - 1 + (last_pos ? w : 0); if (cw) *cw = last_pos ? 1 : w; return ret; } }
/* callbacks */ static void _enscribi_input_frame_cb_matches(void *data, Evas_Object *obj, const char *emission, const char *source) { Match *match; Eina_List *matches, *l; int i; Edje_Message_String_Set *msg; Edje_Message_Int_Set *msg2; Smart_Data *sd; sd = data; matches = enscribi_canvas_matches_get(sd->canvas); if (!matches) return; msg = calloc(1, sizeof(Edje_Message_String_Set) + ((9-1) * sizeof(char *))); msg->count = 9; msg2 = calloc(1, sizeof(Edje_Message_String_Set) + ((9-1) * sizeof(int))); msg2->count = 9; for (i = 0; i < 8; i++) { l = eina_list_nth_list(matches, i); match = l->data; msg->str[i] = match->str; // Get and send the unicode value of the glyph as well int glyph; evas_string_char_next_get(match->str, 0, &(glyph)); msg2->val[i] = glyph; printf("%s\t(%d)\n", msg->str[i], msg2->val[i]); } msg->str[8] = ""; // Why do we have to set a 9th element to not get scrap in 8th? msg2->val[8] = 0; edje_object_message_send(obj, EDJE_MESSAGE_STRING_SET, 1, msg); edje_object_message_send(obj, EDJE_MESSAGE_INT_SET, 1, msg2); free(msg); free(msg2); }
END_TEST /* Tests for functions that are in evas_object_text.c but * don't really have anything to do with it. */ START_TEST(evas_text_unrelated) { START_TEXT_TEST(); const char *buf = "נסיון"; int pos; int value; /* Actually, they are tested in eina, just doing it for completeness. */ fail_if(evas_string_char_len_get(buf) != 5); pos = 0; fail_if(2 != evas_string_char_next_get(buf, pos, &value)); fail_if(value != 1504); pos = 2; fail_if(0 != evas_string_char_prev_get(buf, pos, &value)); fail_if(value != 1505); END_TEXT_TEST(); }
/* A utility function to insert some text inside the editable object. * It doesn't update the position of the cursor, nor the selection... */ static int _e_editable_text_insert(Evas_Object *editable, int pos, const char *text) { E_Editable_Smart_Data *sd; int char_length = -1, unicode_length = -1; int prev_char_length, new_char_length, new_unicode_length; int index = 0, i = 0; if ((!editable) || (!(sd = evas_object_smart_data_get(editable)))) return 0; if ((!text) || (*text == '\0')) return 0; if (pos < 0) pos = 0; else if (pos > sd->unicode_length) pos = sd->unicode_length; for (i = 0; i != char_length; i = evas_string_char_next_get(text, i, NULL)) { char_length = i; unicode_length++; } for (i = 0; i < pos; i++) index = evas_string_char_next_get(sd->text, index, NULL); if ((unicode_length <= 0) || (char_length <= 0)) return 0; prev_char_length = sd->char_length; new_char_length = sd->char_length + char_length; new_unicode_length = sd->unicode_length + unicode_length; if (new_char_length > sd->allocated_length) { int new_allocated_length = E_EDITABLE_SIZE_TO_ALLOC(new_char_length); char *old = sd->text; if (sd->password_mode) { /* security -- copy contents into new buffer, and overwrite old contents */ sd->text = malloc(new_allocated_length + 1); if (!sd->text) { sd->text = old; return 0; } if (old) { memcpy(sd->text, old, prev_char_length + 1); memset(old, 0, prev_char_length); free(old); } } else { sd->text = realloc(sd->text, new_allocated_length + 1); if (!sd->text) { sd->text = old; return 0; } } sd->allocated_length = new_allocated_length; } sd->unicode_length = new_unicode_length; sd->char_length = new_char_length; if (prev_char_length > index) memmove(&sd->text[index + char_length], &sd->text[index], prev_char_length - index); strncpy(&sd->text[index], text, char_length); sd->text[sd->char_length] = '\0'; _e_editable_text_update(editable); return unicode_length; }
static void _e_kbd_normalise_init(void) { int i; const char *table[][2] = { {"À", "a"}, {"Á", "a"}, {"Â", "a"}, {"Ã", "a"}, {"Ä", "a"}, {"Å", "a"}, {"Æ", "a"}, {"Ç", "c"}, {"È", "e"}, {"É", "e"}, {"Ê", "e"}, {"Ë", "e"}, {"Ì", "i"}, {"Í", "i"}, {"Î", "i"}, {"Ï", "i"}, {"Ð", "d"}, {"Ñ", "n"}, {"Ò", "o"}, {"Ó", "o"}, {"Ô", "o"}, {"Õ", "o"}, {"Ö", "o"}, {"×", "x"}, {"Ø", "o"}, {"Ù", "u"}, {"Ú", "u"}, {"Û", "u"}, {"Ü", "u"}, {"Ý", "y"}, {"Þ", "p"}, {"ß", "s"}, {"à", "a"}, {"á", "a"}, {"â", "a"}, {"ã", "a"}, {"ä", "a"}, {"å", "a"}, {"æ", "a"}, {"ç", "c"}, {"è", "e"}, {"é", "e"}, {"ê", "e"}, {"ë", "e"}, {"ì", "i"}, {"í", "i"}, {"î", "i"}, {"ï", "i"}, {"ð", "o"}, {"ñ", "n"}, {"ò", "o"}, {"ó", "o"}, {"ô", "o"}, {"õ", "o"}, {"ö", "o"}, {"ø", "o"}, {"ù", "u"}, {"ú", "u"}, {"û", "u"}, {"ü", "u"}, {"ý", "y"}, {"þ", "p"}, {"ÿ", "y"} }; // 63 items if (_e_kbd_normalise_ready) return; _e_kbd_normalise_ready = 1; for (i = 0; i < 128; i++) _e_kbd_normalise_base[i] = tolower(i); for (;i < MAXLATIN; i++) { int glyph, j; for (j = 0; j < 63; j++) { evas_string_char_next_get(table[j][0], 0, &glyph); if (glyph == i) { _e_kbd_normalise_base[i] = *table[j][1]; break; } } } }
static const char * _edje_text_fit_x(Edje *ed, Edje_Real_Part *ep, Edje_Calc_Params *params, const char *text, const char *font, int size, Evas_Coord sw, int *free_text) { Evas_Coord tw = 0, th = 0, p; int l, r; int i; char *buf; int uc1 = -1, uc2 = -1, c1 = -1, c2 = -1; int loop = 0, extra; size_t orig_len; FLOAT_T sc; sc = ed->scale; if (sc == ZERO) sc = _edje_scale; *free_text = 0; if (sw <= 1) return ""; if (ep->part->scale) evas_object_scale_set(ep->object, TO_DOUBLE(sc)); evas_object_text_font_set(ep->object, font, size); evas_object_text_text_set(ep->object, text); part_get_geometry(ep, &tw, &th); evas_object_text_style_pad_get(ep->object, &l, &r, NULL, NULL); p = ((sw - tw) * params->type.text.elipsis); /* chop chop */ if (tw > sw) { if (params->type.text.elipsis != 0.0) /* should be the last in text! not the rightmost */ uc1 = evas_object_text_last_up_to_pos(ep->object, -p + l, th / 2); if (params->type.text.elipsis != 1.0) { /* should be the last in text! not the rightmost */ if ((-p + sw -r) < 0) uc2 = evas_object_text_last_up_to_pos(ep->object, 0, th / 2); else uc2 = evas_object_text_last_up_to_pos(ep->object, -p + sw - r, th / 2); } if ((uc1 < 0) && (uc2 < 0)) { uc1 = 0; uc2 = 0; } } if (!(((uc1 >= 0) || (uc2 >= 0)) && (tw > sw))) return text; if ((uc1 == 0) && (uc2 == 0)) return text; orig_len = strlen(text); /* don't overflow orig_len by adding extra * FIXME: we might want to set a max string length somewhere... */ extra = 1 + 3 + 3; /* terminator, leading and trailing ellipsis */ orig_len = MIN(orig_len, ((size_t) 8192 - extra)); if (!(buf = malloc(orig_len + extra))) return text; /* Convert uc1, uc2 -> c1, c2 */ i = 0; if (uc1 >= 0) { c1 = 0; for ( ; i < uc1 ; i++) { c1 = evas_string_char_next_get(text, c1, NULL); } } if (uc2 >= 0) { if (c1 >= 0) { c2 = c1; } else { c2 = 0; } for ( ; i < uc2 ; i++) { c2 = evas_string_char_next_get(text, c2, NULL); } } buf[0] = '\0'; while (((c1 >= 0) || (c2 >= 0)) && (tw > sw)) { loop++; if (sw <= 0.0) { buf[0] = 0; break; } if ((c1 >= 0) && (c2 >= 0)) { if ((loop & 0x1)) { if (c1 >= 0) c1 = evas_string_char_next_get(text, c1, NULL); } else { if (c2 >= 0) { c2 = evas_string_char_prev_get(text, c2, NULL); if (c2 < 0) { buf[0] = 0; break; } } } } else { if (c1 >= 0) c1 = evas_string_char_next_get(text, c1, NULL); else if (c2 >= 0) { c2 = evas_string_char_prev_get(text, c2, NULL); if (c2 < 0) { buf[0] = 0; break; } } } if ((c1 >= 0) && (c2 >= 0)) { if (c1 >= c2) { buf[0] = 0; break; } } else if ((c1 > 0 && (size_t) c1 >= orig_len) || c2 == 0) { buf[0] = 0; break; } buf[0] = 0; _edje_text_fit_set(buf, text, c1, c2); evas_object_text_text_set(ep->object, buf); part_get_geometry(ep, &tw, &th); } *free_text = 1; return buf; }