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
);
201 g_ptr_array_add (ret
,
202 mc_search__cond_struct_new (lc_mc_search
, buffer
,
203 recoded_str_len
, codepages
[loop1
].id
));
207 g_ptr_array_add (ret
,
208 (gpointer
) mc_search__cond_struct_new (lc_mc_search
, lc_mc_search
->original
,
209 lc_mc_search
->original_len
,
213 g_ptr_array_add (ret
,
214 (gpointer
) mc_search__cond_struct_new (lc_mc_search
, lc_mc_search
->original
,
215 lc_mc_search
->original_len
,
216 str_detect_termencoding ()));
218 lc_mc_search
->conditions
= ret
;
220 return (lc_mc_search
->error
== MC_SEARCH_E_OK
);
223 /* --------------------------------------------------------------------------------------------- */
226 mc_search_run (mc_search_t
* lc_mc_search
, const void *user_data
,
227 gsize start_search
, gsize end_search
, gsize
* found_len
)
229 gboolean ret
= FALSE
;
233 if (!mc_search_is_type_avail (lc_mc_search
->search_type
)) {
234 lc_mc_search
->error
= MC_SEARCH_E_INPUT
;
235 lc_mc_search
->error_str
= g_strdup (_(STR_E_UNKNOWN_TYPE
));
238 #ifdef SEARCH_TYPE_GLIB
239 if (lc_mc_search
->regex_match_info
) {
240 g_match_info_free (lc_mc_search
->regex_match_info
);
241 lc_mc_search
->regex_match_info
= NULL
;
243 #endif /* SEARCH_TYPE_GLIB */
245 lc_mc_search
->error
= MC_SEARCH_E_OK
;
246 g_free (lc_mc_search
->error_str
);
247 lc_mc_search
->error_str
= NULL
;
249 if ((lc_mc_search
->conditions
== NULL
) && !mc_search_prepare (lc_mc_search
))
253 switch (lc_mc_search
->search_type
) {
254 case MC_SEARCH_T_NORMAL
:
255 ret
= mc_search__run_normal (lc_mc_search
, user_data
, start_search
, end_search
, found_len
);
257 case MC_SEARCH_T_REGEX
:
258 ret
= mc_search__run_regex (lc_mc_search
, user_data
, start_search
, end_search
, found_len
);
260 case MC_SEARCH_T_GLOB
:
261 ret
= mc_search__run_glob (lc_mc_search
, user_data
, start_search
, end_search
, found_len
);
263 case MC_SEARCH_T_HEX
:
264 ret
= mc_search__run_hex (lc_mc_search
, user_data
, start_search
, end_search
, found_len
);
272 /* --------------------------------------------------------------------------------------------- */
275 mc_search_is_type_avail (mc_search_type_t search_type
)
277 switch (search_type
) {
278 case MC_SEARCH_T_GLOB
:
279 case MC_SEARCH_T_NORMAL
:
280 case MC_SEARCH_T_REGEX
:
281 case MC_SEARCH_T_HEX
:
290 /* --------------------------------------------------------------------------------------------- */
292 const mc_search_type_str_t
*
293 mc_search_types_list_get (size_t *num
)
295 /* don't count last NULL item */
297 *num
= sizeof (mc_search__list_types
) / sizeof (mc_search__list_types
[0]) - 1;
299 return mc_search__list_types
;
302 /* --------------------------------------------------------------------------------------------- */
305 mc_search_prepare_replace_str (mc_search_t
* lc_mc_search
, GString
* replace_str
)
309 if (lc_mc_search
== NULL
)
310 return g_string_new_len (replace_str
->str
, replace_str
->len
);
312 if (replace_str
== NULL
|| replace_str
->str
== NULL
|| replace_str
->len
== 0)
313 return g_string_new ("");
315 switch (lc_mc_search
->search_type
) {
316 case MC_SEARCH_T_REGEX
:
317 ret
= mc_search_regex_prepare_replace_str (lc_mc_search
, replace_str
);
319 case MC_SEARCH_T_GLOB
:
320 ret
= mc_search_glob_prepare_replace_str (lc_mc_search
, replace_str
);
322 case MC_SEARCH_T_NORMAL
:
323 ret
= mc_search_normal_prepare_replace_str (lc_mc_search
, replace_str
);
325 case MC_SEARCH_T_HEX
:
326 ret
= mc_search_hex_prepare_replace_str (lc_mc_search
, replace_str
);
329 ret
= g_string_new_len (replace_str
->str
, replace_str
->len
);
335 /* --------------------------------------------------------------------------------------------- */
338 mc_search_prepare_replace_str2 (mc_search_t
* lc_mc_search
, char *replace_str
)
341 GString
*replace_str2
= g_string_new (replace_str
);
342 ret
= mc_search_prepare_replace_str (lc_mc_search
, replace_str2
);
343 g_string_free (replace_str2
, TRUE
);
345 return g_string_free (ret
, FALSE
);
349 /* --------------------------------------------------------------------------------------------- */
352 mc_search_is_fixed_search_str (mc_search_t
* lc_mc_search
)
354 if (lc_mc_search
== NULL
)
356 switch (lc_mc_search
->search_type
) {
357 case MC_SEARCH_T_REGEX
:
358 case MC_SEARCH_T_GLOB
:
367 /* --------------------------------------------------------------------------------------------- */
370 mc_search (const gchar
* pattern
, const gchar
* str
, mc_search_type_t type
)
373 mc_search_t
*search
= mc_search_new (pattern
, -1);
376 search
->search_type
= type
;
377 search
->is_case_sentitive
= TRUE
;
379 if (type
== MC_SEARCH_T_GLOB
)
380 search
->is_entire_line
= TRUE
;
382 ret
= mc_search_run (search
, str
, 0, strlen (str
), NULL
);
383 mc_search_free (search
);
387 /* --------------------------------------------------------------------------------------------- */
390 mc_search_getstart_rezult_by_num (mc_search_t
* lc_mc_search
, int lc_index
)
394 if (lc_mc_search
->search_type
== MC_SEARCH_T_NORMAL
)
396 #ifdef SEARCH_TYPE_GLIB
400 g_match_info_fetch_pos (lc_mc_search
->regex_match_info
, lc_index
, &start_pos
, &end_pos
);
401 return (int) start_pos
;
403 #else /* SEARCH_TYPE_GLIB */
404 return lc_mc_search
->iovector
[lc_index
* 2];
405 #endif /* SEARCH_TYPE_GLIB */
409 /* --------------------------------------------------------------------------------------------- */
412 mc_search_getend_rezult_by_num (mc_search_t
* lc_mc_search
, int lc_index
)
416 if (lc_mc_search
->search_type
== MC_SEARCH_T_NORMAL
)
418 #ifdef SEARCH_TYPE_GLIB
422 g_match_info_fetch_pos (lc_mc_search
->regex_match_info
, lc_index
, &start_pos
, &end_pos
);
423 return (int) end_pos
;
425 #else /* SEARCH_TYPE_GLIB */
426 return lc_mc_search
->iovector
[lc_index
* 2 + 1];
427 #endif /* SEARCH_TYPE_GLIB */
431 /* --------------------------------------------------------------------------------------------- */