By the way, the latest changes also broke word wrapping when the width of the etox region is smaller than the current word. I have not come up with a fix for that yet - just turned off word wrapping. :(
-- Bart Elberg I.D.E.A.L. Technology Corporation
#include "Etox_private.h"
Evas_List *active_selections = NULL; #define SELECTION_LOOP_START(selected) \ do { \ Evas_Object *bit = NULL; \ Etox_Line *line; \ Evas_List *l, *bl; \ Evas_Coord w, h; \ line = selected->start.line; \ l = evas_list_find_list(selected->etox->lines, selected->start.line); \ bl = evas_list_find_list(line->bits, selected->start.bit); \ while (bl && bit != selected->end.bit) { \ bit = bl->data; \ evas_object_geometry_get(bit, NULL, NULL, &w, NULL); \ line->w -= w #define SELECTION_LOOP_END \ evas_object_geometry_get(bit, NULL, NULL, &w, &h); \ line->w += w; \ if (h > line->h) \ line->h = h; \ bl = bl->next; \ if (!bl) { \ l = l->next; \ if (l) { \ line = l->data; \ bl = line->bits; \ } \ } \ } \ } while (0) Evas_Object * etox_split_bit(Etox_Line *line, Evas_Object *bit, int index) { Evas_List *l; Evas_Object *point = bit; Etox_Selection *selected; /* * Split the leading bit, only need to inform selections that end with * this bit. */ if (index && index < etox_style_length(bit)) { point = etox_style_split(bit, index); evas_object_smart_member_add(point, line->et->smart_obj); line->bits = evas_list_append_relative(line->bits, point, bit); l = active_selections; while (l) { selected = l->data; if (selected->end.bit == bit) selected->end.bit = point; l = l->next; } } return point; } Etox_Selection * etox_selection_new(Etox *etox, Etox_Line *l1, Etox_Line *l2, Evas_Object *s1, Evas_Object *s2, int i1, int i2) { Evas_Object *temp; Etox_Selection *selected; /* * Split bits on their index boundaries, this updates selections that * contain the bits. */ temp = etox_split_bit(l1, s1, i1); if (s1 == s2) { i2 -= i1; s2 = temp; } s1 = temp; /* * Split on the ending index, we use the original s2 for the end, * since it's the bit portion before the split. */ etox_split_bit(l2, s2, i2); selected = calloc(1, sizeof(Etox_Selection)); memset(selected, 0, sizeof(Etox_Selection)); selected->etox = etox; selected->start.line = l1; selected->start.bit = s1; selected->end.line = l2; selected->end.bit = s2; active_selections = evas_list_prepend(active_selections, selected); etox_layout(etox); return selected; } /** */ void etox_selection_free(Etox_Selection *selected) { CHECK_PARAM_POINTER("selected", selected); active_selections = evas_list_remove(active_selections, selected); FREE(selected); } /** */ void etox_selection_free_by_etox(Evas_Object *obj) { Etox *etox; Evas_List *l, *r = NULL; Etox_Selection *selected; CHECK_PARAM_POINTER("obj", obj); etox = evas_object_smart_data_get(obj); /* * loop through all active selections. add the ones on etox * to a second list, to be removed later. */ for (l = active_selections; l; l = l->next) { selected = l->data; if (selected->etox == etox) { r = evas_list_append(r, selected); } } for (l = r; l; l = l->next) { selected = l->data; active_selections = evas_list_remove(active_selections, selected); free(selected); } evas_list_free(r); } /** */ Etox_Selection * etox_select_coords(Evas_Object *obj, Evas_Coord sx, Evas_Coord sy, Evas_Coord ex, Evas_Coord ey) { int i1, i2; Etox *et; Etox_Line *sl, *el = NULL; Evas_Object *sb, *eb = NULL; Etox_Selection *selected = NULL; CHECK_PARAM_POINTER_RETURN("obj", obj, NULL); et = evas_object_smart_data_get(obj); sl = etox_coord_to_line(et, sy); if (!sl) goto out; el = etox_coord_to_line(et, ey); if (!el) goto out; sb = etox_line_coord_to_bit(sl, sx); if (!sb) goto out; eb = etox_line_coord_to_bit(el, ex); if (!eb) goto out; i1 = etox_style_text_at_position(sb, sx, sy, NULL, NULL, NULL, NULL); i2 = etox_style_text_at_position(eb, sx, sy, NULL, NULL, NULL, NULL); selected = etox_selection_new(et, sl, el, sb, eb, i1, i2); out: return selected; } /** * etox_select_index - create a selection based on two indices * @et: the etox to choose the selection * @si: the starting index of characters to be selected * @ei: the ending index of characters to be selected * * Returns a newly allocated selection on success, NULL on failure. */ Etox_Selection * etox_select_index(Evas_Object * obj, int si, int ei) { Etox *et; Etox_Line *sl = NULL, *el = NULL; Evas_Object *sb = NULL, *eb = NULL; Etox_Selection *selected = NULL; CHECK_PARAM_POINTER_RETURN("obj", obj, NULL); et = evas_object_smart_data_get(obj); /* * First determine the lines containing the indices. */ sl = etox_index_to_line(et, &si); if (!sl) goto out; el = etox_index_to_line(et, &ei); if (!el) goto out; sb = etox_line_index_to_bit(sl, &si); if (!sb) goto out; eb = etox_line_index_to_bit(el, &ei); if (!eb) goto out; /* * Create the new selection and assign it's fields */ selected = etox_selection_new(et, sl, el, sb, eb, si, ei); out: return selected; } /** */ Etox_Selection * etox_select_str(Evas_Object * obj, char *match, int *index) { char *text = NULL, *pos = NULL; int i = 0, si = 0, ei = 0; CHECK_PARAM_POINTER_RETURN("obj", obj, NULL); /* * FIXME possibly search bit by bit to cut down on * memory for really large strings */ text = etox_get_text(obj); if (index) i = *index; pos = strstr(text + i, match); if (pos == NULL) { if (index) *index = -1; free(text); return NULL; } si = pos - text; ei = si + strlen(match); printf("si: %d, ei: %d\n", si, ei); if (index) *index = ei; free(text); return etox_select_index(obj, si, ei); } /** */ void etox_selection_bounds(Etox_Selection *selected, Evas_Coord *sx, Evas_Coord *sy, Evas_Coord *ex, Evas_Coord *ey) { } /** */ void etox_selection_add_callback(Etox_Selection *selected, Evas_Callback_Type callback, void (*func) (void *data, Evas *e, Evas_Object *o, int b, int x, int y), void *data) { } /** */ void etox_selection_del_callback(Etox_Selection *selected, Evas_Callback_Type callback) { } void etox_selection_apply_context(Etox_Selection *selected, Etox_Context *context) { Evas_List *l; Etox_Line *line; CHECK_PARAM_POINTER("selected", selected); CHECK_PARAM_POINTER("context", context); if (selected->start.line == selected->end.line) { etox_line_apply_context(selected->start.line, context, selected->start.bit, selected->end.bit); } else { /* start on the first line */ l = evas_list_find_list(selected->etox->lines, selected->start.line); line = l->data; for (; l; l = l->next) { line = l->data; /* * if start.bit is not on line, then the first bit of line will be * used as the starting bit. same for end.bit. */ etox_line_apply_context(line, context, selected->start.bit, selected->end.bit); if (line == selected->end.line) break; } } etox_layout(selected->etox); } void etox_selections_update(Evas_Object *bit, Etox_Line *line) { Evas_List *l; for (l = active_selections; l; l = l->next) { Etox_Selection *selected = evas_list_data(l); if (selected->start.bit == bit) { selected->start.line = line; } if (selected->end.bit == bit) { selected->end.line = line; } } } Etox_Rect * etox_selection_get_geometry(Etox_Selection *selected, int *num) { Etox_Rect *rects = NULL, *cur = NULL; Evas_List *l = NULL, *midlines = NULL; Evas_Coord x, y, w, h; int count = 0; l = evas_list_find_list(selected->etox->lines, selected->start.line); // Start with the second line (if any) l = l->next; count++; /* count the first line */ while (l) { Etox_Line *line = l->data; count++; /* count the last line also */ if (line == selected->end.line) break; midlines = evas_list_append(midlines, line); l = l->next; } printf("count: %d\n", count); rects = calloc(count, sizeof(Etox_Rect)); /* start and end line also */ /* first line */ //etox_line_index_to_geometry(selected->start.line, selected->start.index, // &x, &y, &w, &h); evas_object_geometry_get(selected->start.bit, &x, &y, &w, &h); rects->x = x; rects->y = y; etox_line_get_geometry(selected->start.line, &x, &y, &w, &h); rects->w = x + w - rects->x; rects->h = y + h - rects->y; cur = rects; /* printf("cur1: %d\n", cur); */ for (l = midlines; l; l = l->next) { Etox_Line *line = l->data; cur++; /* printf("cur2: %d\n", cur); */ etox_line_get_geometry(line, &x, &y, &w, &h); cur->x = x; cur->y = y; cur->w = w; cur->h = h; } if (selected->end.line != selected->start.line) { etox_line_get_geometry(selected->end.line, &x, &y, &w, &h); cur++; cur->x = x; cur->y = y; } //etox_line_index_to_geometry(selected->end.line, selected->end.index, // &x, &y, &w, &h); evas_object_geometry_get(selected->end.bit, &x, &y, &w, &h); cur->w = x + w - cur->x; cur->h = y + h - cur->y; if (num) *num = count; return rects; }