5 Copyright (C) 2009, 2011
6 The Free Software Foundation, Inc.
9 Slava Zanko <slavazanko@gmail.com>, 2009,2010,2011
10 Vitaliy Filippov <vitalif@yourcmc.ru>, 2011
12 This file is part of the Midnight Commander.
14 The Midnight Commander is free software: you can redistribute it
15 and/or modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation, either version 3 of the License,
17 or (at your option) any later version.
19 The Midnight Commander is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with this program. If not, see <http://www.gnu.org/licenses/>.
32 #include "lib/global.h"
33 #include "lib/strutil.h"
34 #include "lib/search.h"
35 #include "lib/strescape.h"
37 #include "lib/charsets.h"
41 /*** global variables ****************************************************************************/
43 /*** file scope macro definitions ****************************************************************/
45 #define REPLACE_PREPARE_T_NOTHING_SPECIAL -1
46 #define REPLACE_PREPARE_T_REPLACE_FLAG -2
47 #define REPLACE_PREPARE_T_ESCAPE_SEQ -3
49 /*** file scope type declarations ****************************************************************/
53 REPLACE_T_NO_TRANSFORM
= 0,
54 REPLACE_T_UPP_TRANSFORM_CHAR
= 1,
55 REPLACE_T_LOW_TRANSFORM_CHAR
= 2,
56 REPLACE_T_UPP_TRANSFORM
= 4,
57 REPLACE_T_LOW_TRANSFORM
= 8
58 } replace_transform_type_t
;
61 /*** file scope variables ************************************************************************/
63 /*** file scope functions ************************************************************************/
66 mc_search__regex_str_append_if_special (GString
* copy_to
, const GString
* regex_str
,
71 const char **spec_chr
;
72 const char *special_chars
[] = {
87 spec_chr
= special_chars
;
89 tmp_regex_str
= &(regex_str
->str
[*offset
]);
93 spec_chr_len
= strlen (*spec_chr
);
94 if (!strncmp (tmp_regex_str
, *spec_chr
, spec_chr_len
))
96 if (!strutils_is_char_escaped (regex_str
->str
, tmp_regex_str
))
98 if (!strncmp ("\\x", *spec_chr
, spec_chr_len
))
100 if (*(tmp_regex_str
+ spec_chr_len
) == '{')
102 while ((spec_chr_len
< regex_str
->len
- *offset
)
103 && *(tmp_regex_str
+ spec_chr_len
) != '}')
105 if (*(tmp_regex_str
+ spec_chr_len
) == '}')
111 g_string_append_len (copy_to
, tmp_regex_str
, spec_chr_len
);
112 *offset
+= spec_chr_len
;
122 /* --------------------------------------------------------------------------------------------- */
124 mc_search__cond_struct_new_regex_hex_add (const char *charset
, GString
* str_to
,
125 const char *one_char
, gsize str_len
)
131 upp
= mc_search__toupper_case_str (charset
, one_char
, str_len
);
132 low
= mc_search__tolower_case_str (charset
, one_char
, str_len
);
134 for (loop
= 0; loop
< upp
->len
; loop
++)
139 if (upp
->str
[loop
] == low
->str
[loop
])
140 tmp_str
= g_strdup_printf ("\\x%02X", (unsigned char) upp
->str
[loop
]);
143 g_strdup_printf ("[\\x%02X\\x%02X]", (unsigned char) upp
->str
[loop
],
144 (unsigned char) low
->str
[loop
]);
148 tmp_str
= g_strdup_printf ("\\x%02X", (unsigned char) upp
->str
[loop
]);
150 g_string_append (str_to
, tmp_str
);
153 g_string_free (upp
, TRUE
);
154 g_string_free (low
, TRUE
);
157 /* --------------------------------------------------------------------------------------------- */
160 mc_search__cond_struct_new_regex_accum_append (const char *charset
, GString
* str_to
,
163 GString
*recoded_part
;
166 recoded_part
= g_string_sized_new (32);
168 while (loop
< str_from
->len
)
172 gboolean just_letters
;
175 mc_search__get_one_symbol (charset
, &(str_from
->str
[loop
]),
176 min (str_from
->len
- loop
, 6), &just_letters
);
177 one_char_len
= strlen (one_char
);
179 if (one_char_len
== 0)
183 loop
+= one_char_len
;
186 mc_search__cond_struct_new_regex_hex_add (charset
, recoded_part
, one_char
,
189 g_string_append_len (recoded_part
, one_char
, one_char_len
);
195 g_string_append (str_to
, recoded_part
->str
);
196 g_string_free (recoded_part
, TRUE
);
197 g_string_set_size (str_from
, 0);
200 /* --------------------------------------------------------------------------------------------- */
203 mc_search__cond_struct_new_regex_ci_str (const char *charset
, const GString
* astr
)
205 GString
*accumulator
, *spec_char
, *ret_str
;
208 ret_str
= g_string_sized_new (64);
209 accumulator
= g_string_sized_new (64);
210 spec_char
= g_string_sized_new (64);
213 while (loop
<= astr
->len
)
215 if (mc_search__regex_str_append_if_special (spec_char
, astr
, &loop
))
217 mc_search__cond_struct_new_regex_accum_append (charset
, ret_str
, accumulator
);
218 g_string_append_len (ret_str
, spec_char
->str
, spec_char
->len
);
219 g_string_set_size (spec_char
, 0);
223 if (astr
->str
[loop
] == '[' && !strutils_is_char_escaped (astr
->str
, &(astr
->str
[loop
])))
225 mc_search__cond_struct_new_regex_accum_append (charset
, ret_str
, accumulator
);
227 while (loop
< astr
->len
&& !(astr
->str
[loop
] == ']'
228 && !strutils_is_char_escaped (astr
->str
,
229 &(astr
->str
[loop
]))))
231 g_string_append_c (ret_str
, astr
->str
[loop
]);
235 g_string_append_c (ret_str
, astr
->str
[loop
]);
242 g_string_append_c (accumulator
, astr
->str
[loop
]);
245 mc_search__cond_struct_new_regex_accum_append (charset
, ret_str
, accumulator
);
247 g_string_free (accumulator
, TRUE
);
248 g_string_free (spec_char
, TRUE
);
253 /* --------------------------------------------------------------------------------------------- */
255 static mc_search__found_cond_t
256 mc_search__regex_found_cond_one (mc_search_t
* lc_mc_search
, mc_search_regex_t
* regex
,
257 GString
* search_str
)
259 #ifdef SEARCH_TYPE_GLIB
260 GError
*error
= NULL
;
262 if (!g_regex_match_full
263 (regex
, search_str
->str
, -1, 0, G_REGEX_MATCH_NEWLINE_ANY
, &lc_mc_search
->regex_match_info
,
266 g_match_info_free (lc_mc_search
->regex_match_info
);
267 lc_mc_search
->regex_match_info
= NULL
;
270 lc_mc_search
->error
= MC_SEARCH_E_REGEX
;
271 lc_mc_search
->error_str
=
272 str_conv_gerror_message (error
, _("Regular expression error"));
273 g_error_free (error
);
274 return COND__FOUND_ERROR
;
276 return COND__NOT_FOUND
;
278 lc_mc_search
->num_results
= g_match_info_get_match_count (lc_mc_search
->regex_match_info
);
279 #else /* SEARCH_TYPE_GLIB */
280 lc_mc_search
->num_results
= pcre_exec (regex
, lc_mc_search
->regex_match_info
,
281 search_str
->str
, search_str
->len
- 1, 0, 0,
282 lc_mc_search
->iovector
, MC_SEARCH__NUM_REPLACE_ARGS
);
283 if (lc_mc_search
->num_results
< 0)
285 return COND__NOT_FOUND
;
287 #endif /* SEARCH_TYPE_GLIB */
288 return COND__FOUND_OK
;
292 /* --------------------------------------------------------------------------------------------- */
294 static mc_search__found_cond_t
295 mc_search__regex_found_cond (mc_search_t
* lc_mc_search
, GString
* search_str
)
298 mc_search_cond_t
*mc_search_cond
;
299 mc_search__found_cond_t ret
;
301 for (loop1
= 0; loop1
< lc_mc_search
->conditions
->len
; loop1
++)
303 mc_search_cond
= (mc_search_cond_t
*) g_ptr_array_index (lc_mc_search
->conditions
, loop1
);
305 if (!mc_search_cond
->regex_handle
)
309 mc_search__regex_found_cond_one (lc_mc_search
, mc_search_cond
->regex_handle
,
312 if (ret
!= COND__NOT_FOUND
)
315 return COND__NOT_ALL_FOUND
;
318 /* --------------------------------------------------------------------------------------------- */
321 mc_search_regex__get_max_num_of_replace_tokens (const gchar
* str
, gsize len
)
325 for (loop
= 0; loop
< len
- 1; loop
++)
327 if (str
[loop
] == '\\' && g_ascii_isdigit (str
[loop
+ 1]))
329 if (strutils_is_char_escaped (str
, &str
[loop
]))
331 if (max_token
< str
[loop
+ 1] - '0')
332 max_token
= str
[loop
+ 1] - '0';
335 if (str
[loop
] == '$' && str
[loop
+ 1] == '{')
340 if (strutils_is_char_escaped (str
, &str
[loop
]))
344 loop
+ tmp_len
+ 2 < len
&& (str
[loop
+ 2 + tmp_len
] & (char) 0xf0) == 0x30;
346 if (str
[loop
+ 2 + tmp_len
] == '}')
348 tmp_str
= g_strndup (&str
[loop
+ 2], tmp_len
);
349 tmp_token
= atoi (tmp_str
);
350 if (max_token
< tmp_token
)
351 max_token
= tmp_token
;
359 /* --------------------------------------------------------------------------------------------- */
362 mc_search_regex__get_token_by_num (const mc_search_t
* lc_mc_search
, gsize lc_index
)
364 int fnd_start
= 0, fnd_end
= 0;
366 #ifdef SEARCH_TYPE_GLIB
367 g_match_info_fetch_pos (lc_mc_search
->regex_match_info
, lc_index
, &fnd_start
, &fnd_end
);
368 #else /* SEARCH_TYPE_GLIB */
369 fnd_start
= lc_mc_search
->iovector
[lc_index
* 2 + 0];
370 fnd_end
= lc_mc_search
->iovector
[lc_index
* 2 + 1];
371 #endif /* SEARCH_TYPE_GLIB */
373 if (fnd_end
- fnd_start
== 0)
376 return g_strndup (lc_mc_search
->regex_buffer
->str
+ fnd_start
, fnd_end
- fnd_start
);
380 /* --------------------------------------------------------------------------------------------- */
383 mc_search_regex__replace_handle_esc_seq (const GString
* replace_str
, const gsize current_pos
,
384 gsize
* skip_len
, int *ret
)
386 char *curr_str
= &(replace_str
->str
[current_pos
]);
387 char c
= *(curr_str
+ 1);
389 if (replace_str
->len
> current_pos
+ 2)
393 for (*skip_len
= 2; /* \{ */
394 current_pos
+ *skip_len
< replace_str
->len
395 && *(curr_str
+ *skip_len
) >= '0'
396 && *(curr_str
+ *skip_len
) <= '7'; (*skip_len
)++);
397 if (current_pos
+ *skip_len
< replace_str
->len
&& *(curr_str
+ *skip_len
) == '}')
400 *ret
= REPLACE_PREPARE_T_ESCAPE_SEQ
;
405 *ret
= REPLACE_PREPARE_T_NOTHING_SPECIAL
;
412 *skip_len
= 2; /* \x */
416 for (*skip_len
= 3; /* \x{ */
417 current_pos
+ *skip_len
< replace_str
->len
418 && g_ascii_isxdigit ((guchar
) * (curr_str
+ *skip_len
)); (*skip_len
)++);
419 if (current_pos
+ *skip_len
< replace_str
->len
&& *(curr_str
+ *skip_len
) == '}')
422 *ret
= REPLACE_PREPARE_T_ESCAPE_SEQ
;
427 *ret
= REPLACE_PREPARE_T_NOTHING_SPECIAL
;
431 else if (!g_ascii_isxdigit ((guchar
) c
))
433 *skip_len
= 2; /* \x without number behind */
434 *ret
= REPLACE_PREPARE_T_NOTHING_SPECIAL
;
440 if (!g_ascii_isxdigit ((guchar
) c
))
441 *skip_len
= 3; /* \xH */
443 *skip_len
= 4; /* \xHH */
444 *ret
= REPLACE_PREPARE_T_ESCAPE_SEQ
;
450 if (strchr ("ntvbrfa", c
) != NULL
)
453 *ret
= REPLACE_PREPARE_T_ESCAPE_SEQ
;
459 /* --------------------------------------------------------------------------------------------- */
462 mc_search_regex__process_replace_str (const GString
* replace_str
, const gsize current_pos
,
463 gsize
* skip_len
, replace_transform_type_t
* replace_flags
)
467 const char *curr_str
= &(replace_str
->str
[current_pos
]);
469 if (current_pos
> replace_str
->len
)
470 return REPLACE_PREPARE_T_NOTHING_SPECIAL
;
474 if ((*curr_str
== '$') && (*(curr_str
+ 1) == '{') && ((*(curr_str
+ 2) & (char) 0xf0) == 0x30)
475 && (replace_str
->len
> current_pos
+ 2))
477 if (strutils_is_char_escaped (replace_str
->str
, curr_str
))
480 return REPLACE_PREPARE_T_NOTHING_SPECIAL
;
484 current_pos
+ *skip_len
+ 2 < replace_str
->len
485 && (*(curr_str
+ 2 + *skip_len
) & (char) 0xf0) == 0x30; (*skip_len
)++);
487 if (*(curr_str
+ 2 + *skip_len
) != '}')
488 return REPLACE_PREPARE_T_NOTHING_SPECIAL
;
490 tmp_str
= g_strndup (curr_str
+ 2, *skip_len
);
492 return REPLACE_PREPARE_T_NOTHING_SPECIAL
;
494 ret
= atoi (tmp_str
);
497 *skip_len
+= 3; /* ${} */
498 return ret
; /* capture buffer index >= 0 */
501 if ((*curr_str
== '\\') && (replace_str
->len
> current_pos
+ 1))
503 if (strutils_is_char_escaped (replace_str
->str
, curr_str
))
506 return REPLACE_PREPARE_T_NOTHING_SPECIAL
;
509 if (g_ascii_isdigit (*(curr_str
+ 1)))
511 ret
= g_ascii_digit_value (*(curr_str
+ 1)); /* capture buffer index >= 0 */
512 *skip_len
= 2; /* \\ and one digit */
516 if (!mc_search_regex__replace_handle_esc_seq (replace_str
, current_pos
, skip_len
, &ret
))
519 ret
= REPLACE_PREPARE_T_REPLACE_FLAG
;
521 switch (*(curr_str
+ 1))
524 *replace_flags
|= REPLACE_T_UPP_TRANSFORM
;
525 *replace_flags
&= ~REPLACE_T_LOW_TRANSFORM
;
528 *replace_flags
|= REPLACE_T_UPP_TRANSFORM_CHAR
;
531 *replace_flags
|= REPLACE_T_LOW_TRANSFORM
;
532 *replace_flags
&= ~REPLACE_T_UPP_TRANSFORM
;
535 *replace_flags
|= REPLACE_T_LOW_TRANSFORM_CHAR
;
538 *replace_flags
= REPLACE_T_NO_TRANSFORM
;
541 ret
= REPLACE_PREPARE_T_NOTHING_SPECIAL
;
548 /* --------------------------------------------------------------------------------------------- */
551 mc_search_regex__process_append_str (GString
* dest_str
, const char *from
, gsize len
,
552 replace_transform_type_t
* replace_flags
)
559 if (len
== (gsize
) - 1)
562 if (*replace_flags
== REPLACE_T_NO_TRANSFORM
)
564 g_string_append_len (dest_str
, from
, len
);
569 tmp_str
= mc_search__get_one_symbol (NULL
, from
+ loop
, len
- loop
, NULL
);
570 char_len
= strlen (tmp_str
);
571 if (*replace_flags
& REPLACE_T_UPP_TRANSFORM_CHAR
)
573 *replace_flags
&= ~REPLACE_T_UPP_TRANSFORM_CHAR
;
574 tmp_string
= mc_search__toupper_case_str (NULL
, tmp_str
, char_len
);
575 g_string_append (dest_str
, tmp_string
->str
);
576 g_string_free (tmp_string
, TRUE
);
579 else if (*replace_flags
& REPLACE_T_LOW_TRANSFORM_CHAR
)
581 *replace_flags
&= ~REPLACE_T_LOW_TRANSFORM_CHAR
;
582 tmp_string
= mc_search__toupper_case_str (NULL
, tmp_str
, char_len
);
583 g_string_append (dest_str
, tmp_string
->str
);
584 g_string_free (tmp_string
, TRUE
);
587 else if (*replace_flags
& REPLACE_T_UPP_TRANSFORM
)
589 tmp_string
= mc_search__toupper_case_str (NULL
, tmp_str
, char_len
);
590 g_string_append (dest_str
, tmp_string
->str
);
591 g_string_free (tmp_string
, TRUE
);
594 else if (*replace_flags
& REPLACE_T_LOW_TRANSFORM
)
596 tmp_string
= mc_search__tolower_case_str (NULL
, tmp_str
, char_len
);
597 g_string_append (dest_str
, tmp_string
->str
);
598 g_string_free (tmp_string
, TRUE
);
603 g_string_append (dest_str
, tmp_str
);
611 /* --------------------------------------------------------------------------------------------- */
614 mc_search_regex__process_escape_sequence (GString
* dest_str
, const char *from
, gsize len
,
615 replace_transform_type_t
* replace_flags
,
622 if (len
== (gsize
) (-1))
634 if (i
< len
&& from
[i
] == '{')
638 if (from
[i
] >= '0' && from
[i
] <= '9')
639 c
= c
* 16 + from
[i
] - '0';
640 else if (from
[i
] >= 'a' && from
[i
] <= 'f')
641 c
= c
* 16 + 10 + from
[i
] - 'a';
642 else if (from
[i
] >= 'A' && from
[i
] <= 'F')
643 c
= c
* 16 + 10 + from
[i
] - 'A';
648 else if (from
[i
] >= '0' && from
[i
] <= '7')
649 for (; i
< len
&& from
[i
] >= '0' && from
[i
] <= '7'; i
++)
650 c
= c
* 8 + from
[i
] - '0';
677 mc_search_regex__process_append_str (dest_str
, from
, len
, replace_flags
);
682 if (c
< 0x80 || !is_utf8
)
683 g_string_append_c (dest_str
, (char) c
);
687 g_string_append_c (dest_str
, b
);
688 b
= 0x80 | (c
& 0x3F);
689 g_string_append_c (dest_str
, b
);
691 else if (c
< 0x10000)
693 b
= 0xE0 | (c
>> 12);
694 g_string_append_c (dest_str
, b
);
695 b
= 0x80 | ((c
>> 6) & 0x3F);
696 g_string_append_c (dest_str
, b
);
697 b
= 0x80 | (c
& 0x3F);
698 g_string_append_c (dest_str
, b
);
700 else if (c
< 0x10FFFF)
702 b
= 0xF0 | (c
>> 16);
703 g_string_append_c (dest_str
, b
);
704 b
= 0x80 | ((c
>> 12) & 0x3F);
705 g_string_append_c (dest_str
, b
);
706 b
= 0x80 | ((c
>> 6) & 0x3F);
707 g_string_append_c (dest_str
, b
);
708 b
= 0x80 | (c
& 0x3F);
709 g_string_append_c (dest_str
, b
);
713 /* --------------------------------------------------------------------------------------------- */
714 /*** public functions ****************************************************************************/
715 /* --------------------------------------------------------------------------------------------- */
718 mc_search__cond_struct_new_init_regex (const char *charset
, mc_search_t
* lc_mc_search
,
719 mc_search_cond_t
* mc_search_cond
)
721 #ifdef SEARCH_TYPE_GLIB
722 GError
*error
= NULL
;
724 if (!lc_mc_search
->is_case_sensitive
)
728 tmp
= mc_search_cond
->str
;
729 mc_search_cond
->str
= mc_search__cond_struct_new_regex_ci_str (charset
, tmp
);
730 g_string_free (tmp
, TRUE
);
732 mc_search_cond
->regex_handle
=
733 g_regex_new (mc_search_cond
->str
->str
, G_REGEX_OPTIMIZE
| G_REGEX_RAW
| G_REGEX_DOTALL
,
738 lc_mc_search
->error
= MC_SEARCH_E_REGEX_COMPILE
;
739 lc_mc_search
->error_str
= str_conv_gerror_message (error
, _("Regular expression error"));
740 g_error_free (error
);
743 #else /* SEARCH_TYPE_GLIB */
746 int pcre_options
= PCRE_EXTRA
| PCRE_MULTILINE
;
748 if (str_isutf8 (charset
) && mc_global
.utf8_display
)
750 pcre_options
|= PCRE_UTF8
;
751 if (!lc_mc_search
->is_case_sensitive
)
752 pcre_options
|= PCRE_CASELESS
;
756 if (!lc_mc_search
->is_case_sensitive
)
760 tmp
= mc_search_cond
->str
;
761 mc_search_cond
->str
= mc_search__cond_struct_new_regex_ci_str (charset
, tmp
);
762 g_string_free (tmp
, TRUE
);
766 mc_search_cond
->regex_handle
=
767 pcre_compile (mc_search_cond
->str
->str
, pcre_options
, &error
, &erroffset
, NULL
);
768 if (mc_search_cond
->regex_handle
== NULL
)
770 lc_mc_search
->error
= MC_SEARCH_E_REGEX_COMPILE
;
771 lc_mc_search
->error_str
= g_strdup (error
);
774 lc_mc_search
->regex_match_info
= pcre_study (mc_search_cond
->regex_handle
, 0, &error
);
775 if (lc_mc_search
->regex_match_info
== NULL
)
779 lc_mc_search
->error
= MC_SEARCH_E_REGEX_COMPILE
;
780 lc_mc_search
->error_str
= g_strdup (error
);
781 g_free (mc_search_cond
->regex_handle
);
782 mc_search_cond
->regex_handle
= NULL
;
786 #endif /* SEARCH_TYPE_GLIB */
787 lc_mc_search
->is_utf8
= str_isutf8 (charset
);
790 /* --------------------------------------------------------------------------------------------- */
793 mc_search__run_regex (mc_search_t
* lc_mc_search
, const void *user_data
,
794 gsize start_search
, gsize end_search
, gsize
* found_len
)
796 gsize current_pos
, virtual_pos
;
801 if (lc_mc_search
->regex_buffer
!= NULL
)
802 g_string_free (lc_mc_search
->regex_buffer
, TRUE
);
804 lc_mc_search
->regex_buffer
= g_string_sized_new (64);
806 virtual_pos
= current_pos
= start_search
;
807 while (virtual_pos
<= end_search
)
809 g_string_set_size (lc_mc_search
->regex_buffer
, 0);
810 lc_mc_search
->start_buffer
= current_pos
;
814 current_chr
= mc_search__get_char (lc_mc_search
, user_data
, current_pos
);
815 if (current_chr
== MC_SEARCH_CB_ABORT
)
818 if (current_chr
== MC_SEARCH_CB_INVALID
)
823 if (current_chr
== MC_SEARCH_CB_SKIP
)
828 g_string_append_c (lc_mc_search
->regex_buffer
, (char) current_chr
);
831 if (current_chr
== 0 || (char) current_chr
== '\n')
834 if (virtual_pos
> end_search
)
838 switch (mc_search__regex_found_cond (lc_mc_search
, lc_mc_search
->regex_buffer
))
841 #ifdef SEARCH_TYPE_GLIB
842 if (lc_mc_search
->whole_words
)
844 g_match_info_fetch_pos (lc_mc_search
->regex_match_info
, 2, &start_pos
, &end_pos
);
848 g_match_info_fetch_pos (lc_mc_search
->regex_match_info
, 0, &start_pos
, &end_pos
);
850 #else /* SEARCH_TYPE_GLIB */
851 if (lc_mc_search
->whole_words
)
853 start_pos
= lc_mc_search
->iovector
[4];
854 end_pos
= lc_mc_search
->iovector
[5];
858 start_pos
= lc_mc_search
->iovector
[0];
859 end_pos
= lc_mc_search
->iovector
[1];
861 #endif /* SEARCH_TYPE_GLIB */
863 *found_len
= end_pos
- start_pos
;
864 lc_mc_search
->normal_offset
= lc_mc_search
->start_buffer
+ start_pos
;
866 case COND__NOT_ALL_FOUND
:
869 g_string_free (lc_mc_search
->regex_buffer
, TRUE
);
870 lc_mc_search
->regex_buffer
= NULL
;
873 if ((lc_mc_search
->update_fn
!= NULL
) &&
874 ((lc_mc_search
->update_fn
) (user_data
, current_pos
) == MC_SEARCH_CB_ABORT
))
875 current_chr
= MC_SEARCH_CB_ABORT
;
877 if (current_chr
== MC_SEARCH_CB_ABORT
)
880 g_string_free (lc_mc_search
->regex_buffer
, TRUE
);
881 lc_mc_search
->regex_buffer
= NULL
;
882 lc_mc_search
->error
= MC_SEARCH_E_NOTFOUND
;
884 if (current_chr
!= MC_SEARCH_CB_ABORT
)
885 lc_mc_search
->error_str
= g_strdup (_(STR_E_NOTFOUND
));
887 lc_mc_search
->error_str
= NULL
;
892 /* --------------------------------------------------------------------------------------------- */
895 mc_search_regex_prepare_replace_str (mc_search_t
* lc_mc_search
, GString
* replace_str
)
900 int num_replace_tokens
, lc_index
;
904 replace_transform_type_t replace_flags
= REPLACE_T_NO_TRANSFORM
;
907 mc_search_regex__get_max_num_of_replace_tokens (replace_str
->str
, replace_str
->len
);
909 if (lc_mc_search
->num_results
< 0)
910 return g_string_new_len (replace_str
->str
, replace_str
->len
);
912 if (num_replace_tokens
> lc_mc_search
->num_results
- 1
913 || num_replace_tokens
> MC_SEARCH__NUM_REPLACE_ARGS
)
915 lc_mc_search
->error
= MC_SEARCH_E_REGEX_REPLACE
;
916 lc_mc_search
->error_str
= g_strdup (_(STR_E_RPL_NOT_EQ_TO_FOUND
));
920 ret
= g_string_sized_new (64);
921 prev_str
= replace_str
->str
;
923 for (loop
= 0; loop
< replace_str
->len
- 1; loop
++)
925 lc_index
= mc_search_regex__process_replace_str (replace_str
, loop
, &len
, &replace_flags
);
927 if (lc_index
== REPLACE_PREPARE_T_NOTHING_SPECIAL
)
931 mc_search_regex__process_append_str (ret
, prev_str
,
932 replace_str
->str
- prev_str
+ loop
,
934 mc_search_regex__process_append_str (ret
, replace_str
->str
+ loop
+ 1, len
- 1,
936 prev_str
= replace_str
->str
+ loop
+ len
;
942 if (lc_index
== REPLACE_PREPARE_T_REPLACE_FLAG
)
945 mc_search_regex__process_append_str (ret
, prev_str
,
946 replace_str
->str
- prev_str
+ loop
,
948 prev_str
= replace_str
->str
+ loop
+ len
;
953 /* escape sequence */
954 if (lc_index
== REPLACE_PREPARE_T_ESCAPE_SEQ
)
956 mc_search_regex__process_append_str (ret
, prev_str
,
957 replace_str
->str
+ loop
- prev_str
,
959 /* call process_escape_sequence without starting '\\' */
960 mc_search_regex__process_escape_sequence (ret
, replace_str
->str
+ loop
+ 1, len
- 1,
961 &replace_flags
, lc_mc_search
->is_utf8
);
962 prev_str
= replace_str
->str
+ loop
+ len
;
967 /* invalid capture buffer number */
968 if (lc_index
> lc_mc_search
->num_results
)
970 g_string_free (ret
, TRUE
);
971 lc_mc_search
->error
= MC_SEARCH_E_REGEX_REPLACE
;
972 lc_mc_search
->error_str
= g_strdup_printf (_(STR_E_RPL_INVALID_TOKEN
), lc_index
);
976 tmp_str
= mc_search_regex__get_token_by_num (lc_mc_search
, lc_index
);
981 mc_search_regex__process_append_str (ret
, prev_str
, replace_str
->str
- prev_str
+ loop
,
983 prev_str
= replace_str
->str
+ loop
+ len
;
985 mc_search_regex__process_append_str (ret
, tmp_str
, -1, &replace_flags
);
989 mc_search_regex__process_append_str (ret
, prev_str
,
990 replace_str
->str
- prev_str
+ replace_str
->len
,