Updated Russian translation.
[midnight-commander.git] / lib / search / glob.c
blob7002e1a866d8f0a3467ebf8068faad2a2872d959
1 /*
2 Search text engine.
3 Glob-style pattern matching
5 Copyright (C) 2009 The Free Software Foundation, Inc.
7 Written by:
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,
25 MA 02110-1301, USA.
28 #include <config.h>
30 #include "lib/global.h"
31 #include "lib/strutil.h"
32 #include "lib/search.h"
33 #include "lib/strescape.h"
35 #include "lib/charsets.h"
37 #include "internal.h"
39 /*** global variables ****************************************************************************/
41 /*** file scope macro definitions ****************************************************************/
43 /*** file scope type declarations ****************************************************************/
45 /*** file scope variables ************************************************************************/
47 /*** file scope functions ************************************************************************/
49 static GString *
50 mc_search__glob_translate_to_regex (const GString * astr)
52 const char *str = astr->str;
53 GString *buff;
54 gsize loop;
55 gboolean inside_group = FALSE;
57 buff = g_string_sized_new (32);
59 for (loop = 0; loop < astr->len; loop++)
60 switch (str[loop])
62 case '*':
63 if (!strutils_is_char_escaped (str, &(str[loop])))
64 g_string_append (buff, inside_group ? ".*" : "(.*)");
65 break;
66 case '?':
67 if (!strutils_is_char_escaped (str, &(str[loop])))
68 g_string_append (buff, inside_group ? "." : "(.)");
69 break;
70 case ',':
71 if (!strutils_is_char_escaped (str, &(str[loop])))
72 g_string_append_c (buff, '|');
73 break;
74 case '{':
75 if (!strutils_is_char_escaped (str, &(str[loop])))
77 g_string_append_c (buff, '(');
78 inside_group = TRUE;
80 break;
81 case '}':
82 if (!strutils_is_char_escaped (str, &(str[loop])))
84 g_string_append_c (buff, ')');
85 inside_group = FALSE;
87 break;
88 case '+':
89 case '.':
90 case '$':
91 case '(':
92 case ')':
93 case '^':
94 g_string_append_c (buff, '\\');
95 /* fall through */
96 default:
97 g_string_append_c (buff, str[loop]);
98 break;
101 return buff;
104 /* --------------------------------------------------------------------------------------------- */
106 static GString *
107 mc_search__translate_replace_glob_to_regex (gchar * str)
109 GString *buff;
110 int cnt = '0';
111 gboolean escaped_mode = FALSE;
113 buff = g_string_sized_new (32);
115 while (*str)
117 char c = *str++;
118 switch (c)
120 case '\\':
121 if (!escaped_mode)
123 escaped_mode = TRUE;
125 g_string_append_c (buff, c);
126 continue;
127 case '*':
128 case '?':
129 if (!escaped_mode)
131 g_string_append_c (buff, '\\');
132 c = ++cnt;
134 break;
135 case '&':
136 g_string_append_c (buff, '\\');
137 break;
139 g_string_append_c (buff, c);
140 escaped_mode = FALSE;
142 return buff;
145 /*** public functions ****************************************************************************/
147 void
148 mc_search__cond_struct_new_init_glob (const char *charset, mc_search_t * lc_mc_search,
149 mc_search_cond_t * mc_search_cond)
151 GString *tmp;
153 tmp = mc_search__glob_translate_to_regex (mc_search_cond->str);
154 g_string_free (mc_search_cond->str, TRUE);
156 if (lc_mc_search->is_entire_line)
158 g_string_prepend_c (tmp, '^');
159 g_string_append_c (tmp, '$');
161 mc_search_cond->str = tmp;
163 mc_search__cond_struct_new_init_regex (charset, lc_mc_search, mc_search_cond);
166 /* --------------------------------------------------------------------------------------------- */
168 gboolean
169 mc_search__run_glob (mc_search_t * lc_mc_search, const void *user_data,
170 gsize start_search, gsize end_search, gsize * found_len)
172 return mc_search__run_regex (lc_mc_search, user_data, start_search, end_search, found_len);
175 /* --------------------------------------------------------------------------------------------- */
177 GString *
178 mc_search_glob_prepare_replace_str (mc_search_t * lc_mc_search, GString * replace_str)
180 GString *repl = mc_search__translate_replace_glob_to_regex (replace_str->str);
181 GString *res = mc_search_regex_prepare_replace_str (lc_mc_search, repl);
182 g_string_free (repl, TRUE);
183 return res;
186 /* --------------------------------------------------------------------------------------------- */