From e741a19b214936beade1f0a35ba386c670bfb472 Mon Sep 17 00:00:00 2001 From: "Carsten Haitzler (Rasterman)" Date: Thu, 24 Jul 2014 12:41:33 +0900 Subject: [PATCH] fix genlist/grid search item patch to be simpler and just better better - why? 1. no reliance on fnmatrch headers - have special enums for this so fnmatch is an internal detail (casefole may not exist) 2. don't leak strduped strings - free them when done 3. have the same code for genlist and grid (dup for now until an interface makes it the same search interface) 4. improve docs 5. get right @since version 6. use label get func in item class - providing a func won't work when multiple items of multiple classes exist in the list --- legacy/elementary/src/bin/test_gengrid.c | 16 +++------ legacy/elementary/src/bin/test_genlist.c | 29 ++++++----------- legacy/elementary/src/lib/elm_gen.h | 8 +++++ legacy/elementary/src/lib/elm_gengrid.c | 39 +++++++++++++++------- legacy/elementary/src/lib/elm_gengrid.eo | 26 +++++++++++---- legacy/elementary/src/lib/elm_genlist.c | 41 ++++++++++++++++-------- legacy/elementary/src/lib/elm_genlist.eo | 39 ++++++---------------- 7 files changed, 105 insertions(+), 93 deletions(-) diff --git a/legacy/elementary/src/bin/test_gengrid.c b/legacy/elementary/src/bin/test_gengrid.c index a2ca6a08bd..bfdd85fd0f 100644 --- a/legacy/elementary/src/bin/test_gengrid.c +++ b/legacy/elementary/src/bin/test_gengrid.c @@ -1380,21 +1380,12 @@ static const char *_grid5_items_text[] = { "Topeka", "Trenton" }; -static char * -_grid5_search_text_get(void *data, Evas_Object *obj EINA_UNUSED, const char *part EINA_UNUSED) -{ - char buf[32]; - Item_Data *id = data; - - snprintf(buf, sizeof(buf), "%s", _grid5_items_text[id->mode]); - return strdup(buf); -} - static char * _grid5_text_get(void *data, Evas_Object *obj EINA_UNUSED, const char *part EINA_UNUSED) { + Item_Data *id = data; char buf[64]; - snprintf(buf, sizeof(buf), "%s", _grid5_search_text_get(data, NULL, NULL)); + snprintf(buf, sizeof(buf), "%s", _grid5_items_text[id->mode]); return strdup(buf); } @@ -1405,7 +1396,8 @@ _grid5_search_item(grid5_Event_Data *event_data, Elm_Object_Item * it) if (!str || !strlen(str)) return; printf("Looking for \"%s\". ", str); - event_data->last_item_found = elm_gengrid_search_by_text_item_get(event_data->grid_obj, it, _grid5_search_text_get, NULL, str, 0); + event_data->last_item_found = elm_gengrid_search_by_text_item_get + (event_data->grid_obj, it, NULL, str, 0); if (event_data->last_item_found) { diff --git a/legacy/elementary/src/bin/test_genlist.c b/legacy/elementary/src/bin/test_genlist.c index d553be5668..0d80d1c583 100644 --- a/legacy/elementary/src/bin/test_genlist.c +++ b/legacy/elementary/src/bin/test_genlist.c @@ -3508,8 +3508,8 @@ static const char *_gl20_items_text[] = { "Topeka", "Trenton" }; static char * -_gl20_search_text_get(void *data, Evas_Object *obj EINA_UNUSED, - const char *part EINA_UNUSED) +_gl20_text_get(void *data, Evas_Object *obj EINA_UNUSED, + const char *part EINA_UNUSED) { char buf[32]; int item_index = (int)(uintptr_t)data; @@ -3530,29 +3530,18 @@ _gl20_search_text_get(void *data, Evas_Object *obj EINA_UNUSED, return NULL; } -static char * -_gl20_text_get(void *data, Evas_Object *obj EINA_UNUSED, - const char *part EINA_UNUSED) -{ - char buf[64]; - snprintf(buf, sizeof(buf), "(this text is not uset for search) %s", - _gl20_search_text_get(data, NULL, NULL)); - return strdup(buf); -} - static void -_gl20_searsh_item(gl20_Event_Data *event_data, Elm_Object_Item * it) +_gl20_search_item(gl20_Event_Data *event_data, Elm_Object_Item * it) { const char *str = elm_entry_entry_get(event_data->en_obj); if (!str || !strlen(str)) return; - int flag = 0; - if (!elm_check_state_get(event_data->tg_obj)) - flag = FNM_CASEFOLD; + Elm_Glob_Match_Flags flag = 0; + if (!elm_check_state_get(event_data->tg_obj)) flag = ELM_GLOB_MATCH_NOCASE; printf("Looking for \"%s\". ", str); - event_data->last_item_found = elm_genlist_search_by_text_item_get(event_data->gl_obj, - it, _gl20_search_text_get, NULL, str, flag); + event_data->last_item_found = elm_genlist_search_by_text_item_get + (event_data->gl_obj, it, NULL, str, flag); if (event_data->last_item_found) { @@ -3570,7 +3559,7 @@ static void _gl20_search_settings_changed_cb(void *data, Evas_Object *obj EINA_UNUSED, void *einfo EINA_UNUSED) { - _gl20_searsh_item(data, NULL); + _gl20_search_item(data, NULL); } static Elm_Genlist_Item_Class * @@ -3616,7 +3605,7 @@ static void _gl20_on_keydown(void *data, Evas *evas EINA_UNUSED, if (!strcmp(ev->key, "Return")) { printf("Looking for next item\n"); - _gl20_searsh_item(data, event_data->last_item_found); + _gl20_search_item(data, event_data->last_item_found); } } diff --git a/legacy/elementary/src/lib/elm_gen.h b/legacy/elementary/src/lib/elm_gen.h index 431f7b1bb3..8bef0e04bb 100644 --- a/legacy/elementary/src/lib/elm_gen.h +++ b/legacy/elementary/src/lib/elm_gen.h @@ -61,3 +61,11 @@ struct _Elm_Gen_Item_Class #define ELM_GEN_ITEM_CLASS_VERSION 2 #define ELM_GEN_ITEM_CLASS_HEADER ELM_GEN_ITEM_CLASS_VERSION, 0, 0 + +typedef enum +{ + ELM_GLOB_MATCH_NO_ESCAPE = (1 << 0), /**< Treat backslash as an ordinary character instead of escape */ + ELM_GLOB_MATCH_PATH = (1 << 1), /**< Match a slash in string only with a slash in pattern and not by an asterisk (*) or a question mark (?) metacharacter, nor by a bracket expression ([]) containing a slash. */ + ELM_GLOB_MATCH_PERIOD = (1 << 2), /**< Leading period in string has to be matched exactly by a period in pattern. A period is considered to be leading if it is the first character in string, or if both ELM_GLOB_MATCH_PATH is set and the period immediately follows a slash. */ + ELM_GLOB_MATCH_NOCASE = (1 << 3) /**< The pattern is matched case-insensitively. */ +} Elm_Glob_Match_Flags; /**< Glob matching bitfiled flags. @since 1.11 */ diff --git a/legacy/elementary/src/lib/elm_gengrid.c b/legacy/elementary/src/lib/elm_gengrid.c index 9d06c64e60..c357e5a1a0 100644 --- a/legacy/elementary/src/lib/elm_gengrid.c +++ b/legacy/elementary/src/lib/elm_gengrid.c @@ -105,24 +105,41 @@ static const Elm_Action key_actions[] = { EOLIAN static Elm_Object_Item * _elm_gengrid_search_by_text_item_get(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd, - Elm_Object_Item * item_to_search_from, - Elm_Gen_Item_Text_Get_Cb _text_get, - const char * part_name, - const char * pattern, - int flags) + Elm_Object_Item *item_to_search_from, + const char *part_name, + const char *pattern, + Elm_Glob_Match_Flags flags) { Elm_Gen_Item *it = NULL; - const char * str = NULL; - Eina_Inlist * start = NULL; + char *str = NULL; + Eina_Inlist *start = NULL; + int fnflags = 0; - if (!_text_get || !pattern) return NULL; + if (!pattern) return NULL; if (!sd->items) return NULL; - start = (item_to_search_from) ? EINA_INLIST_GET((Elm_Gen_Item *)item_to_search_from) : sd->items; + if (flags & ELM_GLOB_MATCH_NO_ESCAPE) fnflags |= FNM_NOESCAPE; + if (flags & ELM_GLOB_MATCH_PATH) fnflags |= FNM_PATHNAME; + if (flags & ELM_GLOB_MATCH_PERIOD) fnflags |= FNM_PERIOD; +#ifdef FNM_CASEFOLD + if (flags & ELM_GLOB_MATCH_NOCASE) fnflags |= FNM_CASEFOLD; +#endif + + start = (item_to_search_from) ? + EINA_INLIST_GET((Elm_Gen_Item *)item_to_search_from) : + sd->items; EINA_INLIST_FOREACH(start, it) { - str = _text_get((void *)it->base.data, VIEW(it), part_name); - if (!fnmatch(pattern, str, flags)) return (Elm_Object_Item *)it; + if (!it->itc->func.text_get) continue; + str = it->itc->func.text_get((void *)it->base.data, + VIEW(it), part_name); + if (!str) continue; + if (!fnmatch(pattern, str, fnflags)) + { + free(str); + return (Elm_Object_Item *)it; + } + free(str); } return NULL; } diff --git a/legacy/elementary/src/lib/elm_gengrid.eo b/legacy/elementary/src/lib/elm_gengrid.eo index 6b125f97a5..7e34c97db3 100644 --- a/legacy/elementary/src/lib/elm_gengrid.eo +++ b/legacy/elementary/src/lib/elm_gengrid.eo @@ -656,14 +656,28 @@ class Elm_Gengrid (Elm_Layout, Elm_Interface_Scrollable, Evas.Clickable_Interfac @in const(void)* func_data; /*@ Data to be passed to @p func. */ } } - search_by_text_item_get { + search_by_text_item_get { + /*@ + Get gengrid item by given string. + + @return Pointer to the gengrid item which matches search_string in case of success, otherwise returns NULL. + + It takes pointer to the gengrid item that will be used to start + search from it. + + This function uses globs (like "*.jpg") for searching and takes + search flags as last parameter That is a bitfield with values + to be ored together or 0 for no flags. + + @ingroup Gengrid + @since 1.11 */ + return Elm_Object_Item *; params { - @in Elm_Object_Item * item_to_search_from; /*@ Pointer to item to start search from. If NULL search will be started from the first item of the genlist. */ - @in Elm_Gen_Item_Text_Get_Cb _text_get; /*@ Pointer to Elm_Gen_Item_Text_Get_Cb function to get text for comparison. */ - @in const(char)* part_name; /*@ Name of the TEXT part of genlist item to search string in. */ - @in const(char)* pattern; /*@ The search pattern. */ - @in int flags; /*@ fnmatch search flags */ + @in Elm_Object_Item *item_to_search_from; /*@ Pointer to item to start search from. If NULL search will be started from the first item of the gengrid. */ + @in const(char) *part_name; /*@ Name of the TEXT part of gengrid item to search string in. */ + @in const(char) *pattern; /*@ The search pattern. */ + @in Elm_Glob_Match_Flags flags; /*@ Search flags */ } } } diff --git a/legacy/elementary/src/lib/elm_genlist.c b/legacy/elementary/src/lib/elm_genlist.c index e33a8cfa51..f09f1fe90c 100644 --- a/legacy/elementary/src/lib/elm_genlist.c +++ b/legacy/elementary/src/lib/elm_genlist.c @@ -7547,28 +7547,41 @@ _elm_genlist_elm_widget_focus_highlight_geometry_get(Eo *obj EINA_UNUSED, Elm_Ge EOLIAN static Elm_Object_Item * _elm_genlist_search_by_text_item_get(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, - Elm_Object_Item * item_to_search_from, - Elm_Gen_Item_Text_Get_Cb _text_get, - const char * part_name, - const char * pattern, - int flags) + Elm_Object_Item *item_to_search_from, + const char *part_name, + const char *pattern, + Elm_Glob_Match_Flags flags) { Elm_Gen_Item *it = NULL; - const char * str = NULL; - Eina_Bool search_flag = (item_to_search_from) ? EINA_FALSE : EINA_TRUE; + char *str = NULL; + Eina_Inlist *start = NULL; + int fnflags = 0; - if (!_text_get || !pattern) return NULL; + if (!pattern) return NULL; if (!sd->items) return NULL; - EINA_INLIST_FOREACH(sd->items, it) + if (flags & ELM_GLOB_MATCH_NO_ESCAPE) fnflags |= FNM_NOESCAPE; + if (flags & ELM_GLOB_MATCH_PATH) fnflags |= FNM_PATHNAME; + if (flags & ELM_GLOB_MATCH_PERIOD) fnflags |= FNM_PERIOD; +#ifdef FNM_CASEFOLD + if (flags & ELM_GLOB_MATCH_NOCASE) fnflags |= FNM_CASEFOLD; +#endif + + start = (item_to_search_from) ? + EINA_INLIST_GET((Elm_Gen_Item *)item_to_search_from) : + sd->items; + EINA_INLIST_FOREACH(start, it) { - if (search_flag) + if (!it->itc->func.text_get) continue; + str = it->itc->func.text_get((void *)it->base.data, + VIEW(it), part_name); + if (!str) continue; + if (!fnmatch(pattern, str, fnflags)) { - str = _text_get((void *)it->base.data, VIEW(it), part_name); - if (!fnmatch(pattern, str, flags)) return (Elm_Object_Item *)it; + free(str); + return (Elm_Object_Item *)it; } - else if (item_to_search_from == (Elm_Object_Item *)it) - search_flag = EINA_TRUE; + free(str); } return NULL; } diff --git a/legacy/elementary/src/lib/elm_genlist.eo b/legacy/elementary/src/lib/elm_genlist.eo index 14babba7f1..78aed245aa 100644 --- a/legacy/elementary/src/lib/elm_genlist.eo +++ b/legacy/elementary/src/lib/elm_genlist.eo @@ -683,43 +683,22 @@ class Elm_Genlist (Elm_Layout, Elm_Interface_Scrollable, Evas.Clickable_Interfac @return Pointer to the genlist item which matches search_string in case of success, otherwise returns NULL. - This function takes pointer to the function that returns - comparison string for item (it could be the same function as used for setting text for labels). - Also it takes pointer to the genlist item that will be used to start search from it. + It takes pointer to the genlist item that will be used to start + search from it. - This function uses fnmatch() for searching and takes it's seatcing flags as last parameter. - The list of available flags: -
-
FNM_NOESCAPE
-
If this flag is set, treat backslash as an ordinary character, instead of an escape character.
-
FNM_PATHNAME
-
If this flag is set, match a slash in string only with a slash in pattern and not by an asterisk (*) - or a question mark (?) metacharacter, nor by a bracket expression ([]) containing a slash.
-
FNM_PERIOD
-
If this flag is set, a leading period in string has to be matched exactly by a period in pattern. - A period is considered to be leading if it is the first character in string, or if both - FNM_PATHNAME is set and the period immediately follows a slash.
-
FNM_FILE_NAME
-
This is a GNU synonym for FNM_PATHNAME.
-
FNM_LEADING_DIR
-
If this flag (a GNU extension) is set, the pattern is considered to be matched if it matches an - initial segment of string which is followed by a slash. This flag is mainly for the internal - use of glibc and is only implemented in certain cases.
-
FNM_CASEFOLD
-
If this flag (a GNU extension) is set, the pattern is matched case-insensitively.
-
- For more details see Linux Programmer's Manual. FNMATCH() + This function uses globs (like "*.jpg") for searching and takes + search flags as last parameter That is a bitfield with values + to be ored together or 0 for no flags. @ingroup Genlist - @since 1.10 */ + @since 1.11 */ return Elm_Object_Item *; params { @in Elm_Object_Item * item_to_search_from; /*@ Pointer to item to start search from. If NULL search will be started from the first item of the genlist. */ - @in Elm_Gen_Item_Text_Get_Cb _text_get; /*@ Pointer to Elm_Gen_Item_Text_Get_Cb function to get text for comparison. */ - @in const(char)* part_name; /*@ Name of the TEXT part of genlist item to search string in. */ - @in const(char)* pattern; /*@ The search pattern. */ - @in int flags; /*@ fnmatch search flags */ + @in const(char)* part_name; /*@ Name of the TEXT part of genlist item to search string in. */ + @in const(char)* pattern; /*@ The search pattern. */ + @in Elm_Glob_Match_Flags flags; /*@ Search flags */ } } }