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
->charset
= g_strdup (charset
);
69 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
++)
123 lc_mc_search
= (mc_search_cond_t
*) g_ptr_array_index (array
, loop1
);
124 mc_search__cond_struct_free (lc_mc_search
);
126 g_ptr_array_free (array
, TRUE
);
129 /* --------------------------------------------------------------------------------------------- */
131 /*** public functions ****************************************************************************/
134 mc_search_new (const gchar
* original
, gsize str_len
)
136 mc_search_t
*lc_mc_search
;
140 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
)
158 if (lc_mc_search
== NULL
)
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
)
190 gsize loop1
, recoded_str_len
;
192 for (loop1
= 0; loop1
< codepages
->len
; loop1
++)
194 const char *id
= ((codepage_desc
*) g_ptr_array_index (codepages
, loop1
))->id
;
195 if (!g_ascii_strcasecmp (id
, cp_source
))
197 g_ptr_array_add (ret
,
198 mc_search__cond_struct_new (lc_mc_search
, lc_mc_search
->original
,
199 lc_mc_search
->original_len
,
205 mc_search__recode_str (lc_mc_search
->original
, lc_mc_search
->original_len
,
206 cp_source
, id
, &recoded_str_len
);
208 g_ptr_array_add (ret
,
209 mc_search__cond_struct_new (lc_mc_search
, buffer
,
210 recoded_str_len
, id
));
216 g_ptr_array_add (ret
,
217 (gpointer
) mc_search__cond_struct_new (lc_mc_search
,
218 lc_mc_search
->original
,
219 lc_mc_search
->original_len
,
223 g_ptr_array_add (ret
,
224 (gpointer
) mc_search__cond_struct_new (lc_mc_search
, lc_mc_search
->original
,
225 lc_mc_search
->original_len
,
226 str_detect_termencoding ()));
228 lc_mc_search
->conditions
= ret
;
230 return (lc_mc_search
->error
== MC_SEARCH_E_OK
);
233 /* --------------------------------------------------------------------------------------------- */
236 mc_search_run (mc_search_t
* lc_mc_search
, const void *user_data
,
237 gsize start_search
, gsize end_search
, gsize
* found_len
)
239 gboolean ret
= FALSE
;
243 if (!mc_search_is_type_avail (lc_mc_search
->search_type
))
245 lc_mc_search
->error
= MC_SEARCH_E_INPUT
;
246 lc_mc_search
->error_str
= g_strdup (_(STR_E_UNKNOWN_TYPE
));
249 #ifdef SEARCH_TYPE_GLIB
250 if (lc_mc_search
->regex_match_info
)
252 g_match_info_free (lc_mc_search
->regex_match_info
);
253 lc_mc_search
->regex_match_info
= NULL
;
255 #endif /* SEARCH_TYPE_GLIB */
257 lc_mc_search
->error
= MC_SEARCH_E_OK
;
258 g_free (lc_mc_search
->error_str
);
259 lc_mc_search
->error_str
= NULL
;
261 if ((lc_mc_search
->conditions
== NULL
) && !mc_search_prepare (lc_mc_search
))
264 switch (lc_mc_search
->search_type
)
266 case MC_SEARCH_T_NORMAL
:
267 ret
= mc_search__run_normal (lc_mc_search
, user_data
, start_search
, end_search
, found_len
);
269 case MC_SEARCH_T_REGEX
:
270 ret
= mc_search__run_regex (lc_mc_search
, user_data
, start_search
, end_search
, found_len
);
272 case MC_SEARCH_T_GLOB
:
273 ret
= mc_search__run_glob (lc_mc_search
, user_data
, start_search
, end_search
, found_len
);
275 case MC_SEARCH_T_HEX
:
276 ret
= mc_search__run_hex (lc_mc_search
, user_data
, start_search
, end_search
, found_len
);
284 /* --------------------------------------------------------------------------------------------- */
287 mc_search_is_type_avail (mc_search_type_t search_type
)
291 case MC_SEARCH_T_GLOB
:
292 case MC_SEARCH_T_NORMAL
:
293 case MC_SEARCH_T_REGEX
:
294 case MC_SEARCH_T_HEX
:
302 /* --------------------------------------------------------------------------------------------- */
304 const mc_search_type_str_t
*
305 mc_search_types_list_get (size_t * num
)
307 /* don't count last NULL item */
309 *num
= sizeof (mc_search__list_types
) / sizeof (mc_search__list_types
[0]) - 1;
311 return mc_search__list_types
;
314 /* --------------------------------------------------------------------------------------------- */
317 mc_search_prepare_replace_str (mc_search_t
* lc_mc_search
, GString
* replace_str
)
321 if (lc_mc_search
== NULL
)
322 return g_string_new_len (replace_str
->str
, replace_str
->len
);
324 if (replace_str
== NULL
|| replace_str
->str
== NULL
|| replace_str
->len
== 0)
325 return g_string_new ("");
327 switch (lc_mc_search
->search_type
)
329 case MC_SEARCH_T_REGEX
:
330 ret
= mc_search_regex_prepare_replace_str (lc_mc_search
, replace_str
);
332 case MC_SEARCH_T_GLOB
:
333 ret
= mc_search_glob_prepare_replace_str (lc_mc_search
, replace_str
);
335 case MC_SEARCH_T_NORMAL
:
336 ret
= mc_search_normal_prepare_replace_str (lc_mc_search
, replace_str
);
338 case MC_SEARCH_T_HEX
:
339 ret
= mc_search_hex_prepare_replace_str (lc_mc_search
, replace_str
);
342 ret
= g_string_new_len (replace_str
->str
, replace_str
->len
);
348 /* --------------------------------------------------------------------------------------------- */
351 mc_search_prepare_replace_str2 (mc_search_t
* lc_mc_search
, char *replace_str
)
354 GString
*replace_str2
;
356 replace_str2
= g_string_new (replace_str
);
357 ret
= mc_search_prepare_replace_str (lc_mc_search
, replace_str2
);
358 g_string_free (replace_str2
, TRUE
);
359 return (ret
!= NULL
) ? g_string_free (ret
, FALSE
) : NULL
;
362 /* --------------------------------------------------------------------------------------------- */
365 mc_search_is_fixed_search_str (mc_search_t
* lc_mc_search
)
367 if (lc_mc_search
== NULL
)
369 switch (lc_mc_search
->search_type
)
371 case MC_SEARCH_T_REGEX
:
372 case MC_SEARCH_T_GLOB
:
379 /* --------------------------------------------------------------------------------------------- */
382 mc_search (const gchar
* pattern
, const gchar
* str
, mc_search_type_t type
)
385 mc_search_t
*search
= mc_search_new (pattern
, -1);
388 search
->search_type
= type
;
389 search
->is_case_sensitive
= TRUE
;
391 if (type
== MC_SEARCH_T_GLOB
)
392 search
->is_entire_line
= TRUE
;
394 ret
= mc_search_run (search
, str
, 0, strlen (str
), NULL
);
395 mc_search_free (search
);
399 /* --------------------------------------------------------------------------------------------- */
402 mc_search_getstart_result_by_num (mc_search_t
* lc_mc_search
, int lc_index
)
406 if (lc_mc_search
->search_type
== MC_SEARCH_T_NORMAL
)
408 #ifdef SEARCH_TYPE_GLIB
412 g_match_info_fetch_pos (lc_mc_search
->regex_match_info
, lc_index
, &start_pos
, &end_pos
);
413 return (int) start_pos
;
415 #else /* SEARCH_TYPE_GLIB */
416 return lc_mc_search
->iovector
[lc_index
* 2];
417 #endif /* SEARCH_TYPE_GLIB */
420 /* --------------------------------------------------------------------------------------------- */
423 mc_search_getend_result_by_num (mc_search_t
* lc_mc_search
, int lc_index
)
427 if (lc_mc_search
->search_type
== MC_SEARCH_T_NORMAL
)
429 #ifdef SEARCH_TYPE_GLIB
433 g_match_info_fetch_pos (lc_mc_search
->regex_match_info
, lc_index
, &start_pos
, &end_pos
);
434 return (int) end_pos
;
436 #else /* SEARCH_TYPE_GLIB */
437 return lc_mc_search
->iovector
[lc_index
* 2 + 1];
438 #endif /* SEARCH_TYPE_GLIB */
441 /* --------------------------------------------------------------------------------------------- */