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 "../src/global.h"
34 #include "../src/search/search.h"
35 #include "../src/search/internal.h"
36 #include "../src/strutil.h"
37 #include "../src/charsets.h"
39 /*** global variables ****************************************************************************/
41 /*** file scope macro definitions ****************************************************************/
43 /*** file scope type declarations ****************************************************************/
45 /*** file scope variables ************************************************************************/
47 static const mc_search_type_str_t mc_search__list_types
[] = {
48 {N_("Normal"), MC_SEARCH_T_NORMAL
},
49 {N_("&Regular expression"), MC_SEARCH_T_REGEX
},
50 {N_("Hexadecimal"), MC_SEARCH_T_HEX
},
51 {N_("Wildcard search"), MC_SEARCH_T_GLOB
},
55 /*** file scope functions ************************************************************************/
57 static mc_search_cond_t
*
58 mc_search__cond_struct_new (mc_search_t
* lc_mc_search
, const char *str
,
59 gsize str_len
, const char *charset
)
61 mc_search_cond_t
*mc_search_cond
;
62 mc_search_cond
= g_malloc0 (sizeof (mc_search_cond_t
));
64 mc_search_cond
->str
= g_string_new_len (str
, str_len
);
65 mc_search_cond
->len
= str_len
;
66 mc_search_cond
->charset
= g_strdup (charset
);
68 switch (lc_mc_search
->search_type
) {
69 case MC_SEARCH_T_GLOB
:
70 mc_search__cond_struct_new_init_glob (charset
, lc_mc_search
, mc_search_cond
);
72 case MC_SEARCH_T_NORMAL
:
73 mc_search__cond_struct_new_init_normal (charset
, lc_mc_search
, mc_search_cond
);
75 case MC_SEARCH_T_REGEX
:
76 mc_search__cond_struct_new_init_regex (charset
, lc_mc_search
, mc_search_cond
);
79 mc_search__cond_struct_new_init_hex (charset
, lc_mc_search
, mc_search_cond
);
84 return mc_search_cond
;
87 /* --------------------------------------------------------------------------------------------- */
90 mc_search__cond_struct_free (mc_search_cond_t
* mc_search_cond
)
92 if (mc_search_cond
->upper
)
93 g_string_free (mc_search_cond
->upper
, TRUE
);
95 if (mc_search_cond
->lower
)
96 g_string_free (mc_search_cond
->lower
, TRUE
);
98 g_string_free (mc_search_cond
->str
, TRUE
);
99 g_free (mc_search_cond
->charset
);
101 #ifdef SEARCH_TYPE_GLIB
102 if (mc_search_cond
->regex_handle
)
103 g_regex_unref (mc_search_cond
->regex_handle
);
104 #else /* SEARCH_TYPE_GLIB */
105 g_free (mc_search_cond
->regex_handle
);
106 #endif /* SEARCH_TYPE_GLIB */
108 g_free (mc_search_cond
);
111 /* --------------------------------------------------------------------------------------------- */
114 mc_search__conditions_free (GPtrArray
* array
)
117 mc_search_cond_t
*lc_mc_search
;
119 for (loop1
= 0; loop1
< array
->len
; loop1
++) {
120 lc_mc_search
= (mc_search_cond_t
*) g_ptr_array_index (array
, loop1
);
121 mc_search__cond_struct_free (lc_mc_search
);
123 g_ptr_array_free (array
, TRUE
);
126 /* --------------------------------------------------------------------------------------------- */
130 /*** public functions ****************************************************************************/
133 mc_search_new (const gchar
* original
, gsize str_len
)
135 mc_search_t
*lc_mc_search
;
139 if ((gssize
) str_len
== -1) {
140 str_len
= strlen (original
);
145 lc_mc_search
= g_malloc0 (sizeof (mc_search_t
));
146 lc_mc_search
->original
= g_strndup (original
, str_len
);
147 lc_mc_search
->original_len
= str_len
;
151 /* --------------------------------------------------------------------------------------------- */
154 mc_search_free (mc_search_t
* lc_mc_search
)
159 g_free (lc_mc_search
->original
);
160 g_free (lc_mc_search
->error_str
);
162 if (lc_mc_search
->conditions
)
163 mc_search__conditions_free (lc_mc_search
->conditions
);
165 #ifdef SEARCH_TYPE_GLIB
166 if (lc_mc_search
->regex_match_info
)
167 g_match_info_free (lc_mc_search
->regex_match_info
);
168 #else /* SEARCH_TYPE_GLIB */
169 g_free (lc_mc_search
->regex_match_info
);
170 #endif /* SEARCH_TYPE_GLIB */
172 if (lc_mc_search
->regex_buffer
!= NULL
)
173 g_string_free (lc_mc_search
->regex_buffer
, TRUE
);
175 g_free (lc_mc_search
);
178 /* --------------------------------------------------------------------------------------------- */
181 mc_search_prepare (mc_search_t
* lc_mc_search
)
184 ret
= g_ptr_array_new ();
186 if (lc_mc_search
->is_all_charsets
) {
187 gsize loop1
, recoded_str_len
;
189 for (loop1
= 0; loop1
< (gsize
) n_codepages
; loop1
++) {
190 if (!g_ascii_strcasecmp (codepages
[loop1
].id
, cp_source
)) {
191 g_ptr_array_add (ret
,
192 mc_search__cond_struct_new (lc_mc_search
, lc_mc_search
->original
,
193 lc_mc_search
->original_len
, cp_source
));
198 mc_search__recode_str (lc_mc_search
->original
, lc_mc_search
->original_len
, cp_source
,
199 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 /* --------------------------------------------------------------------------------------------- */