5 Copyright (C) 2009 The Free Software Foundation, Inc.
8 Slava Zanko <slavazanko@gmail.com>, 2009.
10 This file is part of the Midnight Commander.
12 The Midnight Commander is free software; you can redistribute it
13 and/or modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation; either version 2 of the
15 License, or (at your option) any later version.
17 The Midnight Commander is distributed in the hope that it will be
18 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
19 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
31 #include <sys/types.h>
33 #include "lib/global.h"
34 #include "lib/strutil.h"
35 #include "lib/search.h"
37 #include "src/charsets.h"
41 /*** global variables ****************************************************************************/
43 /*** file scope macro definitions ****************************************************************/
45 /*** file scope type declarations ****************************************************************/
47 /*** file scope variables ************************************************************************/
49 static const mc_search_type_str_t mc_search__list_types
[] = {
50 {N_("Normal"), MC_SEARCH_T_NORMAL
},
51 {N_("&Regular expression"), MC_SEARCH_T_REGEX
},
52 {N_("Hexadecimal"), MC_SEARCH_T_HEX
},
53 {N_("Wildcard search"), MC_SEARCH_T_GLOB
},
57 /*** file scope functions ************************************************************************/
59 static mc_search_cond_t
*
60 mc_search__cond_struct_new (mc_search_t
* lc_mc_search
, const char *str
,
61 gsize str_len
, const char *charset
)
63 mc_search_cond_t
*mc_search_cond
;
64 mc_search_cond
= g_malloc0 (sizeof (mc_search_cond_t
));
66 mc_search_cond
->str
= g_string_new_len (str
, str_len
);
67 mc_search_cond
->len
= str_len
;
68 mc_search_cond
->charset
= g_strdup (charset
);
70 switch (lc_mc_search
->search_type
) {
71 case MC_SEARCH_T_GLOB
:
72 mc_search__cond_struct_new_init_glob (charset
, lc_mc_search
, mc_search_cond
);
74 case MC_SEARCH_T_NORMAL
:
75 mc_search__cond_struct_new_init_normal (charset
, lc_mc_search
, mc_search_cond
);
77 case MC_SEARCH_T_REGEX
:
78 mc_search__cond_struct_new_init_regex (charset
, lc_mc_search
, mc_search_cond
);
81 mc_search__cond_struct_new_init_hex (charset
, lc_mc_search
, mc_search_cond
);
86 return mc_search_cond
;
89 /* --------------------------------------------------------------------------------------------- */
92 mc_search__cond_struct_free (mc_search_cond_t
* mc_search_cond
)
94 if (mc_search_cond
->upper
)
95 g_string_free (mc_search_cond
->upper
, TRUE
);
97 if (mc_search_cond
->lower
)
98 g_string_free (mc_search_cond
->lower
, TRUE
);
100 g_string_free (mc_search_cond
->str
, TRUE
);
101 g_free (mc_search_cond
->charset
);
103 #ifdef SEARCH_TYPE_GLIB
104 if (mc_search_cond
->regex_handle
)
105 g_regex_unref (mc_search_cond
->regex_handle
);
106 #else /* SEARCH_TYPE_GLIB */
107 g_free (mc_search_cond
->regex_handle
);
108 #endif /* SEARCH_TYPE_GLIB */
110 g_free (mc_search_cond
);
113 /* --------------------------------------------------------------------------------------------- */
116 mc_search__conditions_free (GPtrArray
* array
)
119 mc_search_cond_t
*lc_mc_search
;
121 for (loop1
= 0; loop1
< array
->len
; loop1
++) {
122 lc_mc_search
= (mc_search_cond_t
*) g_ptr_array_index (array
, loop1
);
123 mc_search__cond_struct_free (lc_mc_search
);
125 g_ptr_array_free (array
, TRUE
);
128 /* --------------------------------------------------------------------------------------------- */
132 /*** public functions ****************************************************************************/
135 mc_search_new (const gchar
* original
, gsize str_len
)
137 mc_search_t
*lc_mc_search
;
141 if ((gssize
) str_len
== -1) {
142 str_len
= strlen (original
);
147 lc_mc_search
= g_malloc0 (sizeof (mc_search_t
));
148 lc_mc_search
->original
= g_strndup (original
, str_len
);
149 lc_mc_search
->original_len
= str_len
;
153 /* --------------------------------------------------------------------------------------------- */
156 mc_search_free (mc_search_t
* lc_mc_search
)
161 g_free (lc_mc_search
->original
);
162 g_free (lc_mc_search
->error_str
);
164 if (lc_mc_search
->conditions
)
165 mc_search__conditions_free (lc_mc_search
->conditions
);
167 #ifdef SEARCH_TYPE_GLIB
168 if (lc_mc_search
->regex_match_info
)
169 g_match_info_free (lc_mc_search
->regex_match_info
);
170 #else /* SEARCH_TYPE_GLIB */
171 g_free (lc_mc_search
->regex_match_info
);
172 #endif /* SEARCH_TYPE_GLIB */
174 if (lc_mc_search
->regex_buffer
!= NULL
)
175 g_string_free (lc_mc_search
->regex_buffer
, TRUE
);
177 g_free (lc_mc_search
);
180 /* --------------------------------------------------------------------------------------------- */
183 mc_search_prepare (mc_search_t
* lc_mc_search
)
186 ret
= g_ptr_array_new ();
188 if (lc_mc_search
->is_all_charsets
) {
189 gsize loop1
, recoded_str_len
;
191 for (loop1
= 0; loop1
< (gsize
) n_codepages
; loop1
++) {
192 if (!g_ascii_strcasecmp (codepages
[loop1
].id
, cp_source
)) {
193 g_ptr_array_add (ret
,
194 mc_search__cond_struct_new (lc_mc_search
, lc_mc_search
->original
,
195 lc_mc_search
->original_len
, cp_source
));
200 mc_search__recode_str (lc_mc_search
->original
, lc_mc_search
->original_len
, cp_source
,
201 codepages
[loop1
].id
, &recoded_str_len
);
203 g_ptr_array_add (ret
,
204 mc_search__cond_struct_new (lc_mc_search
, buffer
,
205 recoded_str_len
, codepages
[loop1
].id
));
209 g_ptr_array_add (ret
,
210 (gpointer
) mc_search__cond_struct_new (lc_mc_search
, lc_mc_search
->original
,
211 lc_mc_search
->original_len
,
215 g_ptr_array_add (ret
,
216 (gpointer
) mc_search__cond_struct_new (lc_mc_search
, lc_mc_search
->original
,
217 lc_mc_search
->original_len
,
218 str_detect_termencoding ()));
220 lc_mc_search
->conditions
= ret
;
222 return (lc_mc_search
->error
== MC_SEARCH_E_OK
);
225 /* --------------------------------------------------------------------------------------------- */
228 mc_search_run (mc_search_t
* lc_mc_search
, const void *user_data
,
229 gsize start_search
, gsize end_search
, gsize
* found_len
)
231 gboolean ret
= FALSE
;
235 if (!mc_search_is_type_avail (lc_mc_search
->search_type
)) {
236 lc_mc_search
->error
= MC_SEARCH_E_INPUT
;
237 lc_mc_search
->error_str
= g_strdup (_(STR_E_UNKNOWN_TYPE
));
240 #ifdef SEARCH_TYPE_GLIB
241 if (lc_mc_search
->regex_match_info
) {
242 g_match_info_free (lc_mc_search
->regex_match_info
);
243 lc_mc_search
->regex_match_info
= NULL
;
245 #endif /* SEARCH_TYPE_GLIB */
247 lc_mc_search
->error
= MC_SEARCH_E_OK
;
248 g_free (lc_mc_search
->error_str
);
249 lc_mc_search
->error_str
= NULL
;
251 if ((lc_mc_search
->conditions
== NULL
) && !mc_search_prepare (lc_mc_search
))
255 switch (lc_mc_search
->search_type
) {
256 case MC_SEARCH_T_NORMAL
:
257 ret
= mc_search__run_normal (lc_mc_search
, user_data
, start_search
, end_search
, found_len
);
259 case MC_SEARCH_T_REGEX
:
260 ret
= mc_search__run_regex (lc_mc_search
, user_data
, start_search
, end_search
, found_len
);
262 case MC_SEARCH_T_GLOB
:
263 ret
= mc_search__run_glob (lc_mc_search
, user_data
, start_search
, end_search
, found_len
);
265 case MC_SEARCH_T_HEX
:
266 ret
= mc_search__run_hex (lc_mc_search
, user_data
, start_search
, end_search
, found_len
);
274 /* --------------------------------------------------------------------------------------------- */
277 mc_search_is_type_avail (mc_search_type_t search_type
)
279 switch (search_type
) {
280 case MC_SEARCH_T_GLOB
:
281 case MC_SEARCH_T_NORMAL
:
282 case MC_SEARCH_T_REGEX
:
283 case MC_SEARCH_T_HEX
:
292 /* --------------------------------------------------------------------------------------------- */
294 const mc_search_type_str_t
*
295 mc_search_types_list_get (size_t *num
)
297 /* don't count last NULL item */
299 *num
= sizeof (mc_search__list_types
) / sizeof (mc_search__list_types
[0]) - 1;
301 return mc_search__list_types
;
304 /* --------------------------------------------------------------------------------------------- */
307 mc_search_prepare_replace_str (mc_search_t
* lc_mc_search
, GString
* replace_str
)
311 if (lc_mc_search
== NULL
)
312 return g_string_new_len (replace_str
->str
, replace_str
->len
);
314 if (replace_str
== NULL
|| replace_str
->str
== NULL
|| replace_str
->len
== 0)
315 return g_string_new ("");
317 switch (lc_mc_search
->search_type
) {
318 case MC_SEARCH_T_REGEX
:
319 ret
= mc_search_regex_prepare_replace_str (lc_mc_search
, replace_str
);
321 case MC_SEARCH_T_GLOB
:
322 ret
= mc_search_glob_prepare_replace_str (lc_mc_search
, replace_str
);
324 case MC_SEARCH_T_NORMAL
:
325 ret
= mc_search_normal_prepare_replace_str (lc_mc_search
, replace_str
);
327 case MC_SEARCH_T_HEX
:
328 ret
= mc_search_hex_prepare_replace_str (lc_mc_search
, replace_str
);
331 ret
= g_string_new_len (replace_str
->str
, replace_str
->len
);
337 /* --------------------------------------------------------------------------------------------- */
340 mc_search_prepare_replace_str2 (mc_search_t
* lc_mc_search
, char *replace_str
)
343 GString
*replace_str2
= g_string_new (replace_str
);
344 ret
= mc_search_prepare_replace_str (lc_mc_search
, replace_str2
);
345 g_string_free (replace_str2
, TRUE
);
347 return g_string_free (ret
, FALSE
);
351 /* --------------------------------------------------------------------------------------------- */
354 mc_search_is_fixed_search_str (mc_search_t
* lc_mc_search
)
356 if (lc_mc_search
== NULL
)
358 switch (lc_mc_search
->search_type
) {
359 case MC_SEARCH_T_REGEX
:
360 case MC_SEARCH_T_GLOB
:
369 /* --------------------------------------------------------------------------------------------- */
372 mc_search (const gchar
* pattern
, const gchar
* str
, mc_search_type_t type
)
375 mc_search_t
*search
= mc_search_new (pattern
, -1);
378 search
->search_type
= type
;
379 search
->is_case_sentitive
= TRUE
;
381 if (type
== MC_SEARCH_T_GLOB
)
382 search
->is_entire_line
= TRUE
;
384 ret
= mc_search_run (search
, str
, 0, strlen (str
), NULL
);
385 mc_search_free (search
);
389 /* --------------------------------------------------------------------------------------------- */
392 mc_search_getstart_rezult_by_num (mc_search_t
* lc_mc_search
, int lc_index
)
396 if (lc_mc_search
->search_type
== MC_SEARCH_T_NORMAL
)
398 #ifdef SEARCH_TYPE_GLIB
402 g_match_info_fetch_pos (lc_mc_search
->regex_match_info
, lc_index
, &start_pos
, &end_pos
);
403 return (int) start_pos
;
405 #else /* SEARCH_TYPE_GLIB */
406 return lc_mc_search
->iovector
[lc_index
* 2];
407 #endif /* SEARCH_TYPE_GLIB */
411 /* --------------------------------------------------------------------------------------------- */
414 mc_search_getend_rezult_by_num (mc_search_t
* lc_mc_search
, int lc_index
)
418 if (lc_mc_search
->search_type
== MC_SEARCH_T_NORMAL
)
420 #ifdef SEARCH_TYPE_GLIB
424 g_match_info_fetch_pos (lc_mc_search
->regex_match_info
, lc_index
, &start_pos
, &end_pos
);
425 return (int) end_pos
;
427 #else /* SEARCH_TYPE_GLIB */
428 return lc_mc_search
->iovector
[lc_index
* 2 + 1];
429 #endif /* SEARCH_TYPE_GLIB */
433 /* --------------------------------------------------------------------------------------------- */