Ticket #3885: 3885-search-exclude.patch

File 3885-search-exclude.patch, 48.5 KB (added by esauloff, 7 years ago)

Patch for 3885_search_exclude branch

  • lib/search.h

    From 2f1721bb45082dc5fd4211275208dc7f1715e072 Mon Sep 17 00:00:00 2001
    From: Georgii Iesaulov <esauloff@gmail.com>
    Date: Fri, 8 Dec 2017 00:42:56 -0500
    Subject: [PATCH 1/7] Add support of '|' delimiter to exclude files for shell
     patterns
    
    Signed-off-by: Georgii Iesaulov <esauloff@gmail.com>
    ---
     lib/search.h        | 10 ++++++
     lib/search/regex.c  | 62 +++++++++++++++++++++++++++++----
     lib/search/search.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++
     3 files changed, 164 insertions(+), 6 deletions(-)
    
    diff --git a/lib/search.h b/lib/search.h
    index 6e79609bc..bc6f09b02 100644
    a b typedef struct mc_search_struct 
    110110    /* prepared conditions */ 
    111111    GPtrArray *conditions; 
    112112 
     113    /* prepared conditions: to exclude patterns for MC_SEARCH_T_GLOB type */ 
     114    GPtrArray *conditions_exclude; 
     115 
    113116    /* original search string */ 
    114117    gchar *original; 
    115118    gsize original_len; 
     119 
     120    /* original search string: to exclude patterns for MC_SEARCH_T_GLOB type */ 
     121    gchar *original_exclude; 
     122    gsize original_exclude_len; 
     123 
    116124#ifdef HAVE_CHARSET 
    117125    gchar *original_charset; 
    118126#endif 
    mc_search_t *mc_search_new_len (const gchar * original, gsize original_len, 
    146154void mc_search_free (mc_search_t * lc_mc_search); 
    147155 
    148156gboolean mc_search_prepare (mc_search_t * mc_search); 
     157gboolean mc_search_prepare_include (mc_search_t * mc_search); 
     158gboolean mc_search_prepare_exclude (mc_search_t * mc_search); 
    149159 
    150160gboolean mc_search_run (mc_search_t * mc_search, const void *user_data, gsize start_search, 
    151161                        gsize end_search, gsize * found_len); 
  • lib/search/regex.c

    diff --git a/lib/search/regex.c b/lib/search/regex.c
    index a577ea3d5..f082b1577 100644
    a b mc_search__g_regex_match_full_safe (const GRegex * regex, 
    320320 
    321321static mc_search__found_cond_t 
    322322mc_search__regex_found_cond_one (mc_search_t * lc_mc_search, mc_search_regex_t * regex, 
    323                                  GString * search_str) 
     323                                 GString * search_str, gboolean do_not_cleanup) 
    324324{ 
    325325#ifdef SEARCH_TYPE_GLIB 
    326326    GError *mcerror = NULL; 
    mc_search__regex_found_cond_one (mc_search_t * lc_mc_search, mc_search_regex_t * 
    329329        (regex, search_str->str, search_str->len, 0, G_REGEX_MATCH_NEWLINE_ANY, 
    330330         &lc_mc_search->regex_match_info, &mcerror)) 
    331331    { 
    332         g_match_info_free (lc_mc_search->regex_match_info); 
    333         lc_mc_search->regex_match_info = NULL; 
     332        if (!do_not_cleanup) 
     333        { 
     334            g_match_info_free (lc_mc_search->regex_match_info); 
     335            lc_mc_search->regex_match_info = NULL; 
     336        } 
     337 
    334338        if (mcerror != NULL) 
    335339        { 
    336340            lc_mc_search->error = MC_SEARCH_E_REGEX; 
    mc_search__regex_found_cond_one (mc_search_t * lc_mc_search, mc_search_regex_t * 
    359363/* --------------------------------------------------------------------------------------------- */ 
    360364 
    361365static mc_search__found_cond_t 
    362 mc_search__regex_found_cond (mc_search_t * lc_mc_search, GString * search_str) 
     366mc_search__regex_found_cond_include (mc_search_t * lc_mc_search, GString * search_str) 
    363367{ 
    364368    gsize loop1; 
    365369 
    mc_search__regex_found_cond (mc_search_t * lc_mc_search, GString * search_str) 
    375379 
    376380        ret = 
    377381            mc_search__regex_found_cond_one (lc_mc_search, mc_search_cond->regex_handle, 
    378                                              search_str); 
     382                                             search_str, FALSE); 
     383        if (ret != COND__NOT_FOUND) 
     384            return ret; 
     385    } 
     386    return COND__NOT_ALL_FOUND; 
     387} 
     388 
     389/* --------------------------------------------------------------------------------------------- */ 
     390 
     391static mc_search__found_cond_t 
     392mc_search__regex_found_cond_exclude (mc_search_t * lc_mc_search, GString * search_str) 
     393{ 
     394    gsize loop1; 
     395 
     396    for (loop1 = 0; loop1 < lc_mc_search->conditions_exclude->len; loop1++) 
     397    { 
     398        mc_search_cond_t *mc_search_cond; 
     399        mc_search__found_cond_t ret; 
     400 
     401        mc_search_cond = 
     402            (mc_search_cond_t *) g_ptr_array_index (lc_mc_search->conditions_exclude, loop1); 
     403 
     404        if (!mc_search_cond->regex_handle) 
     405        { 
     406            continue; 
     407        } 
     408 
     409        ret = 
     410            mc_search__regex_found_cond_one (lc_mc_search, mc_search_cond->regex_handle, 
     411                                             search_str, TRUE); 
    379412        if (ret != COND__NOT_FOUND) 
     413        { 
    380414            return ret; 
     415        } 
    381416    } 
     417 
    382418    return COND__NOT_ALL_FOUND; 
    383419} 
    384420 
    mc_search__run_regex (mc_search_t * lc_mc_search, const void *user_data, 
    889925    gint start_pos; 
    890926    gint end_pos; 
    891927 
     928    mc_search__found_cond_t ret_combined; 
     929 
    892930    if (lc_mc_search->regex_buffer != NULL) 
    893931        g_string_set_size (lc_mc_search->regex_buffer, 0); 
    894932    else 
    mc_search__run_regex (mc_search_t * lc_mc_search, const void *user_data, 
    952990            virtual_pos = current_pos; 
    953991        } 
    954992 
    955         switch (mc_search__regex_found_cond (lc_mc_search, lc_mc_search->regex_buffer)) 
     993        ret_combined = 
     994            mc_search__regex_found_cond_include (lc_mc_search, lc_mc_search->regex_buffer); 
     995        if (ret_combined == COND__FOUND_OK) 
     996        { 
     997            if (lc_mc_search->search_type == MC_SEARCH_T_GLOB && 
     998                mc_search__regex_found_cond_exclude (lc_mc_search, 
     999                                                     lc_mc_search->regex_buffer) == COND__FOUND_OK) 
     1000            { 
     1001                ret_combined = COND__NOT_ALL_FOUND; 
     1002            } 
     1003        } 
     1004 
     1005        switch (ret_combined) 
    9561006        { 
    9571007        case COND__FOUND_OK: 
    9581008#ifdef SEARCH_TYPE_GLIB 
  • lib/search/search.c

    diff --git a/lib/search/search.c b/lib/search/search.c
    index e9e160a09..72c786a30 100644
    a b mc_search_free (mc_search_t * lc_mc_search) 
    191191    if (lc_mc_search->conditions != NULL) 
    192192        mc_search__conditions_free (lc_mc_search->conditions); 
    193193 
     194    if (lc_mc_search->conditions_exclude != NULL) 
     195    { 
     196        mc_search__conditions_free (lc_mc_search->conditions_exclude); 
     197    } 
     198 
    194199#ifdef SEARCH_TYPE_GLIB 
    195200    if (lc_mc_search->regex_match_info != NULL) 
    196201        g_match_info_free (lc_mc_search->regex_match_info); 
    mc_search_free (mc_search_t * lc_mc_search) 
    208213 
    209214gboolean 
    210215mc_search_prepare (mc_search_t * lc_mc_search) 
     216{ 
     217    gboolean ret; 
     218 
     219    const gchar *exclusion_delim = "|"; 
     220    gchar **tokens; 
     221 
     222    ret = TRUE; 
     223 
     224    if (lc_mc_search != NULL && lc_mc_search->search_type == MC_SEARCH_T_GLOB) 
     225    { 
     226        tokens = g_strsplit (lc_mc_search->original, exclusion_delim, 0); 
     227        if (g_strv_length (tokens) == 2) 
     228        { 
     229            g_free (lc_mc_search->original); 
     230 
     231            lc_mc_search->original_len = strlen (tokens[0]); 
     232            lc_mc_search->original = g_strndup (tokens[0], lc_mc_search->original_len); 
     233 
     234            lc_mc_search->original_exclude_len = strlen (tokens[1]); 
     235            lc_mc_search->original_exclude = 
     236                g_strndup (tokens[1], lc_mc_search->original_exclude_len); 
     237        } 
     238        g_strfreev (tokens); 
     239 
     240        ret = mc_search_prepare_exclude (lc_mc_search); 
     241    } 
     242 
     243    return (ret && mc_search_prepare_include (lc_mc_search)); 
     244} 
     245 
     246/* --------------------------------------------------------------------------------------------- */ 
     247 
     248gboolean 
     249mc_search_prepare_include (mc_search_t * lc_mc_search) 
    211250{ 
    212251    GPtrArray *ret; 
    213252 
    mc_search_prepare (mc_search_t * lc_mc_search) 
    263302 
    264303/* --------------------------------------------------------------------------------------------- */ 
    265304 
     305gboolean 
     306mc_search_prepare_exclude (mc_search_t * lc_mc_search) 
     307{ 
     308    GPtrArray *ret; 
     309 
     310    ret = g_ptr_array_new (); 
     311#ifdef HAVE_CHARSET 
     312    if (lc_mc_search->is_all_charsets) 
     313    { 
     314        gsize loop1; 
     315 
     316        for (loop1 = 0; loop1 < codepages->len; loop1++) 
     317        { 
     318            const char *id; 
     319            gsize recoded_str_len; 
     320            gchar *buffer; 
     321 
     322            id = ((codepage_desc *) g_ptr_array_index (codepages, loop1))->id; 
     323            if (g_ascii_strcasecmp (id, lc_mc_search->original_charset) == 0) 
     324            { 
     325                g_ptr_array_add (ret, 
     326                                 mc_search__cond_struct_new (lc_mc_search, 
     327                                                             lc_mc_search->original_exclude, 
     328                                                             lc_mc_search->original_exclude_len, 
     329                                                             lc_mc_search->original_charset)); 
     330                continue; 
     331            } 
     332 
     333            buffer = 
     334                mc_search__recode_str (lc_mc_search->original_exclude, 
     335                                       lc_mc_search->original_exclude_len, 
     336                                       lc_mc_search->original_charset, id, &recoded_str_len); 
     337 
     338            g_ptr_array_add (ret, 
     339                             mc_search__cond_struct_new (lc_mc_search, buffer, 
     340                                                         recoded_str_len, id)); 
     341            g_free (buffer); 
     342        } 
     343    } 
     344    else 
     345    { 
     346        g_ptr_array_add (ret, 
     347                         mc_search__cond_struct_new (lc_mc_search, lc_mc_search->original_exclude, 
     348                                                     lc_mc_search->original_exclude_len, 
     349                                                     lc_mc_search->original_charset)); 
     350    } 
     351#else 
     352    g_ptr_array_add (ret, 
     353                     mc_search__cond_struct_new (lc_mc_search, lc_mc_search->original_exclude, 
     354                                                 lc_mc_search->original_exclude_len, 
     355                                                 str_detect_termencoding ())); 
     356#endif 
     357    lc_mc_search->conditions_exclude = ret; 
     358 
     359    return (lc_mc_search->error == MC_SEARCH_E_OK); 
     360} 
     361 
     362/* --------------------------------------------------------------------------------------------- */ 
     363 
    266364/** 
    267365 * Carries out the search. 
    268366 * 
  • lib/search/regex.c

    -- 
    2.14.3
    
    
    From d530c43ea2289ddc9b740b53ef494bdc43c5d19e Mon Sep 17 00:00:00 2001
    From: Georgii Iesaulov <esauloff@gmail.com>
    Date: Fri, 8 Dec 2017 00:44:53 -0500
    Subject: [PATCH 2/7] Comment changed pieces for file search exclusion
    
    Signed-off-by: Georgii Iesaulov <esauloff@gmail.com>
    ---
     lib/search/regex.c  | 26 ++++++++++++++++++++++++++
     lib/search/search.c | 19 +++++++++++++++++++
     2 files changed, 45 insertions(+)
    
    diff --git a/lib/search/regex.c b/lib/search/regex.c
    index f082b1577..82753027f 100644
    a b mc_search__g_regex_match_full_safe (const GRegex * regex, 
    318318 
    319319/* --------------------------------------------------------------------------------------------- */ 
    320320 
     321/* 
     322 * Argument do_not_cleanup is used to distinguish *_include() vs *_exclude() calls to avoid 
     323 * clean-up of lc_mc_search->regex_match_info structure: if file does not match *_include() call, 
     324 * it is not considered anymore, but if file does not match *_exclude() call, it still can be  
     325 * considered and regex_match_info is used later in mc_search__run_regex(). 
     326 */ 
    321327static mc_search__found_cond_t 
    322328mc_search__regex_found_cond_one (mc_search_t * lc_mc_search, mc_search_regex_t * regex, 
    323329                                 GString * search_str, gboolean do_not_cleanup) 
    mc_search__regex_found_cond_one (mc_search_t * lc_mc_search, mc_search_regex_t * 
    362368 
    363369/* --------------------------------------------------------------------------------------------- */ 
    364370 
     371/* 
     372 * To distinguish this method and newly added mc_search__regex_found_cond_exclude() - method was 
     373 * renamed, original name is mc_search__regex_found_cond(). No changes done to method internal 
     374 * logic except for added argument in mc_search__regex_found_cond_one() call. 
     375 */ 
    365376static mc_search__found_cond_t 
    366377mc_search__regex_found_cond_include (mc_search_t * lc_mc_search, GString * search_str) 
    367378{ 
    mc_search__regex_found_cond_include (mc_search_t * lc_mc_search, GString * searc 
    388399 
    389400/* --------------------------------------------------------------------------------------------- */ 
    390401 
     402/* 
     403 * This method logic reflects mc_search__regex_found_cond_include() internals except for using 
     404 * exclusion array lc_mc_search->conditions_exclude to check if considered file matches exclusion 
     405 * pattern and should not be included in search result. 
     406 * TRUE is passed to mc_search__regex_found_cond_one() call to not clean-up 
     407 * lc_mc_search->regex_match_info structure if file does not match exclusion pattern. 
     408 */ 
    391409static mc_search__found_cond_t 
    392410mc_search__regex_found_cond_exclude (mc_search_t * lc_mc_search, GString * search_str) 
    393411{ 
    mc_search__run_regex (mc_search_t * lc_mc_search, const void *user_data, 
    925943    gint start_pos; 
    926944    gint end_pos; 
    927945 
     946    /* Variable will contain result of *_include() method and then *_exclude() if needed */ 
    928947    mc_search__found_cond_t ret_combined; 
    929948 
    930949    if (lc_mc_search->regex_buffer != NULL) 
    mc_search__run_regex (mc_search_t * lc_mc_search, const void *user_data, 
    9901009            virtual_pos = current_pos; 
    9911010        } 
    9921011 
     1012        /* 
     1013         * Check file exclusion for MC_SEARCH_T_GLOB search type. 
     1014         * Each considered file is checked to match inclusion pattern first. 
     1015         * If file matches and COND__FOUND_OK is returned from *_include() method, then exclusion 
     1016         * is checked with *_exclude(). If file matches for exclusion, found status COND__FOUND_OK 
     1017         * is changed to COND__NOT_ALL_FOUND to avoid file from search results. 
     1018         */ 
    9931019        ret_combined = 
    9941020            mc_search__regex_found_cond_include (lc_mc_search, lc_mc_search->regex_buffer); 
    9951021        if (ret_combined == COND__FOUND_OK) 
  • lib/search/search.c

    diff --git a/lib/search/search.c b/lib/search/search.c
    index 72c786a30..fe1887d73 100644
    a b mc_search_free (mc_search_t * lc_mc_search) 
    211211 
    212212/* --------------------------------------------------------------------------------------------- */ 
    213213 
     214/* 
     215 * Wrapper method to cover both mc_search_prepare_include() and mc_search_prepare_exclude() calls. 
     216 * Exclude portion works only for MC_SEARCH_T_GLOB search type. 
     217 */ 
    214218gboolean 
    215219mc_search_prepare (mc_search_t * lc_mc_search) 
    216220{ 
    217221    gboolean ret; 
    218222 
     223    /* Hardcoded delimiter to split lc_mc_search->original to inclusion and exclusion patterns */ 
    219224    const gchar *exclusion_delim = "|"; 
    220225    gchar **tokens; 
    221226 
    mc_search_prepare (mc_search_t * lc_mc_search) 
    224229    if (lc_mc_search != NULL && lc_mc_search->search_type == MC_SEARCH_T_GLOB) 
    225230    { 
    226231        tokens = g_strsplit (lc_mc_search->original, exclusion_delim, 0); 
     232 
     233        /* 
     234         * Only if two tokens (only one delimiter '|' was specified) are found, 
     235         * lc_mc_search->original string is splitted, freed, and then initialized again. 
     236         * lc_mc_search->original_exclude is initialized afterwards. 
     237         */ 
    227238        if (g_strv_length (tokens) == 2) 
    228239        { 
    229240            g_free (lc_mc_search->original); 
    mc_search_prepare (mc_search_t * lc_mc_search) 
    245256 
    246257/* --------------------------------------------------------------------------------------------- */ 
    247258 
     259/* 
     260 * To distinguish this method and newly added mc_search_prepare_exclude() - method was renamed, 
     261 * original name is mc_search_prepare(). No changes done to method internal logic. 
     262 */ 
    248263gboolean 
    249264mc_search_prepare_include (mc_search_t * lc_mc_search) 
    250265{ 
    mc_search_prepare_include (mc_search_t * lc_mc_search) 
    302317 
    303318/* --------------------------------------------------------------------------------------------- */ 
    304319 
     320/* 
     321 * This method logic reflects mc_search_prepare_include() internals except for using 
     322 * exclusion pattern lc_mc_search->original_exclude to fill array lc_mc_search->conditions_exclude. 
     323 */ 
    305324gboolean 
    306325mc_search_prepare_exclude (mc_search_t * lc_mc_search) 
    307326{ 
  • lib/search/search.c

    -- 
    2.14.3
    
    
    From 91a8fbd04abf7c50c9e40f018c62a721a379f14f Mon Sep 17 00:00:00 2001
    From: Georgii Iesaulov <esauloff@gmail.com>
    Date: Mon, 11 Dec 2017 03:44:58 -0500
    Subject: [PATCH 3/7] Check if exclusion delimiter is escaped properly
    
    Signed-off-by: Georgii Iesaulov <esauloff@gmail.com>
    ---
     lib/search/search.c | 22 +++++++++++++++++++++-
     1 file changed, 21 insertions(+), 1 deletion(-)
    
    diff --git a/lib/search/search.c b/lib/search/search.c
    index fe1887d73..8cfed53ba 100644
    a b mc_search__conditions_free (GPtrArray * array) 
    122122    g_ptr_array_free (array, TRUE); 
    123123} 
    124124 
     125/* --------------------------------------------------------------------------------------------- */ 
     126 
     127static gboolean 
     128mc_search_is_character_escaped (gchar * string, gchar ** string_start) 
     129{ 
     130    if (string == NULL || &string == string_start || *(string - 1) != '\\') 
     131    { 
     132        return FALSE; 
     133    } 
     134 
     135    return !mc_search_is_character_escaped (string - 1, string_start); 
     136} 
     137 
    125138/* --------------------------------------------------------------------------------------------- */ 
    126139/*** public functions ****************************************************************************/ 
    127140/* --------------------------------------------------------------------------------------------- */ 
    mc_search_prepare (mc_search_t * lc_mc_search) 
    222235 
    223236    /* Hardcoded delimiter to split lc_mc_search->original to inclusion and exclusion patterns */ 
    224237    const gchar *exclusion_delim = "|"; 
     238    gboolean is_exclusion_escaped; 
    225239    gchar **tokens; 
    226240 
    227241    ret = TRUE; 
    228242 
    229243    if (lc_mc_search != NULL && lc_mc_search->search_type == MC_SEARCH_T_GLOB) 
    230244    { 
     245        is_exclusion_escaped = 
     246            mc_search_is_character_escaped (g_strstr_len (lc_mc_search->original, 
     247                                                          lc_mc_search->original_len, 
     248                                                          exclusion_delim), 
     249                                            &lc_mc_search->original); 
     250 
    231251        tokens = g_strsplit (lc_mc_search->original, exclusion_delim, 0); 
    232252 
    233253        /* 
    mc_search_prepare (mc_search_t * lc_mc_search) 
    235255         * lc_mc_search->original string is splitted, freed, and then initialized again. 
    236256         * lc_mc_search->original_exclude is initialized afterwards. 
    237257         */ 
    238         if (g_strv_length (tokens) == 2) 
     258        if ((g_strv_length (tokens) == 2) && !is_exclusion_escaped) 
    239259        { 
    240260            g_free (lc_mc_search->original); 
    241261 
  • lib/search/regex.c

    -- 
    2.14.3
    
    
    From 23815836e9eb3e8e962fefa020ff8e3d2a47eb53 Mon Sep 17 00:00:00 2001
    From: Georgii Iesaulov <esauloff@gmail.com>
    Date: Tue, 12 Dec 2017 16:18:34 -0500
    Subject: [PATCH 4/7] Apply doxygen format for comments
    
    Signed-off-by: Georgii Iesaulov <esauloff@gmail.com>
    ---
     lib/search/regex.c  | 46 ++++++++++++++++++++++++++++++++--------------
     lib/search/search.c | 51 ++++++++++++++++++++++++++++++++++++++++-----------
     2 files changed, 72 insertions(+), 25 deletions(-)
    
    diff --git a/lib/search/regex.c b/lib/search/regex.c
    index 82753027f..c6ad7174b 100644
    a b mc_search__g_regex_match_full_safe (const GRegex * regex, 
    318318 
    319319/* --------------------------------------------------------------------------------------------- */ 
    320320 
    321 /* 
    322  * Argument do_not_cleanup is used to distinguish *_include() vs *_exclude() calls to avoid 
    323  * clean-up of lc_mc_search->regex_match_info structure: if file does not match *_include() call, 
    324  * it is not considered anymore, but if file does not match *_exclude() call, it still can be  
    325  * considered and regex_match_info is used later in mc_search__run_regex(). 
     321/** 
     322 * Checks if object #search_str matches one particular search criteria represented with #regex. 
     323 * Param #do_not_cleanup is used to avoid clean-up of lc_mc_search->regex_match_info structure: 
     324 * if file does not match *_include() call, it is not considered anymore, but if file 
     325 * does not match *_exclude() call, it still can be considered and regex_match_info 
     326 * is used later in mc_search__run_regex(). 
     327 *  
     328 * @note lc_mc_search->regex_match_info is freed and initialized with NULL 
     329 *       if #search_str does not match #regex 
     330 *  
     331 * @param lc_mc_search search criteria 
     332 * @param regex regular expression representing search criteria 
     333 * @param search_str object to check criteria on 
     334 * @param do_not_cleanup TRUE if lc_mc_search->regex_match_info should be freed and initialized 
     335 *                       with NULL in case #search_str does not match #regex, FALSE otherwise 
     336 *  
     337 * @return search results 
    326338 */ 
    327339static mc_search__found_cond_t 
    328340mc_search__regex_found_cond_one (mc_search_t * lc_mc_search, mc_search_regex_t * regex, 
    mc_search__regex_found_cond_one (mc_search_t * lc_mc_search, mc_search_regex_t * 
    368380 
    369381/* --------------------------------------------------------------------------------------------- */ 
    370382 
    371 /* 
    372  * To distinguish this method and newly added mc_search__regex_found_cond_exclude() - method was 
    373  * renamed, original name is mc_search__regex_found_cond(). No changes done to method internal 
    374  * logic except for added argument in mc_search__regex_found_cond_one() call. 
     383/** 
     384 * Checks if object #search_str matches any inclusion search criterias. 
     385 *  
     386 * @param lc_mc_search search criteria 
     387 * @param search_str object to check criteria on 
     388 *  
     389 * @return search results 
    375390 */ 
    376391static mc_search__found_cond_t 
    377392mc_search__regex_found_cond_include (mc_search_t * lc_mc_search, GString * search_str) 
    mc_search__regex_found_cond_include (mc_search_t * lc_mc_search, GString * searc 
    399414 
    400415/* --------------------------------------------------------------------------------------------- */ 
    401416 
    402 /* 
    403  * This method logic reflects mc_search__regex_found_cond_include() internals except for using 
    404  * exclusion array lc_mc_search->conditions_exclude to check if considered file matches exclusion 
    405  * pattern and should not be included in search result. 
     417/** 
     418 * Checks if object #search_str matches any exclusion search criterias. 
    406419 * TRUE is passed to mc_search__regex_found_cond_one() call to not clean-up 
    407420 * lc_mc_search->regex_match_info structure if file does not match exclusion pattern. 
     421 *  
     422 * @param lc_mc_search search criteria 
     423 * @param search_str object to check criteria on 
     424 *  
     425 * @return search results 
    408426 */ 
    409427static mc_search__found_cond_t 
    410428mc_search__regex_found_cond_exclude (mc_search_t * lc_mc_search, GString * search_str) 
    mc_search__run_regex (mc_search_t * lc_mc_search, const void *user_data, 
    10121030        /* 
    10131031         * Check file exclusion for MC_SEARCH_T_GLOB search type. 
    10141032         * Each considered file is checked to match inclusion pattern first. 
    1015          * If file matches and COND__FOUND_OK is returned from *_include() method, then exclusion 
     1033         * If file matches and COND__FOUND_OK is returned with *_include() method, then exclusion 
    10161034         * is checked with *_exclude(). If file matches for exclusion, found status COND__FOUND_OK 
    10171035         * is changed to COND__NOT_ALL_FOUND to avoid file from search results. 
    10181036         */ 
  • lib/search/search.c

    diff --git a/lib/search/search.c b/lib/search/search.c
    index 8cfed53ba..ad21b007a 100644
    a b mc_search__conditions_free (GPtrArray * array) 
    124124 
    125125/* --------------------------------------------------------------------------------------------- */ 
    126126 
     127/** 
     128 * Checks whether specified character with #string parameter is escaped properly with '\' symbol. 
     129 *  
     130 * @example for string "abc\|def" where character '|' is escaped with single '\', TRUE is returned; 
     131 *          for string "abc\\|def" - character '|' is not escaped while preceding '\' is, 
     132 *          FALSE is returned. 
     133 *  
     134 * @param string fisrt character in string which is checked for preceding escape chars 
     135 * @param string_start start address of full string containing #string 
     136 *  
     137 * @return TRUE if character in #string is escaped properly, FALSE otherwise 
     138 */ 
    127139static gboolean 
    128140mc_search_is_character_escaped (gchar * string, gchar ** string_start) 
    129141{ 
    mc_search_free (mc_search_t * lc_mc_search) 
    224236 
    225237/* --------------------------------------------------------------------------------------------- */ 
    226238 
    227 /* 
    228  * Wrapper method to cover both mc_search_prepare_include() and mc_search_prepare_exclude() calls. 
    229  * Exclude portion works only for MC_SEARCH_T_GLOB search type. 
     239/** 
     240 * Covers mc_search_prepare_include() and mc_search_prepare_exclude() calls. 
     241 * Wrapper method which covers *_include() and *_exclude() calls, and exclude logic works 
     242 * for MC_SEARCH_T_GLOB only. 
     243 * Splits original search criteria only in case single delimiter character exists in 
     244 * criteria string and character is not escaped. 
     245 *  
     246 * @param lc_mc_search search criteria 
     247 *  
     248 * @return TRUE if inclusion and exclusion criterias are initialized successfully, FALSE otherwise 
    230249 */ 
    231250gboolean 
    232251mc_search_prepare (mc_search_t * lc_mc_search) 
    233252{ 
    234253    gboolean ret; 
    235254 
    236     /* Hardcoded delimiter to split lc_mc_search->original to inclusion and exclusion patterns */ 
     255    /* Hardcoded delimiter to split lc_mc_search->original into inclusion and exclusion parts */ 
    237256    const gchar *exclusion_delim = "|"; 
    238257    gboolean is_exclusion_escaped; 
    239258    gchar **tokens; 
    mc_search_prepare (mc_search_t * lc_mc_search) 
    242261 
    243262    if (lc_mc_search != NULL && lc_mc_search->search_type == MC_SEARCH_T_GLOB) 
    244263    { 
     264        /* Check if #exclusion_delim is escaped with '\' symbol */ 
    245265        is_exclusion_escaped = 
    246266            mc_search_is_character_escaped (g_strstr_len (lc_mc_search->original, 
    247267                                                          lc_mc_search->original_len, 
    mc_search_prepare (mc_search_t * lc_mc_search) 
    251271        tokens = g_strsplit (lc_mc_search->original, exclusion_delim, 0); 
    252272 
    253273        /* 
    254          * Only if two tokens (only one delimiter '|' was specified) are found, 
     274         * If two tokens (one delimiter '|' is specified) are found and delimiter is not escaped, 
    255275         * lc_mc_search->original string is splitted, freed, and then initialized again. 
    256276         * lc_mc_search->original_exclude is initialized afterwards. 
    257277         */ 
    mc_search_prepare (mc_search_t * lc_mc_search) 
    276296 
    277297/* --------------------------------------------------------------------------------------------- */ 
    278298 
    279 /* 
    280  * To distinguish this method and newly added mc_search_prepare_exclude() - method was renamed, 
    281  * original name is mc_search_prepare(). No changes done to method internal logic. 
     299/** 
     300 * Initializes inclusion search criteria. 
     301 * Parses inclusion search criteria to regular expression and adds it to lc_mc_search->conditions. 
     302 *  
     303 * @param lc_mc_search search criteria 
     304 *  
     305 * @return TRUE if inclusion search criteria is initialized successfully, FALSE otherwise 
    282306 */ 
    283307gboolean 
    284308mc_search_prepare_include (mc_search_t * lc_mc_search) 
    mc_search_prepare_include (mc_search_t * lc_mc_search) 
    337361 
    338362/* --------------------------------------------------------------------------------------------- */ 
    339363 
    340 /* 
    341  * This method logic reflects mc_search_prepare_include() internals except for using 
    342  * exclusion pattern lc_mc_search->original_exclude to fill array lc_mc_search->conditions_exclude. 
     364/** 
     365 * Initializes exclusion search criteria. 
     366 * Parses exclusion search criteria to regular expression and adds it 
     367 * to lc_mc_search->conditions_exclude. 
     368 *  
     369 * @param lc_mc_search search criteria 
     370 *  
     371 * @return TRUE if exclusion search criteria is initialized successfully, FALSE otherwise 
    343372 */ 
    344373gboolean 
    345374mc_search_prepare_exclude (mc_search_t * lc_mc_search) 
  • doc/man/mc.1.in

    -- 
    2.14.3
    
    
    From 1f2c243a52e6210d3881136a0bbeac6873487d60 Mon Sep 17 00:00:00 2001
    From: Georgii Iesaulov <esauloff@gmail.com>
    Date: Tue, 12 Dec 2017 16:19:56 -0500
    Subject: [PATCH 5/7] Reflect changes in Find Files and Select Files dialogs in
     hlp/man documents
    
    Signed-off-by: Georgii Iesaulov <esauloff@gmail.com>
    ---
     doc/man/mc.1.in    | 14 +++++++++++---
     doc/man/ru/mc.1.in | 16 ++++++++++++++--
     2 files changed, 25 insertions(+), 5 deletions(-)
    
    diff --git a/doc/man/mc.1.in b/doc/man/mc.1.in
    index aace39942..761866e81 100644
    a b figure. 
    14181418The "File name" input field contains a filename pattern to be searched 
    14191419for. It is interpreted as a shell pattern or as a regular expression 
    14201420depending on the state of the "Using shell patterns" checkbox. An empty 
    1421 value is valid and matches any file name. 
     1421value is valid and matches any file name. To exclude some files or 
     1422filename patterns from search results when using shell patterns, 
     1423delimiter '|' (pipe symbol) can be used to split "File name" string 
     1424into inclusion and exclusion parts. If more than one '|' symbol is found, 
     1425exclusion logic does not apply. 
    14221426.PP 
    14231427The "Content" input field contains a string to search for within the 
    14241428files. Leave this field empty to disable searching file contents. 
    inside inodes and thus don't waste much disk space). 
    27542758 
    27552759.\"NODE "Select/Unselect Files" 
    27562760.SH "Select/Unselect Files" 
    2757 The dialog of group of files and directories selection or uselection. 
     2761The dialog of group of files and directories selection or unselection. 
    27582762The 
    27592763.\"LINK2" 
    27602764input line 
    expressions (see ed (1)). When 
    27792783checkbox is on, the selection will be case sensitive characters. 
    27802784If 
    27812785.I Case sensitive 
    2782 is off, the case will be ignored. 
     2786is off, the case will be ignored. To exclude some files or 
     2787filename patterns from selection/unselection results when using 
     2788Shell patterns, delimiter '|' (pipe symbol) can be used to split 
     2789search string into inclusion and exclusion parts. If more than 
     2790one '|' symbol is found, exclusion logic does not apply. 
    27832791.\"NODE "Diff Viewer" 
    27842792.SH "Internal Diff Viewer" 
    27852793The mcdiff is a visual diff tool. You can compare two files and edit them 
  • doc/man/ru/mc.1.in

    diff --git a/doc/man/ru/mc.1.in b/doc/man/ru/mc.1.in
    index 4a1ab012d..7f1de18fe 100644
    a b Midnight Commander\-а. Для возврата к вашему приложен 
    536536то пометка файлов и каталогов будет производиться с учетом регистра символов имён. 
    537537Если опция 
    538538.I С учётом регистра 
    539 отключена, то регистр символов учитываться не будет. 
     539отключена, то регистр символов учитываться не будет. Для того, чтобы исключить 
     540некоторые файлы или маски имён файлов из результатов выборки при использовании 
     541"Образцы в стиле shell", разделяющий символ '|' (вертикальная черта) может быть 
     542использован. Символ '|' разделяет строку поиска на две части, 
     543первая часть используется для включения файлов в результаты выборки, 
     544вторая часть - для исключения файлов. Логика исключения не работает 
     545если в строке найдено больше одного символа '|'. 
    540546.PP 
    541547.B \\\\ (backslash) 
    542548Клавиша "\\" снимает отметку с группы файлов, то есть производит 
    Midnight Commander создает дерево путем просмотра т 
    15031509Поле "Шаблон имени" содержит маску имени файла, по которой происходит поиск. 
    15041510В зависимости от опции "Метасимволы shell" маска интерпретируется либо по тем же 
    15051511правилам, что и в командной оболочке, либо как регулярное выражение. Пустое 
    1506 поле также допустимо и соответствует любому имени. 
     1512поле также допустимо и соответствует любому имени. Для того, чтобы исключить 
     1513некоторые файлы или маски имён файлов из результатов поиска при использовании 
     1514"Метасимволов shell", разделяющий символ '|' (вертикальная черта) может быть 
     1515использован. Символ '|' разделяет строку "Шаблон имени" на две части, 
     1516первая часть используется для включения файлов в результаты поиска, 
     1517вторая часть - для исключения файлов. Логика исключения не работает 
     1518если в строке найдено больше одного символа '|'. 
    15071519.PP 
    15081520Поле "Содержимое" позволяет задать текст, который надо найти. Если это поле 
    15091521пусто, то поиск по содержимому файлов производиться не будет. 
  • doc/man/mc.1.in

    -- 
    2.14.3
    
    
    From 6a388462e0044d75b7c4fe17bb3c5db500c7d8fd Mon Sep 17 00:00:00 2001
    From: Georgii Iesaulov <esauloff@gmail.com>
    Date: Tue, 12 Dec 2017 23:03:30 -0500
    Subject: [PATCH 6/7] Mention how to escape '|' delimiter in hlp/man documents
    
    Signed-off-by: Georgii Iesaulov <esauloff@gmail.com>
    ---
     doc/man/mc.1.in    | 8 ++++++--
     doc/man/ru/mc.1.in | 8 ++++++--
     2 files changed, 12 insertions(+), 4 deletions(-)
    
    diff --git a/doc/man/mc.1.in b/doc/man/mc.1.in
    index 761866e81..56de34912 100644
    a b value is valid and matches any file name. To exclude some files or 
    14221422filename patterns from search results when using shell patterns, 
    14231423delimiter '|' (pipe symbol) can be used to split "File name" string 
    14241424into inclusion and exclusion parts. If more than one '|' symbol is found, 
    1425 exclusion logic does not apply. 
     1425exclusion logic does not apply. To screen delimiter sign and search for 
     1426'|' symbol literally, escape it with single '\\' (backslash symbol) 
     1427like so "\\|". 
    14261428.PP 
    14271429The "Content" input field contains a string to search for within the 
    14281430files. Leave this field empty to disable searching file contents. 
    is off, the case will be ignored. To exclude some files or 
    27872789filename patterns from selection/unselection results when using 
    27882790Shell patterns, delimiter '|' (pipe symbol) can be used to split 
    27892791search string into inclusion and exclusion parts. If more than 
    2790 one '|' symbol is found, exclusion logic does not apply. 
     2792one '|' symbol is found, exclusion logic does not apply. To screen 
     2793delimiter sign and search for '|' symbol literally, escape it 
     2794with single '\\' (backslash symbol) like so "\\|". 
    27912795.\"NODE "Diff Viewer" 
    27922796.SH "Internal Diff Viewer" 
    27932797The mcdiff is a visual diff tool. You can compare two files and edit them 
  • doc/man/ru/mc.1.in

    diff --git a/doc/man/ru/mc.1.in b/doc/man/ru/mc.1.in
    index 7f1de18fe..7a93e6393 100644
    a b Midnight Commander\-а. Для возврата к вашему приложен 
    542542использован. Символ '|' разделяет строку поиска на две части, 
    543543первая часть используется для включения файлов в результаты выборки, 
    544544вторая часть - для исключения файлов. Логика исключения не работает 
    545 если в строке найдено больше одного символа '|'. 
     545если в строке найдено больше одного символа '|'. Для того, чтобы экранировать 
     546разделяющий символ и начать поиск с символом '|', необходимо использовать 
     547одиночный символ '\\' (обратная косая черта): "\\|". 
    546548.PP 
    547549.B \\\\ (backslash) 
    548550Клавиша "\\" снимает отметку с группы файлов, то есть производит 
    Midnight Commander создает дерево путем просмотра т 
    15151517использован. Символ '|' разделяет строку "Шаблон имени" на две части, 
    15161518первая часть используется для включения файлов в результаты поиска, 
    15171519вторая часть - для исключения файлов. Логика исключения не работает 
    1518 если в строке найдено больше одного символа '|'. 
     1520если в строке найдено больше одного символа '|'. Для того, чтобы 
     1521экранировать разделяющий символ и начать поиск с символом '|', необходимо 
     1522использовать одиночный символ '\\' (обратная косая черта): "\\|". 
    15191523.PP 
    15201524Поле "Содержимое" позволяет задать текст, который надо найти. Если это поле 
    15211525пусто, то поиск по содержимому файлов производиться не будет. 
  • lib/search.h

    -- 
    2.14.3
    
    
    From 380031265594cb929a262914be32b57eeda8dee3 Mon Sep 17 00:00:00 2001
    From: Georgii Iesaulov <esauloff@gmail.com>
    Date: Tue, 12 Dec 2017 23:06:39 -0500
    Subject: [PATCH 7/7] Hide mc_search_prepare_include() and *_exclude() methods
     in file static section
    
    Signed-off-by: Georgii Iesaulov <esauloff@gmail.com>
    ---
     lib/search.h        |   2 -
     lib/search/search.c | 266 ++++++++++++++++++++++++++--------------------------
     2 files changed, 133 insertions(+), 135 deletions(-)
    
    diff --git a/lib/search.h b/lib/search.h
    index bc6f09b02..752eea835 100644
    a b mc_search_t *mc_search_new_len (const gchar * original, gsize original_len, 
    154154void mc_search_free (mc_search_t * lc_mc_search); 
    155155 
    156156gboolean mc_search_prepare (mc_search_t * mc_search); 
    157 gboolean mc_search_prepare_include (mc_search_t * mc_search); 
    158 gboolean mc_search_prepare_exclude (mc_search_t * mc_search); 
    159157 
    160158gboolean mc_search_run (mc_search_t * mc_search, const void *user_data, gsize start_search, 
    161159                        gsize end_search, gsize * found_len); 
  • lib/search/search.c

    diff --git a/lib/search/search.c b/lib/search/search.c
    index ad21b007a..4dfd2ae6d 100644
    a b mc_search__cond_struct_free (mc_search_cond_t * mc_search_cond) 
    115115 
    116116/* --------------------------------------------------------------------------------------------- */ 
    117117 
     118/** 
     119 * Initializes inclusion search criteria. 
     120 * Parses inclusion search criteria to regular expression and adds it to lc_mc_search->conditions. 
     121 *  
     122 * @param lc_mc_search search criteria 
     123 *  
     124 * @return TRUE if inclusion search criteria is initialized successfully, FALSE otherwise 
     125 */ 
     126static gboolean 
     127mc_search_prepare_include (mc_search_t * lc_mc_search) 
     128{ 
     129    GPtrArray *ret; 
     130 
     131    ret = g_ptr_array_new (); 
     132#ifdef HAVE_CHARSET 
     133    if (lc_mc_search->is_all_charsets) 
     134    { 
     135        gsize loop1; 
     136 
     137        for (loop1 = 0; loop1 < codepages->len; loop1++) 
     138        { 
     139            const char *id; 
     140            gsize recoded_str_len; 
     141            gchar *buffer; 
     142 
     143            id = ((codepage_desc *) g_ptr_array_index (codepages, loop1))->id; 
     144            if (g_ascii_strcasecmp (id, lc_mc_search->original_charset) == 0) 
     145            { 
     146                g_ptr_array_add (ret, 
     147                                 mc_search__cond_struct_new (lc_mc_search, lc_mc_search->original, 
     148                                                             lc_mc_search->original_len, 
     149                                                             lc_mc_search->original_charset)); 
     150                continue; 
     151            } 
     152 
     153            buffer = 
     154                mc_search__recode_str (lc_mc_search->original, lc_mc_search->original_len, 
     155                                       lc_mc_search->original_charset, id, &recoded_str_len); 
     156 
     157            g_ptr_array_add (ret, 
     158                             mc_search__cond_struct_new (lc_mc_search, buffer, 
     159                                                         recoded_str_len, id)); 
     160            g_free (buffer); 
     161        } 
     162    } 
     163    else 
     164    { 
     165        g_ptr_array_add (ret, 
     166                         mc_search__cond_struct_new (lc_mc_search, lc_mc_search->original, 
     167                                                     lc_mc_search->original_len, 
     168                                                     lc_mc_search->original_charset)); 
     169    } 
     170#else 
     171    g_ptr_array_add (ret, 
     172                     mc_search__cond_struct_new (lc_mc_search, lc_mc_search->original, 
     173                                                 lc_mc_search->original_len, 
     174                                                 str_detect_termencoding ())); 
     175#endif 
     176    lc_mc_search->conditions = ret; 
     177 
     178    return (lc_mc_search->error == MC_SEARCH_E_OK); 
     179} 
     180 
     181/* --------------------------------------------------------------------------------------------- */ 
     182 
     183/** 
     184 * Initializes exclusion search criteria. 
     185 * Parses exclusion search criteria to regular expression and adds it 
     186 * to lc_mc_search->conditions_exclude. 
     187 *  
     188 * @param lc_mc_search search criteria 
     189 *  
     190 * @return TRUE if exclusion search criteria is initialized successfully, FALSE otherwise 
     191 */ 
     192static gboolean 
     193mc_search_prepare_exclude (mc_search_t * lc_mc_search) 
     194{ 
     195    GPtrArray *ret; 
     196 
     197    ret = g_ptr_array_new (); 
     198#ifdef HAVE_CHARSET 
     199    if (lc_mc_search->is_all_charsets) 
     200    { 
     201        gsize loop1; 
     202 
     203        for (loop1 = 0; loop1 < codepages->len; loop1++) 
     204        { 
     205            const char *id; 
     206            gsize recoded_str_len; 
     207            gchar *buffer; 
     208 
     209            id = ((codepage_desc *) g_ptr_array_index (codepages, loop1))->id; 
     210            if (g_ascii_strcasecmp (id, lc_mc_search->original_charset) == 0) 
     211            { 
     212                g_ptr_array_add (ret, 
     213                                 mc_search__cond_struct_new (lc_mc_search, 
     214                                                             lc_mc_search->original_exclude, 
     215                                                             lc_mc_search->original_exclude_len, 
     216                                                             lc_mc_search->original_charset)); 
     217                continue; 
     218            } 
     219 
     220            buffer = 
     221                mc_search__recode_str (lc_mc_search->original_exclude, 
     222                                       lc_mc_search->original_exclude_len, 
     223                                       lc_mc_search->original_charset, id, &recoded_str_len); 
     224 
     225            g_ptr_array_add (ret, 
     226                             mc_search__cond_struct_new (lc_mc_search, buffer, 
     227                                                         recoded_str_len, id)); 
     228            g_free (buffer); 
     229        } 
     230    } 
     231    else 
     232    { 
     233        g_ptr_array_add (ret, 
     234                         mc_search__cond_struct_new (lc_mc_search, lc_mc_search->original_exclude, 
     235                                                     lc_mc_search->original_exclude_len, 
     236                                                     lc_mc_search->original_charset)); 
     237    } 
     238#else 
     239    g_ptr_array_add (ret, 
     240                     mc_search__cond_struct_new (lc_mc_search, lc_mc_search->original_exclude, 
     241                                                 lc_mc_search->original_exclude_len, 
     242                                                 str_detect_termencoding ())); 
     243#endif 
     244    lc_mc_search->conditions_exclude = ret; 
     245 
     246    return (lc_mc_search->error == MC_SEARCH_E_OK); 
     247} 
     248 
     249/* --------------------------------------------------------------------------------------------- */ 
     250 
    118251static void 
    119252mc_search__conditions_free (GPtrArray * array) 
    120253{ 
    mc_search_prepare (mc_search_t * lc_mc_search) 
    296429 
    297430/* --------------------------------------------------------------------------------------------- */ 
    298431 
    299 /** 
    300  * Initializes inclusion search criteria. 
    301  * Parses inclusion search criteria to regular expression and adds it to lc_mc_search->conditions. 
    302  *  
    303  * @param lc_mc_search search criteria 
    304  *  
    305  * @return TRUE if inclusion search criteria is initialized successfully, FALSE otherwise 
    306  */ 
    307 gboolean 
    308 mc_search_prepare_include (mc_search_t * lc_mc_search) 
    309 { 
    310     GPtrArray *ret; 
    311  
    312     ret = g_ptr_array_new (); 
    313 #ifdef HAVE_CHARSET 
    314     if (lc_mc_search->is_all_charsets) 
    315     { 
    316         gsize loop1; 
    317  
    318         for (loop1 = 0; loop1 < codepages->len; loop1++) 
    319         { 
    320             const char *id; 
    321             gsize recoded_str_len; 
    322             gchar *buffer; 
    323  
    324             id = ((codepage_desc *) g_ptr_array_index (codepages, loop1))->id; 
    325             if (g_ascii_strcasecmp (id, lc_mc_search->original_charset) == 0) 
    326             { 
    327                 g_ptr_array_add (ret, 
    328                                  mc_search__cond_struct_new (lc_mc_search, lc_mc_search->original, 
    329                                                              lc_mc_search->original_len, 
    330                                                              lc_mc_search->original_charset)); 
    331                 continue; 
    332             } 
    333  
    334             buffer = 
    335                 mc_search__recode_str (lc_mc_search->original, lc_mc_search->original_len, 
    336                                        lc_mc_search->original_charset, id, &recoded_str_len); 
    337  
    338             g_ptr_array_add (ret, 
    339                              mc_search__cond_struct_new (lc_mc_search, buffer, 
    340                                                          recoded_str_len, id)); 
    341             g_free (buffer); 
    342         } 
    343     } 
    344     else 
    345     { 
    346         g_ptr_array_add (ret, 
    347                          mc_search__cond_struct_new (lc_mc_search, lc_mc_search->original, 
    348                                                      lc_mc_search->original_len, 
    349                                                      lc_mc_search->original_charset)); 
    350     } 
    351 #else 
    352     g_ptr_array_add (ret, 
    353                      mc_search__cond_struct_new (lc_mc_search, lc_mc_search->original, 
    354                                                  lc_mc_search->original_len, 
    355                                                  str_detect_termencoding ())); 
    356 #endif 
    357     lc_mc_search->conditions = ret; 
    358  
    359     return (lc_mc_search->error == MC_SEARCH_E_OK); 
    360 } 
    361  
    362 /* --------------------------------------------------------------------------------------------- */ 
    363  
    364 /** 
    365  * Initializes exclusion search criteria. 
    366  * Parses exclusion search criteria to regular expression and adds it 
    367  * to lc_mc_search->conditions_exclude. 
    368  *  
    369  * @param lc_mc_search search criteria 
    370  *  
    371  * @return TRUE if exclusion search criteria is initialized successfully, FALSE otherwise 
    372  */ 
    373 gboolean 
    374 mc_search_prepare_exclude (mc_search_t * lc_mc_search) 
    375 { 
    376     GPtrArray *ret; 
    377  
    378     ret = g_ptr_array_new (); 
    379 #ifdef HAVE_CHARSET 
    380     if (lc_mc_search->is_all_charsets) 
    381     { 
    382         gsize loop1; 
    383  
    384         for (loop1 = 0; loop1 < codepages->len; loop1++) 
    385         { 
    386             const char *id; 
    387             gsize recoded_str_len; 
    388             gchar *buffer; 
    389  
    390             id = ((codepage_desc *) g_ptr_array_index (codepages, loop1))->id; 
    391             if (g_ascii_strcasecmp (id, lc_mc_search->original_charset) == 0) 
    392             { 
    393                 g_ptr_array_add (ret, 
    394                                  mc_search__cond_struct_new (lc_mc_search, 
    395                                                              lc_mc_search->original_exclude, 
    396                                                              lc_mc_search->original_exclude_len, 
    397                                                              lc_mc_search->original_charset)); 
    398                 continue; 
    399             } 
    400  
    401             buffer = 
    402                 mc_search__recode_str (lc_mc_search->original_exclude, 
    403                                        lc_mc_search->original_exclude_len, 
    404                                        lc_mc_search->original_charset, id, &recoded_str_len); 
    405  
    406             g_ptr_array_add (ret, 
    407                              mc_search__cond_struct_new (lc_mc_search, buffer, 
    408                                                          recoded_str_len, id)); 
    409             g_free (buffer); 
    410         } 
    411     } 
    412     else 
    413     { 
    414         g_ptr_array_add (ret, 
    415                          mc_search__cond_struct_new (lc_mc_search, lc_mc_search->original_exclude, 
    416                                                      lc_mc_search->original_exclude_len, 
    417                                                      lc_mc_search->original_charset)); 
    418     } 
    419 #else 
    420     g_ptr_array_add (ret, 
    421                      mc_search__cond_struct_new (lc_mc_search, lc_mc_search->original_exclude, 
    422                                                  lc_mc_search->original_exclude_len, 
    423                                                  str_detect_termencoding ())); 
    424 #endif 
    425     lc_mc_search->conditions_exclude = ret; 
    426  
    427     return (lc_mc_search->error == MC_SEARCH_E_OK); 
    428 } 
    429  
    430 /* --------------------------------------------------------------------------------------------- */ 
    431  
    432432/** 
    433433 * Carries out the search. 
    434434 *