root/lib/search/lib.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. mc_search__change_case_str
  2. mc_search__recode_str
  3. mc_search__get_one_symbol
  4. mc_search__tolower_case_str
  5. mc_search__toupper_case_str
  6. mc_search_get_types_strings_array

   1 /*
   2    Search text engine.
   3    Common share code for module.
   4 
   5    Copyright (C) 2009-2025
   6    Free Software Foundation, Inc.
   7 
   8    Written by:
   9    Slava Zanko <slavazanko@gmail.com>, 2009, 2011
  10    Andrew Borodin <aborodin@vmail.ru>, 2013
  11 
  12    This file is part of the Midnight Commander.
  13 
  14    The Midnight Commander is free software: you can redistribute it
  15    and/or modify it under the terms of the GNU General Public License as
  16    published by the Free Software Foundation, either version 3 of the License,
  17    or (at your option) any later version.
  18 
  19    The Midnight Commander is distributed in the hope that it will be useful,
  20    but WITHOUT ANY WARRANTY; without even the implied warranty of
  21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  22    GNU General Public License for more details.
  23 
  24    You should have received a copy of the GNU General Public License
  25    along with this program.  If not, see <https://www.gnu.org/licenses/>.
  26  */
  27 
  28 #include <config.h>
  29 
  30 #include <stdlib.h>
  31 #include <sys/types.h>
  32 
  33 #include "lib/global.h"
  34 #include "lib/strutil.h"
  35 #include "lib/search.h"
  36 #ifdef HAVE_CHARSET
  37 #    include "lib/charsets.h"
  38 #endif
  39 
  40 #include "internal.h"
  41 
  42 /*** global variables ****************************************************************************/
  43 
  44 const char *STR_E_NOTFOUND = N_ ("Search string not found");
  45 const char *STR_E_UNKNOWN_TYPE = N_ ("Not implemented yet");
  46 const char *STR_E_RPL_NOT_EQ_TO_FOUND =
  47     N_ ("Num of replace tokens not equal to num of found tokens");
  48 const char *STR_E_RPL_INVALID_TOKEN = N_ ("Invalid token number %d");
  49 
  50 /*** file scope macro definitions ****************************************************************/
  51 
  52 /*** file scope type declarations ****************************************************************/
  53 
  54 typedef gboolean (*case_conv_fn) (const char *ch, char **out, size_t *remain);
  55 
  56 /*** forward declarations (file scope functions) *************************************************/
  57 
  58 /*** file scope variables ************************************************************************/
  59 
  60 /* --------------------------------------------------------------------------------------------- */
  61 /*** file scope functions ************************************************************************/
  62 /* --------------------------------------------------------------------------------------------- */
  63 
  64 static GString *
  65 mc_search__change_case_str (const char *charset, const GString *str, case_conv_fn case_conv)
     /* [previous][next][first][last][top][bottom][index][help]  */
  66 {
  67     GString *ret;
  68     const char *src_ptr;
  69     gchar *dst_str;
  70     gchar *dst_ptr;
  71     gsize dst_len;
  72 #ifdef HAVE_CHARSET
  73     GString *converted_str;
  74 
  75     if (charset == NULL)
  76         charset = cp_source;
  77 
  78     converted_str = mc_search__recode_str (str->str, str->len, charset, cp_display);
  79 
  80     dst_len = converted_str->len + 1;  // +1 is required for str_toupper/str_tolower
  81     dst_str = g_malloc (dst_len);
  82 
  83     for (src_ptr = converted_str->str, dst_ptr = dst_str; case_conv (src_ptr, &dst_ptr, &dst_len);
  84          src_ptr += str_length_char (src_ptr))
  85         ;
  86     *dst_ptr = '\0';
  87 
  88     dst_len = converted_str->len;
  89     g_string_free (converted_str, TRUE);
  90 
  91     ret = mc_search__recode_str (dst_str, dst_len, cp_display, charset);
  92     g_free (dst_str);
  93 #else
  94     (void) charset;
  95 
  96     dst_len = str->len + 1;  // +1 is required for str_toupper/str_tolower
  97     dst_str = g_malloc (dst_len);
  98 
  99     for (src_ptr = str->str, dst_ptr = dst_str; case_conv (src_ptr, &dst_ptr, &dst_len);
 100          src_ptr += str_length_char (src_ptr))
 101         ;
 102     *dst_ptr = '\0';
 103 
 104     ret = g_string_new_len (dst_str, dst_len);
 105     g_free (dst_str);
 106 #endif
 107     return ret;
 108 }
 109 
 110 /* --------------------------------------------------------------------------------------------- */
 111 /*** public functions ****************************************************************************/
 112 /* --------------------------------------------------------------------------------------------- */
 113 
 114 GString *
 115 mc_search__recode_str (const char *str, gsize str_len, const char *charset_from,
     /* [previous][next][first][last][top][bottom][index][help]  */
 116                        const char *charset_to)
 117 {
 118     GString *ret = NULL;
 119 
 120     if (charset_from != NULL && charset_to != NULL
 121         && g_ascii_strcasecmp (charset_to, charset_from) != 0)
 122     {
 123         GIConv conv;
 124 
 125         conv = g_iconv_open (charset_to, charset_from);
 126         if (conv != INVALID_CONV)
 127         {
 128             gchar *val;
 129             gsize bytes_read = 0;
 130             gsize bytes_written = 0;
 131 
 132             val = g_convert_with_iconv (str, str_len, conv, &bytes_read, &bytes_written, NULL);
 133 
 134             g_iconv_close (conv);
 135 
 136             if (val != NULL)
 137             {
 138                 ret = g_string_new_len (val, bytes_written);
 139                 g_free (val);
 140             }
 141         }
 142     }
 143 
 144     if (ret == NULL)
 145         ret = g_string_new_len (str, str_len);
 146 
 147     return ret;
 148 }
 149 
 150 /* --------------------------------------------------------------------------------------------- */
 151 
 152 GString *
 153 mc_search__get_one_symbol (const char *charset, const char *str, gsize str_len,
     /* [previous][next][first][last][top][bottom][index][help]  */
 154                            gboolean *just_letters)
 155 {
 156     GString *converted_str;
 157     const gchar *next_char;
 158 
 159 #ifdef HAVE_CHARSET
 160     GString *converted_str2;
 161 
 162     if (charset == NULL)
 163         charset = cp_source;
 164 
 165     converted_str = mc_search__recode_str (str, str_len, charset, cp_display);
 166 #else
 167     (void) charset;
 168 
 169     converted_str = g_string_new_len (str, str_len);
 170 #endif
 171 
 172     next_char = str_cget_next_char (converted_str->str);
 173     g_string_set_size (converted_str, (gsize) (next_char - converted_str->str));
 174 
 175 #ifdef HAVE_CHARSET
 176     converted_str2 =
 177         mc_search__recode_str (converted_str->str, converted_str->len, cp_display, charset);
 178 #endif
 179     if (just_letters != NULL)
 180         *just_letters = str_isalnum (converted_str->str) && !str_isdigit (converted_str->str);
 181 #ifdef HAVE_CHARSET
 182     g_string_free (converted_str, TRUE);
 183     return converted_str2;
 184 #else
 185     return converted_str;
 186 #endif
 187 }
 188 
 189 /* --------------------------------------------------------------------------------------------- */
 190 
 191 GString *
 192 mc_search__tolower_case_str (const char *charset, const GString *str)
     /* [previous][next][first][last][top][bottom][index][help]  */
 193 {
 194     return mc_search__change_case_str (charset, str, str_tolower);
 195 }
 196 
 197 /* --------------------------------------------------------------------------------------------- */
 198 
 199 GString *
 200 mc_search__toupper_case_str (const char *charset, const GString *str)
     /* [previous][next][first][last][top][bottom][index][help]  */
 201 {
 202     return mc_search__change_case_str (charset, str, str_toupper);
 203 }
 204 
 205 /* --------------------------------------------------------------------------------------------- */
 206 
 207 gchar **
 208 mc_search_get_types_strings_array (size_t *num)
     /* [previous][next][first][last][top][bottom][index][help]  */
 209 {
 210     gchar **ret;
 211     int lc_index;
 212     size_t n;
 213 
 214     const mc_search_type_str_t *type_str;
 215     const mc_search_type_str_t *types_str = mc_search_types_list_get (&n);
 216 
 217     ret = g_try_new0 (char *, n + 1);
 218     if (ret == NULL)
 219         return NULL;
 220 
 221     for (lc_index = 0, type_str = types_str; type_str->str != NULL; type_str++, lc_index++)
 222         ret[lc_index] = g_strdup (type_str->str);
 223 
 224     // don't count last NULL item
 225     if (num != NULL)
 226         *num = (size_t) lc_index;
 227 
 228     return ret;
 229 }
 230 
 231 /* --------------------------------------------------------------------------------------------- */

/* [previous][next][first][last][top][bottom][index][help]  */